Setting up Dovecot

This chapter of our journey leads us to Dovecot – the software that…

  • gets emails 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 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 in the dovecot.conf file:

!include conf.d/*.conf

It loads all files in /etc/dovecot/conf.d/ that end on “.conf” in sorted order. So “10-auth.conf” is loaded first and “90-quota.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 need to be edited…



If your users are still using Outlook Express (Windows XP) or Microsoft Mail (Windows Vista) then you need to add the “LOGIN” authentication mechanism in addition to the standard “PLAIN” mechanism:

auth_mechanisms = plain login

These are plaintext (unencrypted) ways to transmit a mail user’s 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 uses. By default it will use system users (that are listed in /etc/passwd). But we want to use the MySQL 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-vpopmail.conf.ext
#!include auth-static.conf.ext

Now edit the SQL configuration file:


Change the “userdb” section to:

userdb {
  driver = static
  args = uid=vmail gid=vmail home=/var/vmail/%d/%n

The placeholder %d stands for the domain part and %n for the user part if you have an email address like “user@domain”. Dovecot’s variables are documented on their website.


Change the mail_location setting to:

mail_location = maildir:/var/vmail/%d/%n/Maildir

This is the directory where Dovecot will look for the emails of a specific user. So for this leads to “/var/vmail/”.

Further down you will find sections defining the namespaces. These namespaces 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 stores. Using the IMAP protocol you get access to a hierarchy of folders and subfolders. And you can even use folders shared between users. Or public folder that could be accessed by anyone – even anonymously.

Look for the “namespace inbox” section. If you already have emails stored on your server from previous versions of this ISPmail guide you need to change:

separator = .

here. By default the seperator is “/” which creates a directory structure like “/var/vmail/”. This is perfectly fine. But previous ISPmail guides used “.” as a seperator so the mentioned folder would rather have been “/var/vmail/”.


This configuration file deals with services that allow communication with other processes. For example it enables or disables POP3 or IMAP. Don’t worry about the standard unencrypted TCP ports 110 (for POP3) and 143 (for IMAP). They can be kept accessible. If a user connects to these ports they will have to issue a STARTTLS command to switch into encrypted mode before they are allowed to send their password. There is basically no difference between using an plaintext port like 110 for POP3 and then using STARTTLS – or connecting to the encrypted 995 port for POP3S (=secure). See the Dovecot documentation for another explanation.

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. This is what has to be entered:

# 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 use the communication socket file in that chroot area.


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/
ssl_key = </etc/letsencrypt/live/

And enable TLS/SSL encryption by setting:

ssl = yes

You could also set “ssl=required” but as Dovecot disallows sending plaintext passwords over unencrypted connections anyway we don’t actually need it. See the Dovecot documentation on SSL encryption for more information.


You should also add these lines within your “namespace inbox” section:

 mailbox INBOX.Junk {
  auto = subscribe
  special_use = \Junk
 mailbox INBOX.Trash {
  auto = subscribe
  special_use = \Trash

It ensures that a “Junk” and a “Trash” folder are created within the inbox when a user logs in. The user is also automatically subscribed to these folders. (When using IMAP you can choose which folder you want to see by subscribing them.) The “Junk” folder is required so that we can move spam emails to it – we will configure that later. And the “Trash” folder is required so that users using the Roundcube web mailer can actually delete emails.

The names used in “special_use” refer to the special-use mailboxes as described in the RFC 6154.


This file is referred to by /etc/dovecot/conf.d/auth-sql.conf.ext. It tells Dovecot how to access the MySQL database and where to find the information about email users/accounts. You will find it well documented although all configuration directives are commented out. Add these lines at the bottom of the file:

driver = mysql
connect = host= dbname=mailserver user=mailuser password=ChangeMe  <- use your database access password instead
default_pass_scheme = SHA256-CRYPT
password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';

What these lines mean:

  • driver: the kind of database
  • connect: where to find the MySQL database and how to use it (username, password)
  • default_pass_scheme: the format in which the passwords are stored (we use strong salted SHA256 hashes)
  • password_query: an SQL statement that returns the user (=the email address) and the password (SHA256 hash) from the database where “%u” is the login user name (=we use the email address as the user name of an email account). Whenever Dovecot needs to check an email user’s password if will run the above query and verify the password against the hash in the database.

Finishing move

You should also 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:

service dovecot restart

Look at your /var/log/mail.log logfile. You should see:

... dovecot: master: Dovecot v2.2.27 (c0f36b0) starting up for imap, lmtp, sieve, pop3 (core dumps disabled)

If you get any error messages please double-check your configuration files.

20 thoughts on “Setting up Dovecot

  • 2018-01-21 at 14:43

    Hi Christoph,
    Concerning 10-ssl.conf it seems that your text has not be updated since the jessie version. Could you explain how to set up 10-ssl.conf with the let’sEncrypt certificate? Thanks.

    • 2018-01-21 at 16:31

      Thanks for the hint, François. I wonder how I missed to change that.

  • 2018-01-22 at 22:47

    Hi Christoph
    The section about the separator “separator = .” implies that only legacy installations should use the dot as separator but later it is used in the config too – maybe a bit of clarification would help.

    • 2018-01-23 at 08:05

      Hmmm. What I wrote:

      “By default the seperator is “/” which creates a directory structure like “/var/vmail/”. This is perfectly fine. But previous ISPmail guides used “.” as a seperator”

      Where do you mean “later”? I currently don’t see where I mention that.

      • 2018-01-23 at 22:14

        Hi Christoph,

        are you sure about the directory structure?

        According to it only sets the mailbox structure, which must not be the same like the directory structure?
        I tested it and only with LAYOUT=fs the folders are really created without the structure.


      • 2018-01-25 at 22:24

        sorry for not being more clear on this – I meant later in the guide not on this page – specifically in the rspamd config you include INBOX.Junk which if I am not wrong would only exist in the legacy notation using the dot.

  • 2018-01-23 at 15:39

    Is it expected that at the time you modify 10-master.conf, the file /var/spool/postfix/private/auth is not present?

    • 2018-01-23 at 21:42

      In fact the configuration change in 10-master.conf will make Dovecot *create* that socket there so that Postfix can access it. Before the change the socket shouldn’t be there. Is that what you mean?

      • 2018-01-23 at 22:41

        Right, I noticed that later with the lmtp socket. Thanks 🙂

  • 2018-01-23 at 15:44

    Also a question on namespaces inbox; by default there’s already “Junk” and “Trash” mailboxes – I guess those can be left in?

    • 2018-01-23 at 21:40

      Could you try with the default settings? I believe that because I’m on a legacy test installation here I needed INBOX.Junk. But with a fresh installation and “separator=/” it might be actually correct to use “Junk”.

      • 2018-01-23 at 22:43

        Ah, the difference seems to be that “Junk” just puts the folder outside “INBOX”. For personal preference, I just added “auto = subscribe” to the defaults. (which worked in roundcube and email clients)

  • 2018-01-25 at 04:17

    In my auth-sql.conf.ext file was the passdb commented.
    After adding

    passdb {
    driver = sql
    # Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
    args = /etc/dovecot/dovecot-sql.conf.ext

    I was able to connect to the IMAP account.

  • 2018-01-27 at 22:10

    In 15-mailboxes.conf there’s already :

    # NOTE: Assumes “namespace inbox” has been defined in 10-mail.conf.
    namespace inbox {
    # These mailboxes are widely used and could perhaps be created automatically:
    mailbox Drafts {
    special_use = \Drafts
    mailbox Junk {
    special_use = \Junk
    mailbox Trash {
    special_use = \Trash

    • 2018-01-27 at 22:12

      Ok, I just modified the subscription. No pb

  • 2018-02-14 at 13:37

    Hi Christoph,

    While I wait for the section “enforcing mail quotas” I tried the following configuration and it worked, sure there are some improvements to make. Thanks for the guide!!!!

    mysql> ALTER TABLE `virtual_users` ADD `quota_kb` INT NOT NULL

    Enabling quota plugins


    mail_plugins = $mail_plugins quota


    protocol imap {
    mail_plugins = $mail_plugins imap_quota


    uncomment sql:

    userdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf.ext

    comment static:

    #userdb {
    # driver = static
    # args = uid=vmail gid=vmail home=/var/vmail/%d/%n

    Add user_query on: /etc/dovecot/dovecot-sql.conf.ext

    user_query = SELECT CONCAT(‘/var/vmail/’,CONCAT(SUBSTRING_INDEX(email,’@’,-1),’/’,SUBSTRING_INDEX(email,’@’,1))) AS home, 5000 AS uid, 5000 AS gid, CONCAT(‘*:storage=’,quota_kb) AS quota_rule FROM virtual_users WHERE email=’%u’;

    • 2018-02-15 at 10:43

      Beware of the backquotes here, they should be replaced with single quotes (apostrophes) otherwise the query will fail.

  • 2018-04-05 at 18:35

    So your user DB setting works for delivering mail, but doveadm cannot enumerate the users on the system which is needed to get mailbox replication working

    I recognise that’s a feature that may be a little more advanced than you target audience needs, but I found it useful.
    I set the userdb section to read
    userdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf.ext
    and in the dovecot-sql.conf.ext I set the user query and iterate query as
    user_query = SELECT CONCAT(‘/var/vmail/’,(SELECT name FROM virtual_domains WHERE id=domain_id),’/’,REPLACE(‘%u’,CONCAT(‘@’,(SELECT name FROM virtual_domains WHERE id=domain_id)),”)) AS home, 5000 AS uid, 5000 AS gid FROM virtual_users WHERE email =’%u’;
    iterate_query = SELECT email AS username FROM virtual_users;

    This allows doveadm to find all users set on the system using the command `doveadm users ‘*’`

    The dovecot page linked explains how to set up replication once that’s working if you’re interested.

  • 2018-04-30 at 18:33

    I would highly recommend doing the following in the 10-mail.conf instead:
    mail_home = /var/vmail/%d/%n
    mail_location = maildir:~/Maildir

    If you do not define a mail_home, you will end up with conflicts with the sieve folder and the .dovecot.sieve files created for the filters in Roundcube.
    Especially if the separator is a dot (.)

  • 2018-06-12 at 17:25

    The default dovecot SSL configuration – even in the latest version – is not secure. I strongly recommend adding these three lines to the guide (in 10-ssl.conf):

    ssl_protocols = !SSLv3 !TLSv1 !TLSv1.1
    ssl_prefer_server_ciphers = yes

    This disabled SSLv3, TLSv1 and TLSv1.1 (i.e. it only allows TLS 1.2).
    It also disables lots of old insecure ciphers.


Leave a Reply

Your email address will not be published. Required fields are marked *