From bc5c29ff4832ef24469527c0aafb3722039c9a64 Mon Sep 17 00:00:00 2001 From: GuillaumeV <88834548+guillaumevillemont@users.noreply.github.com> Date: Fri, 10 May 2024 10:49:58 +0200 Subject: [PATCH] Add first bookstack chart --- charts/bookstack/.helmignore | 24 ++ charts/bookstack/Chart.yaml | 14 ++ charts/bookstack/templates/_helpers.tpl | 62 +++++ charts/bookstack/templates/deployment.yaml | 216 ++++++++++++++++++ charts/bookstack/templates/ingress.yaml | 55 +++++ charts/bookstack/templates/pvc.yaml | 25 ++ charts/bookstack/templates/secret.yaml | 24 ++ charts/bookstack/templates/service.yaml | 28 +++ .../bookstack/templates/serviceaccount.yaml | 12 + charts/bookstack/values.yaml | 192 ++++++++++++++++ 10 files changed, 652 insertions(+) create mode 100644 charts/bookstack/.helmignore create mode 100644 charts/bookstack/Chart.yaml create mode 100644 charts/bookstack/templates/_helpers.tpl create mode 100644 charts/bookstack/templates/deployment.yaml create mode 100644 charts/bookstack/templates/ingress.yaml create mode 100644 charts/bookstack/templates/pvc.yaml create mode 100644 charts/bookstack/templates/secret.yaml create mode 100644 charts/bookstack/templates/service.yaml create mode 100644 charts/bookstack/templates/serviceaccount.yaml create mode 100644 charts/bookstack/values.yaml diff --git a/charts/bookstack/.helmignore b/charts/bookstack/.helmignore new file mode 100644 index 0000000..faeb926 --- /dev/null +++ b/charts/bookstack/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ +tests/ diff --git a/charts/bookstack/Chart.yaml b/charts/bookstack/Chart.yaml new file mode 100644 index 0000000..a8f20c0 --- /dev/null +++ b/charts/bookstack/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +name: bookstack +description: A Helm chart for running bookstack on Kubernetes +type: application +maintainers: + - name: Element SRE Team + +# This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: "0.1.0" + +# Track the appVersion based on the image: +# renovate: image=ghcr.io/linuxserver/bookstack +appVersion: "version-v23.02.1" diff --git a/charts/bookstack/templates/_helpers.tpl b/charts/bookstack/templates/_helpers.tpl new file mode 100644 index 0000000..1d210de --- /dev/null +++ b/charts/bookstack/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "bookstack.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "bookstack.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "bookstack.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "bookstack.labels" -}} +helm.sh/chart: {{ include "bookstack.chart" . }} +{{ include "bookstack.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "bookstack.selectorLabels" -}} +app.kubernetes.io/name: {{ include "bookstack.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "bookstack.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "bookstack.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/bookstack/templates/deployment.yaml b/charts/bookstack/templates/deployment.yaml new file mode 100644 index 0000000..a8eb39e --- /dev/null +++ b/charts/bookstack/templates/deployment.yaml @@ -0,0 +1,216 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "bookstack.fullname" . }} + labels: + {{- include "bookstack.labels" . | nindent 4 }} +spec: + replicas: 1 + {{- if .Values.revisionHistoryLimit }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + {{- end }} + selector: + matchLabels: + {{- include "bookstack.selectorLabels" . | nindent 6 }} + {{- with .Values.strategy }} + strategy: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + annotations: + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "bookstack.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "bookstack.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + envFrom: + - secretRef: + name: {{ include "bookstack.fullname" . }} + env: + {{- if .Values.settings.url }} + - name: APP_URL + value: {{ .Values.settings.url | quote }} + {{- end }} + {{- if .Values.settings.debug }} + - name: APP_DEBUG + value: {{ .Values.settings.debug | quote }} + {{- end }} + {{- if .Values.settings.sessionLifetime }} + - name: SESSION_LIFETIME + value: {{ .Values.settings.sessionLifetime | quote }} + {{- end }} + {{- if .Values.settings.tz }} + - name: TZ + value: {{ .Values.settings.tz | quote }} + {{- end }} + {{- if .Values.settings.authSaml2.enabled }} + - name: AUTH_METHOD + value: "saml2" + {{- with .Values.settings.authSaml2 }} + - name: SAML2_AUTOLOAD_METADATA + value: {{ .autoloadMetadata | quote }} + - name: SAML2_DISPLAY_NAME_ATTRIBUTES + value: {{ .displayNameAttribute | quote }} + - name: SAML2_EMAIL_ATTRIBUTE + value: {{ .emailAttribute | quote }} + - name: SAML2_EXTERNAL_ID_ATTRIBUTE + value: {{ .externalIdAttribute | quote }} + - name: SAML2_GROUP_ATTRIBUTE + value: {{ .groupAttribute | quote }} + - name: SAML2_IDP_AUTHNCONTEXT + value: {{ .idpAuthnContent | quote }} + - name: SAML2_IDP_ENTITYID + value: {{ .idpEntityId | quote }} + - name: SAML2_NAME + value: {{ .name | quote }} + - name: SAML2_REMOVE_FROM_GROUPS + value: {{ .removeFromGroups | quote }} + - name: SAML2_USER_TO_GROUPS + value: {{ .userToGroups | quote }} + {{- end }} + {{- end }} + {{- if .Values.settings.mail.enabled }} + {{- with .Values.settings.mail }} + - name: MAIL_DRIVER + value: {{ .transport | quote }} + - name: MAIL_ENCRYPTION + value: {{ .encryption | quote }} + - name: MAIL_FROM + value: {{ .from | quote }} + - name: MAIL_FROM_NAME + value: {{ .displayName | quote }} + - name: MAIL_HOST + value: {{ .host | quote }} + - name: MAIL_PORT + value: {{ .port | quote }} + {{- end }} + {{- end }} + {{- with .Values.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + + {{- if .Values.customStartupProbe }} + startupProbe: + {{- toYaml .Values.customStartupProbe | nindent 12 }} + {{- else }} + {{- if .Values.startupProbe.enabled }} + startupProbe: + httpGet: + path: / + port: http + httpHeaders: + - name: Host + value: localhost:2368 + {{- with .Values.startupProbe }} + initialDelaySeconds: {{ .initialDelaySeconds }} + timeoutSeconds: {{ .timeoutSeconds }} + failureThreshold: {{ .failureThreshold }} + successThreshold: {{ .successThreshold }} + periodSeconds: {{ .periodSeconds }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.customLivenessProbe }} + livenessProbe: + {{- toYaml .Values.customLivenessProbe | nindent 12 }} + {{- else }} + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: / + port: http + httpHeaders: + - name: Host + value: localhost:2368 + {{- with .Values.livenessProbe }} + initialDelaySeconds: {{ .initialDelaySeconds }} + timeoutSeconds: {{ .timeoutSeconds }} + failureThreshold: {{ .failureThreshold }} + successThreshold: {{ .successThreshold }} + periodSeconds: {{ .periodSeconds }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.customReadinessProbe }} + readinessProbe: + {{- toYaml .Values.customReadinessProbe | nindent 12 }} + {{- else }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: / + port: http + httpHeaders: + - name: Host + value: localhost:2368 + {{- with .Values.readinessProbe }} + initialDelaySeconds: {{ .initialDelaySeconds }} + timeoutSeconds: {{ .timeoutSeconds }} + failureThreshold: {{ .failureThreshold }} + successThreshold: {{ .successThreshold }} + periodSeconds: {{ .periodSeconds }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.args }} + args: + {{- range .Values.args }} + - {{ . }} + {{- end }} + {{- end }} + volumeMounts: + - mountPath: /config + name: bookstack-vol + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: bookstack-vol + {{- if .Values.storage.persistentVolumeClaimName }} + persistentVolumeClaim: + claimName: {{ .Values.storage.persistentVolumeClaimName }} + {{- else }} + {{- if .Values.storage.requestedSize }} + persistentVolumeClaim: + claimName: {{ include "bookstack.fullname" . }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} diff --git a/charts/bookstack/templates/ingress.yaml b/charts/bookstack/templates/ingress.yaml new file mode 100644 index 0000000..48e5a41 --- /dev/null +++ b/charts/bookstack/templates/ingress.yaml @@ -0,0 +1,55 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "bookstack.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "bookstack.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/bookstack/templates/pvc.yaml b/charts/bookstack/templates/pvc.yaml new file mode 100644 index 0000000..62678b9 --- /dev/null +++ b/charts/bookstack/templates/pvc.yaml @@ -0,0 +1,25 @@ +{{- $createPvc := and (empty .Values.storage.persistentVolumeClaimName) (.Values.storage.requestedSize) }} +{{- if $createPvc }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "bookstack.fullname" . }} + labels: + {{- include "bookstack.labels" . | nindent 4 }} + {{- if .Values.storage.keepPvc }} + annotations: + "helm.sh/resource-policy": keep + {{- end }} +spec: + {{- with .Values.storage }} + accessModes: + {{- toYaml .accessModes | nindent 4 }} + volumeMode: Filesystem + resources: + requests: + storage: {{ .requestedSize }} + {{- if .className }} + storageClassName: {{ .className }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/bookstack/templates/secret.yaml b/charts/bookstack/templates/secret.yaml new file mode 100644 index 0000000..7036dae --- /dev/null +++ b/charts/bookstack/templates/secret.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "bookstack.fullname" . }} + labels: + {{- include "bookstack.labels" . | nindent 4 }} +data: +{{- with .Values.database }} + DB_HOST: {{ .host | b64enc }} + DB_PORT: {{ (.port | default "3306") | toString | b64enc }} + DB_USER: {{ .user | b64enc }} + DB_DATABASE: {{ .name | b64enc }} +{{- end }} +{{- with .Values.customSecrets }} + {{- if .databasePassword }} + DB_PASSWORD: {{ .databasePassword | b64enc }} + {{- end }} + {{- if .smtpUser }} + MAIL_USERNAME: {{ .smtpUser | b64enc }} + {{- end }} + {{- if .smtpPassword }} + MAIL_PASSWORD: {{ .smtpPassword | b64enc }} + {{- end }} +{{- end }} diff --git a/charts/bookstack/templates/service.yaml b/charts/bookstack/templates/service.yaml new file mode 100644 index 0000000..0edd0a3 --- /dev/null +++ b/charts/bookstack/templates/service.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "bookstack.fullname" . }} + labels: + {{- include "bookstack.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + {{- if and ( or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") ) (.Values.service.nodePort) }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") (.Values.service.loadBalancerIP) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + selector: + {{- include "bookstack.selectorLabels" . | nindent 4 }} diff --git a/charts/bookstack/templates/serviceaccount.yaml b/charts/bookstack/templates/serviceaccount.yaml new file mode 100644 index 0000000..94b1651 --- /dev/null +++ b/charts/bookstack/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "bookstack.serviceAccountName" . }} + labels: + {{- include "bookstack.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/bookstack/values.yaml b/charts/bookstack/values.yaml new file mode 100644 index 0000000..a9961b8 --- /dev/null +++ b/charts/bookstack/values.yaml @@ -0,0 +1,192 @@ +## Default values for the bookstack deployment + +## bookstack docker image +image: + registry: "ghcr.io" + repository: "linuxserver/bookstack" + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +## Pod deployment strategy +strategy: + type: Recreate + +## Optional service account +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +## Pod security options +podSecurityContext: + fsGroup: 1000 + +## Default security options to run bookstack as read only container without privilege escalation +securityContext: + allowPrivilegeEscalation: false + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsGroup: 1000 + runAsUser: 1000 + +## Default bookstack service port (default web service port) +service: + type: ClusterIP + port: 80 + ## The node port (only relevant for type LoadBalancer or NodePort) + nodePort: + ## The cluster ip address (only relevant for type LoadBalancer or NodePort) + clusterIP: + ## The loadbalancer ip address (only relevant for type LoadBalancer) + loadBalancerIP: + # Annotations to add to the service + annotations: {} + +## Ingress configuration +ingress: + enabled: false + className: "" + annotations: {} + # nginx.ingress.kubernetes.io/server-snippet: | + # location ~* "^/metrics" { + # deny all; + # return 403; + # } + hosts: + - host: book.example.com + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: book-example-com-tls + # hosts: + # - book.example.com + +## Resource limits and requests +resources: + limits: + memory: 256M + requests: + cpu: 50m + memory: 32M + +## Additional node selector +nodeSelector: {} + +tolerations: [] + +affinity: {} + +## Maximum number of revisions maintained in revision history +revisionHistoryLimit: 3 + +## Custom startup probe (overwrites default startup probe) +customStartupProbe: {} + +## Default startup probe +startupProbe: + enabled: false + initialDelaySeconds: 10 + timeoutSeconds: 5 + failureThreshold: 30 + successThreshold: 1 + periodSeconds: 10 + +## Custom liveness probe (overwrites default liveness probe) +customLivenessProbe: {} + +## Default liveness probe +livenessProbe: + enabled: false + initialDelaySeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + successThreshold: 1 + periodSeconds: 10 + +## Custom readiness probe (overwrites default readiness probe) +customReadinessProbe: {} + +## Default readiness probe +readinessProbe: + enabled: false + initialDelaySeconds: 30 + timeoutSeconds: 5 + failureThreshold: 3 + successThreshold: 1 + periodSeconds: 10 + +## Additional environment variables +env: [] + +## Arguments for the container entrypoint process +args: [] + +database: + ## Name of the database (default: bookstack) + name: bookstack + + ## Database settings + ## Password comes from customSecrets.databasePassword + user: bookstack + host: db.host + port: 3306 + +## bookstack specific configuration +settings: + ## Default URL (for generated links) + url: https://book.example.com + + debug: false + sessionLifetime: 1656 + tz: UTC + + authSaml2: + enabled: false + autoloadMetadata: true + displayNameAttribute: "firstName|lastName" + emailAttribute: "email" + externalIdAttribute: "email" + groupAttribute: "Role" + idpAuthnContent: true + idpEntityId: https://sso.example.com/auth/realms/company/protocol/saml/descriptor + name: "My SSO" + removeFromGroups: true + userToGroups: true + + ## SMTP connection details + ## Username and password come from customSecrets.smtpUser & customSecrets.smtpPassword + mail: + enabled: true + transport: smtp + encryption: tls + from: noreply@book.example.com + displayName: My Book + host: email-smtp.eu-central-1.amazonaws.com + port: 465 + +## Storage parameters +storage: + ## Set persistentVolumenClaimName to reference an existing PVC + persistentVolumeClaimName: + + ## Alternative set requestedSize to define a size for a dynmaically created PVC + requestedSize: 5Gi + className: "gp3-retain" + accessModes: + - ReadWriteOnce + + ## Keep a created Persistent volume claim when uninstalling the helm chart + keepPvc: false