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!
#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".
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 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.
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.
/var/spool/virtual
Then change the user and group ownership to "vmail" and chmod the directory to
"drwxrwxr-x".
/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.
http://postfix.wl0.org/en/available-packages/
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.
virtual_mailbox_base = /var/spool/virtual
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.
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
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:
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:
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.
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.
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
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.
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
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.
+OK POP3 Welcome to vm-pop3d 1.1.6 <16098.1047605253@some.server.com>
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.
$Date: 2005/05/26 16:44:28 $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:
Creating the virtual domain directory structure
Ok the next step is to create the directory:
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:
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:
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:
#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.
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.
yet-another-domain.com placeholder
freds-domain.com placeholder
etc... etc...
admin@another-domain.com
another-domain.com/admin
sales@another-domain.com
another-domain.com/sales
postmaster@another-domain.com
another-domain.com/postmaster
@another-domain.com
another-domain.com/allmail
Restarting postfix and testing delivery
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:
{
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.
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.
#htpasswd -c passwd admin
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:
user admin@another-domain.com
pass mypassword
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: