Integrasi LDAP ke Dovecot dan Postfix di Debian 13

Postfix + Dovecot + LDAP — Virtual Mail Server di Debian 13
Debian 13 · Dovecot 2.4+ · Postfix · OpenLDAP

Integrasi LDAP ke
Postfix & Dovecot

Full tutorial konfigurasi virtual mail server dengan LDAP authentication. Syntax Dovecot 2.4+ yang baru, step-by-step, beserta tips & tricks dari lapangan.

~20 min read
Tested · Debian 13
Virtual Users
01

Overview & Arsitektur

Tutorial ini cover setup virtual mail server di Debian 13 menggunakan Postfix sebagai MTA, Dovecot sebagai IMAP/LMTP server, dan OpenLDAP sebagai backend autentikasi. Yang bikin setup ini berbeda: kita tidak pakai PAM — Dovecot query LDAP secara langsung (direct LDAP), lebih efisien dan modern.

## Mail Flow Architecture Client (MUA) │ ├── SMTP/SMTPS (Port 25/465) ──────────────► Postfix (MTA) │ │ │ LDAP Lookup user exists? │ ldap:/etc/postfix/ldap-users.cf │ │ │ Deliver via LMTP │ │ │ ▼ │ Dovecot (LMTP) │ unix:private/dovecot-lmtp │ │ │ Write to Maildir │ │ │ ▼ │ /var/vmail/{domain}/{user}/Maildir/ │ └── IMAPS (Port 993) ────────────────────► Dovecot (IMAP) │ Auth via Direct LDAP auth-ldap.conf.ext │ passdb/userdb query ldap://int-01.konco.co.id │ Read from Maildir ✓
๐Ÿ’ก
Kenapa Direct LDAP, bukan PAM? Dengan direct LDAP, user mail hanya ada di LDAP — tidak terdaftar sebagai system user di Linux. Satu vmail user (UID 9999) jadi "parent" yang mengelola semua maildir. Jauh lebih efisien untuk virtual mail setup.
02

Prerequisites

OS
Debian 13 (Trixie)
Mail Server
Postfix + Dovecot 2.4+
Directory
OpenLDAP (slapd)
Domain
konco.co.id (contoh)
LDAP Server
int-01.konco.co.id
LDAP Base DN
dc=konco,dc=co,dc=id
⚠️
Perhatian Syntax Baru! Dovecot 2.4+ punya breaking changes yang cukup signifikan. mail_location diganti mail_driver + mail_path. Format passdb { driver = ldap } diganti passdb ldap { }. Variable %n dan %d diganti %{user|username} dan %{user|domain}. Tutorial ini sudah menggunakan syntax terbaru.

Install Packages

terminal
# Install semua komponen yang dibutuhkan
# apt install postfix postfix-ldap dovecot-core dovecot-imapd dovecot-lmtpd

# Saat instalasi Postfix, pilih: Internet Site
# System mail name: konco.co.id

# Buat dedicated virtual mail user (PENTING!)
# groupadd -g 9999 vmail
# useradd -u 9999 -g 9999 -s /usr/sbin/nologin -d /var/vmail vmail

# Buat base maildir directory
# mkdir -p /var/vmail
# chown -R vmail:vmail /var/vmail
# chmod 700 /var/vmail
03

Konsep Virtual User

Sebelum masuk ke konfigurasi, penting untuk paham model virtual user yang kita pakai. Ini yang bikin setup ini efisien.

## Virtual User Model # System users (/etc/passwd): vmail:x:9999:9999::/var/vmail:/usr/sbin/nologin ← SATU user ini doang # Mail users (di LDAP, bukan /etc/passwd): $ id john@konco.co.id id: 'john@konco.co.id': no such user ← Nggak ada di sistem Linux! $ id alice@konco.co.id id: 'alice@konco.co.id': no such user ← Sama, nggak ada! # Tapi mereka bisa receive/send mail via IMAP/SMTP ✓ # Folder structure (semua owned by vmail UID 9999): /var/vmail/ └── konco.co.id/ ├── john/ │ └── Maildir/ ← owned by vmail:vmail │ ├── cur/ │ ├── new/ │ └── tmp/ └── alice/ └── Maildir/ ← owned by vmail:vmail
Aspek Virtual User (Direct LDAP) System User (PAM)
Entry di /etc/passwd Tidak ada (virtual) Ada per-user
UID/GID management 1 UID (vmail=9999) untuk semua UID unik per user
SSH/Shell access Tidak bisa (secure) Bisa (perlu dibatasi)
Skalabilitas 1000 user = 1 system entry 1000 user = 1000 system entry
Cocok untuk Mail-only service Multi-service (SSH+mail+FTP)

