Stop Postfix from adding new system users for each email address

Q I want to set up Postfix so that it won't add new system users for each email address I want to add. I usually learn quite well by example but the tutorials I have found on this are very confusing. Can you suggest an easy tutorial or HOWTO?

A Better, I can write you one! As always on machines with a firewall policy of ACCEPT, you should start by restricting the relevant port to the local machine until you're satisfied with the configuration. This should do it quite nicely:

iptables -I INPUT -i ! lo -p tcp --
dport 25 -j DROP

The main configuration file for Postfix as a whole (as opposed to the daemon config file, which is master.cf) is main.cf. This is usually found in /etc /postfix. By default, Postfix should come configured to only listen to localhost. Postfix binds to loopback in such a way that it doesn't accept connections from the wild. What we need to do is append the inet_interfaces to the public IP. Usually the entry is:

inet_interfaces = localhost

We change it to:

inet_interfaces = localhost, 123.213.312.132

This enables Postfix to listen on the supplied IP. To make life easier, we'll also be making Postfix look for any variable info - such as added email addresses or domains - in files other than the main configuration file (main.cf). Let's see a dump of the additions required. You may want to append them to the file main.cf:

# /etc/postfix/main.cf
virtual_mailbox_domains = virtualdomain1.tld, virtualdomain2.tld
virtual_mailbox_base = /path/to/mail/root
virtual_mailbox_maps = hash:/path/to/postfix/virtual-mailbox-maps
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_alias_maps = hash:/path/to/postfix/virtual-alias-maps

There are seven configuration lines here. In the first, you tell Postfix which domains are virtual. We want everything except system mails to be virtual, so list any domains on that line that you would like to host. You're really telling Postfix that these domains should be handled by the Postfix Virtual Delivery Agent (man 8 virtual). Line two is where you specify the parent directory where all the emails will be stored. I suggest you specify something other than /var/spool/mail. The argument to hash: is a file with key/value pairs. The virtual_mailbox_maps directive is where you list the one-to-one mappings of email address to filesystem location. We'll get to that in a short while.

Line five, virtual_uid_maps (yes, we skipped one; we'll get back to it right after this one) can be a variety of things. In this example, we went for a common UID for all email users, so we use the keyword static:, which in turn accepts one argument, the UID. Back to virtual_minimum_uid. You've probably guessed by now that it's a security constraint that restricts the user file UIDs to a level above a certain threshold. In our setup, we used a static UID for all users, but if we were using, say, hash, the virtual_minimum_uid would give us the security of knowing that any human errors in defining UIDs would be rendered harmless. Line six, virtual_gid_maps, is just like virtual_uid_maps only for GIDs (group IDs).

Now that we've set those two, let's create the directory in virtual_mailbox_base and change the ownership of that directory to reflect the settings we chose: in our example, user and group 5000. Note that we don't have to create the user or group on the system; it's optional. Line seven, virtual_alias_maps, points Postfix to the file where the virtual alias mappings are listed. Virtual aliases 'redirect' email messages meant for a virtual domain (see above) to any other destination. The file should contain pairs of email address/filesystem destination, such as:

# /path/to/postfix/virtual-mailbox-maps
account1@example.com example.com-dir/account1/
account2@example.com example.com-dir/account2

The first line tells Postfix to dump all emails addressed to account1@example.com in the directory /path/to/mail/root/example.com-dir/account1. The trailing slash makes Postfix use the Maildir format, which is recommended for most IMAP setups - check your POP3/IMAP service documentation. The real destination directory is the value of virtual_mailbox_base and the value of the file appended to it. You'll probably want the settings in /path/to/postfix/virtual-mailbox-maps to be checked when an email message comes in. For this to happen you have to make sure that the domain in the recipient address be listed as a virtual domain. We can do this in the file specified in virtual_alias_maps, which, as far as our settings in main.cf go, is /path/to/postfix/virtual-alias-maps. Let's alias postmaster@example.com and abuse@example.com to account1@example.com:

# /path/to/postfix/virtual-alias-maps
postmaster@example.com
account1@example.com
abuse@example.com
account1@ example.com

This setup is at least compatible with Dovecot IMAP and POP3 servers, except that both mailboxes should be in Maildir format, not Mbox format. Other things to consider are: using dbm instead of hash; moving the setup to MySQL; using Postfix Admin; and setting up a POP3/IMAP server. Before we can revel in a shiny new daemon ready to pipe thousands of email messages to the world, we need two things. First, let's allow access to the port:

iptables -D INPUT -i ! lo -p tcp --dport 25 -j DROP

Then I suggest you pay a visit to http://abuse.net and have your server tested for open relaying. Start it up with service postfix restart on a RHL-like machine. If you need more guidance, you really should see is www.postfix.org/VIRTUAL_README.html#virtual_mailbox

Back to the list