Running postfix as send-only on Alpine Linux


Problem statement

I’m running a plethora of Linux boxes (raspi and otherwise) and I’ve been using ssmtp to push email from them using authenticated smtp to my MX1.

Unfortunately, when the connectivity gets spotty, or the MX uplink goes down, emails get dropped. Because ssmtp doesn’t have a local mail queue.

I needed a better solution.

Since I run postfix for the mail2, it seemed natural to re-use it for this use-case, too.

Requirements

Solution

Super easy, barely an inconvenience4:

# Where to push email
MXHOST=mx.example.com:587

# Credentials for authentication
MXCREDS="user@example.com:a-suitable-password-here"

# Admin (root) email
MAILTO=admin@example.com

# Install the required software -- MTA and `mail` util
apk add postfix mailx

# Alpine now uses `lmdb` instead of `hash` as default map, sigh
MAPTYPE=$(postconf -h default_database_type)

cd /etc/postfix

# Force the session to be TLS
cat - > tls_policy <<EOF
$MXHOST secure
EOF
postmap tls_policy

# Encode the credentials
cat - > relayhost_passwords <<EOF
$MXHOST $MXCREDS
EOF
chmod go= relayhost_passwords
postmap relayhost_passwords

# Set the root@ email address
sed -i "s,^#*root:.*,root: $MAILTO," aliases
newaliases

# Magic to make it all happen
postconf -e "relayhost = $MXHOST"
postconf -e "smtp_sasl_auth_enable = yes"
postconf -e "smtp_sasl_password_maps = $MAPTYPE:/etc/postfix/relayhost_passwords"
postconf -e "smtp_tls_note_starttls_offer = yes"
postconf -e "smtp_tls_security_level = may" # try TLS by default
postconf -e "smtp_tls_loglevel = 0"  # 2 if you're debugging
postconf -e "smtp_sasl_security_options = noanonymous"  # noplaintext = trouble
postconf -e "smtp_tls_policy_maps = $MAPTYPE:/etc/postfix/tls_policy"
postconf -e "smtp_tls_CApath = /etc/ssl/certs"
postconf -e "inet_interfaces = localhost" # send only, limit :25 to localhost
postconf -e "myhostname = $(hostname -f)" # w/o this you'll get a BS domain

# Wire it up
/etc/init.d/postfix restart
rc-update add postfix default

Obviously this won’t work if your smarthost (MX) is something that enforces strict equivalence between MAIL FROM, authenticated user, and From:. Because this setup sends emails as $USER@$(hostname -f) using single $MXCREDS.

Mine doesn’t do that, so I’m fine5.

Closing words

This would be barely worth mentioning, if it weren’t for the inconvenience of all the semi-valid guides all over the net6.

I fought with the default map, smtp_sasl_security_options, obsolete smtp_use_tls, lack of TLS enforcement, etc.

So I wrote this one up.

  1. Mostly to collect cron failures.

  2. The least bad option for MTA, not counting qmail. I would have stayed with qmail, if it weren’t dead as a project. But I’m no longer in possession of enough stamina to maintain a huge set of patches in order to keep my email server running.

  3. Read as: at least alpine and devuan.

  4. Posting install scripts like this is tight.

  5. And the admin’s real swell dude, too; so I’m not worried that this “policy” would change anytime soon.

  6. xkcd 927 comes to mind.