From 822d50b07d31055b3f384cedffa182a6a3abd05b Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Tue, 13 Oct 2026 21:32:11 +1100 Subject: [PATCH 1/3] Allow BinaryLane DMZ VPCs in resolver ACL (#545) The mail edge VMs in the BinaryLane DMZ VPCs query the internal resolvers over the VPN, but the resolver match-clients ACLs do not include their ranges. - add 198.18.30.0/24 (syd) and 198.18.31.0/24 (mel) to `acl-dmz` Reviewed-on: https://git.unkin.net/unkin/argocd-apps/pulls/545 Co-authored-by: unkin-agent Co-committed-by: unkin-agent --- apps/base/bind-internal/resolvers/acls.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/base/bind-internal/resolvers/acls.yaml b/apps/base/bind-internal/resolvers/acls.yaml index 05a7f4f..f3f935f 100644 --- a/apps/base/bind-internal/resolvers/acls.yaml +++ b/apps/base/bind-internal/resolvers/acls.yaml @@ -38,6 +38,8 @@ spec: clusterRef: bind-resolvers entries: - 198.18.24.0/24 + - 198.18.30.0/24 # BinaryLane DMZ VPC syd (mail edge, via VPN) + - 198.18.31.0/24 # BinaryLane DMZ VPC mel (mail edge, via VPN) --- apiVersion: bind.unkin.net/v1alpha1 kind: BindACL From bb45b20f8a8b815d455dcfa2c56e8667fd25c12e Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Tue, 13 Oct 2026 21:43:13 +1100 Subject: [PATCH 2/3] Route rspamd-tagged mail to Junk through Stalwart's spam filter (#544) Stalwart only files mail into Junk natively when its own spam filter marks it, so rspamd-tagged mail reached Junk only for accounts with a Sieve script, and first boot loads upstream DNSBLs, HTTP lists and URL lookups. - enable the spam filter with one header rule scoring `X-Spam: Yes` above the spam threshold, covering every account including newly provisioned ones - remove the upstream spam rules, tags, DNSBL servers, HTTP lists and lookup keys - disable the classifier model and Pyzor Reviewed-on: https://git.unkin.net/unkin/argocd-apps/pulls/544 Co-authored-by: unkin-agent Co-committed-by: unkin-agent --- apps/base/mail/stalwart-configmap.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/base/mail/stalwart-configmap.yaml b/apps/base/mail/stalwart-configmap.yaml index cf485e4..437f83a 100644 --- a/apps/base/mail/stalwart-configmap.yaml +++ b/apps/base/mail/stalwart-configmap.yaml @@ -1,6 +1,7 @@ --- # config.json only names the datastore; everything else lives in Postgres and # is converged from plan.ndjson by the stalwart-apply PostSync Job. +# The spam filter only scores rspamd's X-Spam header, feeding the native Junk path. # The Coordinator uses the plain Redis client: its cluster client never # resubscribes once the Valkey node it subscribed on is replaced. apiVersion: v1 @@ -29,7 +30,14 @@ data: {"@type":"update","object":"MtaOutboundStrategy","value":{"route":{"match":{"0":{"if":"is_local_domain(rcpt_domain)","then":"'local'"}},"else":"'smarthost'"}}} {"@type":"update","object":"MtaStageAuth","value":{"require":{"match":{},"else":"local_port != 25 && local_port != 24"}}} {"@type":"update","object":"SenderAuth","value":{"dkimSignDomain":{"match":{},"else":"false"}}} - {"@type":"update","object":"SpamSettings","value":{"enable":false,"spamFilterRulesUrl":null}} + {"@type":"reconcile","object":"SpamRule","matchOn":["name"],"value":{"rspamd":{"@type":"Header","name":"RSPAMD_SPAM","enable":true,"priority":0,"condition":{"match":{"0":{"if":"name_lower == 'x-spam' && value_lower == 'yes'","then":"'RSPAMD_SPAM'"}},"else":"false"}}}} + {"@type":"reconcile","object":"SpamTag","matchOn":["tag"],"value":{"rspamd":{"@type":"Score","tag":"RSPAMD_SPAM","score":10.0}}} + {"@type":"destroy","object":"SpamDnsblServer"} + {"@type":"destroy","object":"HttpLookup"} + {"@type":"destroy","object":"MemoryLookupKey"} + {"@type":"update","object":"SpamClassifier","value":{"model":{"@type":"Disabled"}}} + {"@type":"update","object":"SpamPyzor","value":{"enable":false}} + {"@type":"update","object":"SpamSettings","value":{"enable":true,"spamFilterRulesUrl":null}} {"@type":"update","object":"Metrics","value":{"prometheus":{"@type":"Enabled","authSecret":{"@type":"None"}}}} {"@type":"update","object":"Http","value":{"allowedEndpoints":{"match":{"0":{"if":"starts_with(path, '/metrics') && local_port != 9090","then":"404"}},"else":"200"}}} {"@type":"update","object":"SystemSettings","value":{"defaultHostname":"mail.unkin.net","defaultDomainId":"#unkin","defaultCertificateId":"#cert"}} From 49a98aa4283d4ed37d28bc11517b18e512cf2a78 Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Tue, 13 Oct 2026 21:43:43 +1100 Subject: [PATCH 3/3] Add main.unkin.net as a second mail domain (#550) main.unkin.net is the test mail domain: it receives into the existing unkin.net mailboxes, and its outbound mail is DKIM-signed as d=unkin.net, which aligns under relaxed DMARC. - relay main.unkin.net on the smarthost and route it to Stalwart over LMTP - add main.unkin.net as a domain alias of unkin.net in Stalwart Reviewed-on: https://git.unkin.net/unkin/argocd-apps/pulls/550 Co-authored-by: unkin-agent Co-committed-by: unkin-agent --- apps/base/mail/smarthost/relay_domains | 1 + apps/base/mail/smarthost/transport | 1 + apps/base/mail/stalwart-configmap.yaml | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/base/mail/smarthost/relay_domains b/apps/base/mail/smarthost/relay_domains index 59818b2..856ab55 100644 --- a/apps/base/mail/smarthost/relay_domains +++ b/apps/base/mail/smarthost/relay_domains @@ -1 +1,2 @@ unkin.net OK +main.unkin.net OK diff --git a/apps/base/mail/smarthost/transport b/apps/base/mail/smarthost/transport index 828306f..73a02db 100644 --- a/apps/base/mail/smarthost/transport +++ b/apps/base/mail/smarthost/transport @@ -1 +1,2 @@ unkin.net lmtp:[stalwart.mail.svc.cluster.local]:24 +main.unkin.net lmtp:[stalwart.mail.svc.cluster.local]:24 diff --git a/apps/base/mail/stalwart-configmap.yaml b/apps/base/mail/stalwart-configmap.yaml index 437f83a..b8da9c9 100644 --- a/apps/base/mail/stalwart-configmap.yaml +++ b/apps/base/mail/stalwart-configmap.yaml @@ -13,7 +13,7 @@ data: config.json: | {"@type":"PostgreSql","host":"stalwart-db-rw.mail.svc","port":5432,"database":"stalwart","authUsername":"stalwart","authSecret":{"@type":"EnvironmentVariable","variableName":"DB_PASSWORD"},"useTls":true} plan.ndjson: | - {"@type":"upsert","object":"Domain","matchOn":["name"],"value":{"unkin":{"name":"unkin.net","certificateManagement":{"@type":"Manual"},"dkimManagement":{"@type":"Manual"},"dnsManagement":{"@type":"Manual"},"subAddressing":{"@type":"Enabled"}}}} + {"@type":"upsert","object":"Domain","matchOn":["name"],"value":{"unkin":{"name":"unkin.net","aliases":{"main.unkin.net":true},"certificateManagement":{"@type":"Manual"},"dkimManagement":{"@type":"Manual"},"dnsManagement":{"@type":"Manual"},"subAddressing":{"@type":"Enabled"}}}} {"@type":"upsert","object":"Certificate","matchOn":["certificate"],"value":{"cert":{"certificate":{"@type":"File","filePath":"/etc/stalwart/tls/tls.crt"},"privateKey":{"@type":"File","filePath":"/etc/stalwart/tls/tls.key"}}}} {"@type":"upsert","object":"Directory","matchOn":["description"],"value":{"authentik":{"@type":"Oidc","description":"Authentik","issuerUrl":"https://identity.unkin.net/application/o/stalwart/","requireAudience":"stalwart","requireScopes":{},"claimUsername":"preferred_username","usernameDomain":"unkin.net","claimName":"name"}}} {"@type":"upsert","object":"Application","matchOn":["description"],"value":{"webui":{"description":"Stalwart Web Interface","resourceUrl":"https://github.com/stalwartlabs/webui/releases/download/v1.0.11/webui.zip","urlPrefix":{"/admin":true,"/account":true},"unpackDirectory":"/var/lib/stalwart/webui","oauthClientId":"stalwart"}}}