How to Set up a Backup Email Server with Postfix on Ubuntu (Complete Guide)
This tutorial will be showing you how to set up a backup email server with Postfix on Ubuntu. A backup email server is often called a backup MX. MX stands for Mail Exchanger. Previously I wrote an article explaining how iRedMail can help you quickly run your own email server. Sometimes your email server can be offline, especially if you run email server at home instead of in a data center. You can set up a backup email server to receive and queue emails when your primary email server is down. The backup MX will relay queued emails to the primary when it’s back online.
Requirements
Since you’re going to set up a backup email server, you need a server with high uptime, so preferably you should rent a virtual private server (VPS) in a data center. Make sure the server can send emails on port 25. I set up my backup email server on a $4/month Kamatera VPS instance (1 CPU, 1GB RAM). You can follow the tutorial below to create a Kamatera VPS.
It’s assumed that your backup MX host isn’t a primary email server for any domains. It’s a good practice to separate the role of primary and secondary email servers on different hosts.
Creating DNS MX Record
The MX record specifies which host or hosts handle emails for a particular domain name. For example, the host that handles emails for linuxbabe.com
is email.linuxbabe.com
, which is the primary email server. You can query MX record with the dig
utility.
dig MX +short linuxbabe.com
If someone with a Gmail account sends an email to [email protected]
, then Gmail server will query the MX record of linuxbabe.com. When it finds out that email.linuxbabe.com
is responsible for accepting email, it then query the A record of email.linuxbabe.com
to get the IP address, thus the email can be delivered.
To set up a backup email server, you need to create another MX record in your DNS manager. Enter @
in the Name field to represent the main domain name, then enter the hostname for the backup email server in the Value field. I named my backup email server mx2.linuxbabe.com
.
Now I have two MX records for my domain name. Notice that there are two numbers at the beginning. They are called preference value or priority value. A small number has higher priority than a big number.
A sending SMTP server will pick the email server with highest priority to deliver email. If that email server is unavailable, then the email server with second highest priority will be tried. You can set the preference vaule in your DNS manager. It can be any number between 0 and 65,356. Make sure the number for backup email server is bigger than that for primary email server. And don’t forget to create an A record for your backup MX.
Setting up Backup Email Server with Postfix on Ubuntu
We just need to install and configure Postfix SMTP server on the backup MX host. No other software is needed. Run the following commands to install Postfix on Ubuntu.
sudo apt update sudo apt install postfix
When you see the following message, press the Tab key and press Enter.
Then choose the second option: Internet Site
.
Next, enter the backup MX hostname for the system mail name. For example, I entered mx2.linuxbabe.com
. Note that you cannot enter your main domain name here. That is to say, I must not enter linuxbabe.com
for the system mail name.
After Postfix is installed, open the configuration file.
sudo nano /etc/postfix/main.cf
By default, /etc/postfix/main.cf
file contains the following line.
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
Explanation:
Permit_mynetworks
tells Postfix to relay emails from SMTP clients on its own network.Permit_sasl_authenticated
tells Postfix to relay emails from authenticated SMTP clients.Defer_unauth_destination
makes Postfix reject request from other SMTP clients if the recipient’s domain name is in neither$relay_domains
nor$my_destination
.
We need to add the relay_domains
parameter, specifying the domain names, so that emails can be relayed to the primary email server when it’s back online.
relay_domains = linuxbabe.com
You can also specify multiple domain names if you want to make it as a backup MX host for multiple domain names.
relay_domains = linuxbabe.com, 2nd-domain.com
It’s recommended that you change the default value of myhostname to mx2.your-domain.com
.
myhostname = mx2.linuxbabe.com
Make sure that the value of mydestination
doesn’t include your main domain name, or your backup MX host will deliver emails to local system instead of relaying to the primary email server. The following values are fine.
mydestination = $myhostname, mx2.linuxbabe.com , localhost, localhost.localdomain, localhost
Postfix continues trying to deliver queued messages for the amount of time specified in the maximal_queue_lifetime
parameter, which determines how long deferred messages stay in the queue before they are bounced back to the sender. The default value is 5 days, as can be seen with the command below.
postconf -d | grep maximal_queue_lifetime
output:
maximal_queue_lifetime = 5d
The SMTP protocol (RFC 2821) recommends that sending SMTP server should retry failed email delivery at least 4-5 days. So if you run a backup MX host, you probably want to extend the queue lifetime like 10 days. Add the following line at the end of main.cf
file.
maximal_queue_lifetime = 10d
Save and close the file. Then restart Postfix for the changes to take effect.
sudo systemctl restart postfix
minimal_backoff_time
parameter, which by default is 300s (5 minutes). If the delivery fails again, the wait time is extended. The maximal wait time between attempts to deliver a deferred message is determined by the maximal_backoff_time
parameter, which by default is 4000s (about 66.66 minutes)Relay Recipients
By default, Postfix on the backup MX host will accept any address that belongs to $relay_domains
. If the primary email server tells the backup MX host that the recipient’s email address doesn’t exist, then the backup MX host must bounce the message to the original sender.
Spammers often send messages to made-up addresses, so your backup MX host will unnecessarily accept a lot of email that must be bounced. If the spammer use other people’s real address as the sender address, then the innocent person will get bounce emails from your server. Sometimes they think that you are a spammer.
It’s highly recommended that you maintain a list of valid recipient addresses on the backup MX host. In /etc/postfix/main.cf
file, add the following line.
relay_recipient_maps = hash:/etc/postfix/relay_recipients
Then you can specify valid recipient addresses in /etc/postfix/relay_recipients
file like below.
[email protected] OK [email protected] OK [email protected] OK
Obviously, manually adding recipient addresses is only viable for small email servers. For large email servers, this is time-consuming. Instead, you can perform real-time lookups using MySQL/MariaDB or LDAP. If your email server uses MariaDB to store email accounts information, then you can set up MariaDB master-slave replication, so the backup email server will have the same email accounts in the database. Note that you also need to copy the MySQL/MariaDB lookup configurations in /etc/postfix/main.cf file
from the primary email server to the backup host, so the backup host knows how to query the database.
Once you set relay_recipient_maps
parameter, you must include email addresses for all domains that you provide backup service. If you don’t know all valid email addresses for a domain, you can use a wildcard entry like below.
[email protected] OK [email protected] OK [email protected] OK @2nd-domain.com OK
The last entry is a wildcard entry that allows any email address of the second domain. Save and close the file. Then create the relay_recipients.db
file.
sudo postmap /etc/postfix/relay_recipients
Anti-Spam Filters
Spammers often target backup MX host to send email spam. So it’s important that you deploy anti-spam filters on both your primary and backup MX host. You can use my 6 tips to block email spam with Postfix. It’s worth mentioning that you need to make sure you backup MX host can get through the spam filters on the primary email server.
Enabling TLS Encryption
By default, Postfix does not encrypt connections from or to other email servers. It’s important that we enable TLS encryption so that emails won’t be snooped by a middle man listening on the network traffic. We can easily obtain a free TLS certificate from Let’s Encrypt. Issue the following commands to install Let’s Encrypt client (certbot) on Ubuntu server from official PPA.
sudo apt install software-properties-common sudo add-apt-repository ppa:certbot/certbot sudo apt update sudo apt install certbot
Now you can obtain a TLS certificate with one of three plugins (standalone, Apache, Nginx), depending on your server.
Obtaining TLS Certificate with the Standalone Plugin
If there’s no web server running on your backup MX host, then you can use the standalone plugin to obtain TLS certificate from Let’s Encrypt by executing the following command.
sudo certbot certonly --standalone --preferred-challenges http --agree-tos --email your-email-address -d mx2.your-domain.com
Explanation:
certonly
: Obtain a certificate but don’t install it.--standalone
: Use the standalone plugin to obtain a certificate--preferred-challenges http
: Perform http-01 challenge to validate our domain, which will use port 80. By default the standalone plugin will perform tls-sni challenge, which uses port 443.--agree-tos
: Agree to Let’s Encrypt terms of service.--email
: Email address is used for account registration and recovery.-d
: Specify your domain name.
As you can see the from the following screenshot, I successfully obtained the certificate.
Obtaining TLS Certificate with the Apache Plugin
If Apache web server is running on your backup MX host, you can use the Apache plugin to obtain TLS certificate. Run the following command to install the Apache plugin.
sudo apt install python3-certbot-apache
You need to have an Apache virtual host for mx2.your-domain.com
before obtaining Let’s Encrypt TLS certificate. Create the virtual host file:
sudo nano /etc/apache2/sites-available/mx2.your-domain.com.conf
Then paste the following text into the file.
<VirtualHost *:80> ServerName mx2.your-domain.com DocumentRoot /var/www/mx2.your-domain.com </VirtualHost>
Save and close the file. Then create the web root directory.
sudo mkdir /var/www/mx2.your-domain.com
Set www-data
(Apache user) as the owner of the web root.
sudo chown www-data:www-data /var/www/mx2.your-domain.com -R
Enable this virtual host.
sudo a2ensite mx2.your-domain.com.conf
Reload Apache for the changes to take effect.
sudo systemctl reload apache2
Once virtual host is created and enabled, run the following command to obtain Let’s Encrypt TLS certificate.
sudo certbot --apache --agree-tos --redirect --hsts --email your-email-address -d mx2.your-domain.com
You should see the following message which means the certificate is successfully obtained.
Obtaining TLS Certificate with the Nginx Plugin
If Nginx web server is running on your backup MX host, you can use the Nginx plugin to obtain TLS certificate. Run the following command to install the Nginx plugin.
sudo apt install python3-certbot-nginx
You need to have a Nginx virtual host for mx2.your-domain.com
before obtaining Let’s Encrypt TLS certificate. Create the virtual host file:
sudo nano /etc/nginx/conf.d/mx2.your-domain.com.conf
Next, paste the following text into the file.
server { listen 80; server_name mx2.your-domain.com; root /var/www/mx2.your-domain.com/; location ~ /.well-known/acme-challenge { allow all; } }
Save and close the file. Then create the web root directory.
sudo mkdir /var/www/mx2.your-domain.com/
Set www-data
(Nginx user) as the owner of the web root.
sudo chown www-data:www-data /var/www/mx2.your-domain.com -R
Reload Nginx for the changes to take effect.
sudo systemctl reload nginx
Once virtual host is created and enabled, run the following command to obtain and install Let’s Encrypt certificate with Nginx plugin.
sudo certbot --nginx --agree-tos --redirect --hsts --email your-email-address -d mx2.your-domain.com
You should see the following which means the certificate is successfully obtained. You can also see the directory under which your cert is stored.
Installing TLS Certificate in Postfix
Now we have obtained a valid TLS certificate, let’s install it in Postfix.
sudo nano /etc/postfix/main.cf
Find the TLS parameters
section and the following two lines.
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
Replace them with:
smtpd_tls_cert_file=/etc/letsencrypt/live/mx2.your-domain.com/fullchain.pem smtpd_tls_key_file=/etc/letsencrypt/live/mx2.your-domain.com/privkey.pem
Then add the following 3 lines, which enables TLS in Postfix SMTP server.
smtpd_tls_security_level=may smtpd_tls_protocols = !SSLv2, !SSLv3 !TLSv1 smtpd_tls_loglevel = 1
Save and close the file. Restart Postfix for the changes to take effect.
sudo systemctl restart postfix
Now Postfix SMTP server can use STARTTLS to establish encrypted connection with SMTP clients on port 25. Note that end user email client won’t communicate with a backup MX host, so there’s no need to enable submission service on port 587 or 465.
Enforce TLS Connection Between the Primary and the Backup
Since your primary email server is also configured with a valid Let’s Encrypt TLS certificate, we can enforce the backup MX host to use TLS when delivering emails to the primary email server. In /etc/postfix/main.cf
file, add the following parameters, which will make Postfix SMTP client to always use TLS and also verify the remote server certificate using trusted root CA certificates in /etc/ssl/certs
directory.
smtp_tls_security_level = verify smtp_tls_verify_cert_match = hostname, nexthop, dot-nexthop smtp_tls_CApath = /etc/ssl/certs smtp_tls_loglevel = 1
Save and close the main.cf
file. Then use the following command to create hash symbolic links.
Ubuntu 18.04: sudo openssl rehash /etc/ssl/certs Ubuntu 16.04: sudo c_rehash /etc/ssl/certs
Restart Postfix for the changes to take effect.
sudo systemctl restart postfix
Now you can send an email from your backup MX host to your email address with the following command.
echo "hello" | sendmail [email protected]
After the message is sent, you can find the following text in /var/log/mail.log
file.
Verified TLS connection established
If your backup MX host tries to establish TLS connection but can not verify the primary email server’s certificate, then the following message can be found.
Untrusted TLS connection established
How to Identify Relayed Email
You can recognize relayed email by looking at the email headers in your email client. For example, I shut down my primary email server, then use my Gmail account to send an email to my domain email account. After a few minutes, I boot my primary email server up again. When checking the email headers, the client IP and HELO hostname belongs to my backup MX host, so I know it’s relayed via my backup MX host.
Received-SPF: Softfail (mailfrom) identity=mailfrom; client-ip=23.254.225.226; helo=mx2.linuxbabe.com; [email protected]; receiver=<UNKNOWN>
Notice that the SPF check result is Softfail
, which means Gmail didn’t designate my backup MX host as being allowed to send emails on behalf of gmail.com, but if my backup MX host sends an email on behalf of gmail.com, the recipient’s SMTP server can accept it and mark it as Softfail.
Setting Up SMTP Fallback Relay
Since you have two SMTP servers now, you can set up SMTP relay between them, so if one SMTP server can’t send an email to a particular recipient, Postfix will use the other SMTP server to deliver the email again. We are going to use the smtp_fallback_relay
parameter to achieve this.
Edit the Postfix main configuration file on the primary mail server.
sudo nano /etc/postfix/main.cf
Add the following line at the end of the file. Replace 12.34.56.78
with the IP address of the secondary mail server.
smtp_fallback_relay = [12.34.56.78]:25
Save and close the file. Then restart Postfix for the change to take effect.
sudo systemctl restart postfix
Then edit the Postfix main configuration file on the secondary mail server.
sudo nano /etc/postfix/main.cf
Find the mynetworks
parameter.
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
Add the IP address of the primary mail server to the list. This allows the primary mail server to use the secondary mail server as relay without SMTP authentication.
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 Primary-Mail-Server-IP
Save and close the file. Then restart Postfix.
sudo systemctl restart postfix
Note that you should not configure the secondary mail server to use the primary mail server as a fallback relay host, because it will cause emails loop back and forth between the two mail servers when you send lots of emails, such as newsletters.
Postfix will use the SMTP fallback relay when:
- Connection timed out.
- The recipient’s SMTP server temporarily deferred email delivery, such as using greylisting.
- The mail queue is full.
Wrapping Up
I hope this tutorial helped you set up a backup email server with Postfix on Ubuntu. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care.
These tutorials are great! I would make note that the Certbot certificates that are “standalone” do not auto-renew. Only the web server based ones do. To that effect, it might be easier to just install nginx to obtain a certificate that way so you can set it and forget it. Manually renewing every three months would be a pain.
Hello Sir,
thanks for your article about the topic I’ve been searching for days.
You say in the introduction that 2nd server can stack emails in queue until primary server is respawn. Does this mean that my smartphone client won’t be able to both receive/emit and search past emails until the primary server is back anyway? If yes, do you know where I can look for tutorial/doc about “failover” secondary server please Sir?
By thanking you in advance
Hello Xiao,
Thank you again for a great tutorial. I have one issue at the last step ENFORCE TLS Connection Between the Primary and the Backup. Note: I obtained the TLS Certificate with the Standalone Plugin.
How do I make this correct setup? Thanks so much.
Ps: I can send email test.
Cheers,
Quang
I don’t have web server on the backup MX. It is understood ports 80 and 443 must be open during certbot encryption. Do I need to keep those two ports open all the time? Or, I can close 80 or both 80 and 443 after certbot is done? thanks
You can close port 80 and 443 after the certificate is obtained, but I think it’s unnecessary. When you use the standalone plugin to obtain TLS certificate, a temporary web server will listen on port 80. After the certificate is obtained, the web server automatically stops.
got it. thanks Xiao. it means no apache or nginx needs to be installed. before acquiring the tls certificate uisng the standalone plugin, port 80 needs to be opened. after the tls cefrtifcate is installed, port 80 can be closed. correct?
Yes. That’s correct.
when i use this backup email server to backup a primary server with iredmail for multiple domains. shall i create MX and A/AAAA DNS records for mx2.domain2.com? or i shall use mx2.domain1.com for domain2? thanks
Both can work. It’s a matter of your preference.
if i choose to create MX and A/AAAA DNS records for mx2.domain2.com and set mx2.domain2.com for MX 5, do i need to obtain TLS certificate for mx2.domain2.com as well?
No. You don’t need to.
Xiao,
Another great tutorial, thank you. I have a question about reverse DNS. Does the server hosting the backup mail server need its PTR record set to mx2.linuxbabe.com?
Many thanks, Steve.
When using “Obtaining TLS Certificate with the Standalone Plugin”, how to set up auto renewal of TLS certificate with crontab?
Many thanks
Just put the following line in your crontab file. It’s the same no matter which plugin you use.
Certbot itself will find which plugin should used to renew your certificate, by checking the .conf files under
/etc/letsencrypt/renewal/
directory.Many mail servers out there today will consider a server who’s PTR record doesn’t match its A record to be suspicious. So it’s best to make sure your PTR record lists the same hostname as the A record.
If you have a static IP, most ISPs will change this if you request it. Most definitely if you have a business class account.
Great tutorial, I was searching about TLS implementation.
Best regards.
Great tutorial. You said “Obviously, manually adding recipient address is only viable for small email servers. For large email servers, this is time-consuming. Instead, you can perform real-time lookups using MySQL or LDAP, which will be discussed in a later tutorial.”
Did you ever make this tutorial?
If your email server uses MariaDB to store email accounts information, then you can set up MariaDB master-slave replication, so the backup email server will have the same email accounts in the database. Note that you also need to copy the MySQL/MariaDB lookup configurations in
/etc/postfix/main.cf
file from the primary email server to the backup host, so the backup host knows how to query the database.The suggestion assumes that the master-slave replication is on the same network, what if my mx2 is in a different datacenter for redundancy.
I’ve looked for tutorial for this type of setup and have not seen any thing that comes close. There is a lot of chat about using gluster to replicate files over WAN, however replicating maria or mysql over WAN seems limited at best. Do you have any tutorials or suggestions for this?
MariaDB master-slave replication can work over the Internet, and I explained how to set up TLS encryption for it.
Can anybody recommend how much RAM will be optimal for this setup? Thanks
Hello Xiao,
All your tutorial series about building an email server from scratch is amazing !
But there is one remaining thing for which I’ve no answer.
I’ve setup 3 MX records :
– mx1.domain.name for main server
– mx2.domain.name for greylisting (same IP as mx1)
– mx3.domain.name for backup and fallback.
My question is :
Should mx2 priority level be higher than mx3 ?
In other word, is it safe to have : 1 for mx1, 5 for mx2 and 10 for mx3 ?
…or should I have : 1 for mx1, 10 for mx2 and 5 for mx 3 ?
Many thanks,
Sébastien
Hi Sébastien,
The priority should be: 1 for mx1, 5 for mx2, and 10 for mx3.
Thanks a lot !
One more thing :
If you’re going to make letsencrypt challenge with Nginx or Apache, it may fail if you have IPv6 enabled because the challenge use it. (It failed for me).
So make your virtual server block listen on IPv6 too.
With my Nginx installation, I’ve just add this line and no more error !
Thanks again for all, Xiao, you will see me on Paypal soon !
I see the problem with SPF on primary server.
When someone will send e-mail using backup server then recipient domain will be rejected ( IP mismatch )
So it require correct configuration SPF on the main MX server:
of course it is highly recommended to install and configure SPF on MX BACKUP SERVER otherwise all mails sent by MX BACKUP SERVER wont be checked by SPF on the main server.
Your site has proved very helpful to me today. Thanks for the effort you put in to this!
hi,
we need to record spf record and A record for backup server or mx record is enough??
You need to create a second MX record for the main domain name and A record for the second MX host.
No need to change SPF record.
Hi,
Surprising the standard smtpd was suggested instead of Postscreen. Any reason for that?
Excellent tutorial by the way.
Postscreen is not a full SMTP server. It’s a component in Postfix that can help block spambots (or zombie machines) away from the real Postfix smtpd daemon.
If you need to configure Postscreen, follow this tutorial:
Enable and Configure Postscreen in Postfix to Block Spambots
I know this is an old HOW-TO, but what IF you have a server at home which can’t receive emails because port 25 is blocked but you wish to set up a relay to your home server using a DIFFERENT port? Basically, accept email on normal port at a static public hosted server but forward it to your mail server at home using non-standard port since home is not port 25 friendly? Why do this? Say I have numerous domains hosted to relay onto my home server and I don’t want all the storage to fill up my cheap VPS / host relay server. Thank you.
Once the email is relayed to the main mail server, it’s removed from the backup SMTP server.
Xiao,
Do you have a tutorial on HOW TO setup a store/forward server? I want to create mail relay server that accepts port 25 for various domains and forward it to final mail server destination that doesn’t have standard port – 25 port is blocked for these guys? I want to be the middle man.
Hope that makes sense. I wannna do what GhettoSMTP does. I want to be the MX server for various domains and forward their mail to them on non-standard ports.
Thanks.
I’m desperate. I’ve been trying every which way to get my secondary MX running postfix to reject any emails to addresses not in relay_recipients(.db). I’ve tried your tutorial at least three times, but when I telnet to port 25 from an outside machine, and provide a non-existent address (with one of my domains as a suffix) with the RCPT TO: command, it accepts it with no question.
I’ve not made much headway on the postfix-users mailing list, so I thought I’d see if you’d be willing to give things a look.
Here is the output of postconf -nf:
Here is the actual main.cf file: https://pastebin.com/njwaFj88
I just don’t understand why it won’t honor the limitations of the relay_recipients(.db) file…
I’ve been following your tutorial and I’m up to sending a test email from MX2 to my primary server, but I can’t find any TLS connection messages in the mail.log file. I must’ve missed something. Any suggestions?
I have set up a working mail server via your build an email server from scratch tutorials. Now, I am trying to set up a backup email server. I have completed all of your steps in this tutorial, but when sending an email from the backup server (
) i get the following errors in my /var/log/mail.log :
Can you help me figure out what is blocking my mail server? Any help or where to begin would be highly appreciated.
Dan