04

Konfigurasi Postfix

/etc/postfix/main.cf

Tambahkan/modifikasi directive berikut. Postfix perlu tahu bahwa user dikelola via LDAP dan delivery dilakukan via LMTP ke Dovecot.

/etc/postfix/main.cf
# Format mailbox: Maildir (bukan mbox)
home_mailbox = Maildir/

# Virtual mailbox: base directory semua mail
virtual_mailbox_base = /var/vmail

# Domain yang dihandle (sesuaikan domain lu)
virtual_mailbox_domains = konco.co.id

# Lookup user di LDAP (file konfigurasi terpisah)
virtual_mailbox_maps = ldap:/etc/postfix/ldap-users.cf

# UID/GID semua virtual mailbox (harus match vmail user)
virtual_uid_maps = static:9999
virtual_gid_maps = static:9999

# Kirim ke Dovecot via LMTP unix socket
virtual_transport = lmtp:unix:private/dovecot-lmtp

# Reject jika sender/recipient tidak terdaftar
smtpd_reject_unlisted_sender = yes
smtpd_reject_unlisted_recipient = yes

# Enable SASL authentication via Dovecot
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous

# Relay restrictions: izinkan mynetworks & authenticated users
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination
⚠️
Hindari duplikasi directive! Pastikan smtpd_reject_unlisted_sender hanya muncul sekali di main.cf. Kalau duplikat, Postfix hanya baca yang terakhir — bisa bikin konflik config yang subtle.

/etc/postfix/master.cf

Tambahkan service submissions untuk SMTPS (port 465 dengan TLS wrapper mode).

/etc/postfix/master.cf
# Format kolom: service type private unpriv chroot wakeup maxproc command
# Tambahkan di akhir file:

submissions  inet  n  -  y  -  -  smtpd
  -o syslog_name=postfix/submissions
  -o smtpd_tls_wrappermode=yes       # SMTPS: TLS dari awal koneksi
  -o smtpd_sasl_auth_enable=yes      # Enable SASL di port ini
๐Ÿ’ก
Catatan kolom master.cf: Kolom ke-4 (private) - artinya default (y = private). Kolom ke-5 (unpriv) y artinya jalankan sebagai non-root. Kolom ke-6 (chroot) y artinya chroot aktif. Pastikan format konsisten atau Postfix bisa throw error saat reload.
05

LDAP Mapping Files

/etc/postfix/ldap-users.cf

File ini digunakan Postfix untuk lookup apakah recipient address valid di LDAP sebelum menerima email.

/etc/postfix/ldap-users.cf
# LDAP server address
server_host = ldap://int-01.konco.co.id

# Search base: OU tempat mail user disimpan di LDAP
search_base = ou=mail,dc=konco,dc=co,dc=id

# Query filter: cari object dengan uid = local part email
# %u = local part dari address (john dari john@konco.co.id)
query_filter = (&(uid=%u)(objectClass=inetOrgPerson))

# Attribute yang dikembalikan (email address)
result_attribute = mail

# Search scope: subtree (cari rekursif di bawah search_base)
scope = sub

# Bind ke LDAP dengan credentials (bukan anonymous)
bind = yes
bind_dn = cn=admin,dc=konco,dc=co,dc=id
bind_pw = Skills39
terminal — test ldap-users.cf
# Test apakah Postfix bisa lookup user di LDAP
# postmap -q john@konco.co.id ldap:/etc/postfix/ldap-users.cf

# Output yang diharapkan:
# john@konco.co.id

# Kalau tidak ada output = user tidak ditemukan di LDAP
# Cek query_filter dan search_base
06

Konfigurasi Dovecot

๐Ÿ”ฅ
Breaking Changes Dovecot 2.4+! Banyak syntax berubah di versi ini. Kalau lu pake tutorial lama, config lu TIDAK AKAN JALAN. Pastikan gunakan syntax baru yang ada di tutorial ini.

