[2018-01-07]

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…

conf.d/

10-auth.conf

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:

auth-sql.conf.ext

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.

10-mail.conf

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 john@example.org this leads to “/var/vmail/example.org/john/Maildir”.

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/example.org/john/Maildir/INBOX/staff/marketing/simon”. This is perfectly fine. But previous ISPmail guides used “.” as a seperator so the mentioned folder would rather have been “/var/vmail/example.org/john/Maildir/.INBOX.staff.marketing.simon”.

10-master.conf

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.

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 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.

15-mailboxes.conf

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.

/etc/dovecot/dovecot-sql.conf.ext

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=127.0.0.1 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.

24 thoughts on “Setting up Dovecot

  • 2018-01-21 at 14:43
    Permalink

    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.
    François

    Reply
    • 2018-01-21 at 16:31
      Permalink

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

      Reply
  • 2018-01-22 at 22:47
    Permalink

    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.

    Reply
    • 2018-01-23 at 08:05
      Permalink

      Hmmm. What I wrote:

      “By default the seperator is “/” which creates a directory structure like “/var/vmail/example.org/john/Maildir/INBOX/staff/marketing/simon”. 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.

      Reply
      • 2018-01-23 at 22:14
        Permalink

        Hi Christoph,

        are you sure about the directory structure?

        According to https://wiki.dovecot.org/Namespaces#Hierarchy_separators 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 .foo.bar structure.

        Regards,
        Andy

        Reply
      • 2018-01-25 at 22:24
        Permalink

        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.

        Reply
  • 2018-01-23 at 15:39
    Permalink

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

    Reply
    • 2018-01-23 at 21:42
      Permalink

      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?

      Reply
      • 2018-01-23 at 22:41
        Permalink

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

        Reply
  • 2018-01-23 at 15:44
    Permalink

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

    Reply
    • 2018-01-23 at 21:40
      Permalink

      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”.

      Reply
      • 2018-01-23 at 22:43
        Permalink

        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)

        Reply
  • 2018-01-25 at 04:17
    Permalink

    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.

    Reply
  • 2018-01-27 at 22:10
    Permalink

    Hi,
    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
    }

    Reply
    • 2018-01-27 at 22:12
      Permalink

      Ok, I just modified the subscription. No pb

      Reply
  • 2018-02-14 at 13:37
    Permalink

    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

    conf.d/10-mail.conf:

    mail_plugins = $mail_plugins quota

    conf.d/20-imap.conf:

    protocol imap {
    mail_plugins = $mail_plugins imap_quota

    /etc/dovecot/conf.d/auth-sql.conf.ext

    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’;

    https://workaround.org/wp-content/uploads/2008/12/ISPmail-tutorial-for-Debian-Lenny.pdf
    https://wiki2.dovecot.org/Quota
    https://wiki2.dovecot.org/Quota/Configuration

    Reply
    • 2018-02-15 at 10:43
      Permalink

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

      Reply
  • 2018-04-05 at 18:35
    Permalink

    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 https://wiki.dovecot.org/Replication

    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.

    Reply
  • 2018-04-30 at 18:33
    Permalink

    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 (.)

    Reply
  • 2018-06-12 at 17:25
    Permalink

    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
    ssl_cipher_list = EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:EDH+aRSA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED

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

    Reply
  • 2018-09-21 at 14:24
    Permalink

    It is unclear if the separator in 10-mail.conf should be set = . or / not specified.

    Reply
  • 2018-10-22 at 08:41
    Permalink

    Is it necessary to set Junk and Trash folder within the INBOX?

    INBOX.Junk
    INBOX.Trash

    Can I set it like this?

    mailbox Junk {
    auto = subscribe
    special_use = \Junk
    }
    mailbox Trash {
    auto = subscribe
    special_use = \Trash
    }

    Reply
    • 2018-10-27 at 07:46
      Permalink

      I prefer to have them outside of INBOX too, so I did as you did and it works fine.
      Just remember to adjust for this in the rest of the guide to avoid conflicts.

      Reply
  • 2018-11-17 at 14:22
    Permalink

    Thanks for great tutorial!

    After reading this I feel one part is missing and I’d really appreciate if you could update or at least explain it. I’m trying to add custom sieve rules for my virtual users that can be managed via DB. I see some bit and pieces in pigeonhole documentation: https://wiki.dovecot.org/Pigeonhole/Sieve/Configuration/Dict but unfortunately it is not clear how it can be achieved.
    Any help will be appreciated.

    Reply

Leave a Reply

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