Virtual Mail hosting on EL6

Step 1 Firstly, we're going to need to install at least the following packages: * postfix (should already be installed) * mysql-server * mysql * spamassassin * procmail * dovecot * dovecot-mysql

This should pull in a number of other packages required. NOTE: You will also need to install the spamass-milter and spamass-milter-postfix packages from epel.

Step 2 Start MySQL on the mail server. # service start mysql

Step 3 This is where we want to create the database for postfix etc to query. Use your favourite tool to do this - I used phpMyAdmin that I install on every system with MySQL installed. In this example, I used the database 'virtualmail' and created a user 'postfix' with password 'postfix'. You should change these to something more suitable - even if its just the password. Once you've created the database, create the cables with the following SQL:

CREATE TABLE IF NOT EXISTS `aliases` (  `redirect` varchar(50) NOT NULL,  `to` varchar(100) NOT NULL,  `active` char(1) NOT NULL DEFAULT 'Y',  PRIMARY KEY (`redirect`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;  CREATE TABLE IF NOT EXISTS `users` (  `username` varchar(128) NOT NULL,  `domain` varchar(128) NOT NULL,  `password` varchar(128) NOT NULL,  `active` char(1) NOT NULL DEFAULT 'Y' ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

This should be fairly self explaining. The users table contains the username & domain of our email users as well as their password (which will be SHA512'ed) and if they are active or not (Y or N). The aliases table is exactly that - aliases to forward to somewhere else.

Step 4 Time to configure postfix for MySQL lookups. Edit /etc/postfix/ and add the following:

## Configuration for virtual domains.
virtual_alias_domains =
virtual_alias_maps = proxy:mysql:/etc/postfix/
virtual_mailbox_domains = proxy:mysql:/etc/postfix/
virtual_mailbox_maps = proxy:mysql:/etc/postfix/
virtual_mailbox_base = /vmail
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_transport = procmail
procmail_destination_recipient_limit = 1

We now need to create the config files to allow lookups. Create the following:


user = postfix
password = postfix
dbname = virtualmail
query = SELECT domain AS virtual FROM users WHERE domain='%s'
hosts = localhost


user = postfix
password = postfix
dbname = virtualmail
query = SELECT CONCAT(LOWER(CONCAT(domain,"/",username)),"/Maildir/") FROM users WHERE CONCAT(username,"@",domain)='%s' AND active="Y"
hosts = localhost


user = postfix
password = postfix
dbname = virtualmail
query = SELECT `to` FROM `aliases` WHERE `redirect` = "%s"
hosts = localhost

Step 5 Create the user which will own all the mailboxes. If you wish to user different UID/GIDs for each user, you will need to do this by editing the users table and adding a uid and gid field, then modifying the query as required. This seems to be covered very well elsewhere so I'll skip it. # adduser -u 5000 -d /vmail -s /sbin/nologin -U vmail This creates a user with UID 5000, home directory as /vmail, sets the shell to /sbin/nologin to make sure nobody can log into the system with that accounts, and create a new usergroup with the same GID as UID.

Step 6 Configure SpamAssassin. Edit /etc/postfix/ and add the following at the bottom:

smtpd_milters = unix:/var/run/spamass-milter/postfix/sock inet:
non_smtpd_milters = $smtpd_milters
milter_default_action = accept

Configure spamass-milter. Edit /etc/sysconfig/spamass-milter to include a few extra flags to skip scanning email sent from local machines. I use:

EXTRA_FLAGS="-r -1 -i -i -i 2002:cb38:f71b::/48 -I"

This will automatically accept email from localhost, my LAN and my IPv6 subnet. The final -I option will also accept any email that has been sent using SMTP AUTH - ie an authenticated user. We also want to update to the latest definitions. # sa-update

Step 7 Now we want to configure procmail. We'll use it as the system-wide delivery method. Edit /etc/postfix/ and add the following:

procmail unix - n n - - pipe  -o flags=RO user=vmail argv=/usr/bin/procmail -t -m USER=${user}  EXTENSION=${extension} DOMAIN=${domain} /etc/postfix/procmailrc.common

We now want to create the global procmail file. This will run for *every* user on the system as /etc/postfix/procmailrc.common.

DOMAIN=`echo $DOMAIN | tr '[A-Z]' '[a-z]'`
USER=`echo $USER | tr '[A-Z]' '[a-z]'`
MKDIR=`mkdir -p $HOME/Maildir`

This will run the users own procmail and output all logging to their own procmail log. This is all done in the format /vmail/pm-\$domain-\$user.log. If you don't want per-user procmail configuration, then remove the SWITCHRC line and the global config should take care of mail delivery for everyone. SECURITY WARNING: As all mail is handled under the same UID:GID, it is possible for a malicious user to do things to other peoples mailboxes if you allow per-user procmailrc files from untrusted sources. I would only recommend having per-user procmailrc files on systems you have complete trust with users. If you find this questionable, remove the SWITCHRC line in the global procmail configuration.

Step 8 Now we configure Dovecot. I'm only going to cover the IMAP setup to keep things short, it can easily be adapted to POP3. Create the file /etc/dovecot/dovecot-sql.conf.ext with the following:

driver = mysql
connect = host=localhost dbname=virtualmail user=postfix password=postfix 
default_pass_scheme = SHA512
password_query = SELECT username, domain, password FROM users WHERE username = '%n' AND domain = '%d' AND active = "Y"

Edit /etc/dovecot/conf.d/auth-sql.conf.ext and alter it as follows:

passdb {  driver = sql  args = /etc/dovecot/dovecot-sql.conf.ext } userdb {  driver = static  args = uid=vmail gid=vmail home=/vmail/%s/%n/ }

Now I want to be nice to users that run Thunderbird etc and enable IMAP COMPRESS to let them get email a bit quicker. If you're running a lot of users, this may be a bit heavy on the CPU, but try it anyway! Edit /etc/dovecot/conf.d/20-imap.conf and add the following:

mail_plugins = $mail_plugins imap_zlib

We also now want to add the zlib plugin in /etc/dovecot/conf.d/10-mail.conf and set the default location for email. Change the following values:

mail_location = maildir:/vmail/%d/%n/Maildir mail_plugins = zlib

Lastly, we just need to enable SQL auth in /etc/dovecot/conf.d/10-auth.conf - uncomment the following line:

!include auth-sql.conf.ext

Step 9 Start it all up.

# chkconfig mysqld on
# chkconfig spamassassin on
# chkconfig spamass-milter on
# chkconfig dovecot on
# service mysqld start
# service spamassassin start
# service spamass-milter start
# service dovecot start

Step 10 Now you'll want to configure your users. In your favourite mysql method, add users and then watch the mail flow. Note that the password is an SHA512 hash of the password - not the password in plain text! To create the hash, use the following:

# echo -n <password> | sha512sum` This will output something like the


# echo -n test | sha512sum ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff -

If you have any corrections to this guide or suggestions, feel free to comment below!

Revision History:

2011-06-06 - Changed MD5 password hash to SHA512 for better security.

2011-06-07 - Altered PROCMAIL global file to deliver without a userspecific procmailrc. Also added logic to make a new users mail directory without having to manually create each directory. Now adding a new user is as simple as a database entry.

2012-02-19 - Changed to use of spamass-milter to avoid spam being forwarded to aliases without checking.


Comments powered by Disqus