This chapter of our journey leads us to Dovecot – the software that…
- gets emails destined to your users from Postfix and saves them to disk
- executes user-based sieve filter rules (can be used to e.g. move emails to different folders based on certain criteria or to send automated vacation responses)
- allows the user to fetch emails using POP3 or IMAP
Before we get to the actual configuration for security reasons I recommend that you create a new system user that will own all virtual mailboxes. The following shell commands will create a system group “vmail” with GID (group ID) 5000 and a system user “vmail” with UID (user ID) 5000. (Make sure that UID and GID are not yet used or choose another – the number can be anything between 1000 and 65000 that is not yet used):
groupadd -g 5000 vmail useradd -g vmail -u 5000 vmail -d /var/vmail -m
If the /var/vmail directory was already there because you assigned it a dedicated mount point then you should make sure that the permissions are set correctly:
chown -R vmail:vmail /var/vmail
The configuration files for Dovecot are found in /etc/dovecot/conf.d
/. All these files are loaded by Dovecot. This is done by this magical line at the end of the /etc/dovecot/dovecot.conf
file:
!include conf.d/*.conf
It loads all files in /etc/dovecot/conf.d/
that end in “.conf” in alphanumerical order. So “10-auth.conf” is loaded first and “90-sieve-extprograms.conf” is loaded last. The big advantage is that you can edit or replace parts of the configuration without having to overwrite the entire configuration. The main /etc/dovecot/dovecot.conf
file does not require any changes. Those other files in conf.d/ however do.
conf.d/
10-auth.conf
The most common authentication mechanism is called PLAIN. However if you have Outl**k users then you need to add the LOGIN mechanism, too.:
auth_mechanisms = plain login
These two mechanisms would ask for a password without enforcing encryption to secure the password. But don’t worry. By default Dovecot sets “disable_plaintext_auth = yes” which ensures that authentication is only accepted over TLS-encrypted connections.
At the end of this file you will find various authentication backends that Dovecot ships with. By default it will use system users (those from the /etc/passwd). But we want to use the MariaDB database backend so go ahead and change this block to:
#!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
10-mail.conf
Change the mail_location setting to:
mail_location = maildir:~/Maildir
This is the directory where Dovecot will look for the emails of a specific user. The tilde character (~) means the user’s home directory. That does not make sense yet. But further down on this page we will tell Dovecot what the home directory is supposed to mean. For example john@example.org will have his home directory in /var/vmail/example.org/john.
Further down in the 10-mail.conf file you will find sections defining the namespaces. Those are folder structures that your email program sees when connecting to the mail server. If you use POP3 you can only access the “inbox” – which is where all incoming email is stored. Using the IMAP protocol you get access to a hierarchy of folders and subfolders. And you can even share folders between users. Or use a public folder that can be accessed by anyone – even anonymously. So IMAP is generally to be preferred.
Also edit the “mail_plugins” line to enable the quota plugin we will configure later and turn it into:
mail_plugins = quota
Migrating from a previous server? Check your separator setting!
"/var/vmail/example.org/john/Maildir/.INBOX.staff.marketing.simon".
If you see folders like this…
"/var/vmail/example.org/john/Maildir/INBOX/staff/marketing/simon"
…then please read Dovecot’s notes on the directory structure and the hierarchy separator. Hint: LAYOUT=fs
.10-master.conf
This configuration file deals with typical service ports like IMAP or POP3.
Plaintext services? Really?
So most settings are sane here and do not have to be changed. However one change is required in the “service auth” section because we want Postfix to allow Dovecot as an authentication service. Make it look like this:
# Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix }
Why that strange path? Well, Postfix runs in a chroot environment located at /var/spool/postfix. It can’t access anything outside of that directory. So to allow communication with Postfix we tell Dovecot to place a communication socket into that chroot.
10-ssl.conf
Earlier in this guide you created both a key and a certificate file to encrypt the communication with POP3, IMAPs and HTTPS between the users and your mail server. You need to tell Dovecot where to find these files:
ssl_cert = </etc/letsencrypt/live/webmail.example.org/fullchain.pem ssl_key = </etc/letsencrypt/live/webmail.example.org/privkey.pem
And enforce TLS encryption by setting:
ssl = required
See the Dovecot documentation on SSL encryption for more information.
Next let’s take a look at how Dovecot knows about users and their passwords:
auth-sql.conf.ext
Dovecot reads the auth-sql.conf.ext
which defines how to find user information in your database. Open the file. There are two sections:
- userdb: where to find a user’s mailbox in the file system
- passdb: where to find the user’s hashed password
By default Dovecot will run two queries at your database. One for the userdb that gets information like the user ID, group ID, home directory and quota. And another for the passdb that gets the hashed password.
The “userdb” section already reads:
userdb { driver = sql args = /etc/dovecot/dovecot-sql.conf.ext }
As you can see Dovecot uses an SQL database lookup to get that information. And it refers to the dovecot-sql.conf.ext file for more information. Let’s see…
/etc/dovecot/dovecot-sql.conf.ext
(This configuration file is one level up and not in “conf.d”.)
You will find this file well documented although all configuration directives are commented out. Add these lines at the bottom of the file:
driver = mysql connect = \ host=127.0.0.1 \ dbname=mailserver \ user=mailserver \ password=x893dNj4stkHy1MKQq0USWBaX4ZZdq user_query = SELECT email as user, \ concat('*:bytes=', quota) AS quota_rule, \ '/var/vmail/%d/%n' AS home, \ 5000 AS uid, 5000 AS gid \ FROM virtual_users WHERE email='%u' password_query = SELECT password FROM virtual_users WHERE email='%u' iterate_query = SELECT email AS user FROM virtual_users
Backslashes
What these lines mean:
- driver: the kind of database. MariaDB is the same kind as MySQL.
- connect: where to find the MySQL database and how to access it (username, password)
- user_query: an SQL query that returns the user name (=the email address), the quota, the home directory, user ID and group ID.
- password_query: this SQL query just gets the password hash from the database
- iterate_query: ‘doveadm’ uses this query to get a list of all users. That allows you to use the “doveadm user ‘*'” command later.
The user_query gets several pieces of information from the database. Let’s look at it one by one:
- email AS user
It gets the the email field from the database which corresponds to the user name. Dovecot expects it in the user field so we set an alias to “user”. - userdb_quota_rule
This is the user’s quota in bytes. Think of it as the maximum possible space on disk that the user can occupy. As documented Dovecot expects the quota in a special format like “*:bytes=10000” if the user should not be able to store more than 10,000 bytes. That’s why we begin the string with ‘*:bytes=’. - userdb_home
This leads to the directory where all emails and various control files for this user are located. The placeholder ‘%d’ replaces the domain and ‘%n’ the user part. So for John that makes it “/var/vmail/example.org/john”. - userdb_uid and userdb_gid
Those are the user ID and group ID of vmail user – 5000 for both. Dovecot uses it to set the permissions of files it creates. As all users share the same system user “vmail” this is just a static number.s
Fix permissions
Make sure that only root can access the SQL configuration file so nobody else is reading your database access passwords:
chown root:root /etc/dovecot/dovecot-sql.conf.ext chmod go= /etc/dovecot/dovecot-sql.conf.ext
Restart Dovecot from the shell:
systemctl restart dovecot
Look at your /var/log/mail.log logfile. You should see:
... Dovecot v2.3.13 (f79e8e7e4) starting up for imap, lmtp, sieve, pop3 (core dumps disabled)
If you get any error messages please double-check your configuration files.
Hi, I have 2 questions:
FIRST
I dont have a “/var/log/mail.log” file. Before this debian 12 guide, I was using the debian 11 guide on debian 12 and I had the same issue so I thought that maybe this is because of the version mis-match. Now with this guide I have started with a clean server but still there is no “/var/log/mail.log” file. Can you please help.
SECOND
I am currently using mailinabox as my personal mail service rather than google and microsoft. After setting up this will it work the same as mailinabox. I am asking this because in this guide you talk about setting this up internally for an organisation but I want it to be public just like mailinabox.
Thanks a lot.
1. In some installations there is indeed no syslog daemon installed. Maybe I should mention that. Just do “apt install rsyslog” and you will get the logs.
2. Yes, it does the same. No worries. The mail server will work as a public mail server for your domain(s).
Debian 12 uses the journald out of the iso. rsyslog is an outboard utility that parses the journal into log files adding overhead and additional storage consumption. If you’re using some sort of monitoring software that parses syslogd files, that would be the only reason you need rsyslog.
fail2ban works with journald.
The command I used is ‘journalctl -u dovecot.service’ You can add a “follow” feature with the -f parameter.
Agreeing with the other comments, I also had no /var/log/mail.log but found the correct log entry by running journalctl -u dovecot
I’m running into an odd problem. When I try to authenticate against the database using ‘doveadm auth test ‘ or using Roundcube, some of my users will succeed and some will not. I manually created passwords with ‘doveadmin pw -s BLF-CRYPT’ and entered them via Adminer.
I’ve tried generating a new password string and rewriting this into the database, but this has never fixed any of the non-working accounts.
The database was imported from the Jesse setup that I had running for years. I overwrote the passwords to use the bcrypt mechanism, rather some really old encodings from pre-Jesse versions of the system.
I’ve tried setting a number of flags within Dovecot (auth_verbose, auth_verbose_passwords, auth_debug, and auth_debug_passwords) but all I can see is that the passwords don’t match for the failed case.
Anyone got a better way to debug this?
Thanks,
johnbo
Hi John. I can only guess. Can you create such an entry that does not work and post it here? Perhaps a newline. Perhaps a wrong quote. I haven’t come across that yet.
Hi Christoph,
Thanks for your prompt response. I’m not sure what I was doing wrong. When I looked at all of the steps, they seemed right, however I was doing a lot of cut and pasting to set up the entries within the database. In the end, I went back through each of the users and redid the hash generation, added it to the database and tested it. Doing that, it all worked this time.
I was hoping to reuse the GRS software for this edition, but it looked a bit non-trivial to add to it. But, I may still do that. It would at least get me out of the manual fiddling with the database.
So, in the end, it seems to be working, the testing from doveadm matches the results with Roundcube. The next step will be exposing it to the users.
Thank you for your effort on these guides, it is very much appreciated.
Later,
johnbo
you may need to check for dovecot restart via journalctl instead of /var/log/mail….
i.e. – journalctl -n 20
I can log into an account using mutt but I can’t log in using Thunderbird (115.9.0).
The Dovecot error log shows an SSL alert number 42:
TLS handshaking: SSL_accept() failed: error:0A000412:SSL routines::sslv3 alert bad certificate: SSL alert number 42, session=
I’m using a wildcard domain certificate that is valid for another five weeks. Any ideas about what I missed/misconfigured?
After installing with the Ansible playbook provided at the end of the guide, I couldn’t connect to IMAP because Dovecot failed to authenticate with MariaDB. The error read:
> Access denied for user ‘mailserver’@’localhost’ (using password: YES)
Obviously, the issue here is “localhost”; it should be 127.0.0.1 instead. I manually verified with mysql CLI tool that connections to IP work fine while connections to the hostname failed.
I never figured out the reason. My Dovecot config says 127.0.0.1, restarting Dovecot and/or MariaDB doesn’t help, and there doesn’t seem there’s anything else I can try.
In the end, I simply added a copy of mailserver user with a hostname of “localhost”. This works fine, but I’m still curious what could have gone wrong with the original recipe.
Instead of editing Dovecot’s myriad of config files, I prefer to keep everything in one place:
/etc/dovecot/local.conf
This will be the last config file loaded by Dovecot, if it exists (check the last lines in dovecot.conf), and can in turn override all other settings.
Just make sure to include the directive blocks where necessary. Mine begins like this:
—–
auth_mechanisms = plain login
mail_location = maildir:~/Maildir
mail_plugins = quota
ssl = required
ssl_cert = </etc/letsencrypt/live/example.org/fullchain.pem
ssl_key = </etc/letsencrypt/live/example.org/privkey.pem
# Postfix smtp-auth
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
# Deliver mails locally using dovecot's LMTP
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
# …
—–
I know Christoph advocates against upgrading Debian versions, but I've had very good results with upgrades – and getting all the changed Dovecot config files right was usually one of the most time consuming tasks during the upgrade. Using this local.conf should make the process entirely hassle-free, at least for Dovecot.