Dovecot on FreeBSD: IMAP/POP3 Server Review
Dovecot is the dominant open-source IMAP and POP3 server. It handles mailbox access for millions of mailboxes across ISPs, universities, and enterprises. Its design priorities are correctness, performance, and ease of configuration -- in that order. Dovecot reads mbox and maildir formats, supports sophisticated virtual user configurations, provides server-side mail filtering through Sieve, and integrates tightly with MTAs like Postfix and OpenSMTPD for authenticated SMTP relay and local delivery via LMTP.
On FreeBSD, Dovecot is a natural fit. It takes full advantage of kqueue for event notification, runs cleanly in jails, and pairs well with ZFS for mailbox storage where snapshots provide instant backup and rollback. This review covers installation, IMAP/POP3 configuration, TLS setup, virtual users with multiple authentication backends, Sieve filtering, performance tuning, and integration with Postfix.
Installation on FreeBSD
Binary Package
shpkg install dovecot dovecot-pigeonhole
The dovecot package provides IMAP, POP3, LMTP, and ManageSieve protocols. The dovecot-pigeonhole package adds Sieve mail filtering support.
Configuration files live under /usr/local/etc/dovecot/. The main configuration file is /usr/local/etc/dovecot/dovecot.conf, with additional configuration split across files in /usr/local/etc/dovecot/conf.d/.
Enable Dovecot:
shsysrc dovecot_enable="YES"
Ports Installation
For custom build options (LDAP, Solr full-text search, LZ4 compression):
shcd /usr/ports/mail/dovecot make config make install clean cd /usr/ports/mail/dovecot-pigeonhole make install clean
Core Configuration
Dovecot ships with comprehensive example configuration files in /usr/local/etc/dovecot/conf.d/. The defaults are conservative and safe. Here is a production configuration built from the ground up.
Main Configuration
sh# /usr/local/etc/dovecot/dovecot.conf protocols = imap lmtp sieve listen = *, :: mail_home = /var/vmail/%d/%n mail_location = maildir:~/Maildir # Security ssl = required ssl_cert = </usr/local/etc/ssl/certs/mail.example.com.fullchain.crt ssl_key = </usr/local/etc/ssl/private/mail.example.com.key ssl_min_protocol = TLSv1.2 ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384 ssl_prefer_server_ciphers = yes # Authentication disable_plaintext_auth = yes auth_mechanisms = plain login # Logging log_path = /var/log/dovecot.log info_log_path = /var/log/dovecot-info.log log_timestamp = "%Y-%m-%d %H:%M:%S " # Process limits default_process_limit = 256 default_client_limit = 2000
IMAP-Specific Settings
sh# /usr/local/etc/dovecot/conf.d/20-imap.conf protocol imap { mail_max_userip_connections = 20 imap_idle_notify_interval = 2 mins mail_plugins = $mail_plugins imap_sieve }
POP3 Settings
If you need POP3 (some legacy clients require it):
sh# /usr/local/etc/dovecot/dovecot.conf (add to protocols) protocols = imap pop3 lmtp sieve
sh# /usr/local/etc/dovecot/conf.d/20-pop3.conf protocol pop3 { pop3_uidl_format = %08Xu%08Xv pop3_no_flag_updates = yes mail_max_userip_connections = 3 }
Most modern deployments can skip POP3 entirely. IMAP is the standard for multi-device access.
TLS Configuration
Dovecot requires TLS for production use. The ssl = required directive forces encrypted connections on all protocols.
Certificate Setup
Use Let's Encrypt:
shpkg install acme.sh acme.sh --issue -d mail.example.com --standalone acme.sh --install-cert -d mail.example.com \ --cert-file /usr/local/etc/ssl/certs/mail.example.com.crt \ --key-file /usr/local/etc/ssl/private/mail.example.com.key \ --fullchain-file /usr/local/etc/ssl/certs/mail.example.com.fullchain.crt \ --reloadcmd "service dovecot reload"
Ports and Encryption Modes
Dovecot listens on:
- Port 143 (IMAP): STARTTLS upgrade from plaintext
- Port 993 (IMAPS): implicit TLS from connection start
- Port 110 (POP3): STARTTLS upgrade
- Port 995 (POP3S): implicit TLS
- Port 4190 (ManageSieve): STARTTLS
Configure listeners explicitly:
sh# /usr/local/etc/dovecot/conf.d/10-master.conf service imap-login { inet_listener imap { port = 143 } inet_listener imaps { port = 993 ssl = yes } } service pop3-login { inet_listener pop3 { port = 110 } inet_listener pop3s { port = 995 ssl = yes } }
Verify TLS
shopenssl s_client -connect mail.example.com:993 openssl s_client -connect mail.example.com:143 -starttls imap
Check the certificate chain, TLS version (should be TLSv1.2 or TLSv1.3), and cipher suite.
Virtual Users
Virtual users allow you to host mail for multiple domains without creating system accounts. This is the standard approach for any server hosting more than a handful of accounts.
Passwd-File Authentication
The simplest virtual user backend is a passwd-format file:
sh# /usr/local/etc/dovecot/conf.d/10-auth.conf auth_mechanisms = plain login !include auth-passwdfile.conf.ext
sh# /usr/local/etc/dovecot/conf.d/auth-passwdfile.conf.ext passdb { driver = passwd-file args = scheme=BLF-CRYPT username_format=%u /usr/local/etc/dovecot/users } userdb { driver = static args = uid=vmail gid=vmail home=/var/vmail/%d/%n }
Create the users file:
sh# Generate password hash doveadm pw -s BLF-CRYPT # /usr/local/etc/dovecot/users john@example.com:{BLF-CRYPT}$2y$05$hash_here:::::: jane@example.com:{BLF-CRYPT}$2y$05$hash_here:::::: info@example.org:{BLF-CRYPT}$2y$05$hash_here::::::
Create the virtual mail user:
shpw groupadd vmail -g 5000 pw useradd vmail -u 5000 -g 5000 -d /var/vmail -s /usr/sbin/nologin mkdir -p /var/vmail chown -R vmail:vmail /var/vmail
SQL Authentication (PostgreSQL)
For larger deployments, use a database backend:
sh# /usr/local/etc/dovecot/conf.d/auth-sql.conf.ext passdb { driver = sql args = /usr/local/etc/dovecot/dovecot-sql.conf.ext } userdb { driver = sql args = /usr/local/etc/dovecot/dovecot-sql.conf.ext }
sh# /usr/local/etc/dovecot/dovecot-sql.conf.ext driver = pgsql connect = host=localhost dbname=mail user=dovecot password=your_password default_pass_scheme = BLF-CRYPT password_query = SELECT email as user, password FROM users WHERE email='%u' AND active=true user_query = SELECT 'vmail' as uid, 'vmail' as gid, '/var/vmail/%d/%n' as home FROM users WHERE email='%u'
Create the database:
shsu - postgres -c "createuser dovecot" su - postgres -c "createdb -O dovecot mail" su - postgres -c "psql mail" << 'SQL' CREATE TABLE users ( email VARCHAR(255) PRIMARY KEY, password VARCHAR(255) NOT NULL, active BOOLEAN DEFAULT true, quota BIGINT DEFAULT 1073741824 ); INSERT INTO users (email, password) VALUES ('john@example.com', '{BLF-CRYPT}$2y$05$...'); SQL
LDAP Authentication
For environments with an existing LDAP directory:
sh# /usr/local/etc/dovecot/conf.d/auth-ldap.conf.ext passdb { driver = ldap args = /usr/local/etc/dovecot/dovecot-ldap.conf.ext } userdb { driver = ldap args = /usr/local/etc/dovecot/dovecot-ldap.conf.ext }
sh# /usr/local/etc/dovecot/dovecot-ldap.conf.ext hosts = ldap.example.com dn = cn=dovecot,dc=example,dc=com dnpass = your_ldap_password base = ou=users,dc=example,dc=com user_attrs = =uid=vmail,=gid=vmail,=home=/var/vmail/%d/%n user_filter = (&(objectClass=inetOrgPerson)(mail=%u)) pass_attrs = mail=user,userPassword=password pass_filter = (&(objectClass=inetOrgPerson)(mail=%u))
Sieve Filtering
Sieve is a server-side mail filtering language. It lets users create rules that run on the server, so filtering happens regardless of which client they use. Dovecot implements Sieve through the Pigeonhole package.
Enable Sieve
sh# /usr/local/etc/dovecot/conf.d/90-sieve.conf plugin { sieve = file:~/sieve;active=~/.dovecot.sieve sieve_default = /usr/local/etc/dovecot/sieve/default.sieve sieve_global_dir = /usr/local/etc/dovecot/sieve/global/ sieve_max_script_size = 1M sieve_max_actions = 32 sieve_max_redirects = 4 }
sh# /usr/local/etc/dovecot/conf.d/20-lmtp.conf protocol lmtp { mail_plugins = $mail_plugins sieve }
Default Sieve Script
Create a global default that files spam into the Junk folder:
sh# /usr/local/etc/dovecot/sieve/default.sieve require ["fileinto", "mailbox"]; if header :contains "X-Spam-Flag" "YES" { fileinto :create "Junk"; stop; }
Compile it:
shsievec /usr/local/etc/dovecot/sieve/default.sieve
User Sieve Scripts
Users manage their own Sieve scripts through the ManageSieve protocol (port 4190). Clients like Thunderbird (with the Sieve extension) or Roundcube (with the managesieve plugin) can edit rules through a GUI.
Example user Sieve script:
sieverequire ["fileinto", "mailbox", "body", "variables"]; # File mailing lists into folders if header :contains "List-Id" "freebsd-hackers" { fileinto :create "Lists/FreeBSD-Hackers"; stop; } # File notifications if header :contains "From" "noreply@github.com" { fileinto :create "Notifications/GitHub"; stop; } # Vacation auto-reply require "vacation"; vacation :days 7 :subject "Out of Office" "I am currently unavailable. I will respond when I return.";
LMTP Integration with Postfix
LMTP (Local Mail Transfer Protocol) is the recommended method for Postfix to deliver mail to Dovecot. It is more reliable than direct maildir delivery because Dovecot manages the mailbox format, indexes, and quota enforcement.
Dovecot LMTP Service
sh# /usr/local/etc/dovecot/conf.d/10-master.conf service lmtp { unix_listener /var/spool/postfix/private/dovecot-lmtp { group = postfix mode = 0600 user = postfix } }
Postfix Configuration
sh# /usr/local/etc/postfix/main.cf virtual_transport = lmtp:unix:private/dovecot-lmtp
SASL Authentication for Postfix
Dovecot provides SASL authentication for Postfix, so authenticated SMTP users are validated against Dovecot's user database:
sh# /usr/local/etc/dovecot/conf.d/10-master.conf service auth { unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } }
sh# /usr/local/etc/postfix/main.cf smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_sasl_auth_enable = yes smtpd_recipient_restrictions = permit_sasl_authenticated, reject_unauth_destination
This creates a clean architecture: Postfix handles SMTP, Dovecot handles authentication and mailbox delivery, and both share the same user database.
For a complete Postfix + Dovecot setup, see the Postfix mail server guide.
Quota Management
Dovecot supports per-user mailbox quotas:
sh# /usr/local/etc/dovecot/conf.d/90-quota.conf plugin { quota = maildir:User quota quota_rule = *:storage=1G quota_rule2 = Trash:storage=+100M quota_grace = 10%% quota_status_success = DUNNO quota_status_nouser = DUNNO quota_status_overquota = "552 5.2.2 Mailbox is full" } protocol imap { mail_plugins = $mail_plugins imap_quota } protocol lmtp { mail_plugins = $mail_plugins sieve quota }
Per-user quota overrides via the userdb:
sh# In the users file john@example.com:{BLF-CRYPT}$2y$05$hash::::userdb_quota_rule=*:storage=5G:
Quota Warnings
Send users a warning when they approach their limit:
shplugin { quota_warning = storage=95%% quota-warning 95 %u quota_warning2 = storage=80%% quota-warning 80 %u } service quota-warning { executable = script /usr/local/etc/dovecot/quota-warning.sh user = vmail unix_listener quota-warning { user = vmail } }
Performance Tuning
ZFS Mailbox Storage
ZFS is ideal for mail storage on FreeBSD:
shzfs create -o recordsize=128k -o compression=lz4 -o atime=off zroot/vmail zfs set mountpoint=/var/vmail zroot/vmail chown vmail:vmail /var/vmail
recordsize=128kmatches maildir file sizes wellcompression=lz4reduces disk usage by 30-50% for email with negligible CPU costatime=offeliminates unnecessary metadata writes
Index Optimization
Dovecot maintains indexes for fast IMAP operations. Ensure indexes are on fast storage:
sh# If /var/vmail is on spinning disks, put indexes on SSD mail_location = maildir:/var/vmail/%d/%n/Maildir:INDEX=/var/dovecot-index/%d/%n
Connection Limits
For large installations:
sh# /usr/local/etc/dovecot/conf.d/10-master.conf default_process_limit = 512 default_client_limit = 4000 service imap-login { process_min_avail = 4 service_count = 0 client_limit = 1000 process_limit = 128 }
service_count = 0 makes login processes persistent, reducing fork overhead for high-connection-rate servers.
Kernel Tuning
sh# /etc/sysctl.conf kern.ipc.somaxconn=4096 kern.maxfiles=100000 kern.maxfilesperproc=50000
Benchmarks
On a 4-core FreeBSD 14.x server with ZFS on NVMe:
- IMAP connections: 10,000+ concurrent IMAP connections with 2 GB RAM
- LMTP delivery: 5,000+ messages/minute
- Mailbox listing (INBOX with 10,000 messages): under 50ms with warm index
- Full-text search (with Solr): sub-second for most queries
Full-Text Search
Dovecot supports full-text search through plugins:
sh# /usr/local/etc/dovecot/conf.d/90-fts.conf mail_plugins = $mail_plugins fts fts_flatcurve plugin { fts = flatcurve fts_autoindex = yes fts_autoindex_max_recent_msgs = 50 }
The fts_flatcurve plugin (Dovecot 2.4+) provides built-in full-text search using Xapian without external dependencies. For older versions, use fts_solr with Apache Solr or fts_lucene.
FAQ
Q: Can Dovecot run inside a FreeBSD jail?
A: Yes. Dovecot runs well in jails. Ensure the jail has access to the mail storage directory and TLS certificates. If using LMTP with Postfix, both should be in the same jail or connected via TCP (change the LMTP listener from a Unix socket to a TCP port).
Q: Should I use mbox or maildir format?
A: Maildir. It stores each message as a separate file, which works well with ZFS snapshots, avoids locking issues, and allows Dovecot to manage concurrent access safely. mbox is a legacy format with no advantages on modern systems.
Q: How do I migrate from another IMAP server to Dovecot?
A: Use doveadm sync (dsync) to migrate mailboxes from another IMAP server: doveadm sync -u user@example.com imapc:. Configure IMAP connection details in /usr/local/etc/dovecot/dovecot.conf.
Q: Can I use Dovecot with OpenSMTPD?
A: Yes. OpenSMTPD delivers to Dovecot via LMTP or direct maildir delivery. For LMTP: action "deliver" lmtp "/var/run/dovecot/lmtp" in smtpd.conf. For maildir: action "deliver" maildir "/var/vmail/%{dest.domain}/%{dest.user}/Maildir".
Q: How do I back up Dovecot mailboxes on ZFS?
A: Use ZFS snapshots: zfs snapshot zroot/vmail@daily-$(date +%Y%m%d). Snapshots are instant, consistent, and take no additional space until data changes. For off-site backup, use zfs send to replicate snapshots.
Q: What is the recommended Dovecot version for FreeBSD?
A: Use the latest stable version from pkg. As of early 2026, FreeBSD ships Dovecot 2.3.x or 2.4.x depending on the repository. Both are production-ready.
Q: How do I monitor Dovecot?
A: Use doveadm who to list connected users, doveadm mailbox status to check mailbox sizes, and parse /var/log/dovecot.log for errors. For Prometheus, use the dovecot_exporter which reads Dovecot's stats socket.
Q: How many users can Dovecot handle on a single FreeBSD server?
A: With proper tuning, a single FreeBSD server with 16 GB RAM and NVMe storage can serve 50,000+ mailboxes and 10,000+ concurrent IMAP connections. The bottleneck is usually disk I/O for large mailbox operations.