Wednesday, February 17, 2010

This is the story of my migration from sendmail to Postfix

SkyHi @ Wednesday, February 17, 2010

Postix Configuration

This is the story of my migration from sendmail to Postfix


I run an Internet server that hosts about 40 different domains with a little over 100 different POP accounts. I started off very small with just my own domain an my own POP account. At the time, sendmail was pretty much the best game in town. For my setup, it was pretty simple to manage. However, now that I’ve grown to managing so many different domains with so many different POP accounts it’s very difficult to keep up with.
The main problem is that I had to have a unix account for every pop account. That meant one more potential vulnerable spot for someone to login to my system and do something bad. I couldn’t just set their shell to /bin/false, this prevented many different things from working. Instead I had to put a logout command in their .bash_profile and make sure they couldn’t modify that file. That also meant I had to give my users weird names like username-domainname.
At one point I had smtp-auth working with sendmail. Then I upgraded sendmail via the debian packages and it broke. The Simple Authentication and Security Layer has got to be the most finicky piece of software ever written. It’s the bane of system administrators everywhere. I’ve never met one who thought sasl wasn’t hell on earth.

The New Setup

The new plan has all the bells and whistles. It’s based on Postfix instead of sendmail. It’s config files are much easier to work with and is feature compatible with sendmail. On incoming smtp connections I have Amavisd-New running to filter mail with both Clam Antivirus and SpamAssassin.
Postfix has support for storing all your lookup tables in MySQL. Courier IMAP is also able to read from MySQL. Using “virtual mailboxes” I can have a single unix userid own all the mailboxes for my POP/IMAP accounts. The userids and passwords for the POP/IMAP accounts are stored in MySQL.
To allow my users to relay mail through my server I configured smtp-auth with the dreaded sasl. I’m running the saslauthd, but it uses PAM to actually do the authentications. There is a pam-mysql module that allows PAM to lookup userids and passwords in MySQL.


Before I started this, I’d never used Postfix. I didn’t have any idea what it’s overall layout and design was. I read the Postfix overview and a tour through its “anatomy”. I don’t know why, but this didn’t really sink in with me. I also got a free 14 day trial subscription to I wasn’t sure if I wanted to do a MySQL configuration or use LDAP. The Safari subscription let me read from several LDAP books to get a feel for what it is and how it works. In the end, looking through the Internet it seemed like most people are using MySQL. As another plus, there are several web-based interfaces for managing the virtual domains with MySQL as the backend. I also used Safari to read Postfix: The Definitive Guide. This is really what gave me a good understanding of Postfix.
Even after all that reading, I was still a little stumped on exactly how to proceed. There were so many different options for everything. In the end, the web-based admin interface is what drove my Postfix config. Both the admin interface and Postfix need to agree on the database scheme. Since most of the admin interfaces are written in PHP, you end up having the db scheme embedded into the “application”. So, the admin interface gives you the db scheme and you configure Postfix to use the same. After much reading, I ended up choosing Postfix Admin. It turns out Mischa Peter’s (the author of Postfix Admin) has written a very nice tutorial on setting it all up. That’s what I ended up using. To get the sasl stuff worked out, I also used notes from Christoph Haas’ ISP-style email service tutorial.

The Software

The trick though is to get the correct version of all the different pieces of software. The new server is running Debian/woody. I curse the day I upgraded my current server from woody to sarge. There’s still too much volatility in sarge to run a production server.
Some of the software needed I backported from Debian/sid. I only did the stuff that was pretty easy:
  • libdigest-nilsimsa-perl-0.06 – message digest algorithm (used by razor)
  • razor-2.361 – spam-catcher using a collaborative filtering network (used by spamassassin)
  • libpam-mysql-0.50 – PAM module allowing authentication from a MySQL server
