Debian 9 Mail Server, Part I: Postfix and Dovecot

In this post, we will configure personal e-mail hosting on a Debian Gnu/Linux 9 (stretch) server. The server will be able to:

  • send and receive e-mails (SMTP with Postfix)
  • read e-mails from clients (IMAP with Dovecot)
  • secure connections (SSL/TLS)
  • authenticate users using system usernames and passwords (PAM)

We assume that you already have your domain name, say example.com, and that the MX records of your DNS configuration point to your server. You can check this quickly using dig:

dig +short MX example.com

Generating SSL certificates

The best solution to generate SSL certificates nowadays is to use Let's Encrypt. Install it by:

sudo apt-get install certbot python3-certbot-nginx

Request a certificate for your mail server by:

certbot certonly --standalone -d mail.mydomain.com

Replacing mail.mydomain.com with the fully qualified domain name (FQDN) of your server. Certificates issued by Let's Encrypt expire after 90 days, but will be automatically renewed every 60 days by a Cron job (installed by default in the Debian distribution).

Configuring Postfix

Postfix is a Mail Transfer Agent (MTA), that is, software that sends and receives e-mails to and from other computers on the network using the Simple Mail Transfer Protocol (SMTP). From the point of view of an e-mail client, POP/IMAP are the protocols used for receiving messages, and SMTP is used for sending. However, it is not true that "POP/IMAP = receive" and "SMTP = send": e-mail servers use SMTP to exchange messages between themselves, that is, both sending and receiving. What is correct is that:

  • POP/IMAP are used by a client to read messages from an e-mail server;
  • SMTP is used to exchange e-mails between computers.

If your computer was on and connected to the network all the time, you could use SMTP to receive messages to your machine. However, as your computer can be turned off or disconnected, the most common pattern is that you ask your e-mail server to keep messages for you, and read them later on using POP/IMAP.

This being said, let us install Postfix!

sudo apt-get install postfix

An ncurses GUI will pop up with some configuration questions. Answer as follows:

  • General type of mail configuration: "Internet Site";
  • Mail name: enter your domain name, example.com in our example;
  • Leave the default values to other questions.

Go to your configuration file /etc/postfix/main.cf and make sure your domain name and SSL configuration fields are correct. Here are some snippets from my configuration file (beware: it is not a complete configuration file):

# Hostname and domain name
myhostname=mymachine.example.com
mydomain=example.com
myorigin=$mydomain

# SSL/TLS certificates
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.mydomain.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.mydomain.com/privkey.pem
smtpd_use_tls=yes
smtpd_tls_auth_only=yes

# Anti-SPAM rules adapted from https://wiki.debian.org/Postfix
# Updated with https://docs.spamhaus.com/datasets/docs/source/40-real-world-usage/PublicMirrors/MTAs/020-Postfix.html
smtpd_recipient_restrictions = permit_sasl_authenticated,
    reject_invalid_hostname,
    reject_unknown_recipient_domain,
    reject_unauth_destination,
    reject_rbl_client zen.spamhaus.org=127.0.0.[2..11]
    reject_rhsbl_sender dbl.spamhaus.org=127.0.1.[2..99]
    reject_rhsbl_helo dbl.spamhaus.org=127.0.1.[2..99]
    reject_rhsbl_reverse_client dbl.spamhaus.org=127.0.1.[2..99]
    warn_if_reject reject_rbl_client zen.spamhaus.org=127.255.255.[1..255]
    permit
smtpd_helo_restrictions = permit_sasl_authenticated,
    reject_invalid_helo_hostname,
    reject_non_fqdn_helo_hostname,
    reject_unknown_helo_hostname
smtpd_client_restrictions = permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    reject_rbl_client cbl.abuseat.org,
    permit

# Mail user agent restrictions adapted from https://askubuntu.com/a/1132874
smtpd_restriction_classes = mua_sender_restrictions,
    mua_client_restrictions,
    mua_helo_restrictions
mua_sender_restrictions = permit_sasl_authenticated, reject
mua_client_restrictions = permit_sasl_authenticated, reject
mua_helo_restrictions = permit_mynetworks,
    reject_non_fqdn_hostname,
    reject_invalid_hostname,
    permit

