Last modification on
I had been using Fastmail, but 8,400 KRW/month (~6 USD) felt unsustainable for email, so I decided to self-host it on my home server, alpha (AMD Athlon 3000G, 8GB RAM).
My requirements were (a) no exposed ports except WireGuard, (b) full IMAP/SMTP access from anywhere, (c) bypass Gmail's spam filter, and (d) no recurring costs like VPS rentals.
Inbound setup with CF email routing, http2lmtp, and dovecot
To receive mail directly from other servers, port 25 needs to be open, which violates (a). So I used CF email routing instead. It can be configured to route mail to a CF Worker, which POSTs the mail to a specific endpoint. Using cloudflared, I can expose an HTTP endpoint proxied by Cloudflare without opening any ports.
For this, I built http2lmtp in Rust. It receives mail POSTed to the HTTP endpoint and writes it to an internal Unix socket with LMTP. Since the endpoint is public, it requires a bearer token. You can find CF worker example interacting with it on its README.
In my setup, the Unix socket for LMTP is opened by Dovecot. It stores the mail it receives over LMTP in a local Maildir, and serves that Maildir over IMAP.
Outbound setup with smtp2go and OpenSMTPD
To satisfy (c), alpha's public IP needs a reverse DNS record, but that requires permissions from the ISP that owns the IP range — impossible with a residential connection. So instead, I decided to use smtp2go's free tier. It allows up to 1,000 sends per month.
Entering smtp2go's credentials on both my iPhone and laptop is a hassle, though. So instead I run OpenSMTPD on alpha for routing. It only listens on wg0 for submission, so it needs no auth or TLS. /etc/smtpd.conf:
table secrets file:/etc/smtpd/secrets
table vusers file:/etc/smtpd/virtuals
listen on lo
listen on wg0 port 587
# rcpt-to: use To: as dovecot user name ([email protected])
action "local" lmtp "/var/run/dovecot/lmtp" rcpt-to virtual <vusers>
action "out" relay host smtp+tls://[email protected]:2525 \
auth <secrets> helo "dilluti0n.com"
action "out-local" relay host smtp+tls://[email protected]:2525 \
auth <secrets> helo "dilluti0n.com" \
mail-from "[email protected]"
match from any for rcpt-to "[email protected]" action "local"
match from local for any action "out-local"
match from src 10.42.0.0/24 for any action "out"
The benefit from OpenSMTPD is that you can route emails like firewall rules. If an email generated locally is sent to [email protected], it is not sent to [email protected], but directly to the local Dovecot via LMTP.
Also, by using it, no need to make changes on the client-side when changing the SMTP routing service or sending it directly via alpha.
Client-side configuration
On both my laptop and my iPhone, alpha is reachable as 10.42.0.1 through WireGuard. Since both SMTP and IMAP are configured on standard ports, no special settings are required other than the IP address. For IMAP auth, account ID/password set in dovecot is needed.
A warning message appears on the iPhone IMAP setting stating that TLS cannot be used, but it is not necessary since communication is done via WireGuard anyway.
Conclusion
Here is ascii art for the structure:
sender MTA
|
v DNS MX
CF Email Routing
|
v CF Worker: POST
CF tunnel (cloudflared)
|
v HTTP (localhost)
http2lmtp
|
v LMTP
Dovecot <----> Maildir
^ |
| v IMAP (wg0:993)
| LMTP MUA
OpenSMTPD
^ |
| +--> smtp2go --> Internet
|
| SMTP (wg0:587)
MUA
Pros
- No cost if you already have homeserver
- No ports exposed
- No need to change client-side configurations when changing cloud backends (smtp2go, cloudflare, ...)
Cons
- All incoming emails are routed through Cloudflare. If an email arrives using TLS over SMTP, CF terminates the TLS connection early.
- DKIM signature is generated by smtp2go. (As well as SPF)
-
Custom headers like
X-Report-Abuseare added by smtp2go.
See also
- Reasons Not to Use Cloudflare - I'm kind of a fan of CF, but I think it's only fair to share this side of the story too. Either way, they offer a lot of free services, and I'm pretty broke.
- Personal mail server on OpenBSD - This is non-cloud version for my setup.
Thank you for reading! Please mail me at [email protected] for a comment.
Copyright 2026 Hee-Suk Kim