Files
twenty/packages/twenty-docker/helm/twenty/templates/_helpers.tpl
T
Lukas Huppertz 9d613dc19d Improve helm chart // Fix linting issues & introduce Redis externalSecret for redis password // Add additional ENVs // Improve migrations (#18157)
This pull request enhances the Helm chart for the Twenty application by
improving how environment variables and Redis credentials are handled
for both server and worker deployments. The main changes include support
for injecting additional environment variables, improved Redis password
management (including external secrets), and a more robust database
migration workflow.

**Environment Variable Injection:**
- Added support for specifying additional environment variables for both
the server and worker deployments via the `additionalEnv` field in
`values.yaml`. These variables are automatically injected into the
respective pods.
[[1]](diffhunk://#diff-b5d958eae48fd1919e5623bcf0144aac7abb323ae8743e6f31367e383c63c296R55)
[[2]](diffhunk://#diff-b5d958eae48fd1919e5623bcf0144aac7abb323ae8743e6f31367e383c63c296R109-R110)
[[3]](diffhunk://#diff-20bb91909627a12b50b3c165a2a027b663479c0104ed8dbf91d2b9ad8ea8a931R74-R77)
[[4]](diffhunk://#diff-20bb91909627a12b50b3c165a2a027b663479c0104ed8dbf91d2b9ad8ea8a931R157-R172)
[[5]](diffhunk://#diff-20bb91909627a12b50b3c165a2a027b663479c0104ed8dbf91d2b9ad8ea8a931R225-R229)
[[6]](diffhunk://#diff-fb612a3b7a13156aaa607b27d23025e2c6831f111b6a582fd313fad26d2fdb5bR89-R92)

**Redis Credential Management:**
- Introduced support for using external secrets for Redis passwords by
adding `secretName` and `passwordKey` fields under `redis.external` in
`values.yaml`, and logic to inject `REDIS_PASSWORD` from a Kubernetes
secret if configured.
[[1]](diffhunk://#diff-b5d958eae48fd1919e5623bcf0144aac7abb323ae8743e6f31367e383c63c296R180-R182)
[[2]](diffhunk://#diff-5c4fa358b10abd7581188995feb9b4d6be0bc4f06a95bf27bb31b5595d6693d8R92-R100)
[[3]](diffhunk://#diff-20bb91909627a12b50b3c165a2a027b663479c0104ed8dbf91d2b9ad8ea8a931R157-R172)
[[4]](diffhunk://#diff-20bb91909627a12b50b3c165a2a027b663479c0104ed8dbf91d2b9ad8ea8a931R196-R205)
[[5]](diffhunk://#diff-fb612a3b7a13156aaa607b27d23025e2c6831f111b6a582fd313fad26d2fdb5bR70-R79)
- Updated the logic for constructing the `REDIS_URL` to include
authentication information if a password is set or an external secret is
used.

**Database Migration Workflow:**
- Improved the startup command for the server deployment to optionally
skip database migrations (using `DISABLE_DB_MIGRATIONS`), check for an
existing schema before running migrations, and ensure setup scripts are
only run on empty databases.

These changes make the chart more flexible and secure, especially for
production deployments requiring externalized secrets and custom
environment configurations.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-03-22 21:36:10 +01:00

214 lines
7.4 KiB
Smarty

{{- define "twenty.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "twenty.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- define "twenty.namespace" -}}
{{ .Release.Namespace }}
{{- end -}}
{{/* Server image fields merged with globals */}}
{{- define "twenty.server.image" -}}
{{- $repo := default $.Values.image.repository (index $.Values.server.image "repository" | default "") -}}
{{- $tag := default (default $.Chart.AppVersion $.Values.image.tag) (index $.Values.server.image "tag" | default "") -}}
{{- $pp := default $.Values.image.pullPolicy (index $.Values.server.image "pullPolicy" | default "") -}}
{{- printf "%s:%s|%s" $repo $tag $pp -}}
{{- end -}}
{{/* Worker image fields merged with globals */}}
{{- define "twenty.worker.image" -}}
{{- $repo := default $.Values.image.repository (index $.Values.worker.image "repository" | default "") -}}
{{- $tag := default (default $.Chart.AppVersion $.Values.image.tag) (index $.Values.worker.image "tag" | default "") -}}
{{- $pp := default $.Values.image.pullPolicy (index $.Values.worker.image "pullPolicy" | default "") -}}
{{- printf "%s:%s|%s" $repo $tag $pp -}}
{{- end -}}
{{/* Extract parts of image helper */}}
{{- define "twenty.image.repository" -}}
{{- regexFind "^([^:|]+)" . -}}
{{- end -}}
{{- define "twenty.image.tag" -}}
{{- regexFind ":([^|]+)" . | trimPrefix ":" -}}
{{- end -}}
{{- define "twenty.image.pullPolicy" -}}
{{- regexFind "\\|(.+)$" . | trimPrefix "|" -}}
{{- end -}}
{{/* Check if using external secret for database password */}}
{{- define "twenty.db.useExternalSecret" -}}
{{- if and (not .Values.db.enabled) .Values.db.external.secretName .Values.db.external.passwordKey -}}
true
{{- else -}}
false
{{- end -}}
{{- end -}}
{{/* Database URL secret name */}}
{{- define "twenty.dbUrl.secretName" -}}
{{- printf "%s-db-url" (include "twenty.fullname" .) -}}
{{- end -}}
{{/* Database password secret name */}}
{{- define "twenty.dbPassword.secretName" -}}
{{- if eq (include "twenty.db.useExternalSecret" .) "true" -}}
{{- .Values.db.external.secretName -}}
{{- else -}}
{{- include "twenty.dbUrl.secretName" . -}}
{{- end -}}
{{- end -}}
{{/* Database password secret key */}}
{{- define "twenty.dbPassword.secretKey" -}}
{{- if eq (include "twenty.db.useExternalSecret" .) "true" -}}
{{- .Values.db.external.passwordKey -}}
{{- else if .Values.db.enabled -}}
appPassword
{{- else -}}
password
{{- end -}}
{{- end -}}
{{/* Database URL template for external secret (will be evaluated at runtime) */}}
{{- define "twenty.dbUrl.template" -}}
{{- if eq (include "twenty.db.useExternalSecret" .) "true" -}}
{{- $scheme := "postgres" -}}
{{- $host := .Values.db.external.host -}}
{{- $port := .Values.db.external.port | default 5432 -}}
{{- $user := .Values.db.external.user | default "postgres" -}}
{{- $db := .Values.db.external.database | default "twenty" -}}
{{- $qs := ternary "?sslmode=require" "" (eq .Values.db.external.ssl true) -}}
{{- printf "%s://%s:$(DB_PASSWORD)@%s:%v/%s%s" $scheme $user $host $port $db $qs -}}
{{- end -}}
{{- end -}}
{{/* Check if using external secret for redis password */}}
{{- define "twenty.redis.useExternalSecret" -}}
{{- if and (not .Values.redisInternal.enabled) .Values.redis.external.secretName .Values.redis.external.passwordKey -}}
true
{{- else -}}
false
{{- end -}}
{{- end -}}
{{/* Compose Redis URL */}}
{{- define "twenty.redisUrl" -}}
{{- if .Values.server.env.REDIS_URL -}}
{{- .Values.server.env.REDIS_URL -}}
{{- else if .Values.redisInternal.enabled -}}
{{- $host := printf "%s-redis" (include "twenty.fullname" .) -}}
{{- printf "redis://%s.%s.svc.cluster.local:6379" $host (include "twenty.namespace" .) -}}
{{- else -}}
{{- $host := .Values.redis.external.host | default "redis" -}}
{{- $port := .Values.redis.external.port | default 6379 -}}
{{- if or (eq (include "twenty.redis.useExternalSecret" .) "true") (.Values.redis.external.password) -}}
{{- $auth := ":$(REDIS_PASSWORD)@" -}}
{{- printf "redis://%s%s:%v" $auth $host $port -}}
{{- else -}}
{{- printf "redis://%s:%v" $host $port -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{/* Compose Server URL from override, ingress, or service */}}
{{- define "twenty.serverUrl" -}}
{{- if .Values.server.env.SERVER_URL -}}
{{- .Values.server.env.SERVER_URL -}}
{{- else if and .Values.server.ingress.enabled (gt (len .Values.server.ingress.hosts) 0) -}}
{{- $host := (index .Values.server.ingress.hosts 0).host -}}
{{- $tls := gt (len .Values.server.ingress.tls) 0 -}}
{{- $scheme := ternary "https" "http" $tls -}}
{{- $port := ternary 443 80 $tls -}}
{{- printf "%s://%s:%v" $scheme $host $port -}}
{{- else -}}
{{- $svc := printf "%s-server" (include "twenty.fullname" .) -}}
{{- $ns := include "twenty.namespace" . -}}
{{- $port := .Values.server.service.port | default 3000 -}}
{{- printf "http://%s.%s.svc.cluster.local:%v" $svc $ns $port -}}
{{- end -}}
{{- end -}}
{{/* Tokens secret name */}}
{{- define "twenty.secret.tokens.name" -}}
{{- .Values.secrets.tokens.name | default "tokens" -}}
{{- end -}}
{{/* Access token value: reuse existing secret if present, else provided value, else generated */}}
{{- define "twenty.secret.tokens.access" -}}
{{- $name := include "twenty.secret.tokens.name" . -}}
{{- $ns := include "twenty.namespace" . -}}
{{- $existing := lookup "v1" "Secret" $ns $name -}}
{{- if and $existing $existing.data.accessToken -}}
{{- b64dec $existing.data.accessToken -}}
{{- else if .Values.secrets.tokens.accessToken -}}
{{- .Values.secrets.tokens.accessToken -}}
{{- else -}}
{{- randAlphaNum 32 -}}
{{- end -}}
{{- end -}}
{{/* Server container port */}}
{{- define "twenty.server.containerPort" -}}
{{- .Values.server.service.port | default 3000 -}}
{{- end -}}
{{/* Storage type: prefer top-level storage.type, else legacy server.env.STORAGE_TYPE, else local */}}
{{- define "twenty.storageType" -}}
{{- if .Values.storage.type -}}
{{- .Values.storage.type -}}
{{- else if .Values.server.env.STORAGE_TYPE -}}
{{- .Values.server.env.STORAGE_TYPE -}}
{{- else -}}
local
{{- end -}}
{{- end -}}
{{/* Additional storage env vars (e.g., S3) */}}
{{- define "twenty.storageEnv" -}}
{{- if eq (include "twenty.storageType" .) "s3" -}}
{{- with .Values.storage.s3.bucket }}
- name: STORAGE_S3_NAME
value: {{ . | quote }}
{{- end }}
{{- with .Values.storage.s3.region }}
- name: STORAGE_S3_REGION
value: {{ . | quote }}
{{- end }}
{{- with .Values.storage.s3.endpoint }}
- name: STORAGE_S3_ENDPOINT
value: {{ . | quote }}
{{- end }}
{{- if and .Values.storage.s3.secretName .Values.storage.s3.accessKeyIdKey }}
- name: STORAGE_S3_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: {{ .Values.storage.s3.secretName | quote }}
key: {{ .Values.storage.s3.accessKeyIdKey | quote }}
{{- else }}
{{- with .Values.storage.s3.accessKeyId }}
- name: STORAGE_S3_ACCESS_KEY_ID
value: {{ . | quote }}
{{- end }}
{{- end }}
{{- if and .Values.storage.s3.secretName .Values.storage.s3.secretAccessKeyKey }}
- name: STORAGE_S3_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.storage.s3.secretName | quote }}
key: {{ .Values.storage.s3.secretAccessKeyKey | quote }}
{{- else }}
{{- with .Values.storage.s3.secretAccessKey }}
- name: STORAGE_S3_SECRET_ACCESS_KEY
value: {{ . | quote }}
{{- end }}
{{- end }}
{{- end -}}
{{- end -}}