1 Commits

Author SHA1 Message Date
dd8f59c90b Update dependency ubuntu to v24 2025-05-07 22:16:28 +00:00
11 changed files with 28 additions and 955 deletions

View File

@@ -1,4 +1,4 @@
name: Package & Sign Helm Chart
name: Packaging Chart
on:
release:
@@ -7,76 +7,29 @@ on:
jobs:
build:
runs-on: ubuntu-24.04
env:
CHART_DIR: bookstack/
CHART_VERSION: ${{ github.event.release.tag_name }}
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
steps:
# 1) Code auschecken
- uses: actions/checkout@v4
# 2) Helm installieren
- uses: azure/setup-helm@v4.3.0
- name: Checkout
uses: actions/checkout@v4
- name: Setup latest Helm
uses: azure/setup-helm@v4.3.0
with:
version: latest
id: install
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
passphrase: ${{ secrets.PASSPHRASE }}
trust_level: 5
# 3) "Generation-1"-Secret-Ring für Helm erzeugen (TMP, 600 Rechte)
- name: Build legacy secret-keyring
- name: Export GPG key in legacy format
run: |
set -euo pipefail
install -m 700 -d /tmp/gpgring
gpg --batch --yes --pinentry-mode loopback \
--passphrase "$PASSPHRASE" \
--export-secret-keys "$GPG_KEY_ID" \
>/tmp/gpgring/secring.gpg
chmod 600 /tmp/gpgring/secring.gpg
echo "$PASSPHRASE" > /tmp/gpgring/passphrase.txt
chmod 600 /tmp/gpgring/passphrase.txt
# 4) Chart bauen & signieren
- name: Package & sign chart
gpg --export-secret-keys --output /tmp/keyring.gpg ${{ secrets.GPG_KEY_ID }}
- name: Package Chart
run: |
cp README.md "$CHART_DIR"/
helm dependency build "$CHART_DIR"
helm package "$CHART_DIR" \
--version "$CHART_VERSION" \
--sign \
--key "Morlana Signing" \
--keyring /tmp/gpgring/secring.gpg \
--passphrase-file /tmp/gpgring/passphrase.txt
# 5) In dein internes Chart-Repo hochladen
- name: Upload to ChartMuseum
cp README.md ./charts/bookstack/.
helm dependency build ./charts/bookstack
helm package --version $CHART_VERSION --sign --keyring /tmp/keyring.gpg ./bookstack --dependency-update
curl -u $REPO_CREDENTIALS -F "chart=@bookstack-$CHART_VERSION.tgz" -F "prov=@bookstack-$CHART_VERSION.tgz.prov" https://charts.morlana.net/api/charts
env:
REPO_CREDENTIALS: ${{ secrets.REPO_CREDENTIALS }}
run: |
curl -H "Authorization: Basic $REPO_CREDENTIALS" \
-F "chart=@bookstack-$CHART_VERSION.tgz" \
-F "prov=@bookstack-$CHART_VERSION.tgz.prov" \
https://charts.morlana.net/api/charts
# 6) Public-Key aus Repo beilegen und als Release-Asset anhängen
- name: Attach release assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event.release.tag_name }}
files: |
bookstack-${{ env.CHART_VERSION }}.tgz
bookstack-${{ env.CHART_VERSION }}.tgz.prov
pubkeys/morlana.asc
# 7) Aufräumen (optional, Runner ist ohnehin kurzlebig)
- name: Cleanup sensitive files
if: ${{ always() }}
run: rm -rf /tmp/gpgring
CHART_VERSION: ${{ github.event.release.tag_name }}

View File

@@ -1,9 +0,0 @@
{
"github.copilot.enable": {
"*": true,
"plaintext": false,
"markdown": false,
"scminput": false,
"yaml": true
}
}

View File

