building a messaging server part two

Setting up Postfix

Installing Postfix

Postfix 2.3 or greater needs to be used on the server. This is because 2.3 has support for Dovecot's SASL authentication feature which will be used for SMTP Auth.

Since 2.3 is not in the stable or testing branches of Debian, it will need to be downloaded through the experimental. Add the following to your /etc/apt/sources.list:

deb http://ftp.debian.org/debian/ experimental main non-free contrib

Then run:

apt-get update

Finally, install the software with:

apt-get install -t experiemental postfix

Running software from the experimental branch means there are more chances for bugs and security holes. I recommend keeping the installation up to date more often than normal. It's a bigger hassle than running software from the stable branch, but I think the extra features are worth it.

Configuring Postfix

Postfix is usually ready to go out of the box, but just in case, make sure the following configuration parameters are correct in the /etc/postfix/main.cf file:

myhostname = mail.server1.local
myorigin = mail.server1.local
mydestination = mail.server1.local, localhost, localhost.localdomain, mail

Next, create a system account called vmail. This account will be used to access all email on behalf of the user. While giving one single account the ability to read all email might seem like a security risk, if the server is properly configured an secured, there's nothing to worry about. The vmail account is simply a dummy account used to retrieve email. Unless a local user gains root access, there's no way to have vmail's permissions. Counter arguments are welcome, however!

useradd vmail

Make note of the uid and gid of the vmail account. For the sake of the article, we'll make both the uid and gid 1001.

The next step is to create a subdirectory called virtual inside /etc/postfix. This directory will house all the virtual hosting information:

mkdir /etc/postfix/virtual

Finally, add the following parameters to /etc/postfix/main.cf (without the line numbers):

1. virtual_mailbox_domains = /etc/postfix/virtual/vdomains.txt
2. virtual_mailbox_base = /var/spool/vmail
3. virtual_mailbox_maps = hash:/etc/postfix/virtual/vmailboxes.txt
4. virtual_uid_maps = static:1001
5. virtual_gid_maps = static:1001
6. virtual_alias_maps = hash:/etc/postfix/virtual/valias.txt

Line 1 specifies a file which will contain a list of all the domains we're hosting. An example will look like this:

server1.local
server2.local
server3.local

Postfix will only read the first column of this file. Therefore, the ability to add additional information inside another column is available. For example, an owner of the domain could be added:

server1.local   joe
server2.local   tom
server3.local   mary

This can be helpful in an ISP-type environment where you will be billing Joe, Tom, and Mary for hosting their domain.

Line 2 specifies the main directory where all email will be housed.

Line 3 specifies a file that will contain a list of all virtual hosted email accounts. It will be hashed with postmap to create faster lookups.

Line 4 and 5 specify the uid and gid of the vmail user.

Finally, Line 6 specifies a file that will be used as the /etc/aliases except for virtual accounts. This is also hashed for faster lookups.

Adding Mail Accounts

Now that Postfix is set up, you can manually add some hosted domains. Inside /etc/postfix/virtual, create a new directory called domains:

mkdir /etc/postfix/virtual/domains

Inside domains, create a plain text file that has a name of one of the domains you're hosting. For example, the domain server1.local will be hosted on this server, so a file called server1.local will be created under the domains directory. Inside this file, the virtual email addresses for that domain will be stored. Here's how we'll set up server1.local for the article:

joe@server1.local       server1.local/joe/
tom@server1.local       server1.local/tom/

As you can see, there are two columns to this file. the first column specifies the full email address. The second column looks like the email address reversed and with some slashes. This is actually the directory in which the email for that account will be stored. To get the full path of the mailbox, attach the second column to the value the virtual_mailbox_base parameter specified in /etc/postfix/main.cf.

So if virtual_mailbox_base has a value of /var/spool/vmail, the full path of the mailbox for joe@server1.local will be:

/var/spool/vmail/server1.local/joe/

The added slash at the end means that the mailbox will be in Maildir format as opposed to mbox.

Create a similar setup for /etc/postfix/virtual/domains/server2.local:

joe@server2.local       server2.local/joe/
mary@server2.local  server2.local/mary/

Now the directory structure should look like this:

$ ls /etc/postfix/virtual/domains
server1.local       server2.local

The vdomains.txt file specified in main.cf can easily be created like so:

ls /etc/postfix/virtual/domains > /etc/postfix/virtual/vdomains.txt

Likewise, the completed vmailboxes.txt file can be created like this:

cat /etc/postfix/virtual/domains/* > /etc/postfix/virtual/vmailboxes.txt

The vmailboxes.txt file will need to be hashed:

cd /etc/postfix/virtual
postmap vmailboxes.txt

Though there are currently no mail aliases, the valias.txt file will need created and hashed:

cd /etc/postfix/virtual
touch valias.txt
postmap valias.txt

The final step is to create the mailboxes for the users. Here's how to create one -- you can create the others in the same way:

mkdir /var/spool/vmail
chmod 700 /var/spool/vmail
chown vmail.vmail /var/spool/vmail
cd /var/spool/vmail
mkdir server1.local
cd server1.local
mkdir joe
cd joe
mkdir new cur tmp
cd ..
chmod -R 700 *
chown vmail.vmail *

Sylvain writes in the comments of this article that rather than making the new, cur, and tmp directories manually, you can use the maildirmake.dovecot utility bundled with Dovecot.

Testing the Account

Once everything is set up, reload Postfix:

postfix reload

If no errors are given, everything should work. You can test this like so:

telnet server1.local 25
helo
mail from: joe@somewhere.local
rcpt to: joe@server1.local
data
Hello!
.
quit

Now check the /var/spool/vmail/server1.local/joe/new directory and there should be a piece of mail waiting!