
On the surface of it, getting a self-hosted email server running sounds like a 10-minute job with Postfix and Dovecot. Except it is not quite so easy! I kept running into an issue where sending email was fine but not receiving or vice-versa.
After much investigation and numerous re-installs, I stumbled onto the issue by accident: when setting up Postfix with Dovecot, the postfix
service needs to be in a ‘stopped’ state for this particular configuration change.
Prerequisites
The following assumes that DNS records are in place for the mail server and the mail domain is configured for TLS encryption. I use Let’s Encrypt. This guide was used to install Postfix and Dovecot on Ubuntu 20.04 LTS. Further, this guide assumes that:
- The apex domain is = example.com
- The mail subdomain is = mail.example.com
- Therefore, the SMTP server address = mail.example.com
No additional system users will need to be configured; instead, users are maintained in /etc/aliases
. If the user-name is not present in the aliases file, the mail will not be delivered. An example of /etc/aliases
is below and shows the explicitly-named users will be diverted to root
. In turn, emails addressed to root will be diverted to admin
. We therefore end up with admin@example.com
being a type of catch-all for root@example.com
, webmaster@example.com
and so on.
#aliases
mailer-daemon: postmaster
postmaster: root
nobody: root
hostmaster: root
usenet: root
news: root
webmaster: root
www: root
ftp: root
abuse: root
root: admin
Install Postfix
To install Postfix, run the command:
$ sudo apt update && sudo apt install postfix -y
- During install, Postfix will ask about the type of configuration required, so select
Internet Site
. - Postfix will then request the apex domain name. Enter the name, e.g.
example.com
.
Installation will complete and Postfix can be used immediately from the command line. Ensure that port 25 is open on your firewall. Using UFW, this can be done with:
$ sudo ufw allow 25/tcp
Send a test email:
$ echo "hello" | sendmail someone@somewhere.com
The email should be delivered to the recipient without issue at this point.
Install Dovecot
Because we are not in 1975 and we would like to access email from a client, we will install Dovecot. The remainder of this guide will assume we are only using IMAP (not POP3).
IMPORTANT: before proceeding, Postfix must be stopped
Check if Postfix is running:
$ postfix status
postfix: Postfix is running with backwards-compatible default settings
postfix: See http://www.postfix.org/COMPATIBILITY_README.html for details
postfix: To disable backwards compatibility use "postconf compatibility_level=2" and "postfix reload"
postfix/postfix-script: the Postfix mail system is running: PID: 697
Stop Postfix:
$ sudo postfix stop
Install Dovecot:
$ sudo apt install dovecot-core dovecot-imapd
Configure Dovecot
We will empty the dovecot.conf
file so let’s backup the original:
$ sudo cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
Open dovecot.conf
:
$ sudo nano /etc/dovecot/dovecot.conf
Empty the file and add the following:
disable_plaintext_auth = no
mail_privileged_group = mail
mail_location = mbox:~/mail:INBOX=/var/mail/%u
userdb {
driver = passwd
}
passdb {
args = %s
driver = pam
}
protocols = " imap"
namespace inbox {
inbox = yes
mailbox Trash {
auto = subscribe
special_use = \Trash
}
mailbox Sent {
auto = subscribe
special_use = \Sent
}
}
service auth {
unix_listener /var/spool/postfix/private/auth {
group = postfix
mode = 0660
user = postfix
}
}
ssl=required
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
Save and close the file. Two key points to note here: This configuration will use the default mbox
format instead of Maildir
. SSL is required (not optional) so point Dovecot to the certificates.
Configure Postfix
We will empty the main
and the master
config files so let’s backup the originals:
$ sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.orig
$ sudo cp /etc/postfix/master.cf /etc/postfix/master.cf.orig
Open main.cf
:
$ sudo nano /etc/postfix/main.cf
Empty the file and add the following:
myhostname = mail.example.com
myorigin = /etc/mailname
mydestination = mail.example.com, example.com, localhost, localhost.localdomain
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.example.com/privkey.pem
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_security_level=may
smtpd_tls_protocols = !SSLv2, !SSLv3
local_recipient_maps = proxy:unix:passwd.byname $alias_maps
Note that myhostname
is the mail subdomain aka the SMTP server address. Note also that mydestination
includes both the apex domain name as well as the mail subdomain. The TLS/SSL certificates will point to the same Let’s Encrypt certificates as per the Dovecot configuration.
Save and close the file.
Finally, we will configure Postfix master.cf
:
$ sudo nano /etc/postfix/master.cf
Empty the file and add the following:
submission inet n - - - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_wrappermode=no
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
Save and close the file.
Start Postfix:
$ sudo postfix start
Restart Dovecot:
$ sudo systemctl restart dovecot
Ensure that ports 25, 587 and 993 are open:
$ sudo ufw allow 25,587,993/tcp
That was easy, wasn’t it?