You write the rule, restart Dovecot, get no error — and mailboxes keep growing past the limit. The rule is not wrong. The file is never read.
A stock Dovecot install splits its configuration into fragments under /etc/dovecot/conf.d/ and pulls them in with an !include conf.d/*.conf line in the main file. When CyberPanel writes its own dovecot.conf, it omits that include line. Everything you add under conf.d — quota included — is written to disk and never read. The fix is to put the quota block directly in the main dovecot.conf, or to add the include line deliberately. Verification is one command: doveconf -n prints the effective configuration, and if your quota lines are not in it, they are not in force.
Everything looks done: a rule sits in /etc/dovecot/conf.d/90-quota.conf, the service has been restarted, the log is clean. And yet mailboxes sail past the limit and users are never warned.
At this point most people start questioning the syntax and spend an afternoon trying different quota_rule spellings. The syntax is fine. The file is simply never opened.
Dovecot as shipped by most distributions splits configuration into fragments: 10-mail.conf, 10-auth.conf, 90-quota.conf and friends, all under /etc/dovecot/conf.d/. The only thing that makes them take effect is one line at the end of the main file:
!include conf.d/*.conf
When CyberPanel provisions the mail stack it generates /etc/dovecot/dovecot.conf from its own template. That template is a self-contained, single-file configuration and does not contain the include line. The conf.d directory still exists on disk, the files in it are readable, and Dovecot never looks at them.
This failure is silent by nature. Including a file that does not exist is an error. Not including a file that does exist is not an error — so nothing is ever logged.
Before guessing, read the effective configuration. doveconf -n prints what Dovecot is actually using, with defaults stripped out:
# Anything quota-related that is actually in force
doveconf -n | grep -i quota
# Does the main file pull in conf.d at all?
grep -n 'include' /etc/dovecot/dovecot.conf
If the first command prints nothing, your quota configuration is not active. If the second shows no line mentioning conf.d, you have found the reason.
These two commands are worth turning into a habit for this whole class of problem: look at what the server reads, not at what the file says.
There are two routes. To avoid fighting the panel's generated structure, the preferred one is to append the quota block directly to the main file:
# at the end of /etc/dovecot/dovecot.conf
mail_plugins = $mail_plugins quota
plugin {
quota = maildir:User quota
quota_rule = *:storage=2G
quota_rule2 = Trash:storage=+200M
quota_grace = 10%
}
The quota_rule2 line grants Trash an allowance on top of the main quota. Without it, a user who has hit the limit cannot free space by deleting mail — deleted mail moves to Trash, which is inside the same quota, so usage never drops.
The other route is to restore the include. That returns Dovecot to standard behaviour, but carries the risk that a panel update regenerates the file and drops your line:
echo '!include conf.d/*.conf' >> /etc/dovecot/dovecot.conf
Whichever you choose, back the file up somewhere outside the web root before you touch it.
Enforcing a quota and letting the client see the quota are two different things. For a mail client to show "80% full", the IMAP protocol needs its own plugin:
protocol imap {
mail_plugins = $mail_plugins imap_quota
}
Without that line the quota still works — mail is rejected once the box is full — but the user gets no warning beforehand and discovers the limit through a bounce.
After the change, restart the service and verify per user:
systemctl restart dovecot
doveconf -n | grep -i quota # in force?
doveadm quota get -u user@example.com
That last command prints the user's current usage and limit as a table. If the limit column on the STORAGE row is empty, the quota is still not applied.
New mailboxes pick up the quota immediately. For existing ones Dovecot recalculates its usage counter on first access; if you are impatient, force it with doveadm quota recalc -u user@example.com.
The lesson here is not about quota syntax. It is about never assuming where configuration is read from. On panel-provisioned stacks the directory layout looks standard, but whether those files are actually included is a separate question. doveconf -n answers it, and so do nginx -T and apachectl -S for their servers: they show the running reality rather than the intention on disk.
!include conf.d/*.confdoveconf -n | grep -i quota printing nothing means inactivequota_rule2 = Trash:storage=+200M users cannot delete to free spaceimap_quota plugin users never see how full they aredoveadm quota get -u user@example.comBecause the /etc/dovecot/dovecot.conf that CyberPanel generates has no line including the conf.d directory. Dovecot reads only the main file. Your files are in the right place, their permissions are fine and their syntax is valid — they are simply never opened. You can confirm this in seconds with doveconf -n.
Deleted mail is moved to Trash, and Trash sits inside the same quota, so usage does not drop. Give Trash an allowance on top of the main quota with a rule such as quota_rule2 = Trash:storage=+200M. Alternatively, configure automatic expiry for the Trash folder.
Yes, but Dovecot updates the usage counter lazily and recalculates on first access to the mailbox. To see it immediately, run doveadm quota recalc -u user@example.com. Newly created mailboxes have no such delay.
Technically yes — it restores Dovecot's standard behaviour. The risk is that a panel update regenerates dovecot.conf from its template, your line disappears and the quota silently stops applying. Writing the quota block directly into the main file, and backing up the change, is more durable.