I had to build a mail server for one client. So I decided to use postfix + dovecot as a combination for the setup.
After a week of usage, my client called and asked for per user quotas. Since the setup is with virtual users this required some changes. So here I’ll try to outline what I have done to setup the system.

First of all you should have to know that I setup the machine to be working with postfix + mysql + postfixadmin + dovecot. So the first step I took was to alter the database and add user ids there:


ALTER TABLE mailbox ADD COLUMN uid int NOT NULL AUTO_INCREMENT AFTER active, ADD KEY (uid);

Since on the machine there are already a lot of UIDs allocated from 0 to 1000 I decided that I will use UIDs over 30000 for this setup. But since the machine was in use for a week now, the above query populated the uid column with values. So what you do is, select the last UID from the table and update the AUTO_INCREMENT counter to the value you have + 30000. Here is how you could do it:


ALTER TABLE mailbox AUTO_INCREMENT=30173;
UPDATE mailbox SET uid=uid+30000;

Ok, so we have updated the database and we have the new UIDs that we have to use on the machine. The next step is to update the UIDs on the filesystem, so you enter your mail storage dir(mine is /var/vmail) and run this to fix the permissions:

mysql -e 'SELECT uid,maildir FROM mailbox' postfix|while read uid dir; do chown -R $uid $dir; done

The following steps are configurations for postfix and dovecot.

Since the current configuration for postfix was with static UID/GID maps for all users, now I had to update that. In the main.cf you will usually find these lines:

virtual_uid_maps = static:110
virtual_gid_maps = static:110

These are the static uid/gid maps. So we change ONLY the UID maps to:

virtual_uid_maps = proxy:mysql:/etc/postfix/mysql-virtual-uid-maps.cf

After you have done this you have to create the uid-maps.cf…:

user = postfix
password = *********
dbname = postfix
hosts = localhost
query = SELECT uid FROM mailbox WHERE username='%s' AND active = true

Now restart postfix and you have finished with it…

So what we have left to do is fix dovecot configuration:

in the protocol imap section you have to add this line:
mail_plugins = quota imap_quota
In the protocol pop3 section you have to add this line:
mail_plugins = quota
Then in the plugin section you have to add this line:
quota = fs:user

The last change is to the user_query for dovecot. You have to change this:
user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, '110' AS uid, '110' AS gid, CONCAT('maildir:',CONCAT('/var/vmail/',maildir)) AS mail, CONCAT('maildir:storage=', ROUND( mailbox.quota / 1024 ) ) AS quota_rule FROM mailbox WHERE username = '%u'

To that:
user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, uid, '110' AS gid, CONCAT('maildir:',CONCAT('/var/vmail/',maildir)) AS mail, CONCAT('maildir:storage=', ROUND( mailbox.quota / 1024 ) ) AS quota_rule FROM mailbox WHERE username = '%u'

Now after restart of dovecot you have everything setup and running.

And some plus is the automated quota handling. By adding one simple line to cron you can update the fs quota for all users:
mysql -e 'SELECT uid,ROUND(quota/1024),ROUND(quota/1024),"0","0" FROM mailbox' postfix|setquota -B /

Now you control the quota for all these users from the postfixadmin panel :)

Quite nice and quite easy. It took me 2hours to read all the documentation for that and to implement it.


Comments are closed.

Posted by HackMan
Dated: 30th January 2010
Filled Under: Linux General, Technology