DNS & domains
Four DNS records (plus DKIM) make your domain a working mail domain. Get these right and most deliverability problems never happen.
The records
Replace yourdomain.com with yours and 203.0.113.10 with your server's public IP.
| Record | Name | Value |
|---|---|---|
| MX | @ | 10 mail.yourdomain.com. |
| A | mail | 203.0.113.10 |
| TXT (SPF) | @ | v=spf1 mx ~all |
| TXT (DKIM) | mail._domainkey | the record from docker compose logs mta (see below) |
| TXT (DMARC) | _dmarc | v=DMARC1; p=none; rua=mailto:postmaster@yourdomain.com |
The mail A record must be DNS-only (grey cloud). Cloudflare's proxy doesn't handle SMTP — proxied mail records break receiving entirely. Your website can stay behind the proxy; the mail hostname must not.
DKIM
On first boot the MTA generates a DKIM signing key and prints the DNS record to its logs:
docker compose logs mta | sed -n '/== DKIM DNS/,/== end DKIM DNS/p'
Paste the whole thing as a TXT record at mail._domainkey.yourdomain.com. The key itself lives in the mail_dkim Docker volume — back it up with everything else, because rotating it means updating DNS.
DMARC policy
Start at p=none (monitoring only). Watch the aggregate reports arriving at postmaster@ for a week or two of real traffic, then move to quarantine, then reject. Jumping straight to reject is how legitimate mail silently disappears while you're still misconfigured.
Reverse DNS (PTR)
Ask whoever owns your IP (VPS panel, ISP) to set a PTR record pointing at mail.yourdomain.com. Gmail and friends weigh this heavily — without it, expect the spam folder. On a residential connection you usually can't set this, which is one more reason home servers should relay outbound (see Sending: direct or relayed).
Dynamic DNS for home IPs
BearerMail addition
If your server sits behind a residential connection, your public IP changes — and your MX/A records have to follow it. BearerMail includes a Cloudflare dynamic-DNS updater: give it a Cloudflare API token and the zone, and it keeps your mail A record pointed at your current IP.
# Cloudflare API token with DNS:Edit on your zone, then:
export CF_API_TOKEN="your-token"
export CF_ZONE="yourdomain.com"
export CF_RECORD="mail"
docker compose --profile mail up -d
The updater runs alongside the stack and refreshes the record on a schedule. Pair this with an outbound relay (Mailjet etc.) and a home connection becomes a workable mail server: inbound finds you via the updated A record, outbound deliverability rides on the relay's reputation instead of your residential IP's.
Port 25 inbound reachable (test: telnet mail.yourdomain.com 25 from outside) · A record on DNS-only, kept current by the DDNS updater · outbound via relay, not direct · SPF/DKIM/DMARC published. Miss any one of these and something subtle breaks.