feat: initial take on stalwart-mail

This commit is contained in:
Tommy 2024-05-26 21:53:17 +02:00
parent b8b4c9a44a
commit f5a638bb59
No known key found for this signature in database
9 changed files with 348 additions and 0 deletions

View file

@ -0,0 +1 @@
*/configs/*

View file

@ -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/

View file

@ -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.

View file

@ -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"

View file

@ -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

View file

@ -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" . }}

View file

@ -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 }}

View file

@ -0,0 +1,7 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "stalwart-mail.fullname" . }}
labels:
{{- include "stalwart-mail.labels" . | nindent 4 }}

View file

@ -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