HOW TO Setup Postfix and vm-pop3d with virtual mailboxes

By

Abstract

Provides basic steps involved in setting up Postfix V2.0 (onwards) and vm-pop3d to host a multiple domain mail setup with independent user space for each domain. This guide assumes a basic understanding of general Postfix configuration and the operation of a pop mail server. It also assumes knowledge of basic Linux admin tasks like adding users.


Introduction

Recently I had to setup virtual mailbox style domains on a server that serves mail for multiple domains. I did some hunting around the web but couldn't find a how-to that incorporated the enhanced virtual mailbox features of Postfix V2.0 onwards. Most of the existing guides and How-Tos were based on Postfix V1.2, where implementing virtual mailbox domains was much more difficult.

So I decided to write this document to record the steps I took to implement this setup. I hope you find it of some use!

A brief introduction to virtual domain mail hosting

Virtual Alias vs. Virtual Mailbox

Postfix has support for two types of "virtual" mail hosting. The first type is known as "virtual alias" mail. This is relatively straight forward to implement and basically allows mail addressed to user@anydomain.com to be re-directed to a local mail account by means of a "virtual" lookup table. This is not unlike aliases with the notable difference being you can specify non-local source and destination addresses in virtual tables which cannot be done with aliases.

The problem with virtual alias domains

The limitation of virtual aliases becomes apparent when the numbers of users and/or domains the server must host, increases. Let's use an example. Your postfix mail server is configured with a "mydomain" parameter of "foo-domain.com" but you also host mail for the domain "another-domain.com". Now using a virtual alias table, you create a "virtual" mail address of "admin@another-domain.com" and you direct this to a local mailbox called "admin" as that makes sense, right? So your virtual alias table in postfix would look something like this.

#virtual alias table
another-domain.com                    placeholder
admin@another-domain.com      admin

So far so good. Mail addressed to admin@another-domain.com goes to the local mailbox "admin". When the client from "another-domain.com" wants to collect their mail they would log in via POP using a user name of "admin" and their password.

But what happens if you want the address of "admin@foo-domain.com" too, it would then get delivered to the same mailbox?? So maybe specifying the local address "admin" for the mailbox wasn't such a sensible idea after all and instead you should have picked something that you would be unlikely to need as a local mailbox.

You can see the issue that arises though. Each virtual domain address needs a corresponding local address but once you start getting multiple domains with the same user name, things get difficult to manage and new local mailboxes need to be created.

Wouldn't it be great if there was a way of having mailboxes for each domain stored separately?? Enter the realm of "Virtual Mailbox Domains".

Virtual Mailbox Domains

Since quite early on, Postfix has supported "Virtual Mailbox Domains", however prior to V2.0.X, it was quite tricky to implement. The reason was you had to setup a table to tell Postfix to deliver mail to your "virtual domains" using a different local delivery agent.

However, now that we're in the V2.0.X era, that requirement has gone and Postfix is smart enough to deliver virtual mailbox mail via it's super-duper "virtual" delivery agent automagically.

In a nutshell, the virtual delivery agent allows you to setup virtual domains and mailboxes in lookup tables similar to "virtual alias" lookup tables. You can then have the mail delivered to a mailbox in a definable directory structure. So instead of having mail delivery to the local "/var/spool/mail/username". You could, for example setup mail (lets use the admin@another-domain.com example) to go to "/var/spool/virtual/another-domain.com/admin". You can instantly see the appeal of this setup. Each virtual mailbox domain has it's own directory, under which all user's mailboxes relative to that domain reside.

vm-pop3d

Ok, that's all lovely, but I can hear you asking, how do the clients get their mail from these mailboxes tucked away in these directories?? The answer is vm-pop3d.

Vm-pop3d is a replacement for your current pop3 server. It serves pop3 mail just like any other, but with one main difference. Along with serving pop3 mail from the local /var/spool/mail/username mailboxes, it can also accept logins of user names that contain a domain name. So our example above would login to check their mail using a username of "admin@another-domain.com". This tells vm-pop3 that the user's mailbox resides elsewhere. The exact location of the mailbox is constructed by vm-pop3d by assuming a base virtual mailbox directory of "/var/spool/virtual" (this can be changed by recompiling vm-pop3d but if you're using the RPM, you'll need to stick with this default). Vm-pop3d then adds the domain name to the path, in this case that's "another-domain.com" and finally it expects to find the user's mailbox, by name in that directory. So using the username of "admin@another-domain.com" as our pop3 login, vm-pop3d will go to /var/spool/virtual/another-domain.com/admin and open that as their mailbox. The added bonus is too, that "admin@another-domain.com" does not need to have a local Unix account. The passwords are verified from a completely separate password file but we will go into that later.

Preparing the system

Setting up the virtual mail user

