Blog
Self-Hosting Email? The Postfix Reality Check
Every April someone (including me) stumbles on a "build a full mail server with Docker in five minutes" tutorial and their fingers drift toward docker compose up. This post is the bucket of cold water before you click: I'd talk you out of self-hosting a full send-and-receive mailbox in a homelab. If you have a specific need, keep reading for workable alternatives; if your goal is just "one more service in the lab," email is the worst fun-to-pain ratio of the bunch.
Why "Postfix is up" doesn't mean you can send mail
Getting an MTA running is the easy part. Getting Gmail, Outlook, and corporate mail servers to reliably accept your messages is a different business — and their rules keep changing while your home connection doesn't get any cleaner.
IP reputation. Home broadband exits almost always sit in dynamic pools, and a lot of those ranges are blocked outright or spam-foldered. Cheap VPS subnets from mainstream clouds are just as "dirty": the previous tenant spammed, and you inherit the blacklist. A clean IP is either expensive or takes a long time to age — and during that aging period your friends have already complained twice about "verification codes not arriving."
The DNS package. SPF, DKIM, DMARC, and PTR (reverse DNS) are all mandatory; PTR often requires a support ticket to change. Getting them right is only the entry ticket — then you get to live with the queue's defers, bounces, and complaint feedback loops. The day your DMARC report shows a pile of failures, you need to be prepared to actually read those reports, not screenshot the green checkmarks.
Appeals and bans. One morning everything lands in spam, and you go plead "it's just a homelab" with Spamhaus and a dozen ISP tickets. That burns calendar time and feelings, not CPU time. Tutorials skip this part because it makes them less pretty.
Availability expectations. Email is asynchronous, but bills, verification codes, password resets, and reunion invites all ride on it. Lab host reboots, disk alerts, expired certs — your friends just know your domain "can't receive mail," they don't care that you were upgrading OpenWrt.
Running an MTA is easy; getting other mail servers to want your mail is hard. The gap between the two isn't a config line — it's reputation and an ops commitment. Most homelab services can "break and get fixed tomorrow"; once email becomes family's or friends' primary contact, you're running quasi-production communications SLA on spare time, and that trade is usually not worth it.
Common delusions
- "My SPF and DKIM are all green, so I'm fine" — green is syntax, not reputation.
- "A residential IP looks more legit" — many ISPs block outbound port 25 outright, turning "legit" into "can't send."
- "I'm only using it for myself" — your own phone vendors' push and Git platforms still bind to your email; hitting spam hurts there too.
- "The Docker image configured everything for me" — the image doesn't own your IP's history or their policy changes.
- "If it breaks I'll just reinstall" — email loses trust and timeliness, not a container layer.
Workable alternatives (in my order of preference)
One: hand primary communications to mature hosting. For personal or family use: Fastmail, Purelymail, Migadu, or a big-name domain mailbox. Money buys deliverability and an already-aged outbound pool. Save your "self-host" energy for the data services you actually care about: photos, backups, password vaults, code. Email depends so heavily on the other side's policy that outsourcing is usually the rational call.
Two: transactional mail and alerts go out through external SMTP. Prometheus Alertmanager, panel notifications, app registration emails: use SES, Resend, Mailgun, or the SMTP your host provides. Put the hostname in the subject, keep credentials in the secret store, and decouple outbound from home broadband. That way the "disk is about to die" notice doesn't depend on your own wobbly mail stack.
# Alertmanager sketch: don't point SMTP at your own Postfix
global:
smtp_smarthost: 'smtp.example-provider:587'
smtp_from: '[email protected]'
smtp_auth_username: '...'
smtp_auth_password: '...'
Three: if you insist on self-hosting, make it an internal-only relay (optional). Let your Postfix listen on the LAN or VPN only and forward outbound to the external SMTP above (smart host). Local services can still write to localhost:25, and the actual outbound reputation never binds to home broadband. That's no longer a "full mailbox" — it's a relay, with a much smaller complexity and risk profile.
Four: the minimum bar if you truly must self-host the full thing. A clean dedicated IP, full PTR with SPF/DKIM/DMARC, matching forward and reverse lookups, feedback loops and queue monitoring, outbound rate cooling, and a separate abuse-complaint process. Send test mail to Gmail and Outlook twice a week for two weeks and watch placement before inviting any real human to use it. Most people switch back to hosted by week two — that's not failure, it's rational convergence once the information lands.
When I wouldn't talk you out of it
- You work on or research email, and the lab is the experiment itself — failure is acceptable.
- Your company already has a clean ASN and dedicated anti-abuse staff, and you're one part of it.
- Receive-only, and all receivers are systems you control (you still need to design what happens when delivery fails).
If none of those apply, spending your life fighting blacklists usually isn't worth it. The boundary sense of self-hosting is sometimes worth more than one more container. Knowing when to tap out is engineering maturity: not every service deserves a spot in the rack.
My own landing spot is pragmatic: hosted mail for the public identity address; external SMTP for lab alerts and system notifications; and at most a smart-host relay if the LAN needs local delivery. That keeps a bit of "I control the path" feel without re-aging a reputation after every ISP move. If you read all this and still want full self-hosting, at least treat the minimum bar above as a go-live checklist, not an easter egg at the end of a tutorial.