From f5a638bb5996a28319a30859a4cd921e14d53e76 Mon Sep 17 00:00:00 2001 From: Tommy Date: Sun, 26 May 2024 21:53:17 +0200 Subject: [PATCH] feat: initial take on stalwart-mail --- charts/stalwart-mail/.helmignore | 1 + charts/stalwart-mail/Chart.yaml | 16 +++ charts/stalwart-mail/templates/_helpers.tpl | 46 ++++++++ .../templates/configuration.yaml | 101 ++++++++++++++++++ charts/stalwart-mail/templates/db-init.yaml | 20 ++++ .../stalwart-mail/templates/deployment.yaml | 81 ++++++++++++++ charts/stalwart-mail/templates/service.yaml | 35 ++++++ .../templates/serviceaccount.yaml | 7 ++ charts/stalwart-mail/values.yaml | 41 +++++++ 9 files changed, 348 insertions(+) create mode 100644 charts/stalwart-mail/.helmignore create mode 100644 charts/stalwart-mail/Chart.yaml create mode 100644 charts/stalwart-mail/templates/_helpers.tpl create mode 100644 charts/stalwart-mail/templates/configuration.yaml create mode 100644 charts/stalwart-mail/templates/db-init.yaml create mode 100644 charts/stalwart-mail/templates/deployment.yaml create mode 100644 charts/stalwart-mail/templates/service.yaml create mode 100644 charts/stalwart-mail/templates/serviceaccount.yaml create mode 100644 charts/stalwart-mail/values.yaml diff --git a/charts/stalwart-mail/.helmignore b/charts/stalwart-mail/.helmignore new file mode 100644 index 0000000..e746a6c --- /dev/null +++ b/charts/stalwart-mail/.helmignore @@ -0,0 +1 @@ +*/configs/* \ No newline at end of file diff --git a/charts/stalwart-mail/Chart.yaml b/charts/stalwart-mail/Chart.yaml new file mode 100644 index 0000000..e63a40f --- /dev/null +++ b/charts/stalwart-mail/Chart.yaml @@ -0,0 +1,16 @@ +apiVersion: v2 +name: stalwart-mail +description: Stalwart is a JMAP, IMAP4 and SMTP server +version: 0.1.2 +appVersion: 0.8.0 +maintainers: +- name: Tommy Skaug + email: tommy@skaug.me +keywords: +- mail +- imap +- jmap +- server +sources: +- https://stalw.art/docs/get-started/ +- https://stalw.art/docs/cluster/kubernetes/ diff --git a/charts/stalwart-mail/templates/_helpers.tpl b/charts/stalwart-mail/templates/_helpers.tpl new file mode 100644 index 0000000..58e5fe2 --- /dev/null +++ b/charts/stalwart-mail/templates/_helpers.tpl @@ -0,0 +1,46 @@ +# Define a template for the chart's full name. +{{/* +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). +*/}} +{{- define "stalwart-mail.fullname" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end }} + +{{/* +Expand the name of the chart. +*/}} +{{- define "stalwart-mail.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "stalwart-mail.labels" -}} +helm.sh/chart: {{ include "stalwart-mail.chart" . }} +{{ include "stalwart-mail.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +date: "{{ now | htmlDate }}" +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "stalwart-mail.selectorLabels" -}} +app.kubernetes.io/name: {{ include "stalwart-mail.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +# Define a template for the chart name and version. +{{/* +Generate basic labels +*/}} +{{- define "stalwart-mail.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" -}} +{{- end }} + +# Optionally, add more helper templates as needed. diff --git a/charts/stalwart-mail/templates/configuration.yaml b/charts/stalwart-mail/templates/configuration.yaml new file mode 100644 index 0000000..17c8ca1 --- /dev/null +++ b/charts/stalwart-mail/templates/configuration.yaml @@ -0,0 +1,101 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "stalwart-mail.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "stalwart-mail.labels" . | nindent 4 }} +data: + stalwart-mail.conf: | + [server.listener."smtp"] + bind = ["[::]:25"] + protocol = "smtp" + + [server.listener."submissions"] + bind = ["[::]:465"] + protocol = "smtp" + tls.implicit = true + + [server.listener."imaptls"] + bind = ["[::]:993"] + protocol = "imap" + tls.implicit = true + + [store."rocksdb"] + type = "rocksdb" + path = "/data" + min-blob-size = 16834 + write-buffer-size = 134217728 + + [store."rocksdb".pool] + workers = 10 + + [store."postgresql"] + type = "postgresql" + host = "%{env:STALWART_POSTGRES_HOST}%" + port = 5432 + database = "%{env:STALWART_POSTGRES_DATABASE}%" + user = "%{env:STALWART_POSTGRES_USERNAME}%" + password = "%{env:STALWART_POSTGRES_PASSWORD}%" + timeout = "15s" + enable = true + allow-invalid-certs = false + + [storage] + data = "postgresql" + fts = "rocksdb" + blob = "rocksdb" + lookup = "rocksdb" + directory = "ldap" + + [store."postgresql".tls] + enable = false + allow-invalid-certs = false + + [store."postgresql".pool] + max-connections = 10 + + [storage.full-text] + default-language = "en" + + [tracer."stdout"] + type = "stdout" + level = "info" + ansi = false + enable = true + + [authentication.fallback-admin] + user = "admin" + secret = "%{env:STALWART_ADMIN_SECRET}%" + + [directory."ldap"] + type = "ldap" + url = "{{ .Values.ldap.url }}" + base-dn = "{{ .Values.ldap.baseDN }}" + timeout = "30s" + + [directory."ldap".bind] + dn = "{{ .Values.ldap.bindDN }}" + secret = "%{env:STALWART_LDAP_BIND_SECRET}%" + + [directory."ldap".tls] + enable = false + allow-invalid-certs = false + + [directory."ldap".filter] + name = "{{ .Values.ldap.filter.name }}" + email = "{{ .Values.ldap.filter.email }}" + verify = "{{ .Values.ldap.filter.verify }}" + expand = "{{ .Values.ldap.filter.expand }}" + domains = "{{ .Values.ldap.filter.domains }}" + + [oauth] + key = "%{env:STALWART_OAUTH_KEY}%" + + [oauth.expiry] + user-code = "30m" + auth-code = "10m" + token = "1h" + refresh-token = "30d" + refresh-token-renew = "4d" diff --git a/charts/stalwart-mail/templates/db-init.yaml b/charts/stalwart-mail/templates/db-init.yaml new file mode 100644 index 0000000..39d1619 --- /dev/null +++ b/charts/stalwart-mail/templates/db-init.yaml @@ -0,0 +1,20 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "stalwart-mail.fullname" . }}-db-init + labels: + {{- include "stalwart-mail.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +spec: + template: + spec: + restartPolicy: Never + containers: + - name: general-db-init + image: "{{ .Values.initContainers.dbInit.image.repository }}:{{ .Values.initContainers.dbInit.image.tag }}" + envFrom: + - secretRef: + name: {{ .Values.existingSecret }} + backoffLimit: 3 diff --git a/charts/stalwart-mail/templates/deployment.yaml b/charts/stalwart-mail/templates/deployment.yaml new file mode 100644 index 0000000..6ddcada --- /dev/null +++ b/charts/stalwart-mail/templates/deployment.yaml @@ -0,0 +1,81 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "stalwart-mail.fullname" . }} + labels: + {{- include "stalwart-mail.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "stalwart-mail.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "stalwart-mail.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: {{ include "stalwart-mail.fullname" . }} + containers: + - name: stalwart-mail + image: "{{ .Values.image.repository }}:v{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["sh", "-c", "/usr/local/bin/stalwart-mail --config /etc/stalwart-mail.conf"] + ports: + - containerPort: 8080 + - containerPort: 443 + - containerPort: 25 + - containerPort: 587 + - containerPort: 465 + - containerPort: 143 + - containerPort: 993 + - containerPort: 4190 + env: + - name: STALWART_POSTGRES_HOST + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: STALWART_POSTGRES_HOST + - name: STALWART_POSTGRES_DATABASE + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: STALWART_POSTGRES_DATABASE + - name: STALWART_POSTGRES_USERNAME + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: STALWART_POSTGRES_USERNAME + - name: STALWART_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: STALWART_POSTGRES_PASSWORD + - name: STALWART_ADMIN_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: STALWART_ADMIN_SECRET + - name: STALWART_LDAP_BIND_SECRET + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: STALWART_LDAP_BIND_SECRET + - name: STALWART_OAUTH_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.existingSecret }} + key: STALWART_OAUTH_KEY + volumeMounts: + - name: stalwart-data + mountPath: /data + - mountPath: /etc/stalwart-mail.conf + subPath: stalwart-mail.conf + name: stalwart-conf + readOnly: true + volumes: + - name: stalwart-data + persistentVolumeClaim: + claimName: {{ include "stalwart-mail.fullname" . }} + - name: stalwart-conf + configMap: + name: {{ include "stalwart-mail.fullname" . }} \ No newline at end of file diff --git a/charts/stalwart-mail/templates/service.yaml b/charts/stalwart-mail/templates/service.yaml new file mode 100644 index 0000000..6090508 --- /dev/null +++ b/charts/stalwart-mail/templates/service.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "stalwart-mail.fullname" . }} + labels: + {{- include "stalwart-mail.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - name: http + port: 8080 + targetPort: 8080 + - name: https + port: 443 + targetPort: 443 + - name: smtp + port: 25 + targetPort: 25 + - name: submission + port: 587 + targetPort: 587 + - name: smtps + port: 465 + targetPort: 465 + - name: imap + port: 143 + targetPort: 143 + - name: imaps + port: 993 + targetPort: 993 + - name: sieve + port: 4190 + targetPort: 4190 + selector: + {{- include "stalwart-mail.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/charts/stalwart-mail/templates/serviceaccount.yaml b/charts/stalwart-mail/templates/serviceaccount.yaml new file mode 100644 index 0000000..08e4eb9 --- /dev/null +++ b/charts/stalwart-mail/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "stalwart-mail.fullname" . }} + labels: + {{- include "stalwart-mail.labels" . | nindent 4 }} \ No newline at end of file diff --git a/charts/stalwart-mail/values.yaml b/charts/stalwart-mail/values.yaml new file mode 100644 index 0000000..2d7e85a --- /dev/null +++ b/charts/stalwart-mail/values.yaml @@ -0,0 +1,41 @@ + +ldap: + url: ldap://lldap.security.svc.cluster.local:389 + baseDN: dc=home,dc=arpa + bindDN: "" + filter: + name: "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(uid=?))" + email: "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=?)(mailAlias=?)(mailList=?)))" + verify: "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=*?*)(mailAlias=*?*)))" + expand: "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(mailList=?))" + domains: "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=*@?)(mailAlias=*@?)))" + +existingSecret: stalwart-mail-secret + +replicaCount: 1 + +initContainers: + dbInit: + image: + repository: ghcr.io/onedr0p/postgres-init + tag: "16" + envFrom: + - secretRef: + name: stalwart-mail-secret + +image: + repository: stalwartlabs/mail-server + pullPolicy: IfNotPresent + tag: "" + +service: + type: NodePort + ports: + http: 8080 + https: 443 + smtp: 25 + submission: 587 + smtps: 465 + imap: 143 + imaps: 993 + sieve: 4190