Installing Dovecot and sieve on a vpopmail + qmail server

As the openssl project itself pointed out the SSLv3 protocol is not secure, so it's very important to disable it also in dovecot, leaving  TLS as the only allowed protocol. In order to secure your dovecot you have to modify your 10-ssl.conf as follows:

ssl_protocols = !SSLv2 !SSLv3

Timo Sirainen, the dovecot developer, assured yesterday in the mailing list that this can be a good choice, since only very old clients will not be able to do the connection using TLS.


Dovecot is an open source IMAP and POP3 email server for Linux/UNIX-like systems, written with security primarily in mind. Dovecot is an excellent choice for both small and large installations. It's fast, simple to set up, requires no special administration and it uses very little memory.

Dovecot is simple to configure, the project is alive and the documentation is exhaustive. In addition there is the support for vpopmail (while Courier IMAP no more). I found Dovecot so friendly that I decided to switch off qmail-pop3d and use Dovecot not only as an IMAP but also as a POP3 server. I will show how to configure a secure connection as well.

If you want to support filters in your email you have to manage Sieve rules by means of the dovecot-pigeonhole server. When you create a filter with your webmail or email client, you write a Sieve script to customize how messages are delivered, e.g. whether they are forwarded, rejected or stored in special folders. But, in order to do so, Dovecot must also act as a Local Delivery Agent in place of vpopmail/vdelivermail, e.g. it must be Dovecot to store the email messages in the users' Maildirs. This guide will try to show how to accomplish this.


cd /usr/local/src
tar xzf dovecot-2.2.14.tar.gz
chown -R root.root dovecot-2.2.14
cd dovecot-2.2.14

./configure \
        --prefix=/usr/local/dovecot \
        --with-vpopmail \
        --with-sql \
        --with-mysql \
        --with-docs \
        --with-ssl \
        --without-shadow \
        --without-pam \
        --without-ldap \
        --without-pgsql \

Install prefix . : /usr/local/dovecot
File offsets ... : 64bit
I/O polling .... : epoll
I/O notifys .... : inotify
SSL ............ : yes (OpenSSL)
GSSAPI ......... : no
passdbs ........ : static passwd passwd-file checkpassword sql vpopmail
                 : -shadow -pam -bsdauth -sia -ldap
userdbs ........ : static prefetch passwd passwd-file checkpassword sql vpopmail nss
                 : -ldap
SQL drivers .... : mysql
                 : -pgsql -sqlite
Full text search : squat
                 : -lucene -solr

Check if SSL was detected and if the sql/mysql authentication backend is supported. Compile:


If the old dovecot is running, stop it and delete the symbolic link before installing:

dovecotctl stop
rm /usr/local/dovecot
make install

cd /usr/local
mv dovecot dovecot-2.2.14
ln -s dovecot-2.2.14 dovecot
This installs Dovecot in /usr/local/dovecot.


Create the dovecot user/group, the log folder and the directory where to store runtime data.

groupadd dovecot
useradd -g dovecot dovecot
useradd -g dovecot dovenull

mkdir -p /var/log/dovecot 
touch /var/log/dovecot/dovecot.log
chgrp vchkpw /var/log/dovecot/dovecot.log
chmod 660 /var/log/dovecot/dovecot.log

The config files must be copied from the share/doc to etc/dovecot folder