@@ -1,15 +0,0 @@
# Changelog
## 0.1.0+up25.5.0 - 2025-06-12
- **Changed** ✦ Packages upstream BookStack v25.5.0
- [Release Notes](https://github.com/solidnerd/docker-bookstack/releases/tag/25.5.0)
- [Project homepage](https://www.bookstackapp.com/)
## 0.1.0+up25.2.3 2025-05-08
- **Added** Initial Helm chart for BookStack.
- ✦ Packages upstream BookStack v25.2.3
- [Project homepage](https://www.bookstackapp.com/)
- **Added** ✦ Ingress, persistence, TLS and SMTP settings readymade
- **Added** ✦ Includes optional MariaDB and Redis subcharts
- [MariaDB subchart](https://artifacthub.io/packages/helm/bitnami/mariadb)
- [Redis subchart](https://artifacthub.io/packages/helm/bitnami/redis)

143
README.md
View File

@@ -1,142 +1,3 @@
# BookStack Helm Chart
# bookstack-chart
Deploys the BookStack wiki platform on Kubernetes with optional MariaDB and Redis sub-charts.
---
## Versioning
The chart uses **dual semantic versioning**:
```
<chart semver>+<upstream BookStack semver>
# example: 1.2.3+25.2.3
```
This allows Helm to track compatibility changes independently from upstream BookStack releases.
---
## Prerequisites
* Helm 3
* Kubernetes 1.24+
* (Optional) External MariaDB 10.5+ and/or Redis 6+ instances if you disable the bundled subcharts
---
## Quick start
```bash
helm repo add morlana https://charts.morlana.net
helm repo update
helm install bookstack morlana/bookstack \
--namespace bookstack --create-namespace
```
The first run generates a **Laravel APP\_KEY** secret. The deployment automatically restarts once the key is present.
---
## Upgrading
```bash
helm upgrade bookstack morlana/bookstack -n bookstack --reuse-values
```
Helm recognises new chart versions that follow the `x.y.z+<bookstack>` scheme. Check the upstream projects release notes as well as the charts `CHANGELOG.md` before upgrading across major versions.
---
## Uninstalling
```bash
helm uninstall bookstack -n bookstack
```
PersistentVolumeClaims and One-Time generated secrets are **not** removed automatically.
---
## Configuration (excerpt)
| Key | Description | Default |
| ------------------------------- | --------------------------------------------------- | --------------------- |
| `bookstack.image.repository` | Container image repository | `solidnerd` |
| `bookstack.image.name` | Image name | `bookstack` |
| `bookstack.image.tag` | Image tag (defaults to upstream version when empty) | `""` |
| `bookstack.replicaCount` | Number of pods | `1` |
| `bookstack.config.app.url` | Public URL users will access | `https://example.com` |
| `bookstack.config.app.key` | Laravel APP\_KEY (autogenerated if empty) | `""` |
| `bookstack.mail.host` | SMTP host (set to enable email) | `""` |
| `bookstack.mail.port` | SMTP port | `1025` |
| `bookstack.persistence.enabled` | Persist uploads and storage | `true` |
| `bookstack.persistence.size` | PVC size | `10Gi` |
| `service.type` | Kubernetes Service type | `ClusterIP` |
| `ingress.enabled` | Create an Ingress | `false` |
| `db.enabled` | Deploy bundled MariaDB | `true` |
| `redis.enabled` | Deploy bundled Redis | `true` |
Override values with `--set key=value` or put them in `my-values.yaml` and pass `-f`.
---
## Persistence
A single ReadWriteMany PVC is created by default so all replicas share the same data. Customise size, StorageClass or accessMode via `bookstack.persistence.*`.
---
## Ingress example
```yaml
ingress:
enabled: true
class: nginx
hostname: wiki.example.com
tls:
- hosts: [wiki.example.com]
secretName: wiki-tls
```
---
## Using external services
Disable the subcharts and point BookStack at existing database/redis servers:
```yaml
db:
enabled: false
bookstack:
externalDatabase:
host: mariadb.example.com
database: bookstack
username: bookstack
password: supersecret
redis:
enabled: false
bookstack:
externalRedis:
servers: redis://:password@redis.example.com:6379/0
```
---
## Backup & restore
* **Database**: use `mysqldump` / `mysql` against the MariaDB service (or your external DB).
* **Application data**: back up the BookStack PVC with your preferred tool (Velero, restic, etc.).
---
## Contributing
Bug reports and pull requests are welcome in the [chart repository](https://git.morlana.online/f.weber/bookstack-chart).
For issues specific to BookStack itself, please use the [upstream projects tracker](https://github.com/BookStackApp/BookStack/issues).
Happy documenting! 📚
This is an unofficial Helm Chart for bookstackapp.com

View File

@@ -1,13 +1,12 @@
apiVersion: v2
name: bookstack
description: |
Deploys the BookStack wiki platform on Kubernetes with optional MariaDB and Redis sub-charts.
description: A Helm chart for Kubernetes
type: application
version: "0.1.0+up25.5.0"
version: "0.1.0+up25.2.3"
appVersion: "25.5.0"
appVersion: "25.2.3"
dependencies:
- name: mariadb
@@ -19,27 +18,3 @@ dependencies:
version: ">=21.0.0 <22.0.0"
repository: "oci://registry-1.docker.io/bitnamicharts"
condition: redis.enabled
annotations:
artifacthub.io/license: MIT
artifacthub.io/links: |
- name: Git Repository
url: https://git.morlana.online/f.weber/bookstack-chart
- name: Issues
url: https://github.com/flweber/helm-bookstack/issues
- name: GitHub Mirror
url: https://github.com/flweber/helm-bookstack
artifacthub.io/maintainers: |
- name: Florian Weber
email: kosmos@morlana.net
artifacthub.io/signKey: |
fingerprint: 8975 6E20 1E4C 99B1 A2E9 5712 DF7D F259 CD8F CAAA
url: https://raw.githubusercontent.com/flweber/helm-bookstack/refs/heads/main/pubkeys/morlana.asc
artifacthub.io/changes: |
- kind: changed
description: ✦ Packages upstream BookStack v25.5.0
links:
- name: Release Notes
url: https://github.com/solidnerd/docker-bookstack/releases/tag/25.5.0
- name: Project homepage
url: https://www.bookstackapp.com/

View File

@@ -84,12 +84,6 @@ spec:
- secretRef:
name: {{ include "bookstack.secret" . }}
{{- end }}
{{- range $key, $conf := .Values.bookstack.auth }}
{{- if and (ne $key "method") (ne $key "auto.initiate") ($conf.enabled) $conf.existingSecret }}
- secretRef:
name: {{ $conf.existingSecret }}
{{- end }}
{{- end }}
ports:
- containerPort: 8080
name: bookstack-http

View File

@@ -1,4 +1,4 @@
{{- if or (not .Values.db.enabled) (not (.Values.bookstack.auth | default dict | len | eq 0)) .Values.bookstack.config.additionalSecrets .Values.bookstack.mail.username .Values.bookstack.config.additionalSecrets .Values.bookstack.mail.password }}
{{- if or (not .Values.db.enabled) (not (.Values.bookstack.auth | default dict | len | eq 0)) }}
apiVersion: v1
kind: Secret
type: Opaque
@@ -32,7 +32,7 @@ data:
$conf.clientSecret | b64enc | quote }}
{{- end }}
{{- end }}
{{- if and .Values.bookstack.auth.ldap.enabled (not .Values.bookstack.auth.ldap.existingSecret) }}
{{- if .Values.bookstack.auth.ldap.enabled }}
LDAP_SERVER: {{ required
"You have to define a bookstack.auth.ldap.server"
.Values.bookstack.auth.ldap.server | b64enc | quote }}
@@ -40,16 +40,7 @@ data:
"You have to define a bookstack.auth.ldap.dn"
.Values.bookstack.auth.ldap.dn | b64enc | quote }}
LDAP_PASS: {{ required
"You have to define a bookstack.auth.ldap.pass"
"You have to define a bookstack.auth.ldap.passw"
.Values.bookstack.auth.ldap.pass | b64enc | quote }}
{{- end }}
{{- if .Values.bookstack.mail.username }}
MAIL_USERNAME: {{ .Values.bookstack.mail.username | b64enc | quote }}
{{- end }}
{{- if .Values.bookstack.mail.password }}
MAIL_PASSWORD: {{ .Values.bookstack.mail.password | b64enc | quote }}
{{- end }}
{{- range $key, $value := .Values.bookstack.config.additionalSecrets }}
{{ $key | snakecase | upper }}: {{ $value | b64enc | quote }}
{{- end }}
{{- end }}

View File

@@ -1,569 +0,0 @@
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"global": {
"type": "object",
"description": "Global settings for all applications.",
"additionalProperties": false,
"properties": {
"imageRegistry": {
"type": "string",
"description": "The image registry to use for all applications. This is used to pull the images from the registry.",
"default": ""
},
"imagePullSecrets": {
"type": "array",
"description": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod",
"items": {
"$ref": "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.31.6/_definitions.json#/definitions/io.k8s.api.core.v1.LocalObjectReference"
},
"x-kubernetes-patch-merge-key": "name",
"x-kubernetes-patch-strategy": "merge",
"default": []
},
"defaultStorageClass": {
"type": "string",
"description": "The default storage class to use for all applications. This is used to create persistent volumes for the applications.",
"default": ""
},
"clusterDomain": {
"type": "string",
"description": "The domain name of the cluster. This is used to resolve services within the cluster.",
"default": "cluster.local"
}
}
},
"bookstack": {
"type": "object",
"description": "",
"additionalProperties": false,
"properties": {
"image": {
"type": "object",
"description": "",
"additionalProperties": false,
"properties": {
"registry": {
"type": "string",
"description": "The image registry to use for all applications. This is used to pull the images from the registry.",
"default": ""
},
"repository": {
"type": "string",
"description": "The repository of the image.",
"default": "solidnerd"
},
"name": {
"type": "string",
"description": "The name of the image.",
"default": "bookstack"
},
"tag": {
"type": "string",
"description": "Tag of the application you want to deploy. Could be a version number, commit sha or bad practice like \"latest\", \"dev\", \"qs\", \"prd\"",
"default": ""
},
"imagePullSecrets": {
"type": "array",
"description": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod",
"items": {
"$ref": "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.31.6/_definitions.json#/definitions/io.k8s.api.core.v1.LocalObjectReference"
},
"x-kubernetes-patch-merge-key": "name",
"x-kubernetes-patch-strategy": "merge",
"default": []
},
"pullPolicy": {
"type": "string",
"description": "",
"default": "Always"
}
}
},
"replicaCount": {
"type": "integer",
"description": "The number of replicas to run.",
"default": 1
},
"updateStrategy": {
"description": "The update strategy to use for the deployment.",
"$ref": "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.31.6/_definitions.json#/definitions/io.k8s.api.apps.v1.DeploymentStrategy"
},
"externalDatabase": {
"type": "object",
"description": "If you want to use an external database, set this to true and provide the connection details.",
"additionalProperties": false,
"properties": {
"host": {
"type": "string",
"description": "The host (including port) of the external database."
},
"database": {
"type": "string",
"description": "The name of the database."
},
"username": {
"type": "string",
"description": "The username for the external database."
},
"password": {
"type": "string",
"description": "The password for the external database."
}
},
"required": [
"host",
"database",
"username",
"password"
]
},
"externalRedis": {
"type": "object",
"description": "If you want to use an external redis, set this to true and provide the connection details.",
"additionalProperties": false,
"properties": {
"servers": {
"type": "string",
"description": "One or more redis servers. See bookstack documentation for more details."
}
},
"required": [
"servers"
]
},
"config": {
"type": "object",
"description": "Bookstack application configuration section.",
"properties": {
"app": {
"type": "object",
"additionalProperties": true,
"description": "These settings will be provided as environment variables to bookstack. All of them will be automatically prefixed with \"APP_\" and the upper-case version of the provided key. e.g. \"url\" will be \"APP_URL\". If you have variables like \"APP_DEFAULT_DARK_MODE\" replace underscores with \".\" e.g. \"default.dark.mode\".",
"properties": {
"key": {
"type": [
"string",
"null"
],
"description": "If not provided a random key will be generated on the first deployment",
"default": null
},
"url": {
"type": "string",
"description": ""
}
},
"required": [
"url"
]
},
"additional": {
"type": "object",
"additionalProperties": true,
"description": "Here you can define environment variables by yourself which don't have a specific prefix e.g. \"STORAGE_TYPE\". Set it like key-value yaml pairs. For example: \"STORAGE_TYPE\": \"local\". Don't replace \"_\" with \".\"!"
},
"additionalSecrets": {
"type": "object",
"additionalProperties": true,
"description": "It's like \"additional\" section but the values will be stored in a Kubernetes secret. Base64 encoding will be done by the chart, so you have to input the clear values."
}
},
"required": [
"app"
]
},
"mail": {
"type": "object",
"description": "Bookstack mail settings. If your needed values are not listed here, you can also set them if the values are prefixed with \"MAIL_\". If you need \"MAIL_VERIFY_SSL\" write it as \"verify.ssl\".",
"additionalProperties": true,
"properties": {
"driver": {
"type": "string",
"description": "",
"default": "smtp",
"enum": [
"smtp",
"sendmail"
]
},
"host": {
"type": "string",
"description": "",
"default": ""
},
"from": {
"type": "string",
"description": "",
"default": "bookstack@cluster.local"
},
"from.name": {
"type": "string",
"description": "",
"default": "BookStack"
},
"username": {
"type": "string",
"description": "",
"default": "changeme"
},
"password": {
"type": "string",
"description": "",
"default": "changeme"
},
"port": {
"type": "integer",
"description": "",
"default": 1025
},
"encryption": {
"type": "string",
"description": "",
"default": "null",
"enum": [
"tls",
"null"
]
},
"verify.ssl": {
"type": "boolean",
"description": "",
"default": true
},
"sendmail.command": {
"type": "string"
}
},
"required": [
"driver"
]
},
"auth": {
"type": "object",
"description": "",
"additionalProperties": false,
"properties": {
"method": {
"type": "string",
"description": "See for more information: https://github.com/BookStackApp/BookStack/blob/development/.env.example.complete#L149"
},
"auto.initiate": {
"type": "boolean",
"default": false,
"description": "See for more information: https://github.com/BookStackApp/BookStack/blob/development/.env.example.complete#L153"
},
"oidc": {
"type": "object",
"description": "Here you can define BookStack OIDC settings. To set additional values not listed here define them in lowercase and replace \"_\" with \".\" in variable names. E.g. \"OIDC_ISSUER_DISCOVER\" as \"issuer.discover\"",
"required": ["enabled"],
"additionalProperties": true,
"properties": {
"name": {
"type": "string",
"description": "",
"default": "Open ID Connect"
},
"clientId": {
"type": "string",
"description": "",
"default": ""
},
"clientSecret": {
"type": "string",
"description": "",
"default": ""
},
"issuer": {
"type": "string",
"description": "",
"default": ""
}
}
},
"azure": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"AZURE_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"discord": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"DISCORD_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"facebook": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"FACEBOOK_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"github": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"GITHUB_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"gitlab": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"GITLAB_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"google": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"GOOGLE_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"okta": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"OKTA_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"slack": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"SLACK_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"twitch": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"TWITCH_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"twitter": {
"description": "Enable or disable social auth option. You can set additional values like auto registration by replacing \"_\" with \".\" and in lowercase e.g. \"TWITTER_AUTO_REGISTER\" as \"auto.register\". You don't need the social auth key as a prefix.",
"$ref": "#/definitions/socialAuth"
},
"ldap": {
"type": "object",
"description": "Enable or disable social auth option. You can set additional values like email attribute by replacing \"_\" with \".\" and in lowercase e.g. \"LDAP_EMAIL_ATTRIBUTE\" as \"email.attribute\". You don't need the \"LDAP_\" key as a prefix.",
"additionalProperties": true,
"properties": {
"enabled": {
"type": "boolean",
"default": "false",
"description": "Wether LDAP auth is enabled"
},
"server": {
"type": "string",
"default": "",
"description": "The LDAP server to connect to."
},
"dn": {
"type": "string",
"default": "",
"description": "User DN used for authentication"
},
"pass": {
"type": "string",
"default": "",
"description": "Password used for authentication"
},
"base.dn": {
"type": "string",
"default": "",
"description": "LDAP Base search dn"
}
},
"required": ["enabled"]
}
}
},
"extraEnv": {
"type": "object",
"additionalProperties": {
"type": ["string", "object"],
"description": "Extra environment variables for bookstack. Could be a simple string or a valueFrom..."
}
},
"persistence": {
"type": "object",
"description": "Defines volume settings for data persistence in bookstack",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean",
"default": true,
"description": "Wether volume will be created"
},
"size": {
"type": "string",
"default": "10Gi",
"description": "The size of the volume which will be created. Be careful some storage interfaces don't support resizing."
},
"storageClass": {
"type": "string",
"description": "",
"default": ""
},
"accessMode": {
"type": "string",
"default": "ReadWriteMany",
"description": "Access mode to define how many times the volume could be mounted."
}
},
"required": ["enabled", "size", "accessMode"]
}
}
},
"ingress": {
"type": "object",
"description": "Here you can define the ingress settings for your application. This is only needed if you want to expose your application to the outside world.",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean",
"description": "Enable the ingress",
"default": false
},
"annotations": {
"annotations": {
"additionalProperties": {
"type": "string"
},
"description": "You can add these Kubernetes annotations to specific Ingress objects to customize their behavior.\n!!! tip Annotation keys and values can only be strings. Other types, such as boolean or numeric values must be quoted, i.e. \"true\", \"false\", \"100\". More info: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md",
"type": "object"
}
},
"tls": {
"description": "tls represents the TLS configuration. Currently the Ingress only supports a single TLS port, 443. If multiple members of this list specify different hosts, they will be multiplexed on the same port according to the hostname specified through the SNI TLS extension, if the ingress controller fulfilling the ingress supports SNI.",
"items": {
"$ref": "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.31.6/_definitions.json#/definitions/io.k8s.api.networking.v1.IngressTLS"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"class": {
"type": "string",
"description": "The class of the ingress. This is used to select the ingress controller that should handle this ingress. If not set, the default ingress class will be used."
},
"hostname": {
"type": "string",
"description": "The hostname for the ingress. This is used to route traffic to the correct service."
},
"path": {
"type": "string",
"description": "The path for the ingress. This is used to route traffic to the correct service.",
"default": "/"
},
"pathType": {
"type": "string",
"description": "The path type for the ingress. This is used to route traffic to the correct service.",
"enum": [
"Exact",
"Prefix",
"ImplementationSpecific"
],
"default": "Prefix"
}
},
"required": [
"enabled",
"hostname",
"path",
"pathType"
]
},
"service": {
"type": "object",
"description": "Here you can define the service settings for your application.",
"additionalProperties": false,
"properties": {
"port": {
"type": "integer",
"description": "The port that the service should listen on.",
"default": 8080
},
"type": {
"type": "string",
"enum": [
"ClusterIP",
"NodePort",
"LoadBalancer",
"Headless"
],
"description": "The type of the service. This defines how the service is exposed or not.",
"default": "ClusterIP"
},
"loadBalancerIP": {
"type": [
"string",
"null"
],
"description": "LoadBalancerIP is the IP address that will be assigned to the service when it is created. This is only used if the service type is LoadBalancer.",
"default": ""
},
"nodePort": {
"type": [
"integer",
"string",
"null"
],
"description": "NodePort is the port that will be assigned to the service when it is created. This is only used if the service type is NodePort.",
"default": ""
},
"clusterIP": {
"type": [
"string",
"null"
],
"description": "ClusterIP is the IP address that will be assigned to the service when it is created. This is only used if the service type is ClusterIP.",
"default": ""
}
},
"required": [
"port",
"type"
]
},
"db": {
"type": "object",
"description": "Here you can define the database settings for your application.",
"additionalProperties": true,
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether this deployment is enabled",
"default": true
}
},
"required": [
"enabled"
]
},
"redis": {
"type": "object",
"description": "Here you can define the redis settings for your application.",
"additionalProperties": true,
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether this deployment is enabled",
"default": true
}
},
"required": [
"enabled"
]
}
},
"required": [
"global",
"bookstack",
"db",
"redis",
"service",
"ingress"
],
"definitions": {
"socialAuth": {
"type": "object",
"additionalProperties": true,
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether this auth option is enabled",
"default": false
},
"appId": {
"type": "string",
"description": "",
"default": ""
},
"appSecret": {
"type": "string",
"description": "",
"default": ""
}
}
}
}
}

