Configuring a personal mail server with OpenSMTPD and MailRoute
It’s been less than a year since the first production release of OpenSMTPD, but I’d heard good things and wanted to give it a try. Like most OpenBSD projects the manpages are excellent, but like all young projects examples are thin on the ground.
I decided to try setting it up for my new home server: a tiny domU holding mail for just 4 accounts. All of my mail is relayed via MailRoute, and while it’s a normal smarthost setup I didn’t find any clear examples, so here’s mine in the hope that it might be of some benefit.
Goals:
- Only accept inbound mail if it is relayed through MailRoute.
- Relay all outbound mail through MailRoute, including mail generated locally on the machine (passively from scripts or actively with mutt).
- Allow clients to submit mail from any IP but only if they authenticate.
- Require encryption on all connections, inbound and outbound.
- Listen on a non-standard port. MailRoute lets you specify one, and as we’re only accepting mail from them this helps reduce load on an underpowered vm.
The following smtpd.conf
achieves this:
# Certificate conf
pki example.com certificate "/path/to/certs/example.crt"
pki example.com key "/path/to/private/example.key"
listen on eth0 port 45678 tls-require pki example.com auth-optional
listen on lo
# Aliases: remember to run "smtpctl update table aliases"
table aliases file:/etc/smtpd/aliases
# Deliver inbound mail from MailRoute
accept from source 199.89.0.0/21 \
for domain "example.com" alias <aliases> \
deliver to maildir
# Deliver local mail
accept from local \
for local alias <aliases> \
deliver to maildir
# Relay outbound mail to MailRoute
# N.B. this works because authenticated users are treated as local
accept from local \
for any \
relay via tls://outbound.mailroute.net verify
I’ve been running this for a few days now, handling my normal mail load (~200 mails per day). The total private memory used according to pmap
:
# pgrep smtpd | xargs pmap -d \
| grep -o "private: \([0-9]\+\)" \
| awk '{ SUM += $2 } END { print SUM / 1024 " MB"}'
12.8633 MB
(I’m aware this isn’t an accurate measure.)