/etc/dovecot/dovecot.conf

/etc/dovecot/dovecot.conf
# Aktifkan protokol IMAP dan LMTP
protocols = imap lmtp

# Listen di semua interface (IPv4 & IPv6)
listen = *

/etc/dovecot/conf.d/10-auth.conf

/etc/dovecot/conf.d/10-auth.conf
# Larang autentikasi cleartext (tanpa TLS)
auth_allow_cleartext = no

# Enable debug auth (bagus untuk troubleshooting, nonaktifkan di production)
auth_debug = yes

# Include konfigurasi LDAP auth (pastikan baris ini ada, uncomment jika perlu)
!include auth-ldap.conf.ext

/etc/dovecot/conf.d/10-mail.conf

/etc/dovecot/conf.d/10-mail.conf
# Dovecot 2.4+: gunakan mail_driver bukan mail_location
mail_driver = maildir

# Path ke maildir — %{user|domain} = domain, %{user|username} = username
mail_path = /var/vmail/%{user|domain}/%{user|username}/Maildir

# Home directory user (parent dari Maildir)
mail_home = /var/vmail/%{user|domain}/%{user|username}
๐Ÿ’ก
Perubahan variable di Dovecot 2.4+:
%d (domain) → %{user|domain}
%n atau %u (username) → %{user|username}
%u (full user@domain) → %{user}

/etc/dovecot/conf.d/10-master.conf

/etc/dovecot/conf.d/10-master.conf
# Disable plain IMAP (port 143), hanya izinkan IMAPS (port 993)
service imap-login {
  inet_listener imap {
    port = 0        # 0 = disable
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

# Disable submission ports di Dovecot (Postfix yang handle)
service submission-login {
  inet_listener submission {
    port = 0        # 0 = disable
  }
  inet_listener submissions {
    port = 0        # 0 = disable
  }
}

# LMTP unix socket — Postfix kirim mail ke sini
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0666
    user = postfix
    group = postfix
  }
}

# Auth socket untuk Dovecot userdb
service auth {
  unix_listener auth-userdb {
    mode = 0666
    user = vmail
    group = vmail
  }
  # Auth socket untuk Postfix SASL
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
}

# Stats writer permission (Dovecot 2.4+ requirement)
service stats {
  unix_listener stats-writer {
    mode = 0666
    user = dovecot
    group = vmail
  }
}

/etc/dovecot/conf.d/10-ssl.conf

/etc/dovecot/conf.d/10-ssl.conf
# Wajibkan SSL — koneksi tanpa TLS akan ditolak
ssl = required

# Path ke certificate dan private key (sesuaikan)
ssl_cert = </etc/ssl/certs/dovecot.pem
ssl_key = </etc/ssl/private/dovecot.pem

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

File paling krusial — ini yang handle direct LDAP auth di Dovecot 2.4+ dengan syntax baru.

/etc/dovecot/conf.d/auth-ldap.conf.ext
# passdb: verifikasi password user dari LDAP
# Syntax Dovecot 2.4+: "passdb ldap { }" bukan "passdb { driver = ldap }"
passdb ldap {
  ldap_auth_dn = cn=admin,dc=konco,dc=co,dc=id      # DN untuk bind ke LDAP
  ldap_auth_dn_password = Skills39              # Password LDAP admin
  ldap_uris = ldap://int-01.konco.co.id            # URI LDAP server
  ldap_base = ou=mail,dc=konco,dc=co,dc=id            # Search base
  ldap_version = 3                               # LDAP v3
  ldap_filter = (&(objectClass=inetOrgPerson)(uid=%{user|username}))
  ldap_scope = subtree
  fields {
    password=%{ldap:userPassword}  # Ambil password dari attribute userPassword
  }
}

# userdb: ambil info user (home, uid, gid) dari LDAP
userdb ldap {
  ldap_uris = ldap://int-01.konco.co.id
  ldap_base = ou=mail,dc=konco,dc=co,dc=id
  ldap_version = 3
  ldap_filter = (&(objectClass=inetOrgPerson)(uid=%{user|username}))
  ldap_scope = subtree
  fields {
    home=/var/vmail/%{user|domain}/%{user|username}  # Home dir per user
    uid = vmail    # Semua mail file owned by vmail
    gid = vmail    # Group ownership: vmail
  }
}
⚠️
Konsistensi path! Pastikan home= di userdb ldap fields sama persis dengan mail_home di 10-mail.conf. Kalau beda, Dovecot akan buat maildir di lokasi yang salah dan delivery bisa gagal.
07