# Mail will be stored in users' ~/Maildir directories
#
# NB: make sure to enforce this setting as well in the `mail_location`
# of /etc/dovecot/conf.d/10-mail.conf (thanks to Markus Hoffmann for
# pointing this out):
#
#     mail_location = maildir:~/Maildir
#
home_mailbox = Maildir/
mailbox_command =

# From http://wiki2.dovecot.org/HowTo/PostfixAndDovecotSASL
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

Here we are forcing secure authentication with smtpd_tls_auth_only (just comment it out to allow for unencrypted traffic). An important field is the list of smtpd_recipient_restrictions (note that it is specific to Postfix 2.9.x, which comes by default on Debian Wheezy; for later versions of Postfix, use smtpd_relay_restrictions). It is a list of instructions, such as "permit" or "reject", that the server will apply in this order to received e-mails.

Later on, you may want to look at aliases (used to forward e-mails) or virtual e-mail addresses (used to create mailboxes not tied to a Unix account), both of which are described in the Debian Wiki page for Postfix.

Next, go to /etc/postfix/master.cf and uncomment the lines starting with #submission and #smtps. On my machine, it was:

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=$mua_client_restrictions
  -o smtpd_helo_restrictions=$mua_helo_restrictions
  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=$mua_client_restrictions
  -o smtpd_helo_restrictions=$mua_helo_restrictions
  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

Also, add the following line at the bottom of the file for Dovecot:

dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=email:email argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}

Configuring Dovecot

To install Dovecot with the IMAP stack:

sudo apt-get install dovecot-common dovecot-imapd

(You can throw in dovecot-pop3d if you want the POP3 server as well; however, we will focus on IMAP in this tutorial.) Dovecot's configuration files are in /etc/dovecot/conf.d/. To configure the SSL certificates, open 10-ssl.conf and make sure the following three settings are set to:

ssl = required
ssl_cert = </etc/letsencrypt/live/mail.mydomain.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.mydomain.com/privkey.pem

To force SSL/TLS encryption, open 10-auth.conf and uncomment the following line:

disable_plaintext_auth = yes

Next, open the main configuration file 10-master.conf and uncomment the paragraph for Postfix in the auth service block:

service auth {
  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    user = postfix
    group = postfix
    mode = 0660
  }
}

This will create the private/auth path that we set up in the SASL and Postfix will not be able to read it), or alternatively set the mode to 0666. configuration of Postfix. (Postfix runs chrooted in /var/spool/postfix, group lines if they are not present (otherwise the file will be owned by root which is why we put a relative path.) Make sure to either add the user and

Client Configuration

For e-mail clients, your server configuration should now be:

  • Server: example.com
  • User account: user@example.com (full e-mail address)
  • Password: the user's Unix password
  • Protocol: SMTP for sending (authentication required), IMAP for receiving
  • Ports: SMTPS 587 and IMAPS 993

And that's it! You should be good to go, or, most likely and otherwise, able to debug your next configuration errors 😜 You can follow them at:

tail -f /var/log/mail.log

You may need some extra configuration for your e-mail server to survive in the wild, that is to say: defend yourself against spam, and get the proper credentials so that other e-mail providers do not treat you as a spammer. See the follow-up post on SPF and DKIM for instructions on how to do that.

Webography

At the time of writing this post, I learned from articles of the Debian Wiki and the Dovecot Wiki. The tutorial How to set up a simple mail server on Debian in 5 easy steps also helped. Initial details on SSL certification were provided by Switch to HTTPS Now, For Free from Eric Mill's blog (now outdated). When updating this post to Debian 9, I also found this GitHub gist most concise and useful.

Discussion

You can subscribe to this  Discussion's atom feed to stay tuned.

  • Avatar

    Timbo Neko

    Posted on

    This howto has aged quite well, my mail server is doing service for some years now. Apart from the listings, the explanations are really helpful! Thanks for sharing this!

Feel free to post a comment by e-mail using the form below. Your e-mail address will not be disclosed.

📝 You can use Markdown with $\LaTeX$ formulas in your comment.

By clicking the button below, you agree to the publication of your comment on this page.

Opens your e-mail client.