There are various guides online for setting up Postfix as a backup (hold and forward) mail server which knows which accounts are valid on the primary (to prevent backscatter spam, so it only accepts emails for actual accounts that exist on the primary mail server). All of them are slightly different and none of them worked out of the box for me. This is how I did it – this method is facilitated by using Virtualmin on the primary since it has already generated map files that we can use.
There are two files we need on the backup mail server: a list of domains to relay and a list of valid email accounts. With a little tweaking, we can just copy a couple of Virtualmin configuration files over from the primary and the backup will automatically know what the valid accounts are.
Note: if you’re using Virtualmin, make sure your alias domains are copying the accounts from the domain they are aliasing rather than running a catch-all domain (which is the default setting), otherwise it rather defeats the purpose of specifying the valid accounts. To set this up on future-created domains, go to System Settings, Server Templates, select your template(s), go to Mail for domain and change “Mail alias mode for alias domains” to “Copy aliases from target” and Save. If you have existing catch-all alias domains, if you select that domain and go to Server Configuration, Email Settings, you can change the Mail aliases mode there.
So, back to those two files. They need to be files that Postfix can map into a hash file for itself to use. The standard way of doing this is to have the domain (or email address) and then a space and then the word OK
, so each line would be:
user@domain.com OK
However, the second part can be anything for the hash to work, it doesn’t have to be OK
, and Virtualmin creates a virtual mapping file which maps email addresses to accounts that we can use as a perfectly good relay recipient list. The file is at /etc/postfix/virtual
so the first step is to copy that file to the backup as /etc/postfix/relay_recipients
. (This will all need to be done as the root
user.)
[primary] scp /etc/postfix/virtual user@backupmx.com:~
[backup] cp /home/user/virtual /etc/postfix/relay_recipients
Then we need to tell Postfix to use those email addresses, so as root:
[backup] postmap /etc/postfix/relay_recipients
If that fails, you may need to adjust the permissions of /etc/postfix
so that it can create the .db file (and then run the command again):
[backup] chmod 777 /etc/postfix
[backup] postmap /etc/postfix/relay_recipients
Then update the Postfix configuration and reload it:
[backup] postconf -e "relay_recipient_maps = hash:/etc/postfix/relay_recipients"
[backup] postfix reload
Next we need a list of valid domains to relay. Virtualmin does create a map of domains for itself with the format domain.com=1234567890
, so all we need to do it replace the equals sign with a space and we have a valid map file.
[primary] scp /etc/webmin/virtual-server/map.dom user@backupmx.com:~
[backup] sed -i 's/=/ /g' /home/user/map.dom
[backup] cp /home/user/map.dom /etc/postfix/relay_domains
Then similar to above, update the config and reload:
[backup] postmap /etc/postfix/relay_domains
[backup] postconf -e "relay_domains = hash:/etc/postfix/relay_domains"
[backup] postfix reload
That’s it! If there were no problems, they are now in sync.
Obviously you don’t want to have to do this manually each time, so we need to set up a ssh key-pair so that you don’t have to enter your password and then create scripts that we will run automatically every few minutes to retain the sync.
Creating a passwordless key-pair is pretty simple. Type in:
[primary] ssh-keygen -t rsa
Use the default info and no password. Then copy to the backup:
[primary] ssh-copy-id -i ~/.ssh/id_rsa.pub user@backup.com
Enter the remote password. All done.
Now we need to create the scripts:
[primary] vi /home/user/backupmx.sh
What we’ll do is check if Virtualmin’s files are newer than the ones we last copied to the backup and if so then copy over the new files (having updated the domain map). So paste in:
#!/bin/sh
# postfix/vmin backup mx file 1/2 (primary)
# copy virtual (valid email addresses)
if test /etc/postfix/virtual -nt /home/user/virtual
then
cp /etc/postfix/virtual /home/user/virtual
scp /home/user/virtual user@backupmx.com:~
fi
# copy map.dom (list of domains)
if test /etc/webmin/virtual-server/map.dom -nt /home/user/map.dom
then
cp /etc/webmin/virtual-server/map.dom /home/user/map.dom
sed -i 's/=/ /g' /home/user/map.dom
scp /home/user/map.dom user@backupmx.com:~
fi
And a similar script on the backup – check if the files are newer and if so, copy them and update the config:
[backup] vi /home/user/backupmx.sh
And paste in:
#!/bin/sh
# postfix/vmin backup mx file 2/2 (backup)
# copy virtual (valid email addresses)
if test /home/user/virtual -nt /etc/postfix/relay_recipients
then
cp /home/user/virtual /etc/postfix/relay_recipients
/usr/sbin/postmap /etc/postfix/relay_recipients
/usr/sbin/postfix reload
fi
# copy map.dom (list of domains)
if test /home/user/map.dom -nt /etc/postfix/relay_domains
then
cp /home/user/map.dom /etc/postfix/relay_domains
/usr/sbin/postmap /etc/postfix/relay_domains
/usr/sbin/postfix reload
fi
Then add those files to the cron on both systems
[primary] crontab -e
And add the line (to run every 5 minutes):
*/5 * * * * /home/user/backupmx.sh
Do the same on the backup computer.
Voila. Automated secondary mail server.
Thanks for the instructions. Used this on 2 setups now and neither has had any issues with the MX slaves not being in sync with the master 🙂
That’s great – thanks for letting me know!
Great tutorial
Any tips on merging /relay_recipients from more than one primary ? or can you supply more than one file to relay_recipient_maps = ?
Thankyou so much for this!! Works brilliantly
This is brilliant. Thank you!