Setup vmail User & Permissions

terminal — setup vmail
# Buat group vmail dengan GID 9999
# groupadd -g 9999 vmail

# Buat user vmail: no shell, no login, home = /var/vmail
# useradd -u 9999 -g 9999 \
#   -s /usr/sbin/nologin \
#   -d /var/vmail \
#   -c "Virtual Mail User" \
#   vmail

# Buat base directory
# mkdir -p /var/vmail

# Set ownership ke vmail
# chown -R vmail:vmail /var/vmail

# Set permission: hanya vmail yang bisa masuk
# chmod 700 /var/vmail

# Verify
# id vmail
# uid=9999(vmail) gid=9999(vmail) groups=9999(vmail)

# ls -la /var/vmail
# drwx------ vmail vmail /var/vmail ← ini yang benar
08

Verifikasi & Testing

1
Validasi syntax config
terminal
# Cek syntax Postfix — harus tidak ada error
# postfix check

# Cek syntax Dovecot — output = effective config
# doveconf -n

# Cek status service
# systemctl status postfix dovecot
2
Test LDAP lookup dari Postfix
terminal
# Test lookup user di LDAP via Postfix
# postmap -q john@konco.co.id ldap:/etc/postfix/ldap-users.cf
# Expected output: john@konco.co.id

# Kalau kosong: user tidak ditemukan di LDAP
# Cek query_filter, search_base, dan LDAP objectClass
3
Test Dovecot auth ke LDAP
terminal
# Test autentikasi Dovecot untuk user john@konco.co.id
# doveadm auth test john@konco.co.id passwordnya

# Expected output:
# passdb: john@konco.co.id auth succeeded
# extra fields: user=john@konco.co.id home=/var/vmail/konco.co.id/john

# Test user info lookup
# doveadm user john@konco.co.id
# Expected: uid=9999, gid=9999, home=/var/vmail/konco.co.id/john
4
Test kirim email & cek delivery
terminal
# Kirim test email
$ echo "Test mail delivery" | mail -s "Test Subject" john@konco.co.id

# Cek apakah maildir sudah terbuat
# ls -la /var/vmail/konco.co.id/john/Maildir/new/
# Harus ada file email baru di sini

# Cek Postfix mail log
# tail -f /var/log/mail.log
# Cari: status=sent (250 2.0.0 OK)
5
Cek port yang listening
terminal
# Cek semua port mail yang listening
# ss -tlnp | grep -E "25|143|465|587|993"

# Expected output:
# tcp LISTEN *:25   (postfix smtpd)
# tcp LISTEN *:465  (postfix submissions)
# tcp LISTEN *:993  (dovecot imaps)
09

Tips & Tricks

