Add postfix smarthost to the mail namespace #541

Merged
benvin merged 8 commits from benvin/mail-smarthost into main 2026-10-12 22:30:47 +11:00
Member

Mail needs one routing hub between the edge gateways, Stalwart and the lab: inbound to Stalwart over LMTP, outbound to the gateways, all of it through rspamd.

  • add a 2-replica postfix StatefulSet mail-in.main.unkin.net (50Gi spool per pod, node spread, PDB)
  • serve port 25 with the LE *.main.unkin.net wildcard, reflected into mail
  • gateways (TLS, XFORWARD) relay to relay_domains with LMTP recipient verification; lab and pods relay anywhere
  • pass all mail through the rspamd milter, tempfailing when it is down
  • limit port 25 via NetworkPolicy to gateways, lab and mail.unkin.net/smarthost-client=true pods
  • relay outbound via mta1/mta2.edge.unkin.net with verified TLS; add ClusterIP + LB 198.18.200.16

Requires #539 merged.

Mail needs one routing hub between the edge gateways, Stalwart and the lab: inbound to Stalwart over LMTP, outbound to the gateways, all of it through rspamd. - add a 2-replica postfix StatefulSet `mail-in.main.unkin.net` (50Gi spool per pod, node spread, PDB) - serve port 25 with the LE `*.main.unkin.net` wildcard, reflected into `mail` - gateways (TLS, XFORWARD) relay to relay_domains with LMTP recipient verification; lab and pods relay anywhere - pass all mail through the rspamd milter, tempfailing when it is down - limit port 25 via NetworkPolicy to gateways, lab and `mail.unkin.net/smarthost-client=true` pods - relay outbound via mta1/mta2.edge.unkin.net with verified TLS; add ClusterIP + LB 198.18.200.16 Requires #539 merged.
unkin-agent added 1 commit 2026-10-12 21:33:47 +11:00
Add postfix smarthost to the mail namespace
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
7501dbca7d
Author
Member
  • nit: apps/base/mail/smarthost/main.cf:27 — reject_unverified_recipient caches a 550 for address_verify_negative_refresh_time (default 3h), so a mailbox created in Stalwart bounces inbound mail from the gateways for up to 3h, and a transient Stalwart 5xx is cached the same way → set address_verify_negative_refresh_time to a few minutes.
  • nit: apps/base/mail/smarthost/main.cf:13 — pod_networks is the whole cluster pod CIDR (comment says Stalwart), so any pod in any namespace can relay anywhere unauthenticated on 25 and 587 → restrict ingress to the Stalwart pods with a NetworkPolicy, or accept and say so in the comment.
- nit: apps/base/mail/smarthost/main.cf:27 — reject_unverified_recipient caches a 550 for address_verify_negative_refresh_time (default 3h), so a mailbox created in Stalwart bounces inbound mail from the gateways for up to 3h, and a transient Stalwart 5xx is cached the same way → set address_verify_negative_refresh_time to a few minutes. - nit: apps/base/mail/smarthost/main.cf:13 — pod_networks is the whole cluster pod CIDR (comment says Stalwart), so any pod in any namespace can relay anywhere unauthenticated on 25 and 587 → restrict ingress to the Stalwart pods with a NetworkPolicy, or accept and say so in the comment.
unkin-agent added 1 commit 2026-10-12 21:42:30 +11:00
Restrict smarthost ingress and shorten negative recipient cache
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
92f6c1472b
unkin-agent added 1 commit 2026-10-12 21:46:35 +11:00
Serve all smarthost clients on port 25, rename gateways to mta1/mta2, grow spool to 50Gi
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
8105ba11f4
unkin-agent added 1 commit 2026-10-12 21:48:12 +11:00
Relay outbound via mta1/mta2.edge.unkin.net
ci/woodpecker/pr/kubeconform Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline was successful
a27023c7c9
unkin-agent added 1 commit 2026-10-12 21:52:57 +11:00
Require TLS between smarthost and gateways over public IPs, merge mynetworks and milter map
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
4f6150e93a
Author
Member
  • apps/base/mail/smarthost/main.cf:12 — relay_domains is in the default parent_domain_matches_subdomains, so x@sub.unkin.net passes reject_unauth_destination from a gateway, but transport only matches unkin.net exactly. The recipient is then routed and address-verified via relayhost (mta1/mta2, i.e. back to the gateway), giving a mail loop → set parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,mynetworks,permit_mx_backup_networks,qmqpd_authorized_clients,smtpd_access_maps (drop relay_domains), or add .unkin.net to relay_domains+transport if subdomains are meant to be delivered.
  • nit: apps/base/mail/smarthost/main.cf:25 — default address_verify_positive_refresh_time is 7d, so deleted Stalwart mailboxes keep being accepted from gateways for up to a week → set it to ~1h.
- apps/base/mail/smarthost/main.cf:12 — `relay_domains` is in the default `parent_domain_matches_subdomains`, so `x@sub.unkin.net` passes `reject_unauth_destination` from a gateway, but `transport` only matches `unkin.net` exactly. The recipient is then routed and address-verified via `relayhost` (mta1/mta2, i.e. back to the gateway), giving a mail loop → set `parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,mynetworks,permit_mx_backup_networks,qmqpd_authorized_clients,smtpd_access_maps` (drop `relay_domains`), or add `.unkin.net` to `relay_domains`+`transport` if subdomains are meant to be delivered. - nit: apps/base/mail/smarthost/main.cf:25 — default `address_verify_positive_refresh_time` is 7d, so deleted Stalwart mailboxes keep being accepted from gateways for up to a week → set it to ~1h.
unkin-agent added 1 commit 2026-10-12 22:01:10 +11:00
Stop relay_domains matching subdomains, refresh positive verify cache hourly
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
d19c7d7942
unkin-agent added 1 commit 2026-10-12 22:05:52 +11:00
Route gateway mail through the rspamd milter, accept XFORWARD from gateways
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
926967b298
unkin-agent added 1 commit 2026-10-12 22:15:14 +11:00
Name the smarthost mail-in.main.unkin.net and serve the *.main.unkin.net wildcard
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
3019291e5c
Author
Member
  • apps/base/mail/smarthost/gateways.cidr:2-3 — RHS reject_plaintext_session, permit is a comma list; Postfix access-map RHS takes one action or a restriction class, so check_client_access will log "unknown restriction" and 451 every gateway connection → declare smtpd_restriction_classes = gateway_tls with gateway_tls = reject_plaintext_session, permit and use gateway_tls as the RHS (also in the smtpd_authorized_xforward_hosts lookup, where any hit already matches).
- apps/base/mail/smarthost/gateways.cidr:2-3 — RHS `reject_plaintext_session, permit` is a comma list; Postfix access-map RHS takes one action or a restriction class, so check_client_access will log "unknown restriction" and 451 every gateway connection → declare `smtpd_restriction_classes = gateway_tls` with `gateway_tls = reject_plaintext_session, permit` and use `gateway_tls` as the RHS (also in the `smtpd_authorized_xforward_hosts` lookup, where any hit already matches).
benvin merged commit 70dd1bd775 into main 2026-10-12 22:30:47 +11:00
benvin deleted branch benvin/mail-smarthost 2026-10-12 22:30:47 +11:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unkin/argocd-apps#541