I started this small project a while back for my own use and over the course of several years the Infrastructure I had planned came together. I can't really recall when I started getting interested in all this mail stuff. I've always been fascinated by any kind of communications technology. I think it must have been a year or two before I transitioned into an Email/LDAP administrator role at a former enterprise company. In any case, despite the difficulties that Email technology undoubtedly brings I am quite proud of what I've accomplished. Everything was and still is a learning process. Here is some basic info.


Mail Layout

I'm not really a fan of the POP/POP3 protocols, so the Infrastructure uses IMAP by default. IMAP mail is synced and replicated between two Dovecot hosts using dsync. This works great alongside the ManageSieve protocol for server-side mail filtering. For SMTP there are three MX hosts. TLS on port 587 with required LDAP authentication.

As for the backend, from what I can tell it seems to be far more common to see some kind of SQL deployment used and not really Directory Services like LDAP. For instance, virtual users are commonly stored in a MySQL database and are managed using the PostfixAdmin web based interface. Rather than SQL, I opted for OpenLDAP to store all virtual information. This includes mailboxes, aliases, domains and mail distribution groups. I use OpenLDAP exclusively for most services. The great thing that I really like about this kind of setup is how well replication over TLS between the LDAP master and child hosts works. I know replication also exists with SQL servers like MySQL/MariaDB and PostgreSQL, but honestly I'm not a big fan of using SQL for mail services.

There is a shiny webmail instance powered by Roundcubemail that of course does use SQL for it's backend database. Roundcubemail is also tied into OpenLDAP, so users can use their LDAP credentials to login. Some useful plugins that are already available:

  1. Sieve mail rules
  2. Password
  3. PGP
  4. 2-Factor Auth using TOTP compatible app such as google-authenticator


The mail infrastructure incorporates OpenDKIM and SPF. I'm not going to go into the specifics of OpenDKIM and SPF here, but basically mail sent from any of the LDAP loaded domains will be validated as not spam by evaluating the authenticity of a particular message.

SpamAssassin is also used in conjunction with ClamAV - an open source standard for mail gateway scanning software. Here is an example showing valid OpenDKIM signing and SpamAssassin scanning from the mail headers.

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;;
    s=mail; t=1500851753;
X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on
X-Spam-Status: No, score=-1.1 required=5.0 tests=ALL_TRUSTED,DKIM_SIGNED,
    DKIM_VALID,DKIM_VALID_AU autolearn=ham autolearn_force=no version=3.4.1
Received: from [] (localhost)
    (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
    (No client certificate requested)
    (Authenticated sender: tony)
    by (Postfix) with ESMTPSA id B2508202D4;
    Sun, 23 Jul 2017 16:15:52 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;;
    s=mail; t=1500851752;


I've written some useful tools to help manage LDAP records. For example, I have some simple interactive scripts to help with creating new mail accounts and mail distribution groups. Apache Directory Studio is also a great desktop application to manage Directory Services like LDAP.


The Dovecot wiki does a really good job at explaining how to have Dovecot and OpenLDAP work together, but in this post I will describe the steps I took to configure Dovecot to work with OpenLDAP on a Linux host.

LDAP authentication

As described in the wiki - Dovecot offers two ways to perform LDAP authentication, but I chose LDAP password lookups. This is recommended over authentication binds.


Normally !include auth-system.conf.ext is enabled, but this should be commented and !include auth-ldap.conf.ext uncommented.


passdb {
  driver = ldap

userdb {
  driver = ldap
  args = /etc/dovecot/dovecot-ldap.conf.ext
  default_fields = home=/home/vmail/%d/%u

Here we're simply telling Dovecot to use LDAP instead of PAM or MySQL, respectively. For default_fields I'm using a domain/user structure as referenced by the %d and %u variables you can pass to Dovecot. Following this was configuring the relevant options in dovecot-ldap.conf.ext.


hosts =
auth_bind = no
dn = uid=dovecot,ou=System,dc=domain,dc=net
dnpass = MyP@sswd
ldap_version = 3
base = ou=Mail,dc=domain,dc=net
deref = never
scope = subtree
default_pass_scheme = SSHA

# user filter
user_attrs = mailHomeDirectory=home,mailStorageDirectory=mail,mailUidNumber=uid,mailGidNumber=gid,mailQuota=quota_rule=*:bytes=%$
user_filter = (&(objectClass=inetOrgPerson)(uid=%n)(mailEnabled=TRUE))

# password filter
pass_attrs  = mail=user,userPassword=password
pass_filter = (&(objectClass=inetOrgPerson)(uid=%n))

iterate_attrs = mail=user
iterate_filter = (objectClass=inetOrgPerson)

Because I am using specific LDAP attributes shown in both user_attrs and user_filter I needed to get postfix-book.schema loaded into OpenLDAP.


While I use a global quota I also like the option of setting user specific quotas. Since I'm using postfix-book.schema in OpenLDAP, mailQuota=quota_rule=*:bytes=%$ works just fine so that the mailQuota attribute can be added to mail user records.



One last thing I needed to do was tell PAM that Dovecot should use LDAP for authentication. This involved editing /etc/pam.d/dovecot with the following

auth    required nullok
account required


Once everything has been verified the last thing is to restart Dovecot. With systemd one can execute systemctl restart dovecot. It's also a good idea to verify no errors are shown in the mail log usingtail -f /path/to/mail.log.