Add rspamd, ClamAV and sentinel Valkey to the mail namespace #542

Merged
benvin merged 3 commits from benvin/mail-rspamd into main 2026-10-12 22:36:55 +11:00
Member

The smarthost routes all mail through one rspamd: inbound that survived the edge gets the AI (LiteLLM Haiku) pass and is tagged for Stalwart's Junk filing; outbound from the lab and pods is DKIM-signed.

  • add rspamd (milter via ClusterIP only), ClamAV and a 3-node sentinel Valkey
  • tag inbound (X-Spam, X-Spam-Status, X-Spamd-Result), reject only viruses, tempfail when ClamAV fails
  • score inbound against the hop before the edge relays (external_relay)
  • DKIM-sign and skip GPT only for the smarthost's mynetworks sources
  • elect the highest-offset Valkey on full restart; RDB, 384mb volatile-ttl
  • read a hashed controller password (password_hash)

Requires password_hash in kv mail/default/rspamd-controller.

The smarthost routes all mail through one rspamd: inbound that survived the edge gets the AI (LiteLLM Haiku) pass and is tagged for Stalwart's Junk filing; outbound from the lab and pods is DKIM-signed. - add rspamd (milter via ClusterIP only), ClamAV and a 3-node sentinel Valkey - tag inbound (`X-Spam`, `X-Spam-Status`, `X-Spamd-Result`), reject only viruses, tempfail when ClamAV fails - score inbound against the hop before the edge relays (`external_relay`) - DKIM-sign and skip GPT only for the smarthost's mynetworks sources - elect the highest-offset Valkey on full restart; RDB, 384mb `volatile-ttl` - read a hashed controller password (`password_hash`) Requires `password_hash` in kv `mail/default/rspamd-controller`.
unkin-agent added 1 commit 2026-10-12 21:47:51 +11:00
Add rspamd, ClamAV and sentinel Valkey to the mail namespace
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
f627902dd6
Author
Member
  • apps/base/mail/rspamd/options.inc:2 — local_addrs includes all of 198.18.0.0/16; with sign_local = true any inbound mail whose connecting IP is in that range (DMZ gateways over WireGuard if the milter client IP is not forwarded) is DKIM-signed for a spoofed From: unkin.net and skips the gpt module → narrow to the smarthost/Stalwart source ranges only, or confirm the gateways forward the real client IP.
  • nit: apps/base/mail/rspamd-valkey/start.sh:19 — any boot where no peer sentinel answers makes pod 0 master on its own PVC; after a full restart that can be a stale master that overwrites newer bayes data on the others → seed only when /data is empty, otherwise retry peers before falling back.
  • nit: apps/base/mail/rspamd-valkey.yaml:51 — no --maxmemory against a 512Mi limit (AOF rewrite forks) → OOMKill instead of bounded memory; set --maxmemory ~384mb in start.sh.
  • nit: apps/base/mail/rspamd/worker-controller.inc:1 — plaintext password reused for enable_password → store rspamadm pw hashes in Vault.
  • nit: apps/base/mail/rspamd/antivirus.conf — no force_actions on CLAM_VIRUS_FAIL, so mail passes unscanned when clamd is down → add a soft-reject rule.
- apps/base/mail/rspamd/options.inc:2 — `local_addrs` includes all of `198.18.0.0/16`; with `sign_local = true` any inbound mail whose connecting IP is in that range (DMZ gateways over WireGuard if the milter client IP is not forwarded) is DKIM-signed for a spoofed `From: unkin.net` and skips the gpt module → narrow to the smarthost/Stalwart source ranges only, or confirm the gateways forward the real client IP. - nit: apps/base/mail/rspamd-valkey/start.sh:19 — any boot where no peer sentinel answers makes pod 0 master on its own PVC; after a full restart that can be a stale master that overwrites newer bayes data on the others → seed only when `/data` is empty, otherwise retry peers before falling back. - nit: apps/base/mail/rspamd-valkey.yaml:51 — no `--maxmemory` against a 512Mi limit (AOF rewrite forks) → OOMKill instead of bounded memory; set `--maxmemory` ~384mb in start.sh. - nit: apps/base/mail/rspamd/worker-controller.inc:1 — plaintext password reused for `enable_password` → store `rspamadm pw` hashes in Vault. - nit: apps/base/mail/rspamd/antivirus.conf — no `force_actions` on `CLAM_VIRUS_FAIL`, so mail passes unscanned when clamd is down → add a soft-reject rule.
unkin-agent added 1 commit 2026-10-12 22:15:01 +11:00
Scan inbound and outbound via the smarthost only, harden rspamd and Valkey
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
ecede40f7f
- tag inbound instead of rejecting, keep virus reject and tempfail when ClamAV fails
- score inbound against the first hop before the edge relays
- sign and skip GPT only for smarthost mynetworks sources
- elect the highest-offset Valkey on full restart, cap memory at 384mb
- read a hashed controller password
Author
Member

No findings.

No findings.
unkin-agent added 1 commit 2026-10-12 22:33:07 +11:00
Merge remote-tracking branch 'origin/main' into benvin/mail-rspamd
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
3265fa0703
# Conflicts:
#	apps/base/mail/kustomization.yaml
benvin merged commit 0ee11a065b into main 2026-10-12 22:36:55 +11:00
benvin deleted branch benvin/mail-rspamd 2026-10-12 22:36:55 +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#542