Postfix + Dovecot with LDAP Integration: Continuation
Purpose:
Configure Postfix and Dovecot to use OpenLDAP for alias resolution and mailbox delivery, allowing one real mailbox (testuser@example.com
) to receive mail for many virtual addresses (e.g., admin, webmaster, postmaster).
This is part two and if you missed part one it is here.
Step 0: Prerequisites
- Operating System: Debian 12
- LDAP server running at
ldap://127.0.0.1
, basedc=example,dc=com
- phpldapadmin installed (optional for LDAP entry management)
- Root or sudo access
Step 1: Install Required Packages
apt update -y
apt install -y \
postfix postfix-ldap \
dovecot-core dovecot-imapd dovecot-pop3d dovecot-ldap dovecot-lmtpd \
sasl2-bin libsasl2-modules mailutils mutt
- Postfix: main MTA and LDAP lookup support
- Dovecot: IMAP, POP3, LMTP, LDAP auth
- mailutils & mutt: testing clients
During Postfix install, choose “Internet Site” and set example.com
as the mail name if it shows something else.
Step 2: Configure Postfix for LDAP Lookups
2.1 LDAP Aliases (/etc/postfix/ldap-aliases.cf
)
vim /etc/postfix/ldap-aliases.cf
Add:
version = 3
server_host = 127.0.0.1
server_port = 389
# point at your people tree
search_base = ou=people,dc=example,dc=com
scope = sub
bind = no
# match ONLY on mailAlias
query_filter = (&(objectClass=mailAccount)(mailAlias=%s))
# return the real mailbox
result_attribute = mailAddress
# If you add the following line you get a listing of all of the user aliases.
# result_attribute = mailAlias
timeout = 5
2.2 LDAP Mailboxes (/etc/postfix/ldap-mailboxes.cf
)
vim /etc/postfix/ldap-mailboxes.cf
Add:
version = 3
server_host = 127.0.0.1
server_port = 389
search_base = ou=people,dc=example,dc=com
scope = sub
bind = no
query_filter = (&(objectClass=posixAccount)(mailAddress=%s))
result_attribute = homeDirectory
2.3 Main Configuration (/etc/postfix/main.cf
)
Backup the file temporarily.
cp /etc/postfix/main.cf /tmp
Open:
vim /etc/postfix/main.cf
Add and modify:
Remove example.com
from mydestination
:
mydestination = $myhostname, localhost.$mydomain, localhost
Add your virtual settings:
# virtual domains
virtual_mailbox_domains = example.com
# mailbox lookup: map user@example.com → homeDirectory (/home/testuser)
virtual_mailbox_maps = ldap:/etc/postfix/ldap-mailboxes.cf
# alias lookup: map admin@example.com → testuser@example.com, etc.
virtual_alias_maps = ldap:/etc/postfix/ldap-aliases.cf
# deliver via Dovecot LMTP
virtual_transport = lmtp:unix:private/dovecot-lmtp
# enable SMTP AUTH via Dovecot
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_recipient_restrictions =
permit_sasl_authenticated,
permit_mynetworks,
reject_unauth_destination
Step 3: Reload Postfix:
postfix reload
Step 4: Configure Dovecot for LDAP & LMTP
4.1 LDAP Driver (/etc/dovecot/dovecot-ldap.conf.ext
)
vim /etc/dovecot/dovecot-ldap.conf.ext
For bind-as-user:
hosts = 127.0.0.1
ldap_version = 3
base = ou=people,dc=example,dc=com
# enable binding as authenticating user
auth_bind = yes
user_filter = (&(objectClass=posixAccount)(|(uid=%u)(mailAddress=%u)))
for the above comment out the other line for base
or add these lines there.
Or for password-compare:
hosts = 127.0.0.1
ldap_version = 3
base = ou=people,dc=example,dc=com
pass_filter = (&(objectClass=posixAccount)(|(uid=%u)(mailAddress=%u)))
pass_attrs = userPassword=userPassword
default_pass_scheme = SSHA
user_filter = (&(objectClass=posixAccount)(|(uid=%u)(mailAddress=%u)))
user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid
4.2 Enable in Dovecot
In /etc/dovecot/conf.d/10-auth.conf
:
vim /etc/dovecot/conf.d/10-auth.conf
Modify:
!include auth-system.conf.ext
!include auth-ldap.conf.ext
Ensure /etc/dovecot/conf.d/auth-ldap.conf.ext
points to the file above.
4.3 LMTP & SASL Socket (/etc/dovecot/conf.d/10-master.conf
)
vim /etc/dovecot/conf.d/10-master.conf
Comment out the existing configuration and add:
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
4.4 Mail Location & Auto-Creation (/etc/dovecot/conf.d/10-mail.conf
)
vim /etc/dovecot/conf.d/10-mail.conf
Note: Set mail location and check that there is a namespace inbox
but stop there as the file 15-mailboxes.conf contains mailbox setup.
mail_location = maildir:~/Maildir
Verify this exists.
namespace inbox {...
4.5 Mail Location & Auto-Creation (/etc/dovecot/conf.d/15-mailboxes.conf
)
Here is the mailbox configuraton. # NOTE: Assumes “namespace inbox” has been defined in 10-mail.conf. Most of what is added is the auto
lines.
vim /etc/dovecot/conf.d/15-mailboxes.conf
Modify:
namespace inbox {
# Added LDAP
separator = /
# These mailboxes are widely used and could perhaps be created automatically:
mailbox Drafts {
auto = subscribe
special_use = \Drafts
}
mailbox Junk {
special_use = \Junk
}
mailbox Trash {
auto = subscribe
special_use = \Trash
}
# 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 {
auto = subscribe
special_use = \Sent
}
mailbox "Sent Messages" {
special_use = \Sent
}
# If you have a virtual "All messages" mailbox:
#mailbox virtual/All {
# special_use = \All
# comment = All my messages
#}
# If you have a virtual "Flagged" mailbox:
#mailbox virtual/Flagged {
# special_use = \Flagged
# comment = All my flagged messages
#}
# If you have a virtual "Important" mailbox:
#mailbox virtual/Important {
# special_use = \Important
# comment = All my important messages
#}
}
Step 5: Restart Dovecot:
systemctl restart dovecot
Step 6: UNIX Accounts & Maildirs
LDAP UIDs/GIDs must exist locally:
Create matching group and user
groupadd -g 10000 testuser
useradd -u 10000 -g 10000 -m -d /home/testuser -s /usr/sbin/nologin testuser
Bootstrap Maildir
mkdir -p /home/testuser/Maildir/{new,cur,tmp}
chown -R testuser:testuser /home/testuser/Maildir
Next Steps:
Testing End-to-End and how this all works will be published soon as part three in this series.
Here is a zip file of this article in text which makes it easier to copy and paste.