Separate Dovecot Index State from Maildir Storage
Keep Dovecot's mutable index, cache, and log files off the same filesystem as user Maildirs to protect quotas, backups, and restores.
18 Sept 2026, 13:30 UTC

The problem: index writes share space with your mail
In a default Dovecot maildir deployment, Dovecot writes index, cache, and log files into the same directory tree as the user’s mail. Those files are mutable: Dovecot updates them when flags change, when clients search, and when mail is delivered. Because they live inside the user’s home or mail directory, they consume quota, get captured by home-directory backups, and can be restored to a stale state if you roll back the mail directory without also rolling back the index files.
This is not a Dovecot bug; it is a storage-layout choice. The useful alternative is to keep the Maildir as the source of truth for messages and direct Dovecot’s helper state to a separate local path.
What mail_location INDEX= actually does
mail_location tells Dovecot where to find mail and where to write its own state. For maildir, the value has three parts: the driver, the mail path, and optional state paths. The INDEX= part redirects index, cache, and log files. The mail itself stays where it was.
A value like this keeps messages under ~/Maildir while moving state under /var/lib/dovecot/index:
mail_location = maildir:~/Maildir:INDEX=/var/lib/dovecot/index/%u
%u expands to the authenticated username, so each user gets a separate index directory. Dovecot creates the per-user directory and its files automatically; you only need to prepare the parent path and permissions.
Terms worth knowing: a maildir stores each message as its own file in cur/, new/, or tmp/. Index/cache/log files are Dovecot’s local copies of flags, keywords, UID mappings, and search metadata. They are cache-like state: if they disappear, Dovecot rebuilds them from the maildir, but the rebuild costs I/O and can force IMAP clients to re-sync.
Worked example: relocate index state for one user domain
Run the following as root on the Dovecot host. Replace dovecot with the UID/GID your mail_uid, mail_gid, or mail_privileged_group configuration actually uses.
- Create the parent index path:
- Edit Dovecot’s mail configuration, typically
/etc/dovecot/conf.d/10-mail.confor/etc/dovecot/dovecot.conf, and set: - Validate the effective configuration before touching the running service:
- Reload Dovecot:
- Test with a real user. Run as root or as the Dovecot service user:
mkdir -p /var/lib/dovecot/index
chown -R dovecot:dovecot /var/lib/dovecot/index
chmod 0700 /var/lib/dovecot/index
mail_location = maildir:~/Maildir:INDEX=/var/lib/dovecot/index/%u
doveconf -n | grep mail_location
Expected output should show the INDEX= path exactly as written. If doveconf reports a syntax error, fix it before reloading.
systemctl reload dovecot
Risk: a syntax error in mail_location can prevent Dovecot from starting or cause mailbox access failures after reload. Keep a shell session open and be ready to restore the previous configuration.
doveadm mailbox status -u [contact removed] messages uidvalidity unseen
Expected: a status line with no permission or index errors. Then log in to that account over IMAP and check the index path:
ls /var/lib/dovecot/index/[contact removed]
Expected: Dovecot-created files such as dovecot.index, dovecot.index.cache, or log files appear after first access. The user’s ~/Maildir should still contain cur/, new/, and tmp/ with message files.
Verification checklist
doveconf -nshowsmail_locationwith the intendedINDEX=path.doveadm mailbox statusreturns for a test user without index or permission errors.- The per-user directory under
/var/lib/dovecot/indexcontains Dovecot-created files after first IMAP access. - Dovecot logs show no index, locking, or
mail_locationerrors during reload and first login.
Trade-offs and limitations
Separate indexes add storage and another stateful path to operate. Treat the index path as disposable cache-like state: put it on fast local disk, exclude it from backups, and monitor disk usage. Excluding it from backups means a restore will not recover old index files; the first access after restore will be slower while Dovecot rebuilds.
This is a storage-layout decision, not high availability. If the index path is lost, corrupted, or placed on a filesystem with locking semantics Dovecot does not support, users can see mailbox errors even though the maildir is intact. Do not assume network filesystems are safe for index state; verify locking support for your Dovecot version and storage.
Usernames can contain @ and other characters when %u expands. Confirm your filesystem, backup tools, and monitoring tolerate those names.
Reverting the change
Because this changes configuration state, you can revert by restoring the previous mail_location value, running doveconf -n, and reloading Dovecot. The orphaned index directory under /var/lib/dovecot/index can be left in place or removed; Dovecot will recreate index state inside the Maildir on next access if INDEX= is removed.
Closing
Pilot the change on one domain or a small group of users. Compare doveadm mailbox status output and disk usage before and after, and confirm backups no longer capture volatile index files. If the test looks clean, roll it out gradually. The mail stays in the Maildir; only the scratch space moves.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.