๐Ÿ”
Debug LDAP Auth dengan Log
Set auth_debug = yes di 10-auth.conf sementara, lalu tail -f /var/log/dovecot/dovecot.log. Log akan show detail setiap langkah LDAP query. Matikan setelah troubleshooting selesai (overhead di production).
๐Ÿ“
Konsistensi Path antara userdb dan mail_home
home= di userdb ldap fields harus sama persis dengan mail_home di 10-mail.conf. Kalau beda, Dovecot akan buat maildir di lokasi yang berbeda dan email tidak akan ditemukan saat login IMAP.
Urutan Restart yang Benar
Selalu restart Dovecot dulu, baru Postfix. Karena Postfix butuh unix socket dari Dovecot (dovecot-lmtp dan private/auth) — kalau Postfix start duluan, socket belum ada dan service bisa error.
๐Ÿ”
Permission Socket yang Sering Bikin Galau
Unix socket di /var/spool/postfix/private/ harus bisa dibaca Postfix. Set mode = 0666, user = postfix, group = postfix. Kalau permission salah, LMTP delivery akan gagal dengan error "Connection refused".
๐Ÿ›ก️
Jangan Commit Credentials LDAP ke Git
File ldap-users.cf dan auth-ldap.conf.ext berisi bind_pw dan ldap_auth_dn_password. Tambahkan ke .gitignore dan set permission chmod 600 di kedua file tersebut agar hanya root yang bisa baca.
๐Ÿงช
Test LDAP Langsung dengan ldapsearch
Sebelum debug Postfix/Dovecot, verifikasi dulu bahwa LDAP-nya sendiri bisa diquery: ldapsearch -x -H ldap://int-01.konco.co.id -D "cn=admin,dc=konco,dc=co,dc=id" -w Skills39 -b "ou=mail,dc=konco,dc=co,dc=id" "(uid=john)". Kalau ini gagal, masalahnya ada di LDAP, bukan di Postfix/Dovecot.
๐Ÿ”„
Virtual User vs PAM: Pilih Sesuai Use Case
Direct LDAP (virtual user) cocok untuk mail-only setup. Kalau perlu multi-service auth (SSH + mail + OpenVPN), pertimbangkan PAM+LDAP untuk reusability. Keduanya valid — pilih yang sesuai requirement, bukan dogmatik.
๐Ÿ“Š
Cek Effective Config dengan doveconf
doveconf -n menampilkan semua config yang aktif (non-default). Gunakan ini untuk memastikan nilai yang Dovecot benar-benar baca, bukan yang lu tulis. Jauh lebih reliable daripada buka file satu-satu.

Troubleshooting Quick Reference

terminal — common issues
## MASALAH: User tidak bisa login IMAP
# Cek Dovecot auth log
# tail -100 /var/log/dovecot/dovecot.log | grep "john@konco.co.id"
# Cek apakah user exist di LDAP
# doveadm user john@konco.co.id

## MASALAH: Email tidak terdeliver (bounce)
# Cek Postfix log
# tail -50 /var/log/mail.log | grep "john@konco.co.id"
# Test LDAP lookup dari Postfix
# postmap -q john@konco.co.id ldap:/etc/postfix/ldap-users.cf

## MASALAH: "SASL authentication failed"
# Cek apakah Dovecot auth socket exists
# ls -la /var/spool/postfix/private/auth
# Restart Dovecot dulu, baru Postfix
# systemctl restart dovecot && systemctl restart postfix

## MASALAH: "Permission denied" saat delivery LMTP
# Cek permission socket LMTP
# ls -la /var/spool/postfix/private/dovecot-lmtp
# Harus: srw-rw-rw- root postfix
# systemctl restart dovecot

## MASALAH: Maildir tidak terbuat
# Cek ownership /var/vmail
# ls -la /var/vmail/
# Harus: drwx------ vmail vmail
# chown -R vmail:vmail /var/vmail && chmod 700 /var/vmail
10

Glosarium

MTA
Mail Transfer Agent — software yang bertugas menerima dan meneruskan email antar server. Postfix adalah MTA-nya di setup ini.
LMTP
Local Mail Transfer Protocol — protokol untuk transfer mail di dalam satu mesin, dari Postfix ke Dovecot via unix socket.
Virtual User
User mail yang tidak memiliki system account di Linux (/etc/passwd). Hanya ada di LDAP, tapi bisa kirim/terima email.
passdb
Password database di Dovecot — digunakan untuk verifikasi password saat login IMAP/SMTP.
userdb
User database di Dovecot — digunakan untuk mendapatkan informasi user setelah autentikasi berhasil (home, uid, gid).
SASL
Simple Authentication and Security Layer — framework autentikasi yang dipakai Postfix untuk verifikasi user saat SMTP AUTH.
Maildir
Format penyimpanan email di filesystem — setiap email = satu file terpisah di folder cur/, new/, tmp/. Lebih aman dari mbox.
Direct LDAP
Pendekatan dimana Dovecot query LDAP secara langsung tanpa melewati PAM. Lebih efisien dan user tidak tercreate sebagai system user.
bind_dn / bind_pw
Credentials yang digunakan untuk login ke LDAP server sebelum melakukan search query. Biasanya DN admin LDAP.
inetOrgPerson
LDAP objectClass yang digunakan untuk menyimpan informasi user, termasuk atribut uid, mail, dan userPassword.

Comments

Popular posts from this blog

Apa itu Link Aggregation?

Apa Itu Port Security di Switch Cisco