release.yaml (9767B)
1 apiVersion: helm.toolkit.fluxcd.io/v2 2 kind: HelmRelease 3 metadata: 4 name: stalwart-mail 5 namespace: stalwart 6 spec: 7 interval: 5m 8 chart: 9 spec: 10 chart: stalwart-mail 11 version: "1.0.x" 12 sourceRef: 13 kind: HelmRepository 14 name: wrenix 15 namespace: stalwart 16 interval: 60m 17 install: 18 crds: CreateReplace 19 upgrade: 20 crds: CreateReplace 21 postRenderers: 22 - kustomize: 23 patches: 24 - target: 25 version: v1 26 kind: Service 27 name: stalwart-mail 28 patch: | 29 - op: add 30 path: /spec/ports/- 31 value: 32 name: submission-internal 33 port: 2587 34 protocol: TCP 35 targetPort: 2587 36 - target: 37 group: monitoring.coreos.com 38 version: v1 39 kind: ServiceMonitor 40 name: stalwart-mail 41 patch: | 42 - op: replace 43 path: /spec/endpoints/0/basicAuth/password 44 value: 45 key: metrics-password 46 name: stalwart-secret 47 - op: replace 48 path: /spec/endpoints/0/basicAuth/username 49 value: 50 key: metrics-username 51 name: stalwart-secret 52 - op: add 53 path: /spec/endpoints/0/metricRelabelings 54 value: 55 - sourceLabels: [__name__] 56 regex: (.+) 57 targetLabel: __name__ 58 replacement: stalwart_$1 59 values: 60 replicaCount: 1 61 62 backup: 63 enabled: true 64 65 image: 66 registry: ghcr.io 67 repository: stalwartlabs/stalwart 68 pullPolicy: IfNotPresent 69 70 # Don't use the chart's built-in secret — we manage our own stalwart-secret 71 secrets: 72 create: false 73 74 # Env vars from stalwart-secret (S3, DB, admin password, LDAP) 75 env: 76 - name: PG_PASSWORD 77 valueFrom: 78 secretKeyRef: 79 name: stalwart-secret 80 key: pg-password 81 - name: S3_ACCESS_KEY 82 valueFrom: 83 secretKeyRef: 84 name: stalwart-secret 85 key: s3-access-key 86 - name: S3_SECRET_KEY 87 valueFrom: 88 secretKeyRef: 89 name: stalwart-secret 90 key: s3-secret-key 91 - name: FALLBACK_ADMIN_SECRET 92 valueFrom: 93 secretKeyRef: 94 name: stalwart-secret 95 key: admin-password 96 - name: METRICS_USERNAME 97 value: prometheus 98 - name: METRICS_SECRET 99 valueFrom: 100 secretKeyRef: 101 name: stalwart-secret 102 key: metrics-password 103 - name: LDAP_BIND_SECRET 104 valueFrom: 105 secretKeyRef: 106 name: stalwart-secret 107 key: ldap-bind-password 108 109 persistence: 110 enabled: true 111 storageClass: longhorn 112 size: 10Gi 113 accessMode: ReadWriteMany 114 115 # cert-manager issues the TLS cert used by SMTP/IMAP TLS listeners 116 certificate: 117 certmanager: 118 enabled: true 119 issuerRef: 120 group: cert-manager.io 121 kind: ClusterIssuer 122 name: letsencrypt-dns 123 dnsNames: 124 - mail.midnightthoughts.space 125 - mail.nordgedanken.dev 126 127 prometheus: 128 servicemonitor: 129 enabled: true 130 labels: 131 release: kube-prometheus-stack 132 133 config: 134 # Keys stored in the local config file (not the DB) 135 config: 136 local-keys: 137 - "store.*" 138 - "directory.*" 139 - "tracer.*" 140 - "!server.blocked-ip.*" 141 - "server.*" 142 - "authentication.fallback-admin.*" 143 - "cluster.*" 144 - "config.local-keys.*" 145 - "storage.data" 146 - "storage.blob" 147 - "storage.lookup" 148 - "storage.fts" 149 - "storage.directory" 150 - "certificate.*" 151 - "server.allowed-ip.*" 152 - "metrics.prometheus.*" 153 - "auth.dkim.sign.*" 154 - "auth.dkim.verify" 155 - "http.use-x-forwarded" 156 - "report.domain" 157 - "queue.*" 158 - "session.auth.*" 159 - "session.rcpt.*" 160 - "calendar.*" 161 162 authentication: 163 fallback-admin: 164 user: admin 165 secret: "%{env:FALLBACK_ADMIN_SECRET}%" 166 167 metrics: 168 prometheus: 169 enable: true 170 auth: 171 username: "%{env:METRICS_USERNAME}%" 172 secret: "%{env:METRICS_SECRET}%" 173 174 http: 175 use-x-forwarded: true 176 177 calendar: 178 scheduling: 179 http-rsvp: 180 url: https://webmail.midnightthoughts.space/calendar/rsvp 181 182 # ── Storage ───────────────────────────────────────────────────────── 183 storage: 184 data: db 185 blob: s3blob 186 fts: db 187 lookup: db 188 directory: default 189 190 store: 191 db: 192 type: postgresql 193 host: pg-cluster-v2-rw.postgres-cluster.svc.cluster.local 194 port: 5432 195 database: stalwart 196 user: stalwart 197 password: "%{env:PG_PASSWORD}%" 198 s3blob: 199 type: s3 200 bucket: midnightthoughts-stalwart 201 region: hel1 202 endpoint: https://hel1.your-objectstorage.com 203 access-key: "%{env:S3_ACCESS_KEY}%" 204 secret-key: "%{env:S3_SECRET_KEY}%" 205 206 # ── Directory (Authentik LDAP) ─────────────────────────────────────── 207 directory: 208 default: 209 type: internal 210 store: db 211 212 # ── Listeners (proxy-protocol from Envoy Gateway) ──────────────────── 213 server: 214 hostname: mail.midnightthoughts.space 215 listener: 216 smtp: 217 bind: ["[::]:25"] 218 protocol: smtp 219 proxy: 220 trusted-networks: 221 - 10.0.0.0/8 222 - fd00::/8 223 submission: 224 bind: ["[::]:587"] 225 protocol: smtp 226 proxy: 227 trusted-networks: 228 - 10.0.0.0/8 229 - fd00::/8 230 submission-internal: 231 bind: ["[::]:2587"] 232 protocol: smtp 233 submissions: 234 bind: ["[::]:465"] 235 protocol: smtp 236 tls: 237 implicit: true 238 proxy: 239 trusted-networks: 240 - 10.0.0.0/8 241 - fd00::/8 242 imap: 243 bind: ["[::]:143"] 244 protocol: imap 245 proxy: 246 trusted-networks: 247 - 10.0.0.0/8 248 - fd00::/8 249 imaptls: 250 bind: ["[::]:993"] 251 protocol: imap 252 tls: 253 implicit: true 254 proxy: 255 trusted-networks: 256 - 10.0.0.0/8 257 - fd00::/8 258 http: 259 bind: ["[::]:80"] 260 protocol: http 261 262 # ── TLS certificate (cert-manager) ──────────────────────────────────── 263 certificate: 264 default: 265 default: true 266 cert: "%{file:/opt/stalwart/etc/certs/tls.crt}%" 267 private-key: "%{file:/opt/stalwart/etc/certs/tls.key}%" 268 269 # ── DKIM signing ────────────────────────────────────────────────────── 270 auth: 271 dkim: 272 sign: 273 - if: "listener != 'smtp' && is_local_domain('', sender_domain)" 274 then: "['rsa-' + sender_domain, 'ed25519-' + sender_domain]" 275 - else: false 276 verify: relaxed 277 278 # ── SMTP session: relay lists domain without directory lookup ───────── 279 session: 280 auth: 281 must-match-sender: 282 - if: "sender_domain == 'lists.midnightthoughts.space' && authenticated_as == 'support@midnightthoughts.space'" 283 then: false 284 - else: true 285 rcpt: 286 directory: 287 - if: "rcpt_domain == 'lists.midnightthoughts.space' || rcpt_domain == 'phorge.mtrnord.blog'" 288 then: "'*'" 289 - else: "'default'" 290 291 # ── Routing ─────────────────────────────────────────────────────────── 292 queue: 293 route: 294 local: 295 type: local 296 phorge-relay: 297 type: relay 298 address: 10.0.64.129 299 port: 25 300 protocol: smtp 301 tls: 302 implicit: false 303 allow-invalid-certs: true 304 mailman-lmtp: 305 type: relay 306 address: mailman.mailserver.svc.cluster.local 307 port: 8024 308 protocol: lmtp 309 tls: 310 implicit: false 311 enable: false 312 strategy: 313 route: 314 # TODO: remove once nordgedanken.dev is migrated to Stalwart 315 - if: "rcpt_domain == 'nordgedanken.dev'" 316 then: "'mx'" 317 - if: "rcpt_domain == 'lists.midnightthoughts.space'" 318 then: "'mailman-lmtp'" 319 - if: "rcpt_domain == 'phorge.mtrnord.blog'" 320 then: "'phorge-relay'" 321 - if: "is_local_domain('', rcpt_domain)" 322 then: "'local'" 323 - else: "'mx'" 324 325 tracer: 326 stdout: 327 enable: true 328 type: stdout 329 level: info 330 ansi: false