Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions charts/mailu/Chart.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
dependencies:
- name: common
repository: https://charts.bitnami.com/bitnami
version: 2.31.4
- name: redis
repository: https://charts.bitnami.com/bitnami
version: 22.0.7
Expand All @@ -11,5 +8,5 @@ dependencies:
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 22.0.0
digest: sha256:df5f781d02793d5caf58b611f02cb260311d23cf9a4937de549eb8ebb32c0a5d
generated: "2025-08-28T21:20:18.098711811+02:00"
digest: sha256:281a64cc591c02586a4ef68228f19de0968514b3946477e7fc5db32f3eca0672
generated: "2025-11-16T20:41:17.136901+01:00"
7 changes: 1 addition & 6 deletions charts/mailu/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: v2
# renovate: datasource=github-releases depName=Mailu/mailu
appVersion: 2024.06.45
version: 2.6.1
version: 2.6.2
name: mailu
description: This chart installs the Mailu mail system on Kubernetes
home: https://mailu.io
Expand All @@ -23,11 +23,6 @@ maintainers:
- name: Mailu
url: https://mailu.io
dependencies:
- name: common
repository: https://charts.bitnami.com/bitnami
tags:
- bitnami-common
version: 2.31.4
- condition: redis.enabled
name: redis
version: 22.0.7
Expand Down
9 changes: 7 additions & 2 deletions charts/mailu/ci/helm-lint-values.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# global:
# imagePullSecrets:
# - name: image-secret-global

hostnames:
- mailu.cluster.local

Expand Down Expand Up @@ -207,8 +211,9 @@ rspamd:

clamav:
logLevel: INFO
# image:
# tag: master
# image:
# pullSecrets:
# - name: image-secret
resources:
requests:
memory: 1Gi
Expand Down
10 changes: 5 additions & 5 deletions charts/mailu/templates/_database.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,22 @@

{{/* Return the name of the secret for the external database */}}
{{- define "mailu.database.external.secretName" -}}
{{ include "common.secrets.name" (dict "existingSecret" .Values.externalDatabase.existingSecret "defaultNameSuffix" "externaldb" "context" .) }}
{{ include "mailu.secrets.name" (dict "existingSecret" .Values.externalDatabase.existingSecret "defaultNameSuffix" "externaldb" "context" .) }}
{{- end -}}

{{/* Return the name of the external database */}}
{{- define "mailu.database.external.database" -}}
{{ (include "common.secrets.lookup" (dict "secret" (include "mailu.database.external.secretName" .) "key" .Values.externalDatabase.existingSecretDatabaseKey "defaultValue" .Values.externalDatabase.database "context" .)) | toString | b64dec }}
{{ (include "mailu.secrets.lookup" (dict "secret" (include "mailu.database.external.secretName" .) "key" .Values.externalDatabase.existingSecretDatabaseKey "defaultValue" .Values.externalDatabase.database "context" .)) | toString | b64dec }}
{{- end -}}

{{/* Return the username of the external database */}}
{{- define "mailu.database.external.username" -}}
{{ (include "common.secrets.lookup" (dict "secret" (include "mailu.database.external.secretName" .) "key" .Values.externalDatabase.existingSecretUsernameKey "defaultValue" .Values.externalDatabase.username "context" .)) | toString | b64dec }}
{{ (include "mailu.secrets.lookup" (dict "secret" (include "mailu.database.external.secretName" .) "key" .Values.externalDatabase.existingSecretUsernameKey "defaultValue" .Values.externalDatabase.username "context" .)) | toString | b64dec }}
{{- end -}}

{{/* Return the password of the external database */}}
{{- define "mailu.database.external.password" -}}
{{ (include "common.secrets.lookup" (dict "secret" (include "mailu.database.external.secretName" .) "key" .Values.externalDatabase.existingSecretPasswordKey "defaultValue" .Values.externalDatabase.password "context" .)) | toString | b64dec }}
{{ (include "mailu.secrets.lookup" (dict "secret" (include "mailu.database.external.secretName" .) "key" .Values.externalDatabase.existingSecretPasswordKey "defaultValue" .Values.externalDatabase.password "context" .)) | toString | b64dec }}
{{- end -}}