Before we change our postfix configuration, we need to prepare a few things. Firstly you will want to create a new user that will own all the virtual mailbox directories and files. This can be a completely unprivileged user and I chose "vmail" as my username. Here is an example of the entry in my passwd file after creating the user:

vmail:x:200:200:Virtual Mail:/dev/null:/sbin/nologin

I'm using Redhat so a group called "vmail" with a group ID of 200 was automatically created for me when I created the user. However if you're using a different system, you may need to create this group manually.

I picked an easy to remember user number and group number of 200 because you will need this number later on when we configure Postfix. I used 200 too because it's below the normal user accounts Redhat (which I'm using) allocates but it's above the normal system accounts.

Creating the virtual domain directory structure

Ok the next step is to create the directory:

/var/spool/virtual

Then change the user and group ownership to "vmail" and chmod the directory to "drwxrwxr-x".

The next thing you need to do is to recreate sub-directories named after domain name of the domains you wish to virtually host. Remember vm-pop3d uses the domain name to know which directory to look in for the mailboxes so the directory name needs to be identical to the domain name (without the @ symbol of course). In our example of another-domain.com, the directory will simply be called "another-domain.com" so the full path would be:

/var/spool/virtual/another-domain.com

Once you have created this directory change the user and group ownership to "vmail" and chmod the directory to "drwxrwxr-x" as you did for the parent "virtual" directory. Create new directories for each domain you will be virtually hosting mail for.

This completes the preparation, the next step is to get Postfix to deliver mail to mailboxes in these directories.

Configuring Postfix

Upgrade/Install Postfix V2.0.X (minimum)

Ok, if you haven't done so already, you'll need to install V2.0.X or later of Postfix as setting up virtual mailboxes in versions prior to this is beyond the scope of this guide. If you like to avoid having to install from source (like me) you can get some pre-packaged postfix RPM's from:

http://postfix.wl0.org/en/available-packages/

Check master.cf file

If you installed postfix from an RPM as I did, just check the /etc/postfix/master.cf file for the line that starts with "virtual". It should read:

virtual unix      -        n        n        -       -       virtual

When I upgraded my Postfix installation using the RPM, the second "n" was set to "y" and the virtual agent tried to run chrooted. As the documentation states, the virtual delivery agent was not designed to be run chrooted so both options should be "n" as above.

Edit main.cf file

Our next move is to add the virtual mailbox options to the main.cf config file in the /etc/postfix directory. The options you need to add are:

virtual_mailbox_base = /var/spool/virtual
#This option tells postfix to add this path to the beginning of
#all mailbox locations found in the lookup tables that we will
#create later.
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
#This is the path to the lookup table that contains the full
#e-mail address and relative mailbox path for each address
#required in the virtual domains.
virtual_mailbox_domains = hash:/etc/postfix/vmaildomains
#This is the path to the lookup table that contains the
#domain names of all domains that are hosted via virtual mailboxes
virtual_uid_maps = static:200
#This tells postfix to use the "vmail" user we created earlier for
#writing to the mailboxes.
virtual_gid_maps = static:200
#This tells postfix to use the "vmail" group we created earlier for
#writing to the mailboxes.
virtual_mailbox_lock = dotlock
#Vm-pop3d uses "dotlock" to lock mailboxes so we need to tell Postfix to
#use this method also.
virtual_minimum_uid = 200
#This parameter tells postfix what the minimum UID and GID to expect back
#from the "virtual_gid_maps and virtual_uid_maps" parameter. It defaults to
#100 which is probably fine, but since our user is 200, lets raise it to 200.

The important thing to note for later is the path and name of our virtual mailbox lookup tables. In my examples these are stored in the /etc/postfix directory with the other config files and tables. They are called vmailbox and vmaildomains. Remember these names because we're about to create these files.

Creating the virtual mailbox lookup tables

Postfix stores information about your virtual domains in two files. The first file, "vmaildomains" (in my example, although you can choose another name if you wish), is a simple list of the raw domain names you wish to host mail for. Because we will be compiling this into a hash lookup table, the table needs to have two values on each line although the second value is ignored so it's just a placeholder.

In our "another-domain.com" example, the vmaildomains file would simply read:

another-domain.com       placeholder

If you are hosting more domains, simply add them to the list:

another-domain.com              placeholder
yet-another-domain.com       placeholder
freds-domain.com                placeholder
etc... etc...

