Backup MX Server
A backup MX server accepts inbound mail when the primary mail server is unreachable and queues it until the primary comes back online. Without one, sending mail servers retry delivery for a period (typically up to five days) before bouncing the message. With a backup MX, mail is accepted and queued locally, eliminating the risk of bounce during planned or unplanned downtime.
For this three-site network, the backup MX opportunity is built into the existing architecture. The secondary sites each have a server capable of running a lightweight Postfix instance as a backup relay. Using one of the secondary site servers means the backup MX is geographically separated from the primary, connected via the inter-site WireGuard VPN, and already part of the managed infrastructure.
How backup MX works
When a sending mail server looks up the MX records for a domain, it sees a list ordered by priority. Lower priority numbers are tried first. If the primary server (priority 10) is unreachable, the sending server tries the next MX record (priority 20). The backup MX accepts the message, holds it in its queue, and periodically attempts delivery to the primary server.
When the primary recovers, the backup server’s queue drains automatically: Postfix retries all queued messages on its normal retry schedule.
The backup MX does not process, filter, or deliver mail to mailboxes. It only holds and relays.
DNS records
Add a second MX record to the public DNS zone with a higher priority number than the primary:
; Primary mail server (highest priority - lower number)
yourdomain.net. IN MX 10 mail.yourdomain.net.
; Backup mail server (lower priority - higher number)
yourdomain.net. IN MX 20 mail-backup.yourdomain.net.
Add an A record for the backup MX hostname pointing at the secondary site’s public IP:
; Backup mail server hostname
mail-backup.yourdomain.net. IN A secondary.site.wan.ip
mail-backup.yourdomain.net. IN AAAA secondary::site::ipv6
The backup MX must also have a valid PTR (reverse DNS) record, just like the primary. Contact the ISP at the secondary site to set this up.
Container setup on the secondary site
Clone the base container template on the secondary site’s Proxmox host:
pct clone 100 110 --hostname mail-backup --full
pct start 110
Inside the container:
hostnamectl set-hostname mail-backup.yourdomain.net
sed -i 's/base-template/mail-backup/g' /etc/hosts
Installing Postfix as a backup relay
sudo apt install -y postfix
During installation, select Internet Site and enter mail-backup.yourdomain.net as the system mail name.
Postfix backup MX configuration
The backup MX configuration is deliberately minimal. It accepts mail for the hosted domains, holds it in the queue, and relays it to the primary server. It does not deliver to local mailboxes.
Edit /etc/postfix/main.cf:
sudo postconf compatibility_level=3.6
sudo postconf myhostname=mail-backup.yourdomain.net
sudo postconf mydomain=yourdomain.net
sudo postconf myorigin='$mydomain'
# Accept mail for these domains (as backup MX)
sudo postconf "relay_domains=yourdomain.net"
# Relay accepted mail to the primary mail server
# Using the internal VPN address for secure delivery
sudo postconf "relay_transport=smtp"
sudo postconf "transport_maps=hash:/etc/postfix/transport"
# Only accept mail from external servers, not generate local mail
sudo postconf mydestination=
sudo postconf local_recipient_maps=
# Network interfaces to listen on
sudo postconf inet_interfaces=all
sudo postconf inet_protocols=all
# Restrict relaying to backup MX role only
sudo postconf "smtpd_recipient_restrictions=reject_unauth_destination"
Transport map
Create /etc/postfix/transport to route accepted mail to the primary server via the VPN:
yourdomain.net smtp:[10.1.0.12]:25
Replace 10.1.0.12 with the primary mail server’s internal VPN address. Using the internal VPN address ensures delivery between sites is encrypted and does not traverse the public internet.
Build the transport database:
sudo postmap /etc/postfix/transport
Recipient validation
Without recipient validation, the backup MX accepts mail for any address at the hosted domain. This means if a spammer sends to random-invalid@yourdomain.net, the backup MX accepts it and the primary server subsequently rejects it, generating a backscatter bounce. Recipient validation prevents this.
Configure Postfix to check recipients against the primary server before accepting:
sudo postconf "smtpd_recipient_restrictions=reject_unauth_destination, check_recipient_access hash:/etc/postfix/relay_recipients"
Create /etc/postfix/relay_recipients listing valid recipients:
you@yourdomain.net OK
admin@yourdomain.net OK
postmaster@yourdomain.net OK
Build the database:
sudo postmap /etc/postfix/relay_recipients
This approach requires manually maintaining the recipient list. An alternative is to query the primary server’s PostfixAdmin database directly, which requires network access to the database and is covered in the advanced Postfix configuration section.
SMTP restrictions
Add restrictions to prevent the backup MX from being used as an open relay:
sudo tee /etc/postfix/main.cf >> << 'EOF'
# Anti-spam: reject clearly invalid senders
smtpd_sender_restrictions =
reject_non_fqdn_sender,
reject_unknown_sender_domain
# Require FQDN in HELO/EHLO
smtpd_helo_required = yes
smtpd_helo_restrictions =
reject_invalid_helo_hostname,
reject_non_fqdn_helo_hostname
EOF
TLS configuration
The backup MX should support TLS for inbound connections. If a Let’s Encrypt certificate is available for mail-backup.yourdomain.net:
sudo postconf smtpd_tls_security_level=may
sudo postconf smtpd_tls_cert_file=/etc/letsencrypt/live/mail-backup.yourdomain.net/fullchain.pem
sudo postconf smtpd_tls_key_file=/etc/letsencrypt/live/mail-backup.yourdomain.net/privkey.pem
sudo postconf smtpd_tls_loglevel=1
sudo postconf smtp_tls_security_level=may
sudo postconf smtp_tls_loglevel=1
Start Postfix
sudo systemctl enable --now postfix
Verify the configuration:
sudo postfix check
sudo postfix status
Firewall rules
The backup MX needs port 25 (SMTP) open to the internet for inbound mail delivery. Add a port forward on the secondary site’s router pointing at the backup MX container, and a firewall rule permitting inbound TCP on port 25.
On the UniFi gateway at the secondary site, add a port forward identical to the one on the primary site router, but pointing at the backup MX container’s internal address.
On the homelab server firewall:
sudo ufw allow 25/tcp
SPF record update
Add the backup MX server to the SPF record so mail relayed from it to the primary is not rejected:
yourdomain.net. IN TXT "v=spf1 mx a:mail.yourdomain.net a:mail-backup.yourdomain.net -all"
The mx mechanism already includes both MX record targets, but adding the explicit a: record ensures coverage even if SPF resolvers handle the mx mechanism inconsistently.
Testing the backup MX
Test basic acceptance
From an external machine or mobile hotspot, test that the backup MX accepts mail:
nc -v mail-backup.yourdomain.net 25
The backup MX should respond with its SMTP banner. Send a test message:
EHLO test.example.com
MAIL FROM:<test@external.example.com>
RCPT TO:<you@yourdomain.net>
DATA
Subject: Backup MX test
Testing the backup MX relay.
.
QUIT
Check the Postfix queue on the backup MX:
sudo mailq
The message should appear in the queue destined for the primary server’s VPN address.
Test failover behaviour
With the primary mail server stopped, send a test message to your address from an external mail service. The message should be accepted by the backup MX.
Start the primary mail server again. The backup MX should flush its queue within a few minutes, delivering the held messages.
# Force a queue flush on the backup MX
sudo postqueue -f
Monitoring the backup MX queue
An unexpectedly large queue on the backup MX indicates either the primary server is down or the delivery route between sites has a problem. Add queue monitoring to the alerting setup:
cat > /etc/cron.hourly/check-mail-queue << 'EOF'
#!/usr/bin/env bash
# Alert if backup MX queue exceeds threshold
QUEUE_SIZE=$(mailq | grep -c "^[A-F0-9]")
THRESHOLD=50
if [ "$QUEUE_SIZE" -gt "$THRESHOLD" ]; then
echo "Backup MX queue has $QUEUE_SIZE messages. Primary server may be down." | \
mail -s "Backup MX queue alert on $(hostname -s)" root
fi
EOF
chmod 0755 /etc/cron.hourly/check-mail-queue
Alternative: commercial backup MX
For a home network where running infrastructure at a secondary site is impractical, several commercial services provide backup MX for low cost or free:
- Rollernet: reliable secondary MX with queue times up to three weeks
- MXroute: low-cost mail hosting that can also serve as backup MX
- Cloudflare Email Routing: free, but limited to forwarding rather than true backup queuing
These are reasonable alternatives if the three-site architecture is not fully operational yet. The self-hosted approach above is preferable once all three sites are running.
A backup MX that accepts mail for invalid recipients generates backscatter bounces that damage the domain’s reputation. The recipient validation step is not optional. Even a static list of valid recipients is significantly better than accepting all mail and having the primary bounce invalid addresses.
Roll Your Own Network / Server / Mail. Next: Postfix MTA.