New 02-selfhosting/services article: the full Postfix/Dovecot inbound spam stack on Fedora — spamass-milter tag-only wiring (the -r footgun), socket permissions (sa-milt group + UMask), site-wide Bayes DB, Sieve-to-Junk, and sa-learn training (folders, spam/ham balance, manual-not-cron). From the majormail setup. Also extends selinux-dovecot-vmail-context with a Permissive-mode variant + a postfix_cleanup->mysqld_etc companion-denial note. SUMMARY.md nav updated.
5.5 KiB
| title | domain | category | tags | status | created | updated | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| SELinux: Fixing Dovecot Mail Spool Context (/var/vmail) | troubleshooting | general |
|
published | 2026-04-02 | 2026-04-02 |
SELinux: Fixing Dovecot Mail Spool Context (/var/vmail)
If Dovecot is generating SELinux AVC denials and mail delivery or retrieval is broken on a Fedora/RHEL system with SELinux enforcing, the /var/vmail directory tree likely has incorrect file contexts.
Symptoms
- Thousands of AVC denials in
/var/log/audit/audit.logfor Dovecot processes - Denials reference
var_tcontext on files under/var/vmail/ - Mail delivery may fail silently; IMAP folders may appear empty or inaccessible
ausearch -m avc -ts recentshows denials like:type=AVC msg=audit(...): avc: denied { write } for pid=... comm="dovecot" name="..." scontext=system_u:system_r:dovecot_t:s0 tcontext=system_u:object_r:var_t:s0
Why It Happens
SELinux requires files to have the correct security context for the process that accesses them. When Postfix/Dovecot are installed on a fresh system and /var/vmail is created manually (or by the mail stack installer), the directory may inherit the default var_t context from /var/ rather than the mail-specific mail_spool_t context Dovecot expects.
The correct context for the entire /var/vmail tree is mail_spool_t — including the tmp/ subdirectories inside each Maildir folder.
[!warning] Do NOT apply
dovecot_tmp_tto Maildirtmp/directoriesdovecot_tmp_tis for Dovecot's own process-level temp files, not for Maildirtmp/folders. Postfix's virtual delivery agent writes totmp/when delivering new mail. Applyingdovecot_tmp_twill block Postfix from delivering any mail, silently deferring all messages withPermission denied.
Fix
1. Check Current Context
ls -Zd /var/vmail/
ls -Z /var/vmail/example.com/user/
ls -Zd /var/vmail/example.com/user/tmp/
If you see var_t instead of mail_spool_t, the contexts need to be set. If you see dovecot_tmp_t on tmp/, that needs to be corrected too.
2. Define the Correct File Context Rule
One rule covers everything — including tmp/:
sudo semanage fcontext -a -t mail_spool_t "/var/vmail(/.*)?"
If you previously added a dovecot_tmp_t rule for tmp/ directories, remove it:
# Check for an erroneous dovecot_tmp_t rule
sudo semanage fcontext -l | grep vmail
# If you see one like "/var/vmail(/.*)*/tmp(/.*)?" with dovecot_tmp_t, delete it:
sudo semanage fcontext -d "/var/vmail(/.*)*/tmp(/.*)?"
3. Apply the Labels
sudo restorecon -Rv /var/vmail
This relabels all existing files. On a mail server with many users and messages, this may take a moment and will print every relabeled path.
4. Verify
ls -Zd /var/vmail/
ls -Zd /var/vmail/example.com/user/tmp/
Both should show mail_spool_t:
system_u:object_r:mail_spool_t:s0 /var/vmail/
system_u:object_r:mail_spool_t:s0 /var/vmail/example.com/user/tmp/
5. Flush Deferred Mail
If mail was queued while the context was wrong, flush it:
postqueue -f
postqueue -p # should be empty shortly
6. Check That Denials Stopped
ausearch -m avc -ts recent | grep dovecot
No output = no new denials.
Variant: a Freshly-Rebuilt Box Left in Permissive Mode
If a server was rebuilt or migrated and came up Permissive (check getenforce), the symptom flips: mail works fine, but /var/log/audit/audit.log quietly fills with thousands of dovecot_t → var_t denials that would break IMAP/LMTP the instant you switch to Enforcing. The mailstore was created or rsync'd onto /var/vmail with no fcontext rule, so it defaulted to var_t.
Apply the relabel above first, then flip to Enforcing only after verifying zero new denials:
MARK=$(date +%H:%M:%S)
# ...deliver a test message + do an IMAP login...
ausearch -m avc -ts "$MARK" | grep -c denied # expect 0
setenforce 1
sed -i 's/^SELINUX=permissive/SELINUX=enforcing/' /etc/selinux/config
Companion denial: a Postfix virtual-mailbox server that looks up recipients in MySQL also trips postfix_cleanup_t reading /etc/my.cnf* (mysqld_etc_t). Allow it with a small local module:
ausearch -m avc -c cleanup | audit2allow -M local_postfix_mysql
semodule -i local_postfix_mysql.pp
See also postfix-spamassassin-bayes-spam-filtering — the SpamAssassin Bayes DB belongs under /var/lib/spamassassin (spamd_var_lib_t) for the same labeling reason.
Key Notes
- One rule is enough —
"/var/vmail(/.*)?"withmail_spool_tcovers every file and directory under/var/vmail, including alltmp/subdirectories. semanage fcontextis persistent — the rules survive reboots andrestoreconcalls. You only need to runsemanageonce.restoreconapplies current rules to existing files — run it after anysemanagechange and any time you manually create directories.- New mail directories are labeled automatically — SELinux applies the registered
semanagerules to any new files created under/var/vmail. var_tcontext is the default for/var/— any directory created under/var/without a specificsemanagerule will inheritvar_t. This is almost never correct for service data directories.