Dovecot SQL Virtual Users, Maildir and Mail Protocols
Dovecot verifies mailbox credentials and maps virtual users to stable storage identities without creating a Linux account for every address. This lesson treats Dovecot SQL virtual users and Maildir as one decision point in a longer message path. The configuration is useful only when an operator can show which message entered it, which identity and rule matched, what the next daemon returned, and how a failure is retried or contained.
Prerequisites and inherited lab checkpoint
Use the SELECT-only SQL identity and active, disabled and missing fixtures from Lesson 4, plus the recipient truth from Lesson 5.
For the Dovecot SQL virtual users and Maildir lab, use reserved domain example.test, documentation addresses and disposable messages. Preserve postconf -n, postconf -M, package versions, DNS answers and a queue baseline before changing the lab. Keep console access and do not copy credentials, private keys or customer messages into the evidence record.
Install and prepare the required components
sudo dnf info dovecot dovecot-mysql
sudo dnf install -y dovecot dovecot-mysql
sudo cp -a /etc/dovecot /etc/dovecot.before-nitwings
rpm -q dovecot dovecot-mysql- Confirm package availability and ownership in the enabled RHEL repositories before adding a third-party source. Record the repository, signing key fingerprint, version and support lifecycle.
- A package install creates files and service identities; it does not establish safe relay, authentication, delivery or filtering behavior.
- Back up only the files this lesson changes and record modes, owners and SELinux labels so rollback restores more than text.
- Use
systemctl cat, package file lists and local manual pages to identify paths on the installed build instead of assuming a path from another distribution.
Build the Dovecot SQL virtual users and Maildir configuration and understand every boundary
Use one bounded vmail UID and a root-readable SQL query file. Confirm variable syntax against the installed Dovecot major version.
# 90-virtual-sql.conf
protocols = imap lmtp
mail_driver = maildir
mail_path = /var/vmail/%{user | domain}/%{user | username}/Maildir
first_valid_uid = 5000
last_valid_uid = 5000
passdb sql {
driver = mysql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb static {
fields { uid = 5000 gid = 5000 home = /var/vmail/%{user | domain}/%{user | username} }
}Passdb answers authentication. Userdb supplies UID, GID, home and mailbox location. The SQL file contains a generated secret and therefore stays root-owned with mode 0600.
Verify the working path
sudo chmod 0600 /etc/dovecot/dovecot-sql.conf.ext
sudo doveconf -n
sudo doveadm auth test [email protected]
sudo doveadm user [email protected]
sudo doveadm auth test [email protected]
sudo systemctl enable --now dovecot
sudo ss -lntp | grep -E ':(143|993) '- Run the syntax or lookup test before reload. A reload must never be the first parser of a production configuration.
- The positive test proves the intended path. The negative test proves an unauthorized sender, recipient or client is not accidentally accepted.
- Stop the named dependency in the disposable lab and verify temporary failure or controlled bypass matches the documented policy.
- Repeat the accepted path after restart and reboot, then compare effective configuration rather than only source files.
Production decisions before continuing
| Decision | Choose deliberately | Evidence to retain |
|---|---|---|
| Failure policy | SQL outage produces a temporary dependency failure, not a false invalid-password decision or automatic mailbox provisioning. | SMTP transcript, queue state and dependency alert |
| Trust boundary | Only active canonical SQL identities authenticate; mailbox processes access the bounded tree through the dedicated vmail UID and GID. | Matching client, sender, recipient or daemon identity |
| Secrets and data | Restrict credentials, message samples and keys to the minimum service identity. | Owner, mode, label and secret rotation record |
| Activation | Validate, reload, run positive and negative tests, then watch one complete message. | Syntax output, queue ID and linked log events |
| Rollback | Restore the exact files and map/database state changed by this lesson. | Rollback command and repeated acceptance result |
Place Dovecot SQL virtual users and Maildir in the message path
Maildir stores one message per file under new, cur and tmp. Dovecot indexes can often be rebuilt, but message files, subscriptions and Sieve state require backup.Understand the component before configuring it
| Layer | Question to answer | Evidence |
|---|---|---|
| Input | Normalized login and password over TLS | SMTP transcript, lookup input or message header |
| Decision | SQL passdb result, password scheme and static userdb fields | Effective configuration and exact matched rule |
| Output | Authenticated session mapped to one Maildir home | Queue state, delivery status or downstream response |
| Dependency | MariaDB socket, query secret, storage ownership, capacity and TLS | Socket, timeout, journal and controlled outage test |
| Recovery | Can processing resume without duplicate, loss or unauthorized delivery? | Retained queue ID, backup and repeated acceptance |
Build it step by step
- Draw the path. Mark the connection, envelope, content and authenticated identities available at this stage.
- Inventory the effective state. Capture package version, active service, sockets, Postfix parameters, master services and lookup results.
- Prepare one coherent configuration. Substitute documented lab values and verify ownership, mode and SELinux context.
- Validate before activation. Run component syntax checks, map queries and a non-delivering test where supported.
- Exercise three outcomes. Send an intended message, an intended denial and a message while the named dependency is unavailable.
- Trace one queue ID. Join ingress, policy, filtering, routing and final delivery events without relying on subject text.
- Close the change. Restart or reboot where relevant, repeat tests, check queue age and document rollback.
Operate and inspect the component
doveconf -n
doveadm auth test [email protected]
doveadm user [email protected]
doveadm mailbox list -u [email protected]
namei -om /var/vmail/example.test/user/Maildir
ls -ldZ /var/vmail/example.test/user
journalctl -u dovecot --since '-15 minutes'- Replace sample hostnames, addresses and queue IDs only after resolving them from the lab. Do not paste production identities into a public command transcript.
postconf -nshows non-default global parameters;postconf -Mandpostconf -Pexpose master service and field overrides.- A successful lookup proves only that input. Test present, absent, disabled and dependency-unavailable results separately.
- Use the queue ID as the correlation key. Message subjects and recipient addresses are not unique and may contain sensitive information.
Evidence and acceptance criteria
| Evidence | Healthy result | Failure meaning |
|---|---|---|
| Syntax | All component validators succeed before activation | The running service would parse an unreviewed or invalid state |
| Positive path | An active fixture authenticates and resolves to the designed home and UID/GID. | The intended message cannot complete this decision point |
| Negative path | Missing, disabled and wrong-password users fail without disclosing which credential field was wrong. | The configuration may relay, authenticate, route or deliver too broadly |
| Dependency failure | Stopping MariaDB produces a visible lookup failure and no new mailbox. | Messages may be lost, permanently rejected or silently bypass controls |
| Persistence | Effective state and tests agree after restart and reboot | Only transient state was changed |
Root-owned Maildir breaks a valid login
A manual delivery test creates the first mailbox as root. Authentication works, but IMAP cannot update indexes or move messages. Mode 0777 would hide the model failure; the repair is bounded vmail ownership plus restored SELinux labels.Troubleshooting by symptom
| Symptom | Inspect first | Defensible next action |
|---|---|---|
| Login works, mailbox fails | doveadm user, namei, owner, mount and label | Correct userdb fields and bounded ownership |
| All passwords fail | SQL query and password scheme support | Generate one protected test hash |
| Unknown user gets home | userdb and provisioning path | Require active recipient truth |
| Cleartext login visible | TLS requirement and listener | Do not expose password auth before TLS |
Unsafe operations and recovery boundaries
- Unsafe: mode 0777 on /var/vmail exposes message data.
- Unsafe: plaintext or command-line passwords disclose credentials.
- Unsafe: changing the vmail UID after data exists strands ownership.
Rewritten knowledge checks
Cumulative lab checkpoint
- Capture the inherited checkpoint and state the exact sender, recipient, client address and expected SMTP result.
- Install the required package from a recorded source and save the package/file/service inventory.
- Apply the complete lab configuration, including permissions, socket paths, map generation and service ownership.
- Run syntax and lookup validation, then activate without closing the recovery session.
- Complete positive, negative and dependency-outage tests while retaining queue IDs and UTC logs.
- Restart the participating services, repeat the accepted path and confirm no unexplained deferred mail remains.
- Execute rollback once, prove the previous behavior, then reapply the reviewed state as the checkpoint for the next lesson.