ADR-0006: Email into Matrix via Postmoogle, on the apex, over a Tailscale-wildcard zone¶
- Status: Accepted
- Date: 2026-07-14
Context¶
We wanted to receive email as Matrix messages (service mail, receipts, lists), complementing
ntfy (outbound push, ADR-0005) and Mailpit (outbound viewer). Postmoogle
(github.com/etkecc/postmoogle) is the fit: an SMTP server that posts incoming mail into rooms,
1 room = 1 mailbox, running as a plain Matrix bot (client-server API — no appservice
registration, so it works with continuwuity). See docs/runbooks/email-to-matrix.md.
Two questions had to be settled: which mail domain, and how DNS serves the MX given the existing split-horizon.
- Domain: the apex
fmm.housewas chosen over amail.subdomain — cleaner addresses (you@fmm.house). Tradeoff: the apex becomes a mail domain, foreclosing a hosted email provider onfmm.houselater. Switching providers is only a DNS cutover (addresses port), but apex mail is mutually exclusive with a real provider on the same name; a subdomain would have let both coexist. Accepted for a private homelab. - DNS: internal DNS uses AdGuard's DNS Rewrites UI (its "legacy" rewrite table),
which handles A/AAAA/CNAME only and short-circuits all other record types — so it can't
serve an MX, and a
$dnsrewriteMX is shadowed by the name's A rewrite. Converting the apex A onto$dnsrewritewas attempted and rolled back: it risks the root A record, which also feeds Traefik's apex→www redirect, for no real gain.
Decision¶
- Postmoogle on the apex.
POSTMOOGLE_DOMAINS="fmm.house mail.fmm.house", SMTP on host:25, admin@albert, SQLite, joinsmatrix_default. Mailboxes are claimed per-room in Element. - No internal MX. LAN senders rely on implicit MX — apex
A=.49(the AdGuard rewrite) is the mail target; a standard MTA falls back to it when no MX exists. Simple senders use an explicit smarthost. Internal AdGuard rewrites are left as-is. - Public zone → Tailscale wildcard. In porkbun,
*.fmm.houseand the apex point at av's Tailscale AAAA (replacing the per-service records and the apexALIAS → pixie.porkbun.compublic forward). A publicfmm.house MX 10 mail.fmm.houseroutes remote-tailnet mail. Traefik (reached over the tailnet) handles all HTTP routing, the apex→www redirect, and the wildcard cert.
Consequences¶
- All
*.fmm.houseis tailnet-only publicly — non-tailnet visitors get an unroutable Tailscale address. The public apex→www forward is dropped (Traefik does it over the tailnet). Reversible: re-add the apexALIASand per-service records in porkbun. - No public inbound mail — external senders resolve the MX to a non-routable Tailscale address and fail, by design. Remote tailnet devices deliver fine.
- The wildcard hides the service list publicly and exposes no new address (reuses the
Tailscale AAAA already published via
ha.fmm.house). - Bot password +
POSTMOOGLE_DATA_SECRET(stacks/postmoogle/.env) anddata/postmoogle.dbjoin the backup scope (docs/runbooks/monitoring.md). - DNS-01 wildcard cert issuance is unaffected (uses
_acme-challengeTXT, independent of A/AAAA).