cd /usr/local/dovecot/etc/dovecot
cp -rp /usr/local/dovecot/share/doc/dovecot/example-config/* .

Adjust the MANPATH variable (add this line to your /etc/profile as well):

export MANPATH=$MANPATH:/usr/local/dovecot/share/man

Dowload my dovecot's config files

  • Download from here

If you don't want to have the trouble to modify your conf files and want to follow the directives of this guide you can download my config files and adjust them to your needs.

cd /usr/local/dovecot
mv etc etc-bak
tar xzf dovecot.conf.tar.gz
mv dovecot-etc etc
cd etc/dovecot
chown -R root.root .


protocols = imap pop3
# delete IP6 addresses here
listen = *
dict {
  #quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
  #expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext
!include conf.d/*.conf
!include_try local.conf

Note that all conf.d/*.conf files will be included, so rename what is not needed.


disable_plaintext_auth = yes # we are going to configure SSL and the sql driver requires it
# To append @domain to username in plaintext logins
auth_default_realm =
auth_mechanisms = plain login # the sql drivers requires that the pwd is transmitted with no encryption
# !include auth-system.conf.ext # now commented
# !include auth-vpopmail.conf.ext # commented
!include auth-sql.conf.ext


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

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


NB: the file has now to be edited from the etc/dovecot/ directory

# This file is opened as root, so it should be owned by root and mode 0600.
# Database driver: mysql, pgsql, sqlite
driver = mysql

# Database connection string. This is driver-specific setting.
connect = host=[MySQL IP] dbname=vpopmail user=vpopmail password=[PASSWORD]

# Default password scheme.
default_pass_scheme = MD5-CRYPT

# passdb query to retrieve the password. It can return fields:
password_query = SELECT CONCAT(pw_name, '@', '%d') AS user, \
  pw_passwd AS password, \
  pw_dir as userdb_home, \
  89 AS userdb_uid, \
  89 AS userdb_gid \
  FROM `vpopmail` \
  WHERE pw_name = '%n' AND pw_domain = '%d'

# userdb query to retrieve the user information. It can return fields:
# (Thanks to Arturo Blanco for his hints concerning vpopmail limits)
user_query = \
  SELECT pw_dir AS home, \
  89 AS uid, \
  89 AS gid \
  FROM vpopmail \
  WHERE pw_name = '%n' AND pw_domain = '%d' \
  AND ('%a'!='995' or !(pw_gid & 2)) \
  AND ('%r'!='[WEBMAIL-IP]' or !(pw_gid & 4)) \
  AND ('%r'='[WEBMAIL-IP]' or '%a'!='993' or !(pw_gid & 8))

# [WEBMAIL-IP] is the IP of your webmail web server. 
# I'm assuming that the imap connection is only on port 993 and the pop3 connection is on port 955.
# Adjust to your needs
# logically this means:
# SELECT user
# WHEN POP is not disabled for that user connecting on port 995 (995 is the pop3s port allowed from remote in my configuration)
# AND WHEN webmail access is not disabled for that user when connecting from [WEBMAIL-IP]
# AND WHEN IMAP is not disabled for that user connecting on port 993 (993 is the imaps port allowed from remote 
# in my configuration) unless his remote ip the one belonging to the webmail

# Query to get a list of all usernames.
iterate_query = SELECT CONCAT(pw_name,'@',pw_domain) AS username FROM `vpopmail`

Since this file stores the database password and is open only by root, you must secure the access priviledges:

chmod go-wrx ../dovecot-sql.conf.ext


If you don't want to use the Director service rename the conf file, so that it will not be loaded:

mv 10-director.conf 10-director.conf.disabled


Set your log destination. I prefer to have a dedicated logfile for dovecot (default is syslog)

log_path = /var/log/dovecot/dovecot.log
plugin {


Save the below scriptlet as /etc/logrotate.d/dovecot:

cat > /etc/logrotate.d/dovecot << __EOF__
/var/log/dovecot/*.log {
/usr/local/dovecot/bin/doveadm log reopen


We have to tell Dovecot which is the mailbox location. It will look for the Maildir in the home directory (%h):

mail_location = maildir:%h/Maildir
namespace inbox {
  inbox = yes

Set to 89 (vpopmail userid number) the mail_uid and mail_gid. The same for the valid first/last id as you want to manage only vpopmail users:

mail_uid = 89
mail_gid = 89

mail_privileged_group = 89
mail_access_groups = 89

first_valid_uid = 89
last_valid_uid = 89

first_valid_gid = 89
last_valid_gid = 89

Adjust the socket and the plugin folder:

auth_socket_path = /usr/local/dovecot/var/run/dovecot/auth-userdb
mail_plugin_dir = /usr/local/dovecot/lib/dovecot
mail_plugins = $mail_plugins quota


Read carefully this before continuing.

#default_process_limit = 100
#default_client_limit = 1000

# Default VSZ (virtual memory size) limit for service processes. This is mainly
# intended to catch and kill processes that leak memory before they eat up
# everything.
#default_vsz_limit = 256M

# Login user is internally used by login processes. This is the most untrusted
# user in Dovecot system. It shouldn't have access to anything at all.
default_login_user = vpopmail

# Internal user is used by unprivileged processes. It should be separate from
# login user, so that login processes can't disturb other processes.
#default_internal_user = dovecot

service imap-login {
  inet_listener imap {
    #port = 143
  inet_listener imaps {
    #port = 993
    #ssl = yes

  # Number of connections to handle before starting a new process. Typically
  # the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0
  # is faster. <doc/wiki/LoginProcess.txt>
  #service_count = 1

  # Number of processes to always keep waiting for more connections.
  #process_min_avail = 0

  # If you set service_count=0, you probably need to grow this.
  #vsz_limit = $default_vsz_limit

service pop3-login {
  inet_listener pop3 {
    #port = 110
  inet_listener pop3s {
    #port = 995
    #ssl = yes

service lmtp {
  unix_listener lmtp {
    #mode = 0666

  # Create inet listener only if you can't use the above UNIX socket
  #inet_listener lmtp {
    # Avoid making LMTP visible for the entire internet
    #address =
    #port = 

service imap {
  # Most of the memory goes to mmap()ing files. You may need to increase this
  # limit if you have huge mailboxes.
  #vsz_limit = $default_vsz_limit

  # Max. number of IMAP processes (connections)
  #process_limit = 1024

service pop3 {
  # Max. number of POP3 processes (connections)
  #process_limit = 1024

service auth {
  # auth_socket_path points to this userdb socket by default. It's typically
  # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
  # full permissions to this socket are able to get a list of all usernames and
  # get the results of everyone's userdb lookups.
  # The default 0666 mode allows anyone to connect to the socket, but the
  # userdb lookups will succeed only if the userdb returns an "uid" field that
  # matches the caller process's UID. Also if caller's uid or gid matches the
  # socket's uid or gid the lookup succeeds. Anything else causes a failure.
  # To give the caller full permissions to lookup all users, set the mode to
  # something else than 0666 and Dovecot lets the kernel enforce the
  # permissions (e.g. 0777 allows everyone full permissions).
  unix_listener auth-userdb {
    mode = 0600
    user = vpopmail
    group = vchkpw

  # Postfix smtp-auth
  #unix_listener /var/spool/postfix/private/auth {
  #  mode = 0666

  # Auth process is run as this user.
  user = $default_internal_user

service auth-worker {
  # Auth worker process is run as root by default, so that it can access
  # /etc/shadow. If this isn't necessary, the user should be changed to
  # $default_internal_user.
  user = $default_internal_user

service dict {
  # If dict proxy is used, mail processes should have access to its socket.
  # For example: mode=0660, group=vmail and global mail_access_groups=vmail
  unix_listener dict {
    #mode = 0600
    #user = 
    #group = 


Of course we want SSL support. First of all let's create a self-signed SSL certificate. Dovecot includes a script to build self-signed SSL certificates using OpenSSL; you can find it in doc/

cd /usr/local/src/dovecot/doc will create the SSL certificate. Before running you have to customize the cert editing dovecot-openssl.cnf (in the same folder):

> nano dovecot-openssl.cnf

[ req ]
default_bits = 1024
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type
prompt = no

[ req_dn ]
# country (2 letter code)

# State or Province Name (full name)

# Locality Name (eg. city)

# Organization (eg. company)
O=My Organization Name

# Organizational Unit Name (eg. section)
OU=IMAP server

# Common Name (* is also possible)

# E-mail contact

[ cert_type ]
nsCertType = server

Now we are ready to create the SSL certificate:

> sh

and the files /etc/ssl/private/dovecot.pem and /etc/ssl/certs/dovecot.pem have been created. Remember their locations because you have to insert them in 10-ssl.conf:

ssl_cert = </etc/ssl/certs/dovecot.pem
ssl_key = </etc/ssl/private/dovecot.pem

Remember also to switch off SSLv3 because of security reasons:

ssl_protocols = !SSLv2 !SSLv3


As I already said dovecot will also act as an LDA because we want to manage sieve rules and filter our incoming emails.

postmaster_address =
hostname =

sendmail_path = /var/qmail/bin/sendmail
# the next two to auto create folders
lda_mailbox_autocreate = yes
lda_mailbox_autosubscribe = yes

protocol lda {
  # Space separated list of plugins to load (default is global mail_plugins).
  mail_plugins = $mail_plugins quota # if you want to use sieve put sieve here


## Mailbox definitions

# NOTE: Assumes "namespace inbox" has been defined in 10-mail.conf.
namespace inbox {

  #mailbox name {
    # auto=create will automatically create this mailbox.
    # auto=subscribe will both create and subscribe to the mailbox.
    #auto = no

    # Space separated list of IMAP SPECIAL-USE attributes as specified by
    # RFC 6154: \All \Archive \Drafts \Flagged \Junk \Sent \Trash
    #special_use =

  # These mailboxes are widely used and could perhaps be created automatically:
  mailbox Drafts {
    special_use = \Drafts
    auto = subscribe
  mailbox Junk {
    special_use = \Junk
    auto = subscribe
  mailbox Trash {
    special_use = \Trash
    auto = subscribe

  # 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 {
    special_use = \Sent
    auto = subscribe
#  mailbox "Sent Messages" {
#    special_use = \Sent
#  }

  # If you have a virtual "All messages" mailbox:
  #mailbox virtual/All {
  #  special_use = \All

  # If you have a virtual "Flagged" mailbox:
  #mailbox virtual/Flagged {
  #  special_use = \Flagged


protocol imap {
  mail_plugins = $mail_plugins imap_quota


I don't want the support for proxying to other LMTP/SMTP servers, so I disable lmtp:

mv 20-lmtp.conf 20-lmtp.conf.disabled


protocol pop3 {
  mail_plugins = $mail_plugins quota


If no acl is needed you can disable it:

mv 90-acl.conf 90-acl.conf.disabled


plugin {
# autocreate plugin
# This plugin allows administrator to specify mailboxes that must always 
# exist for all users. They can optionally also be subscribed. The 
# mailboxes are created and subscribed always after user logs in. 
# Namespaces are fully supported, so namespace prefixes need to be used 
# where necessary. 
  autocreate = Sent
  autocreate2 = Drafts
  autocreate3 = Junk
  autocreate4 = Trash
  #autocreate5 = ..etc..
  autosubscribe = Sent
  autosubscribe2 = Drafts
  autosubscribe3 = Junk
  autosubscribe4 = Trash
  #autosubscribe5 = ..etc


To enable maildir++ comment out this line (thanks to Nicolas for the hint!):

quota = maildir:User quota

Adjusting PATH and MANPATH

You may want to modify your environment variable as follows inside your /etc/profile:

export PATH=$PATH:/usr/local/dovecot/bin
export MANPATH=$MANPATH:/usr/local/dovecot/share/man


First of all thanks for this HOWTO!

anyway i'm having a problem with the "doveadm -A" listing "ErrorUser listing returned failure doveadm",

"doveadm mailbox list -u user@domain" is working just fine.

did i miss something?

If you are using vpopmail as a backend, I don't have an answer. It seems like the driver is not programmed to do the iteration..

I have found a way....this is how is working for me:
(this is just for "Trash" ...same for "Junk" ...just change mailbox param)
# MySQL details


# Output sql to a file that we want to run
echo "USE vpopmail; select concat(pw_name,'@',pw_domain) as username from vpopmail;" > /tmp/query.sql;

# Run the query and get the results
results=`mysql -h $HOST -u $USER -p$PWD -N < /tmp/query.sql`;

# Loop through each row
for row in $results
/usr/local/dovecot/bin/doveadm expunge mailbox Trash -u $row savedbefore 30d

Can you believe it! I was facing the same problem with doveadm expunge and found on google your excellent solution inside your comment of my own blog! Thank you..

The exact same thing happened to me once, isn`t it great how networking works!

to makes IMAP quota working with maildir++, you should change these settings :


You should replace quota with imap_quota


You should uncomment this line:

quota = maildir:User quota

I tested it, and it's ok. Thanks for the contribution!

Thanks for this great HOWTO! Just tested it and it's ok!

Pretty good post. I just stumbled upon your blog and wanted to say that I have really enjoyed reading your blog posts. Any way I'll be subscribing to your feed and I hope you post again soon.

Please be patient with a newbie...I've been trying to install qmail on my F16 64 bit home machine for the past 3 weeks but haven't managed to get it running yet but I'm very hopeful despite the many many frustrations. I wanted to know whether i install dovecot after the successful installation of qmail or do i start my dovecot installation 'independent' of the qmail installation. Thanks for the great piece by....

Despite of the fact that you can have a dovecot successfull installation, if you don't have qmail or another MTA installed it doesn't make much sense having an imap server without the smtp service in order to transfer your emails around the world; at least you should have your MTA in another machine. So yes, you should install qmail firstly.

You may want to take a look at this article which shortly explains how all things work together:

Hi Roberto
Thanks for your excellent guide.

I had no problems upgrading from dovecot 2.1.16 to 2.2.0
Instead of using the vpopmail auth driver, I am set up to use the sql driver. I appreciate this might not be what you are trying to achieve, but at least it will allow you to have vpopmail work with dovecot 2.2.0

My relevant configuration:

in /etc/dovecot/conf.d/10-auth.conf:
!include auth-sql.conf.ext

in /etc/dovecot/conf.d/auth-sql.conf.ext:
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
userdb {
  driver = prefetch

in /etc/dovecot/dovecot-sql.conf.ext:
driver = mysql
default_pass_scheme = MD5-CRYPT
password_query = SELECT CONCAT(pw_name, '@', '%d') AS user, \
  pw_passwd AS password, \
  pw_dir as userdb_home, \
  89 AS userdb_uid, \
  89 AS userdb_gid \
  FROM `vpopmail` \
  WHERE pw_name = '%n' AND pw_domain = '%d'

I haven't spent the time looking to see what has happened to the vpopmail auth driver.

Best wishes,
Michael Dick

Hi Michael, thanks for your contribution.

of course the sql drivers works fine now as worked in the past. Anyway this is not the first time that the vpopmail breaks, so your comment is appreciated. Soon or later I should consider to expand this page with the sql driver method.


Has anyone tried with dovecot 2.2.4/2.2.6?
I am having a mysql issue

Oct 27 04:16:46 auth-worker(464): Warning: mysql: Query failed, retrying: Table 'vpopmail.vpopmail' doesn't exist
Oct 27 04:16:46 auth-worker(464): Error: sql(, Password query failed: Table 'vpopmail.vpopmail' doesn't exist

I had tested pop3 login without any issue. Should i downgrade to 2.2.2?


I'm testing version 2.2.6, telnetting port 143, sql driver, and the auth works fine

Then it must be me. Let me try re-installing it again





I had tried 2.2.6 and still having the same error.
My backend is mysql-5.5.34.

ll /var/lib/mysql/vpopmail/
total 64
-rw-rw---- 1 mysql mysql 8836 Oct 27 05:38 subdomain_domain_com.frm
-rw-rw---- 1 mysql mysql   65 Oct 27 02:35 db.opt
-rw-rw---- 1 mysql mysql 9248 Oct 27 03:48 dir_control.frm
-rw-rw---- 1 mysql mysql 8674 Oct 27 03:49 lastauth.frm
-rw-rw---- 1 mysql mysql 8836 Oct 27 03:49 test_com.frm
-rw-rw---- 1 mysql mysql 8832 Oct 27 05:00 vlog.frm

 Any idea?

I tested with mariadb 5.5, that is pretty much the same as mysql 5.5.

But.. are you sure that the table was actually created?

Nic, you really miss the vpopmail table. I have:

-rw-rw---- 1 mysql mysql      65 Nov  8  2012 db.opt
-rw-rw---- 1 mysql mysql    3509 Jul  2 13:15 dir_control.MYD
-rw-rw---- 1 mysql mysql    2048 Jul  2 16:03 dir_control.MYI
-rw-rw---- 1 mysql mysql    9248 Dec 12  2012 dir_control.frm
-rw-rw---- 1 mysql mysql    4185 Oct 27 08:22 lastauth.MYD
-rw-rw---- 1 mysql mysql    2048 Oct 27 08:22 lastauth.MYI
-rw-rw---- 1 mysql mysql    8674 Dec 12  2012 lastauth.frm
-rw-rw---- 1 mysql mysql       0 Dec 12  2012 valias.MYD
-rw-rw---- 1 mysql mysql    1024 Dec 12  2012 valias.MYI
-rw-rw---- 1 mysql mysql    8640 Dec 12  2012 valias.frm
-rw-rw---- 1 mysql mysql 8183044 Oct  1 14:43 vlog.MYD
-rw-rw---- 1 mysql mysql 3813376 Oct  1 16:08 vlog.MYI
-rw-rw---- 1 mysql mysql    8832 Dec 12  2012 vlog.frm
-rw-rw---- 1 mysql mysql    8970 Dec 12  2012 vpopmail.frm

create again the domain and check if it is created.


I had deleted the existing domains and re-added them again.
vpopmail.frm is still no where to be found.

I had checked my other production servers, they are working fine
and yet there isn't any vpopmail.frm also.

Pretty weird. Google has no answer too.


as said above, the problem should be the configuration of vpopmail with

--enable-many-domains     Creates a table for each virtual domain instead of storing all users in a single table. Only valid for MySQL and PostgreSQL

Hi Roberto,

I had configured vpopmail with --disable-many-domains

I had figured out if i use

!include auth-vpopmail.conf.ext

but not

!include auth-sql.conf.ext

I have no problem. Because the latest guide instructs to use auth-sql, Dovecot looks for vpopmail.frm instead.

I don't know by doing is this correct. Please correct me.

Many thanks again


yes if you use the vpopmail driver you don't have to adjust the sql query. I switched to the mysql/sql drivers since the vpomail one was not working for me, but it's interesting to know that you have it working

I correct myself. It appears that you configured vpopmail to use separate tables for each domain, so you have to modify the auth query accordingly, since it is looking for a common table 'vpopmail'


Understand now

Many thanks


Ok, please post the query that should be used in case of many domains if you can

Hi everybody,

just to let you know after a few month of testing I have successfully migrated my old qmailrocks / fedora 6 istallation on a new,

virtualized Centos 6.5 - 64 bit qmail+vpopmail+roundcube+all the other goodies here described.

Everything works fine ! a big thank you to Roberto for this great guide !

BTW, I'm using dovecot 2.2.13 and it works perfectly.

The only problem experienced is related to some POP3 clients re-downloading all the email, even if I have used the script; mostly some MAC+thunderbird.

Cheers up !