After adding your domains (don't forget to create their directories and set permissions in /var/spool/virtual if you haven't done so already), we need to compile the table into hash format with the following command (assuming you're in the /etc/postfix directory):

#postmap vmaildomains

Next we need to create the "vmailbox" table. This table contains the full e-mail addresses you want to be available in the virtual domains, and their respective mailbox locations. Remember that the "virtual_mailbox_base" directory will automatically be added to the start of the path you specify, so continuing our example, the vmailbox table might look like this:

admin@another-domain.com another-domain.com/admin
sales@another-domain.com another-domain.com/sales
postmaster@another-domain.com another-domain.com/postmaster

If you have more than one domain, simply add the e-mail addresses for each domain as above. Remember of course to specify the correct mailbox path to match the domain name. Also keep in mind that any addresses that are not listed here will be rejected as "user unknown". If you want ALL mail from a domain to go to a particular mailbox add an entry:

@another-domain.com another-domain.com/allmail

This will delivery all mail for the another-domain.com to the mailbox "allmail" (or whatever mailbox you specify).

After creating your vmailbox table, you'll need to give it the same compiling treatment that we did for the vmaildomains table. So the command is:

#postmap vmailbox

You should now have two new files in the /etc/postfix directory, called "vmailbox.db" and "vmaildomain.db". These are the compiled tables which postfix can look up faster than the plain text versions of the files. Don't forget to re-run the postmap commands as above, if you ever add or remove entries from the text version of the tables.

Restarting postfix and testing delivery

Our next task is to reload the configuration changes we've just made to postfix with:

#postfix reload

Keep an eye on your /var/log/maillog for any errors from the postfix daemons, in case there are simply typos or similar errors occurring.

Provide the reload occurred without error, test your setup by sending mail to your new virtual domains. If all looks well in /var/log/maillog, you should be able to look in your /var/spool/virtual/another-domain.com directory and see a new mailbox containing the mail you just sent.

If you get errors in /var/log/maillog you need to double check your directories, permissions, tables and don't forget if you didn't look in the master.cf file right back at the beginning that could be the cause of your trouble too. Most error messages from postfix are relatively helpful in narrowing down the point of failure.

Assuming that all worked, we can move onto setting up vm-pop3d.

Configuring vm-pop3d

Installing and setting up vm-pop3d in xinetd

For ease of installation, there are RPMs available and this is what I used. These are normally compiled with default values which works well with our setup above. They are available for download at:

http://www.reedmedia.net/software/virtualmail-pop3d/#download

After installing the RPM, you'll need to decide if you want to run vm-pop3d as a stand along daemon that will startup automatically when the system boots, or, as I chose to do, you can use the xinetd server to call vm-pop3d as required. For the purpose of this guide, I'll stick with what I know works and that was to use the xinetd server.

You'll need to create a new file in the /etc/xinetd.d/ directory, called "vm-pop3d" and insert similar contents to this:

service pop3
    {
        socket_type = stream
        protocol = tcp
        wait = no
        user = root
        instances = 25
        server = /usr/sbin/vm-pop3d
        server_args = -i --user vmail
        log_type = SYSLOG local4 info
        log_on_success = PID HOST EXIT DURATION
        log_on_failure = HOST ATTEMPT
        disable = no
    }
Don't forget to disable your old pop server if you've previously had one running also.

Note the "--user vmail" parameter. This tells vm-pop3d to use this username when accessing mailboxes in the /var/spool/virtual space. It doesn't effect what user it runs as when accessing normal local unix mail accounts.

Creating virtual mailbox passwords

Ok the local mailboxes are fine, but what about passwords for the virtual mailboxes? By default, these are stored in /etc/virtual/another-domain.com/passwd and the passwd file itself takes on an identical form to that of the apache password files.

To this end, you can actually use Apache's "htpasswd" utility to maintain your virtual mailbox passwords. So to create this file, first create the appropriate directory structure for each of your domains under /etc/virtual. Then change into the domain directory you wish to setup the passwd file for (I'm going to use our example "another-domain.com" again and then use htpasswd to create the passwd file as follows:

#cd /etc/virtual/another-domain.com
#htpasswd -c passwd admin

The above example would create an new password file and the first username would be "admin". This username has to be the same as the corresponding mailbox name over in /var/spool/virtual/another-domain.com. After issuing the command above, it will prompt you for a new password and then a retype. This password will be needed for your client admin@another-domain.com to log in and check their mail.

After you have completed this for all your domains, you can restart xinetd to activate vm-pop3d.

Testing vm-pop3d

If all has gone well you should be able to telnet to port 110 on your server and, in our example, we should be able to log in as follows:

+OK POP3 Welcome to vm-pop3d 1.1.6 <16098.1047605253@some.server.com>
user admin@another-domain.com
pass mypassword

Again keep an eye on your maillog file. If you see stuff about /dev/null it means vm-pop3d can't get to the actual mailbox for some reason (incorrect path or permissions?) but otherwise all should be well. This completes the setup and to add further domains, it's simply a matter of repeating these steps again.


Cross References

virtualmail-pop3d home page
Postfix home page


Credits

Thanks to Ashley Brown for correcting my syntax on the htpasswd command. This has now been corrected.


Author:

$Date: 2005/05/26 16:44:28 $