View File

@@ -18,8 +18,12 @@ bookstack:
app:
key: ""
url: "https://example.com"
additional: {}
additionalSecrets: {}
views.books: list
views.bookshelves: grid
views.bookshelf: grid
default.dark.mode: true
additional:
DISABLE_EXTERNAL_SERVICES: false
mail:
driver: "smtp"
host: ""

View File

@@ -1,83 +0,0 @@
#!/usr/bin/env python3
"""
generate_changelog.py - Wandelt den Artifact Hub-Changelog in Chart.yaml
in eine Markdown-Datei (CHANGELOG.md) um.
Aufruf:
python generate_changelog.py # takes ./Chart.yaml
python generate_changelog.py path/to/Chart.yaml
"""
import argparse
import datetime as dt
import pathlib
import sys
import textwrap
import yaml
MD_HEADER = "# Changelog\n\n"
def read_chart(path: pathlib.Path) -> dict:
if not path.exists():
sys.exit(f"❌ Chart.yaml not found: {path}")
with path.open() as f:
return yaml.safe_load(f)
def extract_changes(chart: dict) -> list[dict]:
try:
raw = chart["annotations"]["artifacthub.io/changes"]
except KeyError:
sys.exit("❌ No 'artifacthub.io/changes' annotations found.")
try:
return yaml.safe_load(raw) or []
except yaml.YAMLError as e:
sys.exit(f"❌ Changelog annotations are not in a valid YAML format:\n{e}")
def render_markdown(chart: dict, changes: list[dict]) -> str:
version = chart.get("version", "Unversioniert")
today = dt.date.today().isoformat()
heading = f"## {version} - {today}\n"
bullets = []
for item in changes:
kind = item.get("kind", "").capitalize()
desc = item.get("description", "").strip()
links = item.get("links", [])
link_md = ""
if links:
link_md = " " + " ".join(f"[{l['name']}]({l['url']})" for l in links)
bullets.append(f"- **{kind}** {desc}{link_md}")
return MD_HEADER + heading + "\n".join(bullets) + "\n"
def main() -> None:
parser = argparse.ArgumentParser(
description="Generates CHANGELOG.md from Chart.yaml annotations."
)
parser.add_argument(
"chart_yaml",
nargs="?",
default="Chart.yaml",
help="Pfad zur Chart.yaml (Standard: ./Chart.yaml)",
)
args = parser.parse_args()
chart_path = pathlib.Path(args.chart_yaml)
chart = read_chart(chart_path)
changes = extract_changes(chart)
changelog_md = render_markdown(chart, changes)
outfile = chart_path.parent / "CHANGELOG.md"
outfile.write_text(changelog_md, encoding="utf-8")
print(f"✅ CHANGELOG.md generated under {outfile.resolve()}.")
if __name__ == "__main__":
main()

