Configuring Dovecot2 IMAP server as part of a full mail solution
One of major parts of creating a mail solution is configuring the IMAP server. I chose Dovecot, because it's fairly simple to understand, it can be easily used to meet moderately sophisticated needs and is very well supported by its author and its community. Also, from a performance/security perspective it has a very good record.
In this article I will go over a number of the settings and provide a configuration approach for dovecot2 that I use to provide service for various domains. I also use Dovecot as the SASL authenticator for Postfix SMTP-AUTH.
I will try to give details about what I'm trying to achieve and why this is sufficient for a competent, experienced unix sysadmin who might not have run an IMAP server or Dovecot before.
Notes about the wider mail environment
- Mail is critical; storage should be on a SAN or similar, preferably with regular snapshots which can be backed up without interrupting or even impacting normal IMAP service. This can be achieved using various commercial SAN software. Or, preferably, one can use open source products such as ZFS on FreeBSD or LVM on Linux.
- If you have many users, multiple servers might be necessary; this adds some complexity, but can be done.
- More often than not for IMAP, you should be spending your time and money on acheiving IO performance rather than worrying about cpu/memory. Filters want cpu/memory, IMAP wants IO.
A few background notes about dovecot
- Before we get started, ensure that dovecot2 is installed and you have created a user and a group for virtual mail; I use vmail and pick a high number: 999.
- A dovecot2 configuration, by default, uses a conf.d directory which includes all the .conf files in order.
- Start small, make a minimal configuration first, test it does what you want/expect and then add complexity. This is especially important if you are not familiar with dovecot.
- Use doveconf -n -c <path to dovecot.conf> to check config files.
- The source comes with a dump of the dovecot wiki, which is an invaluable source of information. The folks on both IRC (#dovecot on freenode) and the mailing list (dovecot@dovecot.org) are very helpful. Be nice and they will assist you.
Configuration details
Mailboxes
conf.d/10-mail.conf:
mail_gid = vmail mail_uid = vmail mail_location = maildir:/var/mailstore/%d/%u/mail
where %d is the domain and %u is the username as described in http://wiki2.dovecot.org/Variables. Also, this is the location for some mail storage settings such as when mailboxes are on NFS and for shared mailboxes, but we'll address those later.
A postmaster address must be defined so that bounces can come from somewhere.
conf.d/15-lda.conf:
postmaster_address = postmaster@allgoodbits.org
Authentication
Dovecot needs to know about accounts. For which accounts should it deliver messages received over LMTP? For which accounts should it serve messages over IMAP? As with most of the dovecot config files, the auth file is extensively commented and mostly fairly self-explanatory.
The Authentication Mechanism that I use is always PLAIN because it is the simplest and easiest to debug in the event that a user is having trouble. SSL/TLS is used to ensure that neither authentication credentials nor messages are sent in the clear aross the network.
A password database is required but a separate user database is optional.
For my minimal config, there are only a few settings of interest.
conf.d/10-auth.conf:
disable_plaintext_auth = yes auth_mechanisms = plain !include auth-sql.conf.ext
conf.d/auth-sql.conf.ext:
passdb { driver = sql args = /etc/dovecot/dovecot-sql.conf } userdb { driver = static args = uid=vmail gid=vmail home=/var/mail/mailstore/%d/%u }
dovecot-sql.conf:
##SQLite #driver = sqlite #connect = /etc/dovecot/dovecot.sqlite ##Postgresql #driver = mysql #connect = host=localhost dbname=mailaccounts user=vmail password=sekrit ##MySQL #driver = mysql #connect = host=localhost dbname=mailaccounts user=vmail password=sekrit password_query = SELECT userid AS username, domain, password \ FROM users WHERE userid = '%n' AND domain = '%d' iterate_query = SELECT userid AS username, domain FROM users
Pick the stanza for your driver and connect parameters correctly.
Password Database
The simplest SQL schema that I can devise that permits virtual users and multiple domains has only three fields:
CREATE TABLE users ( userid VARCHAR(128) NOT NULL, domain VARCHAR(128) NOT NULL, password VARCHAR(64) NOT NULL ); select * from users; dhutty|allgoodbits.org|{SSHA256}q6IJ979Tr3tkQleCxwmJoQY/2ZvScqWxwDsAv0pn1q0yIp/f
My password database always contains a password column that has the password scheme embedded in {} at the beginning of the value, that way neither dovecot nor the admin next looking into the mail setup gets confused about how passwords are hashed.
User Database
The user database needs to know uid, gid, home (in order to find sieve scripts), and possibly mail if you want to override the mail_location setting. In my basic configuration, I just use static values as can be seen in conf.d/auth-sql.conf.ext.
SSL
I'm not interested in offering IMAP service that is not encrypted, but fortunately, it's easy to provide. All you need are the key, the cert and the CA's cert.
conf.d/10-ssl.conf:
ssl_cert = </etc/dovecot/imap.allgoodbits.org.pem ssl_key = </etc/dovecot/imap.allgoodbits.org.key ssl_ca = </etc/dovecot/cacert.pem
Service
Now we actually need to listen for requests. IMAP client connections, authentication connections that allow our SMTP server, postfix, to do SMTP-AUTH and LMTP connections so the SMTP server can hand mail messages to dovecot for local delivery.
conf.d/10-master.conf:
service imap-login { inet_listener imap { port = 0 } inet_listener imaps { port = 993 } } service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { group = postfix mode = 0660 user = postfix } } service auth { # Postfix smtp-auth unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } }
This is now a complete, but fairly bare dovecot2 configuration. There is much extra functionality that can be added and much work might need to be done for performance, scaleability or robustness. But this is a good start.
Plugins
Sieve
At the very least I always add sieve filtering. When dovecot receives a message over LMTP for local delivery, it should be run against a sieve script so that the message can be directed to the desired subfolder of the user's mailbox.
conf.d/20-lmtp.conf:
protocol lmtp { mail_plugins = $mail_plugins sieve }
conf.d/90-plugin.conf:
plugin { sieve = /var/mailstore/%d/%u/.dovecot.sieve }