refactor(mailgateway): rename namespace postfix→mailgateway, switch to tozd/postfix

- 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
This commit is contained in:
2026-05-24 12:01:43 +10:00
parent 1cf08dd5c1
commit d980d46a55
22 changed files with 131 additions and 83 deletions
@@ -20,7 +20,6 @@ remotes:
package: "docker" package: "docker"
description: "Docker Hub registry" description: "Docker Hub registry"
immutable_patterns: immutable_patterns:
- "^boky/postfix"
- "^library/almalinux" - "^library/almalinux"
- "^library/busybox" - "^library/busybox"
- "^library/debian" - "^library/debian"
@@ -37,6 +36,7 @@ remotes:
- "^jfrog/" - "^jfrog/"
- "^rancher/" - "^rancher/"
- "^rspamd/rspamd" - "^rspamd/rspamd"
- "^tozd/postfix"
- "^traefik/" - "^traefik/"
- "^ubi9/ubi-minimal" - "^ubi9/ubi-minimal"
- "^victoriametrics/" - "^victoriametrics/"
@@ -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 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
metadata: metadata:
name: postfix-smtp-tls name: postfix-smtp-tls
namespace: postfix namespace: mailgateway
spec: spec:
secretName: postfix-smtp-tls secretName: postfix-smtp-tls
issuerRef: issuerRef:
@@ -11,7 +11,7 @@ metadata:
external-dns.alpha.kubernetes.io/hostname: rspamd.k8s.syd1.au.unkin.net external-dns.alpha.kubernetes.io/hostname: rspamd.k8s.syd1.au.unkin.net
external-dns.alpha.kubernetes.io/target: 198.18.200.4 external-dns.alpha.kubernetes.io/target: 198.18.200.4
name: rspamd name: rspamd
namespace: postfix namespace: mailgateway
spec: spec:
gatewayClassName: traefik-internal gatewayClassName: traefik-internal
listeners: listeners:
@@ -3,11 +3,11 @@ apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute kind: HTTPRoute
metadata: metadata:
name: rspamd name: rspamd
namespace: postfix namespace: mailgateway
spec: spec:
parentRefs: parentRefs:
- name: rspamd - name: rspamd
namespace: postfix namespace: mailgateway
hostnames: hostnames:
- rspamd.k8s.syd1.au.unkin.net - rspamd.k8s.syd1.au.unkin.net
rules: rules:
@@ -18,11 +18,8 @@ resources:
configMapGenerator: configMapGenerator:
- name: postfix-config - name: postfix-config
files: files:
- resources/postfix/custom.cf - main.cf=resources/postfix/main.cf
options: - master.cf=resources/postfix/master.cf
disableNameSuffixHash: true
- name: postfix-transport
files:
- transport=resources/postfix/transport - transport=resources/postfix/transport
options: options:
disableNameSuffixHash: true disableNameSuffixHash: true
@@ -2,4 +2,4 @@
apiVersion: v1 apiVersion: v1
kind: Namespace kind: Namespace
metadata: metadata:
name: postfix name: mailgateway
@@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: postfix name: postfix
namespace: postfix namespace: mailgateway
spec: spec:
selector: selector:
matchLabels: matchLabels:
@@ -17,7 +17,7 @@ spec:
spec: spec:
containers: containers:
- name: postfix - name: postfix
image: boky/postfix:3.9.1 image: tozd/postfix:alpine-322
ports: ports:
- containerPort: 25 - containerPort: 25
name: smtp name: smtp
@@ -26,26 +26,15 @@ spec:
name: submission name: submission
protocol: TCP protocol: TCP
env: 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" value: "mail.main.unkin.net"
- name: MYORIGIN - name: MY_NETWORKS
value: "main.unkin.net"
- name: MYNETWORKS
value: "127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16" 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 - name: MY_DESTINATION
value: "main.unkin.net unkin.net" value: "localhost.localdomain, localhost"
- name: POSTFIX_myhostname - name: LOG_TO_STDOUT
value: "mail.main.unkin.net" value: "1"
- 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"
livenessProbe: livenessProbe:
tcpSocket: tcpSocket:
port: 25 port: 25
@@ -68,23 +57,29 @@ spec:
cpu: "1" cpu: "1"
memory: 512Mi memory: 512Mi
volumeMounts: 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 - name: postfix-config
mountPath: /etc/postfix/custom.d
readOnly: true
- name: postfix-transport
mountPath: /etc/postfix/transport mountPath: /etc/postfix/transport
subPath: transport subPath: transport
readOnly: true # TLS cert from cert-manager Certificate resource
- name: postfix-tls - name: postfix-tls
mountPath: /etc/postfix/tls mountPath: /etc/postfix/tls
readOnly: true readOnly: true
# Persistent mail queue
- name: spool
mountPath: /var/spool/postfix
volumes: volumes:
- name: postfix-config - name: postfix-config
configMap: configMap:
name: postfix-config name: postfix-config
- name: postfix-transport
configMap:
name: postfix-transport
- name: postfix-tls - name: postfix-tls
secret: secret:
secretName: postfix-smtp-tls secretName: postfix-smtp-tls
- name: spool
emptyDir: {}
@@ -3,7 +3,7 @@ apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler kind: HorizontalPodAutoscaler
metadata: metadata:
name: postfix-hpa name: postfix-hpa
namespace: postfix namespace: mailgateway
spec: spec:
scaleTargetRef: scaleTargetRef:
apiVersion: apps/v1 apiVersion: apps/v1
@@ -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
@@ -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
@@ -3,7 +3,7 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: rspamd name: rspamd
namespace: postfix namespace: mailgateway
spec: spec:
selector: selector:
matchLabels: matchLabels:
@@ -3,7 +3,7 @@ apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler kind: HorizontalPodAutoscaler
metadata: metadata:
name: rspamd-hpa name: rspamd-hpa
namespace: postfix namespace: mailgateway
spec: spec:
scaleTargetRef: scaleTargetRef:
apiVersion: apps/v1 apiVersion: apps/v1
@@ -4,7 +4,7 @@ apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: rspamd name: rspamd
namespace: postfix namespace: mailgateway
spec: spec:
selector: selector:
app: rspamd app: rspamd
@@ -27,7 +27,7 @@ apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: postfix name: postfix
namespace: postfix namespace: mailgateway
spec: spec:
selector: selector:
app: postfix app: postfix
@@ -46,7 +46,7 @@ apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: postfix-external name: postfix-external
namespace: postfix namespace: mailgateway
annotations: annotations:
external-dns.alpha.kubernetes.io/hostname: smtp-in.main.unkin.net external-dns.alpha.kubernetes.io/hostname: smtp-in.main.unkin.net
spec: spec:
@@ -3,10 +3,10 @@ apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth kind: VaultAuth
metadata: metadata:
name: default name: default
namespace: postfix namespace: mailgateway
spec: spec:
allowedNamespaces: allowedNamespaces:
- postfix - mailgateway
kubernetes: kubernetes:
audiences: audiences:
- vault - vault
@@ -3,7 +3,7 @@ apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret kind: VaultStaticSecret
metadata: metadata:
name: dkim-keys name: dkim-keys
namespace: postfix namespace: mailgateway
spec: spec:
destination: destination:
create: true create: true
@@ -11,7 +11,7 @@ spec:
overwrite: true overwrite: true
hmacSecretData: true hmacSecretData: true
mount: kv mount: kv
path: kubernetes/namespace/postfix/default/dkim-keys path: kubernetes/namespace/mailgateway/default/dkim-keys
refreshAfter: 5m refreshAfter: 5m
type: kv-v2 type: kv-v2
vaultAuthRef: default vaultAuthRef: default
@@ -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
@@ -3,4 +3,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- ../../../base/postfix - ../../../base/mailgateway
+1 -1
View File
@@ -21,7 +21,7 @@ spec:
- path: apps/overlays/*/inteldeviceplugins-system - path: apps/overlays/*/inteldeviceplugins-system
- path: apps/overlays/*/jfrog - path: apps/overlays/*/jfrog
- path: apps/overlays/*/node-feature-discovery - path: apps/overlays/*/node-feature-discovery
- path: apps/overlays/*/postfix - path: apps/overlays/*/mailgateway
- path: apps/overlays/*/puppet - path: apps/overlays/*/puppet
- path: apps/overlays/*/purelb - path: apps/overlays/*/purelb
- path: apps/overlays/*/reflector-system - path: apps/overlays/*/reflector-system