View File

@@ -1,29 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGgiWykBEACtiiNGno+ZL99rI0qP98Ei+HNcs/MgBWqjPa3/nYv6wK1FVEhu
95w/4Oh/EBEP7vuq5lDfC2JQHiif6AHu4tBB6V2Hx3XLyZE9HY+7SuqIWzeGGr2F
GlD8GkEQ4/HtdHDK+htFUgTPrzW7f/ax5pgvvzAXQcXnC6fIOGsd2IJO0LoEjhTn
KJQqEOgPqGjyfND9+3bfscLJi2CSK23pWz30f1sTzqLM4eMN7poXGqjwjtyKwGog
j66t6Na6A/B3AU9QPP5BB1/Qj09FVsd/InLsyelULG1fZmY0wx2/wiE0VNhenjGa
EejCp8oHieZ++x811ux6wROdJc38HC5lJfXhyob3yJ2OXeGBYnZG8PrT2CqJpTXz
W/5kDVYAyKOh2iiPGADGlMOajnyCgtRI9YEsKYybxlRW7vuvh7ItHb7/iplbamgx
RUrxiJGDMTEENsePTQq4pGOblXptw6PiIogGv9kWJ9WaEIbbAlFJmAIOh2JXRF+Y
JgaCzUjUNRv/z3P5Ymwd2qYxp+RO8QVCPs+/PAqL0BgwCFQXhOC5Yez3/89D5tKy
UOMBxK+xP3i7mj5C6BZa+1ChMdN9yUYpGKVfm16xLVrGBbwWZI6YB4qF+3n4qUtp
Ld7CVEzPVarftb8UpIaqAO/R/MYPUAJeKCykHrlaaOqkj3Dhacqgl+h9FQARAQAB
tDFNb3JsYW5hIFNpZ25pbmcgPGNvbnRhY3QrZGV2ZWxvcG1lbnRAbW9ybGFuYS5u
ZXQ+iQJOBBMBCgA4FiEEiXVuIB5MmbGi6VcS333yWc2PyqoFAmgiWykCGwMFCwkI
BwIGFQoJCAsCBBYCAwECHgECF4AACgkQ333yWc2PyqrhXA//SnEa+hG0hIAB4Ua/
qgqv/7nzpRIFAA5tqSoOPZ0p4YvtsSywc7zJ+ZH7IClvlewOo0Omeo4XiYQCLYSL
LnYv/yqrWVNU35TI29k2RTE4pmcHB9hMdG8heI2c5O3vd9C4yQCWwWKMSD3pEPrq
aLkHkQvLyXZukBeMzNFaVK4wOjPB02MadQLIu9rbUbKW9DvUmt/x8uBVmm/Pq4Ds
HBgxdnOifEhzMG2gG+4UJYt2jfibMwCJpM4d/drs28Qf9dhjj1UHzhhwBW3OpJkJ
E+hHVMObzolefh4eR3gPctIkxuVjYC91FVZkqVV3TgrLKhfgro5ML7IFgCnzHVuZ
PKJsssNZds+2Sv/nf2QtXcGvQgZ3xjNlaQUxE0WTGe+DKx4pMyxx4s+eNYGhA5Yo
rrb9on8TfDNaexU0BDUyt3DLQVxk8niqQPmj9jmD+BrsjWnj7Dn1yCgjre/viZjH
Ys8AHwxSu4qh3XBtjUQ9YDhUMmNqIOtJHiVp97kWbLbQ7CiCI+/7IT6Pk50+GzXV
KaTRfEp6zxpMx2wgsw4CP7aKukLrIFWxDNyQ+030c8TQW8WuL1W3oTzh0iu7DCgR
XVmgS6+YAbxjX/gAD0Dx3jLftQ2Y3PGMWPXtZmtZucIFhg1ArmYb2v1n8sWMi+cK
k/0Bxc8p29/H9s7dv5pVyrx2fcM=
=o6F8
-----END PGP PUBLIC KEY BLOCK-----