How to Configure User Quota in Dovecot & PostfixAdmin

This tutorial is going to show you how to configure user quota in Dovecot and PostfixAdmin.

dovecot postfixadmin quota


To follow this tutorial, it’s assumed that Postfix SMTP server and Dovecot IMAP server have been installed on your mail server. If not, please use the following tutorials.


CentOS 8/RHEL 8

It’s also assumed that you have installed PostfixAdmin, the web-based mail management tool, on your mail server.

Ubuntu 18.04

Ubuntu 20.04

CentOS 8/RHEL 8

Note that if you set up your email server using iRedMail before, user quota is already configured on your server, so you don’t need to follow this tutorial.

Step 1: Configure User Quota in Dovecot From the Command Line

First, we need to enable the quota plugin. Edit the Dovecot 10-mail.conf file with a command-line text editor like Nano.

sudo nano /etc/dovecot/conf.d/10-mail.conf

Find the mail_plugins parameter, uncomment it and set its value to:

mail_plugins = quota

This is the global mail_plugins setting. Save and close the file. Next, we need to enable the quota plugin for LMTP and IMAP services. Edit the Dovecot 20-lmtp.conf file.

sudo nano /etc/dovecot/conf.d/20-lmtp.conf

Add quota to the list of mail_plugins.

protocol lmtp {
  mail_plugins = $mail_plugins sieve quota

Save and close the file. Then edit the 20-imap.conf file.

sudo nano /etc/dovecot/conf.d/20-imap.conf

Enable the imap_quota plugin for IMAP protocol.

protocol imap {
  mail_plugins = $mail_plugins imap_quota

Save and close the file. Then edit the quota configuration file.

sudo nano /etc/dovecot/conf.d/90-quota.conf

In the Quota limits section, configure the plugin as follows. This sets 1G quota for every mail user. The Trash folder of each user will have its own 100M quota afer 1G is reached. You can change the numbers to your needs.

plugin {
  quota_rule = *:storage=1G
  quota_rule2 = Trash:storage=+100M

  # LDA/LMTP allows saving the last mail to bring user from under quota to
  # over quota, if the quota doesn't grow too high. Default is to allow as
  # long as quota will stay under 10% above the limit. Also allowed e.g. 10M.
  quota_grace = 10%%

  # Quota plugin can also limit the maximum accepted mail size.
  quota_max_mail_size = 100M

In the Quota warnings section, configure the plugin as follows, so the Dovecot will send a warning message if a user reaches 80% and 95% of the quota.

plugin {
  quota_warning = storage=100%% quota-warning +100 %u
  quota_warning = storage=95%% quota-warning 95 %u
  quota_warning2 = storage=80%% quota-warning 80 %u
  quota_warning4 = -storage=100%% quota-warning -100 %u # user is no longer over quota

And uncomment the following lines. This defines the location of the shell script that will send the warning message.

service quota-warning {
  executable = script /usr/local/bin/
  user = dovecot
  unix_listener quota-warning {
    user = vmail

In the Quota backends section, configure the plugin as follows, so Dovecot will use the dict backend (MySQL/MariaDB database).

plugin {
  #quota = dirsize:User quota
  #quota = maildir:User quota
  quota = dict:User quota::proxy::quota
  #quota = fs:User quota

Save and close the file.  Then create the file.

sudo nano /usr/local/bin/

Add the following lines to the file if you use Ubuntu.

cat << EOF | /usr/sbin/sendmail $USER -O "plugin/quota=maildir:User quota:noenforcing"
From: [email protected]
Subject: quota warning

Your mailbox is now $PERCENT% full.

Save and close the file. Then make it executable.

sudo chmod +x /usr/local/bin/

Edit the /etc/dovecot/conf.d/10-master.conf file.

sudo nano /etc/dovecot/conf.d/10-master.conf

Scroll down to the end of this file. Configure the dict service as follows.

service dict {
  unix_listener dict {
    mode = 0660
    user = vmail
    group = vmail

Save and close the file.

Step 2: Connecting Dovecot with PostfixAdmin

Now we have enabled quota in Dovecot, we need to connect it with PostfixAdmin. Edit the dovecot-sql.conf.ext file.

sudo nano /etc/dovecot/dovecot-sql.conf.ext

Find the following line.

user_query = SELECT maildir, 2000 AS uid, 2000 AS gid FROM mailbox WHERE username = '%u' AND active='1'

We need to change it to:

user_query = SELECT CONCAT('/var/vmail/', maildir) AS home, 2000 AS uid, 2000 AS gid, CONCAT('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active='1'

So Dovecot can get quota information for each user from the MySQL/MariaDB database. Save and close the file. Then edit Dovecot main configuration file.

sudo nano /etc/dovecot/dovecot.conf

Find the dict {} section and uncomment the quota dictionary.

dict {
    quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
    #expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext

Save and close the file. Then edit /etc/dovecot/dovecot-dict-sql.conf.ext file. (Note that on CentOS 8/RHEL 8, this file doesn’t exist. You just need to manually add the lines described below.)

sudo nano /etc/dovecot/dovecot-dict-sql.conf.ext

Add the following line at the beginning, so Dovecot can access the postfixadmin database in MySQL/MariaDB. If you don’t remember the postfixadmin database password, it can be found in the /etc/dovecot/dovecot-sql.conf.ext file.

connect = host=localhost dbname=postfixadmin user=postfixadmin password=postfixadmin_password

In this file, you can see two map definitions. You need to change quota to quota2.

map {
  pattern = priv/quota/storage
  table = quota2
  username_field = username
  value_field = bytes
map {
  pattern = priv/quota/messages
  table = quota2
  username_field = username
  value_field = messages

Then comment out the third map definition, because PostfixAdmin doesn’t use the expire table.

#map {
#  pattern = shared/expire/$user/$mailbox
#  table = expires
#  value_field = expire_stamp

#  fields {
#    username = $user
#    mailbox = $mailbox
#  }

Save and close the file. Restart Dovecot for the changes to take effect.

sudo systemctl restart dovecot

Check the status. Make sure it’s running.

sudo systemctl status dovecot

To display quota information in PostfixAdmin, edit PostfixAdmin configuration file.


sudo nano /usr/share/postfixadmin/config.local.php

CentOS 8/RHEL 8 Apache

sudo nano /var/www/postfixadmin/config.local.php

CentOS 8/RHEL 8 Nginx

sudo nano /usr/share/nginx/postfixadmin/config.local.php

Add the following two lines at the end of this file to enable quota in PostfixAdmin.

$CONF['quota'] = 'YES';
$CONF['used_quotas'] = 'YES';

//allow maxmium 100 mailboxes for each domain
$CONF['mailboxes'] = '100';

//default 10240MB quota for each user
$CONF['maxquota'] = '10240';

//default 102400MB quota for each domain
$CONF['domain_quota_default'] = '102400';

Save and close the file.

Step 3: Testing From the Command Line

Now you can list all users quota and usage with:

sudo doveadm quota get -A

You can also recalculate the current quota usage with the following command.

sudo doveadm quota recalc -A

dovecot quota

If you see an error message like

Fatal: Unknown command 'quota', but plugin quota exists. Try to set mail_plugins=quota

that means you didn’t set the value of mail_plugins to quota in the /etc/dovecot/conf.d/10-mail.conf file.

And if you see the following error when listing user quotas,

Error: stat(/var/vmail/ failed: Not a directory

you need to add the following line in /etc/dovecot/conf.d/10-mail.conf file and restart Dovecot.

maildir_stat_dirs = yes

Step 4: Setting Quota in PostfixAdmin Web Interface

Now you can go to your PostfixAdmin web interface to set domain and user quotas.

The default quota in PostfixAdmin is too small. If you have added a domain in PostfixAdmin before enabling quota, then you need to edit the domain settings in PostfixAdmin to increase the quota. New domains will have the quota settings specified in the config.local.php file.

Wrapping Up

I hope this tutorial helped you configure user quota in Dovecot & PostfixAdmin. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial
[Total: 7 Average: 5]

18 Responses to “How to Configure User Quota in Dovecot & PostfixAdmin

  • cybernard
    4 years ago

    One thing that isn’t touched on here is the need for security. This tutorial should include how to disable all the old insecure functions including but not limited to disabling anything less than TLS 1.2.

    • Xiao Guoan (Admin)
      4 years ago

      Forcing TLS 1.2 or TLS 1.3 in Postfix and Dovecot was discussed in part 2 of the building email server from scratch tutorial series.

      If you install Let’s Encrypt TLS certificate on a website using the certbot apache or nginx plugin, certbot automatically disables TLS 1.0 and TLS 1.1.

  • Giorgio
    3 years ago

    Hi, have this error.

    root@srv01:/etc/dovecot# doveadm quota get -A
    Error: auth-master: userdb list: User listing returned failure
    doveadm: Error: Failed to iterate through some users
    Username Quota name Type Value Limit 

    Have you any idea where file of config is involved?

    • giorgio
      3 years ago

      solved. Ihad userdb with static driver and not mysql driver.

      • Hi,
        when using the usedb driver=mysql, which file did you put in the args?
        The SQL query might be able to list all the usernames of the table ‘mailbox’ in the postfixadmin database, but the existing user_query in the file /etc/dovecot/dovecot-sql.conf.ext is done to get the data of a unique given user %u

        I’ve tried with static and sql drivers. In both cases:

        doveadm quota get -U [email protected] ==> WORKS
        doveadm quota get -A ==> DOES NOT WORK


  • Julio Azevedo
    3 years ago

    After following the tutorial PostfixAdmin does not allow me to set more than 10MB space quota for my email: MB (max: 10). How to fix this?

    • Julio Azevedo
      3 years ago

      solved. I forgot to set the domain quota.
      is there a way to change all quotas without having to use PostfixAdmin?

  • Mougrim
    2 years ago

    Thank you, all worked beautifully, quota is set and shown in roundcube.

  • Mohamed
    2 years ago

    Hi Xiao,

    Thanks for the explanation, will it be possible to re-do this using postfix, dovecot and MySQL (virtual mailboxes), without postfixadmin?

  • Hi

    If the mailbox is full then user can’t get the warning message.
    Is there any way to fix it?

    Thank you

  • Raffael
    2 years ago

    Thanks again for yet another excellent tutorial.

    I followed the tutorial and everything worked fine, however when opening roundcube it was very slow to load messages, emails with more than 10GB of use are practically impossible to open. Can you give me any tips on where to fix this slowness when loading the email in roundcube?

  • Sweeney
    2 years ago

    Consistently these tutorials are complete and well done. Keep up the awesome work. I am beginning to recommend these as knowledge base article examples for my developer and support engineers!

  • Christian
    1 year ago

    This tutorial is very helpful. The only issue is that the mailbox quotas just return as Unknown/Total even though no errors seem to occur. Even with RoundCube, it just says


  • Christian who also left a reply here has the same issue I’m having.
    I get Value 0 for everything. On roundcube and postfixadmin it shows as unknown/100

    • Christian
      1 year ago

      I was able to get it to work on my end. Had to completely clear everything for Quota Backends to get it to work.

      plugin {
        quota = dict:User quota::proxy::quota
  • Imraan
    1 year ago

    Hi Xiao,

    Super helpful as always, many thanks!

    One strange glitch for me, after I go through these steps quotas work fine, but I suddenly can’t receive email any more. Not sure if I did something wrong, but I followed the steps 3 times to be sure! Any suggestions on what to check?

    Ubuntu 20 system.

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community ( for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here