{{/* Return the name of the mailu database secret with its credentials */}}
Expand Down Expand Up @@ -135,7 +135,7 @@

{{/* Return the database password for Roundcube */}}
{{- define "mailu.database.roundcube.password" -}}
{{- include "common.secrets.passwords.manage" (dict "secret" (include "mailu.database.roundcube.secretName" .) "key" (include "mailu.database.roundcube.secretKey" .) "providedValues" (list "global.database.roundcube.password" "database.mysql.roundcubePassword" "database.postgresql.roundcubePassword") "length" 10 "strong" true "context" .) }}
{{- include "mailu.secrets.passwords.manage" (dict "secret" (include "mailu.database.roundcube.secretName" .) "key" (include "mailu.database.roundcube.secretKey" .) "providedValues" (list "global.database.roundcube.password" "database.mysql.roundcubePassword" "database.postgresql.roundcubePassword") "length" 10 "strong" true "context" .) }}
{{- end -}}

{{/* Return the name of the roundcube database secret */}}
Expand Down
22 changes: 22 additions & 0 deletions charts/mailu/templates/_errors.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{/*
Throw error when upgrading using empty passwords values that must not be empty.

Usage:
{{- $validationError00 := include "mailu.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}}
{{- $validationError01 := include "mailu.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}}
{{ include "mailu.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }}

Required password params:
- validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error.
- context - Context - Required. Parent context.
*/}}
{{- define "mailu.errors.upgrade.passwords.empty" -}}
{{- $validationErrors := join "" .validationErrors -}}
{{- if and $validationErrors .context.Release.IsUpgrade -}}
{{- $errorString := "\nPASSWORDS ERROR: You must provide your current passwords when upgrading the release." -}}
{{- $errorString = print $errorString "\n Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims." -}}
{{- $errorString = print $errorString "\n Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases" -}}
{{- $errorString = print $errorString "\n%s" -}}
{{- printf $errorString $validationErrors | fail -}}
{{- end -}}
{{- end -}}
93 changes: 91 additions & 2 deletions charts/mailu/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Expand the name of the chart.
*/}}
{{- define "mailu.name" -}}
{{- include "common.names.name" . -}}
{{- include "mailu.names.name" . -}}
{{- end -}}

{{/*
Expand All @@ -12,7 +12,7 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
If release name contains chart name it will be used as a full name.
*/}}
{{- define "mailu.fullname" -}}
{{- include "common.names.fullname" . -}}
{{- include "mailu.names.fullname" . -}}
{{- end -}}

{{/*
Expand Down Expand Up @@ -217,3 +217,92 @@ mailu: dovecot
You need to set at least one override for Dovecot's service monitor
{{- end -}}
{{- end -}}

{{/*
Gets a value from .Values given
Usage:
{{ include "mailu.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }}
*/}}
{{- define "mailu.utils.getValueFromKey" -}}
{{- $splitKey := splitList "." .key -}}
{{- $value := "" -}}
{{- $latestObj := $.context.Values -}}
{{- range $splitKey -}}
{{- if not $latestObj -}}
{{- printf "please review the entire path of '%s' exists in values" $.key | fail -}}
{{- end -}}
{{- $value = ( index $latestObj . ) -}}
{{- $latestObj = $value -}}
{{- end -}}
{{- printf "%v" (default "" $value) -}}
{{- end -}}

{{/*
Returns first .Values key with a defined value or first of the list if all non-defined
Usage:
{{ include "mailu.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }}
*/}}
{{- define "mailu.utils.getKeyFromList" -}}
{{- $key := first .keys -}}
{{- $reverseKeys := reverse .keys }}
{{- range $reverseKeys }}
{{- $value := include "mailu.utils.getValueFromKey" (dict "key" . "context" $.context ) }}
{{- if $value -}}
{{- $key = . }}
{{- end -}}
{{- end -}}
{{- printf "%s" $key -}}
{{- end -}}

{{/*
Build env var name given a field
Usage:
{{ include "mailu.utils.fieldToEnvVar" dict "field" "my-password" }}
*/}}
{{- define "mailu.utils.fieldToEnvVar" -}}
{{- $fieldNameSplit := splitList "-" .field -}}
{{- $upperCaseFieldNameSplit := list -}}

