commit c48b88a8d39d5d7499d792b11e84061c5b9a4d6f
parent 3db6bebbf8ef01fc9a5f96290b4d45d6139be8b0
Author: MTRNord <MTRNord@users.noreply.github.com>
Date: Mon, 23 Mar 2026 20:34:50 +0100
switch to stalwart
Signed-off-by: MTRNord <MTRNord@users.noreply.github.com>
Diffstat:
5 files changed, 256 insertions(+), 138 deletions(-)
diff --git a/apps/talos_cluster/mailserver/routing.yaml b/apps/talos_cluster/mailserver/routing.yaml
@@ -1,113 +1,114 @@
-apiVersion: gateway.networking.k8s.io/v1alpha2
-kind: TCPRoute
-metadata:
- name: mailserver-smtp
- namespace: mailserver
- annotations:
- external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
-spec:
- parentRefs:
- - name: email-gateway
- namespace: envoy-gateway
- sectionName: smtp
- rules:
- - backendRefs:
- - name: mailserver-docker-mailserver
- port: 12525
----
-apiVersion: gateway.networking.k8s.io/v1alpha2
-kind: TCPRoute
-metadata:
- name: mailserver-submissions
- namespace: mailserver
- annotations:
- external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
-spec:
- parentRefs:
- - name: email-gateway
- namespace: envoy-gateway
- sectionName: submissions
- rules:
- - backendRefs:
- - name: mailserver-docker-mailserver
- port: 10465
----
-apiVersion: gateway.networking.k8s.io/v1alpha2
-kind: TCPRoute
-metadata:
- name: mailserver-submission
- namespace: mailserver
- annotations:
- external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
-spec:
- parentRefs:
- - name: email-gateway
- namespace: envoy-gateway
- sectionName: submission
- rules:
- - backendRefs:
- - name: mailserver-docker-mailserver
- port: 10587
----
-apiVersion: gateway.networking.k8s.io/v1alpha2
-kind: TCPRoute
-metadata:
- name: mailserver-imap
- namespace: mailserver
- annotations:
- external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
-spec:
- parentRefs:
- - name: email-gateway
- namespace: envoy-gateway
- sectionName: imap
- rules:
- - backendRefs:
- - name: mailserver-docker-mailserver
- port: 10143
----
-apiVersion: gateway.networking.k8s.io/v1alpha2
-kind: TCPRoute
-metadata:
- name: mailserver-imaps
- namespace: mailserver
- annotations:
- external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
-spec:
- parentRefs:
- - name: email-gateway
- namespace: envoy-gateway
- sectionName: imaps
- rules:
- - backendRefs:
- - name: mailserver-docker-mailserver
- port: 10993
----
-apiVersion: gateway.envoyproxy.io/v1alpha1
-kind: BackendTrafficPolicy
-metadata:
- name: mail-policy
- namespace: mailserver
-spec:
- targetRefs:
- - group: gateway.networking.k8s.io
- kind: TCPRoute
- name: mailserver-imaps
- - group: gateway.networking.k8s.io
- kind: TCPRoute
- name: mailserver-imap
- - group: gateway.networking.k8s.io
- kind: TCPRoute
- name: mailserver-submission
- - group: gateway.networking.k8s.io
- kind: TCPRoute
- name: mailserver-submissions
- - group: gateway.networking.k8s.io
- kind: TCPRoute
- name: mailserver-smtp
- proxyProtocol:
- version: "V2"
----
+# --- docker-mailserver TCP routes (commented out after Stalwart cutover; uncomment to roll back) ---
+# apiVersion: gateway.networking.k8s.io/v1alpha2
+# kind: TCPRoute
+# metadata:
+# name: mailserver-smtp
+# namespace: mailserver
+# annotations:
+# external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+# spec:
+# parentRefs:
+# - name: email-gateway
+# namespace: envoy-gateway
+# sectionName: smtp
+# rules:
+# - backendRefs:
+# - name: mailserver-docker-mailserver
+# port: 12525
+# ---
+# apiVersion: gateway.networking.k8s.io/v1alpha2
+# kind: TCPRoute
+# metadata:
+# name: mailserver-submissions
+# namespace: mailserver
+# annotations:
+# external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+# spec:
+# parentRefs:
+# - name: email-gateway
+# namespace: envoy-gateway
+# sectionName: submissions
+# rules:
+# - backendRefs:
+# - name: mailserver-docker-mailserver
+# port: 10465
+# ---
+# apiVersion: gateway.networking.k8s.io/v1alpha2
+# kind: TCPRoute
+# metadata:
+# name: mailserver-submission
+# namespace: mailserver
+# annotations:
+# external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+# spec:
+# parentRefs:
+# - name: email-gateway
+# namespace: envoy-gateway
+# sectionName: submission
+# rules:
+# - backendRefs:
+# - name: mailserver-docker-mailserver
+# port: 10587
+# ---
+# apiVersion: gateway.networking.k8s.io/v1alpha2
+# kind: TCPRoute
+# metadata:
+# name: mailserver-imap
+# namespace: mailserver
+# annotations:
+# external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+# spec:
+# parentRefs:
+# - name: email-gateway
+# namespace: envoy-gateway
+# sectionName: imap
+# rules:
+# - backendRefs:
+# - name: mailserver-docker-mailserver
+# port: 10143
+# ---
+# apiVersion: gateway.networking.k8s.io/v1alpha2
+# kind: TCPRoute
+# metadata:
+# name: mailserver-imaps
+# namespace: mailserver
+# annotations:
+# external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+# spec:
+# parentRefs:
+# - name: email-gateway
+# namespace: envoy-gateway
+# sectionName: imaps
+# rules:
+# - backendRefs:
+# - name: mailserver-docker-mailserver
+# port: 10993
+# ---
+# apiVersion: gateway.envoyproxy.io/v1alpha1
+# kind: BackendTrafficPolicy
+# metadata:
+# name: mail-policy
+# namespace: mailserver
+# spec:
+# targetRefs:
+# - group: gateway.networking.k8s.io
+# kind: TCPRoute
+# name: mailserver-imaps
+# - group: gateway.networking.k8s.io
+# kind: TCPRoute
+# name: mailserver-imap
+# - group: gateway.networking.k8s.io
+# kind: TCPRoute
+# name: mailserver-submission
+# - group: gateway.networking.k8s.io
+# kind: TCPRoute
+# name: mailserver-submissions
+# - group: gateway.networking.k8s.io
+# kind: TCPRoute
+# name: mailserver-smtp
+# proxyProtocol:
+# version: "V2"
+# ---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
diff --git a/apps/talos_cluster/stalwart/kustomization.yaml b/apps/talos_cluster/stalwart/kustomization.yaml
@@ -6,3 +6,4 @@ resources:
- release.yaml
- secret.yaml
- ingress.yaml
+ - routing.yaml
diff --git a/apps/talos_cluster/stalwart/release.yaml b/apps/talos_cluster/stalwart/release.yaml
@@ -237,8 +237,15 @@ spec:
tls:
implicit: false
allow-invalid-certs: true
+ mailman-lmtp:
+ type: relay
+ address: mailman.mailserver.svc.cluster.local
+ port: 8024
+ protocol: lmtp
strategy:
route:
+ - if: "rcpt_domain == 'lists.midnightthoughts.space'"
+ then: "'mailman-lmtp'"
- if: "rcpt_domain == 'phorge.mtrnord.blog'"
then: "'phorge-relay'"
- else: "'mx'"
diff --git a/apps/talos_cluster/stalwart/routing.yaml b/apps/talos_cluster/stalwart/routing.yaml
@@ -0,0 +1,109 @@
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: TCPRoute
+metadata:
+ name: stalwart-smtp
+ namespace: stalwart
+ annotations:
+ external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+spec:
+ parentRefs:
+ - name: email-gateway
+ namespace: envoy-gateway
+ sectionName: smtp
+ rules:
+ - backendRefs:
+ - name: stalwart-mail
+ port: 25
+---
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: TCPRoute
+metadata:
+ name: stalwart-submissions
+ namespace: stalwart
+ annotations:
+ external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+spec:
+ parentRefs:
+ - name: email-gateway
+ namespace: envoy-gateway
+ sectionName: submissions
+ rules:
+ - backendRefs:
+ - name: stalwart-mail
+ port: 465
+---
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: TCPRoute
+metadata:
+ name: stalwart-submission
+ namespace: stalwart
+ annotations:
+ external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+spec:
+ parentRefs:
+ - name: email-gateway
+ namespace: envoy-gateway
+ sectionName: submission
+ rules:
+ - backendRefs:
+ - name: stalwart-mail
+ port: 587
+---
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: TCPRoute
+metadata:
+ name: stalwart-imap
+ namespace: stalwart
+ annotations:
+ external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+spec:
+ parentRefs:
+ - name: email-gateway
+ namespace: envoy-gateway
+ sectionName: imap
+ rules:
+ - backendRefs:
+ - name: stalwart-mail
+ port: 143
+---
+apiVersion: gateway.networking.k8s.io/v1alpha2
+kind: TCPRoute
+metadata:
+ name: stalwart-imaps
+ namespace: stalwart
+ annotations:
+ external-dns.alpha.kubernetes.io/hostname: mail.midnightthoughts.space
+spec:
+ parentRefs:
+ - name: email-gateway
+ namespace: envoy-gateway
+ sectionName: imaps
+ rules:
+ - backendRefs:
+ - name: stalwart-mail
+ port: 993
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+ name: stalwart-mail-policy
+ namespace: stalwart
+spec:
+ targetRefs:
+ - group: gateway.networking.k8s.io
+ kind: TCPRoute
+ name: stalwart-smtp
+ - group: gateway.networking.k8s.io
+ kind: TCPRoute
+ name: stalwart-submissions
+ - group: gateway.networking.k8s.io
+ kind: TCPRoute
+ name: stalwart-submission
+ - group: gateway.networking.k8s.io
+ kind: TCPRoute
+ name: stalwart-imap
+ - group: gateway.networking.k8s.io
+ kind: TCPRoute
+ name: stalwart-imaps
+ proxyProtocol:
+ version: "V2"
diff --git a/apps/talos_cluster/stalwart/secret.yaml b/apps/talos_cluster/stalwart/secret.yaml
@@ -1,34 +1,34 @@
apiVersion: v1
kind: Secret
metadata:
- name: stalwart-secret
- namespace: stalwart
+ name: stalwart-secret
+ namespace: stalwart
type: Opaque
stringData:
- pg-user: ENC[AES256_GCM,data:2M2yBdjpFII=,iv:ixB2FyyZ28MK+EdpG2FWvlVTauy4XexeAkkMlrHyR2U=,tag:grgnCldASwOyfsagds7Gdg==,type:str]
- pg-password: ENC[AES256_GCM,data:UJJQDB9C/1wZWG6bUb+72to/98IJb+EqevKnwaGfqaw70ZCTEJecrM+qzZpp0XTR1FflKqWc2kbsPEn2AEp3,iv:tUwiB50qe+3h6pVvqgc99pABS/6X6f882fzU4Q1lGyM=,tag:+nXaej6dkCsA0Hp2A8WLpQ==,type:str]
- s3-access-key: ENC[AES256_GCM,data:cBUdiQixXubz6NfEt6HZ15GlYSs=,iv:TKfZRXizjGCQvSETs+kjciaPIbKmL7kxHi+UUadU+Qk=,tag:ZD4cjJOsp73EuKylmrXkGg==,type:str]
- s3-secret-key: ENC[AES256_GCM,data:cwJtv65kgiKdq+qm1QJkjFlZ4xLsQQmAt24NsNqXnQHJz0N4xmQZWw==,iv:7Va/MdKN97W6zEBd9G9Gu1pPThWRyMJJOHfPbL0C0/c=,tag:XCMHXq28SLpxgowMitH+oA==,type:str]
- ldap-bind-password: ENC[AES256_GCM,data:VNJjJPbDAv5MxaHe4I+RplmX8wPX9AjscPaKKGst5qhVq7+kPV5UinYGNfxSAocFYzwKvv7YNb/s1pF1E9y+,iv:KoItQlnlqR4poFXr4sr5UU4PVApxmShS0JpUZWazPdM=,tag:sGFbAoIA0L136Q0IKxvidw==,type:str]
- admin-password: ENC[AES256_GCM,data:X4/ZCinPTvkp,iv:jO8RFUs07EaxL5B80TO+VCDheIotkvSK9OqrgZrp84Y=,tag:bDCuHqaQdKTuOSFFmAewYQ==,type:str]
- metrics-password: ENC[AES256_GCM,data:tIcFtJ6mZENWXUYSltwF2BWfoKXugoPpV+JyeiKXLFQ2x7YYbkyHChrCiEVEPMB6frOgk7JCA0XPo9abB/e/,iv:iEeH3+khjpWf7zB2xxsYv8uqKLYZC339EPlKgRReJ0g=,tag:XZXc9vajrZIsAqEjXS0d9Q==,type:str]
+ pg-user: ENC[AES256_GCM,data:2M2yBdjpFII=,iv:ixB2FyyZ28MK+EdpG2FWvlVTauy4XexeAkkMlrHyR2U=,tag:grgnCldASwOyfsagds7Gdg==,type:str]
+ pg-password: ENC[AES256_GCM,data:UJJQDB9C/1wZWG6bUb+72to/98IJb+EqevKnwaGfqaw70ZCTEJecrM+qzZpp0XTR1FflKqWc2kbsPEn2AEp3,iv:tUwiB50qe+3h6pVvqgc99pABS/6X6f882fzU4Q1lGyM=,tag:+nXaej6dkCsA0Hp2A8WLpQ==,type:str]
+ s3-access-key: ENC[AES256_GCM,data:cBUdiQixXubz6NfEt6HZ15GlYSs=,iv:TKfZRXizjGCQvSETs+kjciaPIbKmL7kxHi+UUadU+Qk=,tag:ZD4cjJOsp73EuKylmrXkGg==,type:str]
+ s3-secret-key: ENC[AES256_GCM,data:cwJtv65kgiKdq+qm1QJkjFlZ4xLsQQmAt24NsNqXnQHJz0N4xmQZWw==,iv:7Va/MdKN97W6zEBd9G9Gu1pPThWRyMJJOHfPbL0C0/c=,tag:XCMHXq28SLpxgowMitH+oA==,type:str]
+ ldap-bind-password: ENC[AES256_GCM,data:VNJjJPbDAv5MxaHe4I+RplmX8wPX9AjscPaKKGst5qhVq7+kPV5UinYGNfxSAocFYzwKvv7YNb/s1pF1E9y+,iv:KoItQlnlqR4poFXr4sr5UU4PVApxmShS0JpUZWazPdM=,tag:sGFbAoIA0L136Q0IKxvidw==,type:str]
+ admin-password: ENC[AES256_GCM,data:X4/ZCinPTvkp,iv:jO8RFUs07EaxL5B80TO+VCDheIotkvSK9OqrgZrp84Y=,tag:bDCuHqaQdKTuOSFFmAewYQ==,type:str]
+ metrics-password: ENC[AES256_GCM,data:tIcFtJ6mZENWXUYSltwF2BWfoKXugoPpV+JyeiKXLFQ2x7YYbkyHChrCiEVEPMB6frOgk7JCA0XPo9abB/e/,iv:iEeH3+khjpWf7zB2xxsYv8uqKLYZC339EPlKgRReJ0g=,tag:XZXc9vajrZIsAqEjXS0d9Q==,type:str]
sops:
- kms: []
- gcp_kms: []
- azure_kv: []
- hc_vault: []
- age:
- - recipient: age1esjyg2qfy49awv0ptkzvpk425adczjr38m37w2mmcahzc4p8n54sll2nzh
- enc: |
- -----BEGIN AGE ENCRYPTED FILE-----
- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuc3Y0OEpEVDFqdWE4QmRw
- eDhMckNITmlQUWlKRHFxczBsdHgzMW5ydTEwCmNJRVhNODE0dVZzZThGUDVKWlp4
- SHVmSEF5TG9Hb1dtc0ladmx0M3BpRGMKLS0tIHBGUkM5Ri9QWFVTeXRhV3N3cGp2
- WGgwdjM0R3ZmUFBkVklCRENuMXZXMEkKMUC9tg/123WhsdCiB5gq/W1LIYPiXo8m
- wwrag1l8VsHDhF8TpKSC0v3/5XY/OomZAUVz03+9kCBIERGTsR24SA==
- -----END AGE ENCRYPTED FILE-----
- lastmodified: "2026-03-23T14:10:33Z"
- mac: ENC[AES256_GCM,data:lxWrl7B78axl0rZ/dN9Ioxb4Hy1P6+LmreCmA5305mPUF56nmRFhs0yVH4gEoAoOAa52Nrx3Mzg7QBEE0XrY9Pit8tK5MMxIHqntTmq+7s2BGdvEDg5+vwF+DmkdXfNpAB0TFdLm2W6cjWMeVYo6k++f543C87/Fw81K2A/HEv0=,iv:HkndtOUxrxflkSzqC1QcPR4QWS6vg5spYiy2Vprz3FM=,tag:OmsRhWzxxRfUDsd1aJYgtw==,type:str]
- pgp: []
- encrypted_regex: ^(apiKey|appUserPassword|otelUserPassword|harborAdminPassword|totpVaultKey|kimaiAppSecret|kimaiAdminPassword|GITHUB_CLIENT_ID|GITHUB_CLIENT_SECRET|GITHUB_PRIVATE_KEY|woosh|root_password|rspamd_password|pgdb_password|matrix_access_token|pgdb_remote_url|hmac_secret_key|adminPassword|adminEmail|jenkinsAdminEmail|securityRealm|gerrit.config|routing_key|DATABASE_URL|SMTP_PASSWORD|SECRET_KEY_BASE|admin_password|extraCommands|key|clickhouseDatabaseURL|databaseURL|client_id|client_secret|secret_key_base|otp_secret|private_key|public_key|primaryKey|deterministicKey|keyDerivationSalt|token|clientId|secretKey|installationId|installationKey|uriOverride|adminToken.value|password.value|sql_password|erlangCookie|AUTHENTICATION_PASSWORD|ROOM_API_SECRET_KEY|adminPassword|configPassword|adminUser|configUser|MAIL_PASSWORD|APP_KEY|api_key|api_secret|keys|livekit_key|livekit_secret|secret_key|admin_pass|admin_email|mariadbPassword|mariadbRootPassword|privateKey|data|stringData|PASSWD|password|pass|postgresPassword|smtp_auth_password|addresses|smtp_auth_username|authorization_credentials|postgresqlPassword|redminePassword|smtpPassword|registration_shared_secret|shared_secret|secret|admin_token|integrationKey|integration_key|rootPassword|adminPassword|adminUser|adminEmail|emailPassword|secretKey|appId|clientSecret|webhookSecret)$
- version: 3.9.1
+ kms: []
+ gcp_kms: []
+ azure_kv: []
+ hc_vault: []
+ age:
+ - recipient: age1esjyg2qfy49awv0ptkzvpk425adczjr38m37w2mmcahzc4p8n54sll2nzh
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuc3Y0OEpEVDFqdWE4QmRw
+ eDhMckNITmlQUWlKRHFxczBsdHgzMW5ydTEwCmNJRVhNODE0dVZzZThGUDVKWlp4
+ SHVmSEF5TG9Hb1dtc0ladmx0M3BpRGMKLS0tIHBGUkM5Ri9QWFVTeXRhV3N3cGp2
+ WGgwdjM0R3ZmUFBkVklCRENuMXZXMEkKMUC9tg/123WhsdCiB5gq/W1LIYPiXo8m
+ wwrag1l8VsHDhF8TpKSC0v3/5XY/OomZAUVz03+9kCBIERGTsR24SA==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2026-03-23T14:10:33Z"
+ mac: ENC[AES256_GCM,data:lxWrl7B78axl0rZ/dN9Ioxb4Hy1P6+LmreCmA5305mPUF56nmRFhs0yVH4gEoAoOAa52Nrx3Mzg7QBEE0XrY9Pit8tK5MMxIHqntTmq+7s2BGdvEDg5+vwF+DmkdXfNpAB0TFdLm2W6cjWMeVYo6k++f543C87/Fw81K2A/HEv0=,iv:HkndtOUxrxflkSzqC1QcPR4QWS6vg5spYiy2Vprz3FM=,tag:OmsRhWzxxRfUDsd1aJYgtw==,type:str]
+ pgp: []
+ encrypted_regex: ^(apiKey|appUserPassword|otelUserPassword|harborAdminPassword|totpVaultKey|kimaiAppSecret|kimaiAdminPassword|GITHUB_CLIENT_ID|GITHUB_CLIENT_SECRET|GITHUB_PRIVATE_KEY|woosh|root_password|rspamd_password|pgdb_password|matrix_access_token|pgdb_remote_url|hmac_secret_key|adminPassword|adminEmail|jenkinsAdminEmail|securityRealm|gerrit.config|routing_key|DATABASE_URL|SMTP_PASSWORD|SECRET_KEY_BASE|admin_password|extraCommands|key|clickhouseDatabaseURL|databaseURL|client_id|client_secret|secret_key_base|otp_secret|private_key|public_key|primaryKey|deterministicKey|keyDerivationSalt|token|clientId|secretKey|installationId|installationKey|uriOverride|adminToken.value|password.value|sql_password|erlangCookie|AUTHENTICATION_PASSWORD|ROOM_API_SECRET_KEY|adminPassword|configPassword|adminUser|configUser|MAIL_PASSWORD|APP_KEY|api_key|api_secret|keys|livekit_key|livekit_secret|secret_key|admin_pass|admin_email|mariadbPassword|mariadbRootPassword|privateKey|data|stringData|PASSWD|password|pass|postgresPassword|smtp_auth_password|addresses|smtp_auth_username|authorization_credentials|postgresqlPassword|redminePassword|smtpPassword|registration_shared_secret|shared_secret|secret|admin_token|integrationKey|integration_key|rootPassword|adminPassword|adminUser|adminEmail|emailPassword|secretKey|appId|clientSecret|webhookSecret)$
+ version: 3.9.1