From d980d46a55b933b46fbf961529cdfbdb1604fca2 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Sun, 24 May 2026 12:01:43 +1000 Subject: [PATCH] =?UTF-8?q?refactor(mailgateway):=20rename=20namespace=20p?= =?UTF-8?q?ostfix=E2=86=92mailgateway,=20switch=20to=20tozd/postfix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename apps/base/postfix → apps/base/mailgateway - Rename apps/overlays/au-syd1/postfix → apps/overlays/au-syd1/mailgateway - Namespace postfix → mailgateway throughout all resources - Replace boky/postfix with tozd/postfix:alpine-322 (Postfix 3.10.2 on Alpine 3.22) - Add full main.cf and master.cf as ConfigMap resources mounted via subPath - main.cf: relay-only gateway config, texthash: transport maps, rspamd milter - master.cf: standard smtp + submission (587, TLS required) + internal processes - Remove custom.cf (superseded by main.cf); merge transport into postfix-config ConfigMap - MAILNAME/MY_NETWORKS/MY_DESTINATION env vars kept in sync with main.cf - LOG_TO_STDOUT=1 for k8s log collection - Vault DKIM keys now at kubernetes/namespace/mailgateway/default/dkim-keys - artifactapi: replace boky/postfix with tozd/postfix in dockerhub cache --- .../resources/conf.d/remote-docker.yaml | 2 +- .../{postfix => mailgateway}/certificate.yaml | 5 +- .../{postfix => mailgateway}/gateway.yaml | 2 +- .../{postfix => mailgateway}/httproute.yaml | 4 +- .../kustomization.yaml | 7 +-- .../{postfix => mailgateway}/namespace.yaml | 2 +- .../postfix-deployment.yaml | 49 +++++++++---------- .../{postfix => mailgateway}/postfix-hpa.yaml | 2 +- .../mailgateway/resources/postfix/main.cf | 47 ++++++++++++++++++ .../mailgateway/resources/postfix/master.cf | 42 ++++++++++++++++ .../resources/postfix/transport | 0 .../rspamd/local.d/dkim_signing.conf | 0 .../rspamd/local.d/milter_headers.conf | 0 .../resources/rspamd/local.d/worker-proxy.inc | 0 .../rspamd-deployment.yaml | 2 +- .../{postfix => mailgateway}/rspamd-hpa.yaml | 2 +- .../{postfix => mailgateway}/services.yaml | 6 +-- .../{postfix => mailgateway}/vaultauth.yaml | 4 +- .../vaultstaticsecret.yaml | 4 +- apps/base/postfix/resources/postfix/custom.cf | 30 ------------ .../kustomization.yaml | 2 +- argocd/applicationsets/platform.yaml | 2 +- 22 files changed, 131 insertions(+), 83 deletions(-) rename apps/base/{postfix => mailgateway}/certificate.yaml (54%) rename apps/base/{postfix => mailgateway}/gateway.yaml (97%) rename apps/base/{postfix => mailgateway}/httproute.yaml (82%) rename apps/base/{postfix => mailgateway}/kustomization.yaml (86%) rename apps/base/{postfix => mailgateway}/namespace.yaml (69%) rename apps/base/{postfix => mailgateway}/postfix-deployment.yaml (61%) rename apps/base/{postfix => mailgateway}/postfix-hpa.yaml (96%) create mode 100644 apps/base/mailgateway/resources/postfix/main.cf create mode 100644 apps/base/mailgateway/resources/postfix/master.cf rename apps/base/{postfix => mailgateway}/resources/postfix/transport (100%) rename apps/base/{postfix => mailgateway}/resources/rspamd/local.d/dkim_signing.conf (100%) rename apps/base/{postfix => mailgateway}/resources/rspamd/local.d/milter_headers.conf (100%) rename apps/base/{postfix => mailgateway}/resources/rspamd/local.d/worker-proxy.inc (100%) rename apps/base/{postfix => mailgateway}/rspamd-deployment.yaml (98%) rename apps/base/{postfix => mailgateway}/rspamd-hpa.yaml (96%) rename apps/base/{postfix => mailgateway}/services.yaml (93%) rename apps/base/{postfix => mailgateway}/vaultauth.yaml (88%) rename apps/base/{postfix => mailgateway}/vaultstaticsecret.yaml (76%) delete mode 100644 apps/base/postfix/resources/postfix/custom.cf rename apps/overlays/au-syd1/{postfix => mailgateway}/kustomization.yaml (72%) diff --git a/apps/base/artifactapi/resources/conf.d/remote-docker.yaml b/apps/base/artifactapi/resources/conf.d/remote-docker.yaml index 541b00b..fb2d325 100644 --- a/apps/base/artifactapi/resources/conf.d/remote-docker.yaml +++ b/apps/base/artifactapi/resources/conf.d/remote-docker.yaml @@ -20,7 +20,6 @@ remotes: package: "docker" description: "Docker Hub registry" immutable_patterns: - - "^boky/postfix" - "^library/almalinux" - "^library/busybox" - "^library/debian" @@ -37,6 +36,7 @@ remotes: - "^jfrog/" - "^rancher/" - "^rspamd/rspamd" + - "^tozd/postfix" - "^traefik/" - "^ubi9/ubi-minimal" - "^victoriametrics/" diff --git a/apps/base/postfix/certificate.yaml b/apps/base/mailgateway/certificate.yaml similarity index 54% rename from apps/base/postfix/certificate.yaml rename to apps/base/mailgateway/certificate.yaml index 11c74f9..88d2b7b 100644 --- a/apps/base/postfix/certificate.yaml +++ b/apps/base/mailgateway/certificate.yaml @@ -1,12 +1,9 @@ --- -# TLS certificate for postfix SMTP - stored in Vault and synced via VaultStaticSecret -# The postfix-tls secret is managed via vaultstaticsecret.yaml (keys: tls.crt, tls.key) -# This Certificate resource issues the cert used by Stalwart for SMTP/IMAP TLS apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: postfix-smtp-tls - namespace: postfix + namespace: mailgateway spec: secretName: postfix-smtp-tls issuerRef: diff --git a/apps/base/postfix/gateway.yaml b/apps/base/mailgateway/gateway.yaml similarity index 97% rename from apps/base/postfix/gateway.yaml rename to apps/base/mailgateway/gateway.yaml index e730bb0..7ef9a4f 100644 --- a/apps/base/postfix/gateway.yaml +++ b/apps/base/mailgateway/gateway.yaml @@ -11,7 +11,7 @@ metadata: external-dns.alpha.kubernetes.io/hostname: rspamd.k8s.syd1.au.unkin.net external-dns.alpha.kubernetes.io/target: 198.18.200.4 name: rspamd - namespace: postfix + namespace: mailgateway spec: gatewayClassName: traefik-internal listeners: diff --git a/apps/base/postfix/httproute.yaml b/apps/base/mailgateway/httproute.yaml similarity index 82% rename from apps/base/postfix/httproute.yaml rename to apps/base/mailgateway/httproute.yaml index abf0baa..26d024b 100644 --- a/apps/base/postfix/httproute.yaml +++ b/apps/base/mailgateway/httproute.yaml @@ -3,11 +3,11 @@ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: rspamd - namespace: postfix + namespace: mailgateway spec: parentRefs: - name: rspamd - namespace: postfix + namespace: mailgateway hostnames: - rspamd.k8s.syd1.au.unkin.net rules: diff --git a/apps/base/postfix/kustomization.yaml b/apps/base/mailgateway/kustomization.yaml similarity index 86% rename from apps/base/postfix/kustomization.yaml rename to apps/base/mailgateway/kustomization.yaml index 3975147..0c088c7 100644 --- a/apps/base/postfix/kustomization.yaml +++ b/apps/base/mailgateway/kustomization.yaml @@ -18,11 +18,8 @@ resources: configMapGenerator: - name: postfix-config files: - - resources/postfix/custom.cf - options: - disableNameSuffixHash: true - - name: postfix-transport - files: + - main.cf=resources/postfix/main.cf + - master.cf=resources/postfix/master.cf - transport=resources/postfix/transport options: disableNameSuffixHash: true diff --git a/apps/base/postfix/namespace.yaml b/apps/base/mailgateway/namespace.yaml similarity index 69% rename from apps/base/postfix/namespace.yaml rename to apps/base/mailgateway/namespace.yaml index f0575c5..86e63f3 100644 --- a/apps/base/postfix/namespace.yaml +++ b/apps/base/mailgateway/namespace.yaml @@ -2,4 +2,4 @@ apiVersion: v1 kind: Namespace metadata: - name: postfix + name: mailgateway diff --git a/apps/base/postfix/postfix-deployment.yaml b/apps/base/mailgateway/postfix-deployment.yaml similarity index 61% rename from apps/base/postfix/postfix-deployment.yaml rename to apps/base/mailgateway/postfix-deployment.yaml index 9f41b8a..73fd562 100644 --- a/apps/base/postfix/postfix-deployment.yaml +++ b/apps/base/mailgateway/postfix-deployment.yaml @@ -3,7 +3,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: postfix - namespace: postfix + namespace: mailgateway spec: selector: matchLabels: @@ -17,7 +17,7 @@ spec: spec: containers: - name: postfix - image: boky/postfix:3.9.1 + image: tozd/postfix:alpine-322 ports: - containerPort: 25 name: smtp @@ -26,26 +26,15 @@ spec: name: submission protocol: TCP env: - - name: SERVER_HOSTNAME + # Keep these in sync with main.cf so the tozd startup postconf calls are no-ops + - name: MAILNAME value: "mail.main.unkin.net" - - name: MYORIGIN - value: "main.unkin.net" - - name: MYNETWORKS + - name: MY_NETWORKS value: "127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16" - - name: ALLOWED_SENDER_DOMAINS - value: "main.unkin.net unkin.net" - - name: POSTFIX_myhostname - value: "mail.main.unkin.net" - - name: POSTFIX_mydestination - value: "localhost" - - name: POSTFIX_smtp_tls_security_level - value: "may" - - name: POSTFIX_smtpd_tls_security_level - value: "may" - - name: POSTFIX_smtpd_tls_cert_file - value: "/etc/postfix/tls/tls.crt" - - name: POSTFIX_smtpd_tls_key_file - value: "/etc/postfix/tls/tls.key" + - name: MY_DESTINATION + value: "localhost.localdomain, localhost" + - name: LOG_TO_STDOUT + value: "1" livenessProbe: tcpSocket: port: 25 @@ -68,23 +57,29 @@ spec: cpu: "1" memory: 512Mi volumeMounts: + # Mount main.cf and master.cf from ConfigMap using subPath + - name: postfix-config + mountPath: /etc/postfix/main.cf + subPath: main.cf + - name: postfix-config + mountPath: /etc/postfix/master.cf + subPath: master.cf - name: postfix-config - mountPath: /etc/postfix/custom.d - readOnly: true - - name: postfix-transport mountPath: /etc/postfix/transport subPath: transport - readOnly: true + # TLS cert from cert-manager Certificate resource - name: postfix-tls mountPath: /etc/postfix/tls readOnly: true + # Persistent mail queue + - name: spool + mountPath: /var/spool/postfix volumes: - name: postfix-config configMap: name: postfix-config - - name: postfix-transport - configMap: - name: postfix-transport - name: postfix-tls secret: secretName: postfix-smtp-tls + - name: spool + emptyDir: {} diff --git a/apps/base/postfix/postfix-hpa.yaml b/apps/base/mailgateway/postfix-hpa.yaml similarity index 96% rename from apps/base/postfix/postfix-hpa.yaml rename to apps/base/mailgateway/postfix-hpa.yaml index da0d738..0210544 100644 --- a/apps/base/postfix/postfix-hpa.yaml +++ b/apps/base/mailgateway/postfix-hpa.yaml @@ -3,7 +3,7 @@ apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: postfix-hpa - namespace: postfix + namespace: mailgateway spec: scaleTargetRef: apiVersion: apps/v1 diff --git a/apps/base/mailgateway/resources/postfix/main.cf b/apps/base/mailgateway/resources/postfix/main.cf new file mode 100644 index 0000000..b5466f7 --- /dev/null +++ b/apps/base/mailgateway/resources/postfix/main.cf @@ -0,0 +1,47 @@ +# Basic identity — kept in sync with MAILNAME/MY_NETWORKS/MY_DESTINATION env vars +# so the tozd startup script's postconf calls are no-ops +myhostname = mail.main.unkin.net +myorigin = main.unkin.net +mydestination = localhost.localdomain, localhost +mynetworks = 127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 +inet_protocols = ipv4 +inet_interfaces = all + +# No local delivery — we're a relay-only gateway +local_transport = error:no local delivery +alias_maps = +alias_database = + +# Relay inbound mail for these domains to Stalwart +# texthash: reads plain text without requiring postmap (Alpine has no hash/btree) +relay_domains = main.unkin.net unkin.net +transport_maps = texthash:/etc/postfix/transport + +# rspamd milter (same namespace — short DNS name resolves) +smtpd_milters = inet:rspamd:11332 +non_smtpd_milters = inet:rspamd:11332 +milter_default_action = accept +milter_protocol = 6 +milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen} + +# Inbound TLS (cert from cert-manager Certificate resource) +smtpd_use_tls = yes +smtpd_tls_security_level = may +smtpd_tls_cert_file = /etc/postfix/tls/tls.crt +smtpd_tls_key_file = /etc/postfix/tls/tls.key +smtpd_tls_loglevel = 1 + +# Outbound TLS (opportunistic) +smtp_tls_security_level = may +smtp_tls_loglevel = 1 + +# Message size limit (50 MiB) +message_size_limit = 52428800 +mailbox_size_limit = 0 + +# Queue retention +maximal_queue_lifetime = 5d +bounce_queue_lifetime = 1d + +# Log to stdout for k8s log collection +maillog_file = /dev/stdout diff --git a/apps/base/mailgateway/resources/postfix/master.cf b/apps/base/mailgateway/resources/postfix/master.cf new file mode 100644 index 0000000..471f9c8 --- /dev/null +++ b/apps/base/mailgateway/resources/postfix/master.cf @@ -0,0 +1,42 @@ +# ========================================================================== +# service type private unpriv chroot wakeup maxproc command + args +# (yes) (yes) (yes) (never) (100) +# ========================================================================== + +# SMTP inbound (port 25) — runs rspamd milter, relays to Stalwart via transport_maps +smtp inet n - n - - smtpd + +# Submission (port 587) — TLS required, relay from trusted mynetworks only +submission inet n - n - - smtpd + -o syslog_name=postfix/submission + -o smtpd_tls_security_level=encrypt + -o smtpd_sasl_auth_enable=no + -o smtpd_reject_unlisted_recipient=no + -o smtpd_relay_restrictions=permit_mynetworks,reject + -o milter_macro_daemon_name=ORIGINATING + +# Internal postfix processes +pickup unix n - n 60 1 pickup +cleanup unix n - n - 0 cleanup +qmgr unix n - n 300 1 qmgr +tlsmgr unix - - n 1000? 1 tlsmgr +rewrite unix - - n - - trivial-rewrite +bounce unix - - n - 0 bounce +defer unix - - n - 0 bounce +trace unix - - n - 0 bounce +verify unix - - n - 1 verify +flush unix n - n 1000? 0 flush +proxymap unix - - n - - proxymap +proxywrite unix - - n - 1 proxymap +smtp unix - - n - - smtp +relay unix - - n - - smtp +showq unix n - n - - showq +error unix - - n - - error +retry unix - - n - - error +discard unix - - n - - discard +local unix - n n - - local +virtual unix - n n - - virtual +lmtp unix - - n - - lmtp +anvil unix - - n - 1 anvil +scache unix - - n - 1 scache +postlog unix-dgram n - n - 1 postlogd diff --git a/apps/base/postfix/resources/postfix/transport b/apps/base/mailgateway/resources/postfix/transport similarity index 100% rename from apps/base/postfix/resources/postfix/transport rename to apps/base/mailgateway/resources/postfix/transport diff --git a/apps/base/postfix/resources/rspamd/local.d/dkim_signing.conf b/apps/base/mailgateway/resources/rspamd/local.d/dkim_signing.conf similarity index 100% rename from apps/base/postfix/resources/rspamd/local.d/dkim_signing.conf rename to apps/base/mailgateway/resources/rspamd/local.d/dkim_signing.conf diff --git a/apps/base/postfix/resources/rspamd/local.d/milter_headers.conf b/apps/base/mailgateway/resources/rspamd/local.d/milter_headers.conf similarity index 100% rename from apps/base/postfix/resources/rspamd/local.d/milter_headers.conf rename to apps/base/mailgateway/resources/rspamd/local.d/milter_headers.conf diff --git a/apps/base/postfix/resources/rspamd/local.d/worker-proxy.inc b/apps/base/mailgateway/resources/rspamd/local.d/worker-proxy.inc similarity index 100% rename from apps/base/postfix/resources/rspamd/local.d/worker-proxy.inc rename to apps/base/mailgateway/resources/rspamd/local.d/worker-proxy.inc diff --git a/apps/base/postfix/rspamd-deployment.yaml b/apps/base/mailgateway/rspamd-deployment.yaml similarity index 98% rename from apps/base/postfix/rspamd-deployment.yaml rename to apps/base/mailgateway/rspamd-deployment.yaml index 76eda38..3800779 100644 --- a/apps/base/postfix/rspamd-deployment.yaml +++ b/apps/base/mailgateway/rspamd-deployment.yaml @@ -3,7 +3,7 @@ apiVersion: apps/v1 kind: Deployment metadata: name: rspamd - namespace: postfix + namespace: mailgateway spec: selector: matchLabels: diff --git a/apps/base/postfix/rspamd-hpa.yaml b/apps/base/mailgateway/rspamd-hpa.yaml similarity index 96% rename from apps/base/postfix/rspamd-hpa.yaml rename to apps/base/mailgateway/rspamd-hpa.yaml index d24cf0d..bad2966 100644 --- a/apps/base/postfix/rspamd-hpa.yaml +++ b/apps/base/mailgateway/rspamd-hpa.yaml @@ -3,7 +3,7 @@ apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: rspamd-hpa - namespace: postfix + namespace: mailgateway spec: scaleTargetRef: apiVersion: apps/v1 diff --git a/apps/base/postfix/services.yaml b/apps/base/mailgateway/services.yaml similarity index 93% rename from apps/base/postfix/services.yaml rename to apps/base/mailgateway/services.yaml index 0d8ffcb..3ccbcbf 100644 --- a/apps/base/postfix/services.yaml +++ b/apps/base/mailgateway/services.yaml @@ -4,7 +4,7 @@ apiVersion: v1 kind: Service metadata: name: rspamd - namespace: postfix + namespace: mailgateway spec: selector: app: rspamd @@ -27,7 +27,7 @@ apiVersion: v1 kind: Service metadata: name: postfix - namespace: postfix + namespace: mailgateway spec: selector: app: postfix @@ -46,7 +46,7 @@ apiVersion: v1 kind: Service metadata: name: postfix-external - namespace: postfix + namespace: mailgateway annotations: external-dns.alpha.kubernetes.io/hostname: smtp-in.main.unkin.net spec: diff --git a/apps/base/postfix/vaultauth.yaml b/apps/base/mailgateway/vaultauth.yaml similarity index 88% rename from apps/base/postfix/vaultauth.yaml rename to apps/base/mailgateway/vaultauth.yaml index de10f26..593e2c2 100644 --- a/apps/base/postfix/vaultauth.yaml +++ b/apps/base/mailgateway/vaultauth.yaml @@ -3,10 +3,10 @@ apiVersion: secrets.hashicorp.com/v1beta1 kind: VaultAuth metadata: name: default - namespace: postfix + namespace: mailgateway spec: allowedNamespaces: - - postfix + - mailgateway kubernetes: audiences: - vault diff --git a/apps/base/postfix/vaultstaticsecret.yaml b/apps/base/mailgateway/vaultstaticsecret.yaml similarity index 76% rename from apps/base/postfix/vaultstaticsecret.yaml rename to apps/base/mailgateway/vaultstaticsecret.yaml index 0819ccb..c47cc4c 100644 --- a/apps/base/postfix/vaultstaticsecret.yaml +++ b/apps/base/mailgateway/vaultstaticsecret.yaml @@ -3,7 +3,7 @@ apiVersion: secrets.hashicorp.com/v1beta1 kind: VaultStaticSecret metadata: name: dkim-keys - namespace: postfix + namespace: mailgateway spec: destination: create: true @@ -11,7 +11,7 @@ spec: overwrite: true hmacSecretData: true mount: kv - path: kubernetes/namespace/postfix/default/dkim-keys + path: kubernetes/namespace/mailgateway/default/dkim-keys refreshAfter: 5m type: kv-v2 vaultAuthRef: default diff --git a/apps/base/postfix/resources/postfix/custom.cf b/apps/base/postfix/resources/postfix/custom.cf deleted file mode 100644 index 2ea4623..0000000 --- a/apps/base/postfix/resources/postfix/custom.cf +++ /dev/null @@ -1,30 +0,0 @@ -# Relay domains - mail for these domains is forwarded to Stalwart -relay_domains = main.unkin.net unkin.net - -# Transport map (texthash: reads plain text without postmap) -transport_maps = texthash:/etc/postfix/transport - -# rspamd milter -smtpd_milters = inet:rspamd:11332 -non_smtpd_milters = inet:rspamd:11332 -milter_default_action = accept -milter_protocol = 6 -milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen} - -# Message size limit (50 MiB) -message_size_limit = 52428800 - -# TLS for inbound connections -smtpd_tls_cert_file = /etc/postfix/tls/tls.crt -smtpd_tls_key_file = /etc/postfix/tls/tls.key -smtpd_use_tls = yes -smtpd_tls_security_level = may -smtpd_tls_loglevel = 1 - -# TLS for outbound delivery -smtp_tls_security_level = may -smtp_tls_loglevel = 1 - -# Queue settings -maximal_queue_lifetime = 5d -bounce_queue_lifetime = 1d diff --git a/apps/overlays/au-syd1/postfix/kustomization.yaml b/apps/overlays/au-syd1/mailgateway/kustomization.yaml similarity index 72% rename from apps/overlays/au-syd1/postfix/kustomization.yaml rename to apps/overlays/au-syd1/mailgateway/kustomization.yaml index a853959..def9a9f 100644 --- a/apps/overlays/au-syd1/postfix/kustomization.yaml +++ b/apps/overlays/au-syd1/mailgateway/kustomization.yaml @@ -3,4 +3,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - ../../../base/postfix + - ../../../base/mailgateway diff --git a/argocd/applicationsets/platform.yaml b/argocd/applicationsets/platform.yaml index 3d5c3ce..e25b55e 100644 --- a/argocd/applicationsets/platform.yaml +++ b/argocd/applicationsets/platform.yaml @@ -21,7 +21,7 @@ spec: - path: apps/overlays/*/inteldeviceplugins-system - path: apps/overlays/*/jfrog - path: apps/overlays/*/node-feature-discovery - - path: apps/overlays/*/postfix + - path: apps/overlays/*/mailgateway - path: apps/overlays/*/puppet - path: apps/overlays/*/purelb - path: apps/overlays/*/reflector-system