Posted:
E-Mail Done My Way, Part 2 - dovecot
0. | The Journey - The basics and outlook (on the series, not the Microsoft mail client ;) |
1. | Postfix - the in and out, so to say. The robust, battle-hardened connection point for other mail servers on the internet to send emails to and receive emails from your domain(s). Also known as the MTA, the Mail Transfer Agent. |
2. | Dovecot - where you and your users talk to to get emails to their mail client, be it your smartphone, a mail client on your computer or just even the command line. It’s the IMAP server. |
3. | DKIM/DMARC/SPF - Just having postfix and dovecot up and running isn’t enough. We will also look at user authentication, letsencrypt certificates, DKIM, DMARC, SPF and the daily checks to make sure everything is humming along nicely. |
4. | The final stuff - How to make sure my e-mail server is happy and can do its job. Some simple checks, how to use fail2ban to keep bad servers and users away, checking log files, all those little things. |
After we learned about my general approach and setup in part 0, the details of my postfix configuration in part 1 it is now time to look at how I use dovecot.
WARNING: This series is not for people trying to set up their first ever email server. I expect readers to know the basics and have some experience with dovecot.
In part 1 we saw how emails from other servers arrive at postfix and get either rejected (spam, bots) or accepted. Now we will talk about what happens after the e-mail gets accepted and handed over from postfix to dovecot. But that’s not the only job dovecot has. It also serves as my imap server, meaning its also talking to my various mail clients on my laptop, phone and iPad.
We will do it the same as before, by going through the config files and I will explain what settings I have changed and why. Ready? OK. Here we go again :)
dovecot.conf
Whereas with postfix we made a lot of changes to the main config file /etc/postfix/main.cf
, in /etc/dovecot/
we have to deal with many more files, mostly in the conf.d
subdirectory. The top level config file, /etc/dovecot/dovecot.conf
only needs one line to be changed:
# Protocols we want to be serving.
protocols = imap lmtp
That’s it. All the rest in the file stays as it is. This tells dovecot that we are going to use two protocols. imap to talk to e-mail clients and lmtp to talk to postfix.
passwd
There’s another very important file in this top level directory - /etc/dovecot/passwd
. This is where we store the (hashed, salted) passwords of all e-mail users. As I explained in part 1, we do NOT use local users on the system, we ONLY have users defined in this passwd file.
Here’s a user definition in that file:
user1@tcpid.org:{SSHA256}lOD2+5I3qY4UqRllY8SY6F9eJEBWhkvIdHgF9Av21ZUZuagf:1003:1003::/var/mail/vmail/tcpid.org/user1::
It is important to have the colons at all the right places and the correct parameters, so let’s go through them. user1@tcpid.org
is the e-mail address which also doubles as the username when logging in via imap. Next comes the password, which is a salted SHA256 - hence SSHA256 - hash that you can create with the following command:
doveadm pw -s SSHA256
Enter new password:
Retype new password:
{SSHA256}lOD2+5I3qY4UqRllY8SY6F9eJEBWhkvIdHgF9Av21ZUZuagf
Here I typed in a password twice and got the hash, that I can now add to the line in the passwd file.
Now, as explained in part 1, all incoming e-mails for all domains are handled by the virtual mail config with a single user called vmail. The next two entries, the :1003:1003
are the UID of the user and group. Now a double colon ::
followed by the path to the Maildir of this e-mail address, using the pattern /var/mail/vmail/<DOMAIN>/<USER>
and a double colon ::
at the end. That’s the full definition of an e-mail account in dovecot.
So when I want to add a new e-mail address, I just add a new line to this file. That’s it.
Let’s move into the conf.d
subdirectory that has many files. We don’t need to change them all. But still, quite a few. Let’s work through them!
/conf.d/10-auth.conf
This file defines the authentication process. We want to use just username and passwords as defined in the passwd
file, nothing more. No pam, no LDAP, no local users, no databases. - BUT we will NOT allow logins via unencrypted connections. It all MUST go through TLS. Hence we need 4 changes
disable_plaintext_auth = yes
This makes sure we have to use a TLS connection before authentication can happen.
auth_username_format = %Lu
This forces us to use the full e-mail address as username. Important, because at least I use the same local user for several domains and I want to have them clearly separated with different passwords and maildirs.
Unfortunately many companies out there still haven’t learned that the local part (the part before the @ symbol) indeed is case-sensitive, so jan@ and JAN@ are technically different e-mail recipients. That’s why we put in the %L
which turns everything to lowercase, so no matter if you send to Jan@, jan@, JAN@ or jAn@ - it all gets moved to jan@.
auth_mechanisms = plain login
This makes sure we can use the username/password way to authenticate. And because we have made sure that there must be a TLS connection, we can safely use the plain
method. login
is a quirky variant of plain, mainly for Microsoft Outlook users. Not strictly needed for me, as I’d never touch Outlook, but who knows, other users might. So let’s leave it there. Doesn’t hurt.
#!include auth-deny.conf.ext
#!include auth-master.conf.ext
!include auth-vmail.conf.ext
#!include auth-system.conf.ext
#!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-static.conf.ext
And now we disable all authentication mechanisms except auth-vmail.conf.ext
which points to the passwd
file mentioned earlier. We’ll get to that.
/conf.d/10-logging.conf
This file defines what goes to the logfile. One single change is needed here, to make sure we catch the bots trying many username/passwords combinations to brute-force their way in, trying to turn our mailserver in a spam factory.
# Log unsuccessful authentication attempts and the reasons why they failed.
auth_verbose = yes
By adding this to the logfile, fail2ban can pick up these evil bots and block them. How that works well be in part 3 of this series.
All the rest stays as is.
/conf.d/10-mail.conf
This file defines the location of the maildir, so we make sure it all ends up in /var/mail/vmail/<DOMAIN>/<USER>/Maildir/
mail_location = maildir:~/Maildir
/conf.d/10-master.conf
In this file we define the protocols and the communication via lmtp with postfix. The protocol definitions can stay as they are, we do imap and imaps (with TLS), we don’t care about the other definitions like pop3 because, well, we don’t use them.
We do however have to set up the lmtp connection to postfix with:
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
and add:
unix_listener /var/spool/postfix/private/auth {
mode = 0600
user = postfix
group = postfix
}
to the service auth
section in this file.
/conf.d/10-ssl.conf
Now we can define SSL/TLS. As explained before, we use letsencrypt for getting and updating the certificate files. So now we need to tell postfix where it can find the public and private cert files and that SSL/TLS is required:
ssl = required
ssl_cert = </etc/letsencrypt/live/mailhub.wildeboer.net/fullchain.pem
ssl_key = </etc/letsencrypt/live/mailhub.wildeboer.net/privkey.pem
Dovecot also needs a dh.pem
file for forward secrecy. This is generated with the command (we use 4096 bits):
openssl dhparam -out /etc/dovecot/dh.pem 4096
And added to the config file with:
ssl_dh = </etc/dovecot/dh.pem
Finally we want to make sure we use known good parameters with safe defaults by adding:
ssl_min_protocol = TLSv1.2
And that’s it.
/conf.d/15-mailboxes.conf
When you first connect to the mailserver to fetch your e-mails, dovecot will set up your maildir. This file tells it what folders to add by default in the namespace inbox
section:
# These mailboxes are widely used and could perhaps be created automatically:
mailbox Drafts {
auto = create
special_use = \Drafts
}
mailbox Junk {
auto = create
special_use = \Junk
}
mailbox Trash {
auto = create
special_use = \Trash
}
# For \Sent mailboxes there are two widely used names. We'll mark both of
# them as \Sent. User typically deletes one of them if duplicates are created.
mailbox Sent {
auto = create
special_use = \Sent
}
mailbox "Sent Messages" {
special_use = \Sent
}
Just the typical Drafts, Junk, Trash and Sent folders that most mail clients expect to find.
/conf.d/auth-vmail.conf.ext
And finally the vmail authentication:
# Virtual user auth config
mail_location = maildir:~/Maildir
passdb {
driver = passwd-file
args = /etc/dovecot/passwd
}
userdb {
driver = static
args = uid=vmail gid=vmail username_format=%u home=/var/mail/vmail/%d/%n
}
Here we tell dovecot that passwords can be checked with the passwd
file, that users can be found using the static
driver, which uses the vmail
user and group, that the full e-mail address is the username (%u) and that we switch the logged in users to their correct mail directory under `/var/mail/vmail/
And done
And that’s it! When all of this is set up correctly, the directory /var/mail/vmail is owned by the vmail user, postfix is up and running as described in part 1, we can start dovecot and enjoy the flow of mails coming in and going out.
Comments and tips for an even better configuration are very welcome! Either via Mastodon (see below) or, if you prefer, as issue or maybe even a pull request at the repository that generates this blog:
https://codeberg.org/jwildeboer/jwildeboersource
But we still have a lot of other things to do. SPF, DKIM, DMARC. That will be in:
COMMENTS
You can use your Mastodon or other ActivityPub account to comment on this article by replying to the associated post.