# Stalwart Mail Server - Helm values # # TLS for the mail listeners is sourced from cert-manager: the # mail-vhaudiquet-fr-tls Secret (see certificate.yaml) is mounted into the pod # and pushed to Stalwart by the chart's tls-sync sidecar over JMAP, which also # calls ReloadTlsCertificates on every cert-manager renewal. # Container image image: repository: stalwartlabs/stalwart tag: v0.16.11 pullPolicy: IfNotPresent # Single-node RocksDB deployment. replicaCount: 1 role: "" pushShard: "" # Recovery / bootstrap administrator. # The Secret (stalwart-recovery-admin) is required for the lifetime of the # deployment because the tls-sync sidecar authenticates to Stalwart's JMAP API # with these credentials on every cert-manager renewal. recoveryAdmin: enabled: true username: ENC[AES256_GCM,data:ssWcS9c=,iv:K0cpea1wPDM9tEHcsP2N5rxDegzGWir+Nkh3Vnz7Ejg=,tag:mSoy5nCqTwQSj+tg8MZDFg==,type:str] password: "" existingSecret: ENC[AES256_GCM,data:IMPTLHBqnk1/xkxykOi2Sxgfocdogn0=,iv:kJz4DMVb95w/2px0UjzhtReUK6tjZ3qILPKyqlNdpV4=,tag:dME8/hiUM+XVbwDovDSxeA==,type:str] usernameKey: username passwordKey: password # Recovery mode suspends mail services and exposes only the management listener. # Ship production values with this OFF. recoveryMode: enabled: false port: 8080 logLevel: info extraEnv: {} extraSecretEnv: {} # The bootstrap hook Job provisions a *fresh* domain/accounts/OIDC directory. bootstrap: enabled: false # cert-manager TLS integration for the mail (SMTP/IMAP/POP3 STARTTLS + implicit # TLS) listeners. The Secret below is produced by the Certificate in # certificate.yaml (letsencrypt-production, Cloudflare DNS-01). mailTls: enabled: true existingSecret: ENC[AES256_GCM,data:RyFkt8p//R+qkc3UIG9v7BEXlrVlvA==,iv:S2dOLr8fKPyv5ke++zrajv0UFKJSTx1oa5jv7TZ/+hk=,tag:q1SHST/5aLa+4iNs2TSUVg==,type:str] certKey: tls.crt privateKeyKey: tls.key mountPath: /etc/stalwart/tls/ingress hostname: mail.vhaudiquet.fr domain: vhaudiquet.fr # How often the sidecar re-checks the mounted cert for changes. reloadIntervalSeconds: 300 # config.json contents - ONLY the DataStore object. All other settings # (listeners, storage backends, domains, accounts, certs) live in the database # and are managed via JMAP/WebUI. config: '@type': RocksDb path: /var/lib/stalwart # Main Service: ClusterIP. Used by the Ingress for the management WebUI (mgmt) # and for in-cluster access. Mail L4 ports are exposed separately via mailService. service: type: ClusterIP ports: smtp: 25 smtps: 465 submission: 587 imap: 143 imaps: 993 pop3: 110 pop3s: 995 sieve: 4190 http: 80 https: 443 mgmt: 8080 # Dedicated LoadBalancer for SMTP/IMAP/POP3/Sieve (L4). HTTP/HTTPS/mgmt are NOT # exposed here - the WebUI is reached via the Ingress (Traefik) below. # The WAN router NAT for 25/465/587/993/995/4190 must be repointed to this IP. mailService: enabled: true name: stalwart-mail type: LoadBalancer loadBalancerIP: 10.2.1.5 annotations: {} # WebUI ingress. TLS is terminated by Caddy at the edge (wildcard cert), so the # path is: public -> Caddy (TLS) -> Traefik (HTTP) -> this Ingress -> mgmt:8080. # No TLS block here. ingress: enabled: true annotations: {} hosts: - host: mail.vhaudiquet.fr paths: - path: / pathType: Prefix portName: mgmt tls: [] # Persistent volume for the RocksDB data directory. persistence: enabled: true accessMode: ReadWriteOnce storageClass: longhorn size: 50Gi resources: requests: cpu: 250m memory: 256Mi limits: cpu: "1" memory: 1Gi # Override chart defaults to add fsGroupChangePolicy: OnRootMismatch. # Without this, kubelet recursively chowns every file in the NFS-backed PVC # on every pod start (15k+ RocksDB files), causing multi-minute delays. # OnRootMismatch skips the recursive chown if the volume root already # has the correct owner (UID 2000). podSecurityContext: fsGroup: 2000 fsGroupChangePolicy: OnRootMismatch runAsUser: 2000 runAsGroup: 2000 runAsNonRoot: true seccompProfile: type: RuntimeDefault containerSecurityContext: {} sops: lastmodified: "2026-08-20T20:31:57Z" mac: ENC[AES256_GCM,data:QjvWqFfWs1WiGwpjRG7yeyO4fMlfTk8WwUlTGhNAR/4MP2fyHV31VOgj0Dpamf3zHEOfVG4CQuADWQUbcwFbArdotn9sdsGrTheDWSikjM79AC2rhh/vCeREDyYR4nKm8aZISvGlwF6SQVoYO8VomVDJkNhK9ceWLaDyxrMJIxs=,iv:lQ+Zv4H7O8R8aOwPkru6iBYFR9ODpGwIdZdTQzQ8aJE=,tag:y1MRdyTltz6c9UWOQ3tWBQ==,type:str] pgp: - created_at: "2026-08-20T20:31:57Z" enc: |- -----BEGIN PGP MESSAGE----- hQIMA7uy4qQr71wiAQ/9EUc3vJ3fVYZm4KQ2owVf9IKdpt2rPgaAgZMqwFqNXIi+ ZA4/iiFv0BctD6pgx/Dwe5cHa5Wq3z6NDcO9g/wlZMRBLPIuGXcOey4AwBBvYlgt +A6VxeCHimczImogGHUkJRlM39hdZh32hs8olzkVLk/nYdh6sKeGLm2dphP+kPJg hnfgGA0pc5lSsz2gMHZiOy85mOpoFbj3c4Ndr1mKvSz4PbRAwIXn5idsASCZO/Dv xqzmftrmahaNwfHvmKdYHApyIbb0kxRuWKiwpXFUuwpOOJDlC4QH5XuZc3mslLeb vxI+l2o0ojMImgwXCreCxqGkKQN4osa/AdoqMSafGNgSjhLdkiw+XhG+Wy5EEh0V eOyaLsW/OCxKhGOWPgGd570BSgGZaf9JjB9tKBmlocu/D8vhaREblziNE3/PkfZV YjnrxktJsbT1sEOblfPulUwmkDQOfG1QBC4zxrJPzYnUxd0Klf5bkLFoHLBEK+KE +ZOLW9TDWnccPm1ZdiIpR2CepUILRus3lVNxQUk4NKhssg3YYFH1FJy5t9cDP9eJ hXSE5kq1kTL4W4+o7B6oDAljWe9UGW7OU3M18o8CQJ5nFLdv+gm9Xtzo8I4FTY/J ATz77c/tILUl/TXkXvJNwzxqD4EAlq5ci5MiVFpdO0Fg2roK4fAGE4gzZZsG8FDS XAH+UpKRFmQ43TdB7//yy0Qdziv8xu/FC8nWnYaYYsm6xVkMsGujnyKQ2x/j6eMH 4+Hh8gQocaZm5UKzKf8XFgZhupWKSNjjPivdWeoF/pHyhlzSGG0/bHjpmCpz =/TCV -----END PGP MESSAGE----- fp: DC6910268E657FF70BA7EC289974494E76938DDC encrypted_regex: ^(password|value|ssh-key|api-key|user|username|privateKey|clientSecret|clientId|apiKey|extraArgs.*|.*Secret.*|extraEnvVars|.*SECRET.*|.*secret.*|key|.*Password|.*PASS|.*SOCIALACCOUNT_PROVIDERS|.*\.ya?ml)$ version: 3.10.2