{{- range $fieldNameSplit -}}
{{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}}
{{- end -}}

{{ join "_" $upperCaseFieldNameSplit }}
{{- end -}}

{{/*
Print instructions to get a secret value.
Usage:
{{ include "mailu.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }}
*/}}
{{- define "mailu.utils.secret.getvalue" -}}
{{- $varname := include "mailu.utils.fieldToEnvVar" . -}}
export {{ $varname }}=$(kubectl get secret --namespace {{ include "mailu.names.namespace" .context | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 -d)
{{- end -}}

{{/*
Validate a value must not be empty.

Usage:
{{ include "mailu.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }}

Validate value params:
- valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password"
- secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret"
- field - String - Optional. Name of the field in the secret data, e.g: "mysql-password"
- subchart - String - Optional - Name of the subchart that the validated password is part of.
*/}}
{{- define "mailu.validations.values.single.empty" -}}
{{- $value := include "mailu.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }}
{{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }}

{{- if not $value -}}
{{- $varname := "my-value" -}}
{{- $getCurrentValue := "" -}}
{{- if and .secret .field -}}
{{- $varname = include "mailu.utils.fieldToEnvVar" . -}}
{{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "mailu.utils.secret.getvalue" .) -}}
{{- end -}}
{{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}}
{{- end -}}
{{- end -}}
75 changes: 75 additions & 0 deletions charts/mailu/templates/_images.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{{/*
Return the proper image name.
If image tag and digest are not defined, termination fallbacks to chart appVersion.
{{ include "mailu.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" .Values.global "chart" .Chart ) }}
*/}}
{{- define "mailu.images.image" -}}
{{- $registryName := default .imageRoot.registry ((.global).imageRegistry) -}}
{{- $repositoryName := .imageRoot.repository -}}
{{- $separator := ":" -}}
{{- $termination := .imageRoot.tag | toString -}}

{{- if not .imageRoot.tag }}
{{- if .chart }}
{{- $termination = .chart.AppVersion | toString -}}
{{- end -}}
{{- end -}}
{{- if .imageRoot.digest }}
{{- $separator = "@" -}}
{{- $termination = .imageRoot.digest | toString -}}
{{- end -}}
{{- if $registryName }}
{{- printf "%s/%s%s%s" $registryName $repositoryName $separator $termination -}}
{{- else -}}
{{- printf "%s%s%s" $repositoryName $separator $termination -}}
{{- end -}}
{{- end -}}

{{/*
Return the proper Docker Image Registry Secret Names evaluating values as templates
{{ include "mailu.images.renderPullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "context" $) }}
*/}}
{{- define "mailu.images.renderPullSecrets" -}}
{{- $pullSecrets := list -}}
{{- $context := .context -}}

{{- range (($context.Values.global).imagePullSecrets) -}}
{{- if kindIs "map" . -}}
{{- $pullSecrets = append $pullSecrets (include "mailu.tplvalues.render" (dict "value" .name "context" $context)) -}}
{{- else -}}
{{- $pullSecrets = append $pullSecrets (include "mailu.tplvalues.render" (dict "value" . "context" $context)) -}}
{{- end -}}
{{- end -}}

{{- range .images -}}
{{- range .pullSecrets -}}
{{- if kindIs "map" . -}}
{{- $pullSecrets = append $pullSecrets (include "mailu.tplvalues.render" (dict "value" .name "context" $context)) -}}
{{- else -}}
{{- $pullSecrets = append $pullSecrets (include "mailu.tplvalues.render" (dict "value" . "context" $context)) -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{- if (not (empty $pullSecrets)) -}}
imagePullSecrets:
{{- range $pullSecrets | uniq }}
- name: {{ . }}
{{- end }}
{{- end }}
{{- end -}}

{{/*
Return the proper image version (ingores image revision/prerelease info & fallbacks to chart appVersion)
{{ include "mailu.images.version" ( dict "imageRoot" .Values.path.to.the.image "chart" .Chart ) }}
*/}}
{{- define "mailu.images.version" -}}
{{- $imageTag := .imageRoot.tag | toString -}}
{{/* regexp from https://github.com/Masterminds/semver/blob/23f51de38a0866c5ef0bfc42b3f735c73107b700/version.go#L41-L44 */}}
{{- if regexMatch `^([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?$` $imageTag -}}
{{- $version := semver $imageTag -}}
{{- printf "%d.%d.%d" $version.Major $version.Minor $version.Patch -}}
{{- else -}}
{{- print .chart.AppVersion -}}
{{- end -}}
{{- end -}}
34 changes: 34 additions & 0 deletions charts/mailu/templates/_ingress.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{{/*
Generate backend entry that is compatible with all Kubernetes API versions.

Usage:
{{ include "mailu.ingress.backend" (dict "serviceName" "backendName" "servicePort" "backendPort" "context" $) }}

Params:
- serviceName - String. Name of an existing service backend
- servicePort - String/Int. Port name (or number) of the service. It will be translated to different yaml depending if it is a string or an integer.
- context - Dict - Required. The context for the template evaluation.
*/}}
{{- define "mailu.ingress.backend" -}}
service:
name: {{ .serviceName }}
port:
{{- if typeIs "string" .servicePort }}
name: {{ .servicePort }}
{{- else if or (typeIs "int" .servicePort) (typeIs "float64" .servicePort) }}
number: {{ .servicePort | int }}
{{- end }}
{{- end -}}

{{/*
Return true if cert-manager required annotations for TLS signed
certificates are set in the Ingress annotations
Ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations
Usage:
{{ include "mailu.ingress.certManagerRequest" ( dict "annotations" .Values.path.to.the.ingress.annotations ) }}
*/}}
{{- define "mailu.ingress.certManagerRequest" -}}
{{ if or (hasKey .annotations "cert-manager.io/cluster-issuer") (hasKey .annotations "cert-manager.io/issuer") (hasKey .annotations "kubernetes.io/tls-acme") }}
{{- true -}}
{{- end -}}
{{- end -}}
39 changes: 39 additions & 0 deletions charts/mailu/templates/_labels.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{{/*
Kubernetes standard labels
{{ include "mailu.labels.standard" (dict "customLabels" .Values.commonLabels "context" $) -}}
*/}}
{{- define "mailu.labels.standard" -}}
{{- if and (hasKey . "customLabels") (hasKey . "context") -}}
{{- $default := dict "app.kubernetes.io/name" (include "mailu.names.name" .context) "helm.sh/chart" (include "mailu.names.chart" .context) "app.kubernetes.io/instance" .context.Release.Name "app.kubernetes.io/managed-by" .context.Release.Service -}}
{{- with .context.Chart.AppVersion -}}
{{- $_ := set $default "app.kubernetes.io/version" . -}}
{{- end -}}
{{ template "mailu.tplvalues.merge" (dict "values" (list .customLabels $default) "context" .context) }}
{{- else -}}
app.kubernetes.io/name: {{ include "mailu.names.name" . }}
helm.sh/chart: {{ include "mailu.names.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- with .Chart.AppVersion }}
app.kubernetes.io/version: {{ . | quote }}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Labels used on immutable fields such as deploy.spec.selector.matchLabels or svc.spec.selector
{{ include "mailu.labels.matchLabels" (dict "customLabels" .Values.podLabels "context" $) -}}

We don't want to loop over custom labels appending them to the selector
since it's very likely that it will break deployments, services, etc.
However, it's important to overwrite the standard labels if the user
overwrote them on metadata.labels fields.
*/}}
{{- define "mailu.labels.matchLabels" -}}
{{- if and (hasKey . "customLabels") (hasKey . "context") -}}
{{ merge (pick (include "mailu.tplvalues.render" (dict "value" .customLabels "context" .context) | fromYaml) "app.kubernetes.io/name" "app.kubernetes.io/instance") (dict "app.kubernetes.io/name" (include "mailu.names.name" .context) "app.kubernetes.io/instance" .context.Release.Name ) | toYaml }}
{{- else -}}
app.kubernetes.io/name: {{ include "mailu.names.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{- end -}}
Loading