I started with the standard deb lines in my /etc/apt/sources.list, but also added a deb-src line for sid:
deb-src unstable main
deb-src unstable main
Then to “backport” the packages from sid to woody I just did:
$ sudo apt-get build-deps foo
$ apt-get source foo
$ cd foo-X.Y
$ dpkg-buildpackage -rsudo
$ cd ..
$ sudo dpkg -i foo-blah-blah-blah.i386.deb
For most of the other packages I needed I used the archive from Henrique M. Holschuh (sorry, I can’t find out who that is) archive:
deb hmh/cyrus/
deb hmh/misc/
deb hmh/amavisd-new/
deb hmh/postfix/
With those lines for my sources.list I was able to easily install the following packages:
  • postfix 2.0.16-4.woody.1
  • postfix-dev 2.0.16-4.woody.1
  • postfix-doc 2.0.16-4.woody.1
  • postfix-mysql 2.0.16-4.woody.1
  • postfix-pcre 2.0.16-4.woody.1
  • postfix-tls 2.0.16-4.woody.1
  • libsasl2 2.1.15.woody.5.0
  • libsasl2-modules 2.1.15.woody.5.0
  • libsasl2-modules-gssapi-heimdal 2.1.15-0.woody.5.0
  • libsasl2-modules-mysql 2.1.15-0.woody.5.0
  • sasl2-bin 2.1.15-0.woody.5.0
  • amavisd-new 20030616p5-6
  • clamav 0.60-10
  • clamav-base 0.60-10
  • clamav-data 0.60-10
  • clamav-freshclam 0.60-10
  • libclamav1 0.60-10
  • spamassassin 2.63-1in1
I’m also using
deb woody virus
Some of those packages may have come from there. Right now I’ve got something weird going on between my “unofficial” apt sources with clamav. I’ll need to do some more investigating to get that cleared up.
h2.+ Maildrop and creating maildirs
One of the problems with Maildrop is that it won’t automatically create the maildir before it delivers the mail. So, as the postmaster, you’re responsible for creating the directories when you create the user. I’ve written a script,, to do this for me. The permissions on it are 6755 owned by the same uid and gid that Maildrop runs as. Running setuid scripts is always a little worrying. I’ve tried to write this script as well as I can. The reason it needs to be setuid instead of just running it manually with sudo is that I’ve modified Postfix Admin to make a system call to when a new user is added.
h2.+ Colortail
I’ve downloaded colortail and installed it. While working on my postfix configuration it’s not uncommon for me to have a fairly large term window showing postfix’s mail.log. Of course, as I get more and more users running on my box, the chatter is pretty noisy. Colortail has cleaned that up a bit and helps me focus on the pieces that matter to me. Of course, this is all personal preferences…
$ colortail -k conf.postfix -f /var/log/postfix/mail.log
h2.+ Grepping the mail.log for messages
One problem I have is that when I want to see all the log messages for a given email message, there’s no single identifier I can grep on. Because of the way I have messages received by smtpd, passed to amavis, then spooled back into smptd I end up with two different Postfix IDs for each messages. Plus, the amavis lines don’t include the Postfix ID.
I wrote as an answer to this problem. It’s a little brute force, but I don’t think it will get run very often to cause processor consumption problems. Basically, it parses through all of the mail.log lines and groups them by both their Postfix message ID and the email’s Message-ID taking care to relate the two together. Then after all the log file’s lines are sorted by these two criteria it groups all the lines with only a message-id with the appropriate Posfix ID lines. It then groups multiple sets of Postfix ID lines if they share the same message-id. Meanwhile it does all this while preserving the order the lines were found in the mail.log. Pretty nifty if I may say so myself.
Two limitations. First, it can’t read gzipped files. So, you can’t just give it all of your mail.log* . Second, some lines in the mail.log don’t have a Postfix ID or a Message-ID (i.e. connect and disconnect messages and warnings). These lines get dropped by the wayside.


I’m really pumped about my new mail configuration. I could post all my config files here and may sometime. However, the above information should give you enough to go on. If you have questions, feel free to contact me.