Installing Postfix and uwash imapd on Picasso

We run postfix on polaris as our mail server. I would like to move mail services to picasso, in an effort to minimize what polaris does in the hope that I can pull it from production in the future.

I also needed to install the c-client and uwash imapd/ipopd stuff onto picasso as well. In the process I needed to install it with ssl support, and make sure that it worked properly and had a valid certificate.

However, since I knew nothing about postfix, and I know our installation on polaris was goofy, I had some work to do. Here's my notes.

Installation of postfix

I installed postfix from the ports tree. I changed directories into /usr/ports/mail/postfix and did a "make". I selected the PCRE, SASL, DB3, OpenLDAP, and TLS options.

The build failed because it needed the file "pfixtls-0.8.11a-1.1.11-0.9.6g.tar.gz" which I was able to find on the web. I put it in /usr/ports/distfiles/postfix and all was good.

The next step was to configure the system to run postfix instead of sendmail at startup. This involves editing the files /etc/rc.conf and /etc/mail/mailer.conf. The changes are as follows:



In order to run efficiently, postfix needs more sockets, nmbclusters, and files than the default FreeBSD kernel is configured with. This can be done by editing the file /boot/loader.conf. The changes I made to the kernel configuration are as follows:

Please note, the machine will need to be rebooted after you make these kernel changes.

Installation of uwash imapd/ipopd

We use the uwash imap/pop daemons for remote mail access. Installation was pretty straightforward by using ports.

The first step was to build and install the c-client. The c-client contains low-level headers and library routines for use with various other mail utilities. Think of it as the driver for use with the uwash imap/ipop daemons.

To make and install it, I cd'ed to /usr/ports/mail/cclient and did a make -D WITH_SSL then a make install -D WITH_SSL. This configured and installed the c-client with SSL support.

The next step was to make and install the imap/ipop daemons. I cd'ed to /usr/ports/mail/imap-uw and did a make -D WITH_SSL and then a make install -D WITH_SSL. This built the uwash daemons with SSL support enabled, and installed them in /usr/local/libexec.

SSL Certs
The ports tree looks for the SSL certificates in /usr/local/certs however I placed them in /etc/ssl/certs and made a symlink for the former (ln -s /etc/ssl/certs /usr/local/certs).

The cert was fairly simple to make, as opposed to the stone ages when we had to jump through serious hoops. RedHat was kind enough to provide a Makefile that makes self-signed "test" certficates easy to generate. The Makefile resides in /usr/share/ssl/certs on any redhat 8 machine. I did modify the default life of the certificate to 10 years, as opposed to 365 days, so that we wouldn't have to remember to generate a new cert next year.

After the certificate was generated (make imapd.pem), I copied it to picasso:/etc/ssl/certs. The two certs that we care about are imapd.pem - the SSL imap server and ipop3d.pem - the SSL pop3 server.

The last step was to configure inetd to launch the uwash imap/pop3d servers and test them out. I added the following lines to /etc/inetd.conf in order to launch the imap/pop3 servers:

Then I restarted the inetd super server (kill -HUP `cat /var/run/`). After inetd was restarted, I tested out imap using Netscape-Communicator since it supports SSL imap.

Configuration of Postfix

The ports tree installs the postfix configuration files in the location /usr/local/etc/postfix. However, since we have many mailing lists which are include files, I was concerned that there might be errors when I migrated the list data from polaris. I made a symlink for /etc/postfix to point to /usr/local/etc/postfix, which should resolve any name-space problems.

There are many files installed by default in the postfix configuration directory. Several of them are sample configuration files and can be ignored. The files we care about modifying are:

aliasesMaster aliases file
main.cfMain configuration file (think
transportMail delivery (transport) mapfile

Additionally, we copied some files from polaris without changing them in any way. The copied files are:

body_checksregex list to bounce messages based on content
header_checksregex list to bounce messages based on header
lists/aliases.facAlias list for faculty
lists/aliases.gradinfoAlias list for some grad students
lists/aliases.gsAlias list for other grad students (why 2?)
lists/aliases.guestsAlias list for guests
lists/aliases.pcardAlias list for Tracey's pcard list
lists/aliases.postdocAlias list for postdocs
lists/aliases.staffAlias list for staff
lists/aliases.ugradsAlias list for undergrads
lists/aliases.visitingAlias list for visiting faculty (why 2?)

Changes made to
The following options were changed from the defaults:

Note, the "alias_maps" and "alias_database" entries might be pointless, but I wanted to retain the majority of the configuration that we had from polaris.

Making local delivery work
The next step was configuring the transport. This allows us to explicitly accept mail from other hosts. This way, if user "juan" on system "eggplant" sends an email, and user "joe" on system "rutabega" responds to "juan@eggplant," email will be delivered through the mail server, rather than to "eggplant".

Postfix doesn't accept mail for an entire domain by default. If you try to work around it simply through the configuration of mx-records you'd get an error message like: Unable to deliver message to eggplant mail loops back to myself.

On polaris, there was a kludge to make this work which a predecessor did by creating a file named /etc/hosts.postfix which listed every host in the department. The mydestination line in used to point to the kludge file. The biggest problem with this method is that we always needed to remember to update that file whenever we installed a new host, and invariably we'd forget. By properly configuring the transport, we can work around this and accept delivery for all hosts in a domain by default.

The following lines were added to the file transport:

This tells postfix on the mail server that all mail for should be delivered to the local machine.

After modifying the transport, you need to generate the postfix mapfile and restart postfix. The map is made by running postmap /etc/postfix/transport and postfix is restarted by running postfix reload.

I tested out mail delivery by modifying the mx record for to point to There is no configuration in the picasso postfix setup to explicitly accept mail for fugu. I then logged into, and wrote email to,, and The mail delivery for went through polaris, like it was supposed to. The mail delivery for ken@picasso and ken@fugu went through picasso without a hitch.

Please note: The and transport files are checked into RCS, if you need to modify them, you will need to check them out.

System Scripts that needed to be changed

Two scripts needed to be changed on polaris. They are the account creation and account deletion scripts. I had to modify them to copy the appropriate mailing list aliases to picasso whenever they were done. I have not tested the changes, but they should work..

Throwing Spam Assassin into the mix

Spam Assassin is a perl based tool which allows ruleset based mail processing. It works by having a broad scope of rules. Every email is given a weighted score based on which rules it passes, or fails. The rulesets are weighted differently depending on what they represent. Users will then be able to filter their mail (or not) depending on the results of the score.

Installation of spam assassin is fairly easy. In FreeBSD you can use the ports tree (cd /usr/ports/mail/p5-Mail-SpamAssassin), but you can also use the CPAN interactive shell to download and install SA (see the documentation at for information on using cpan). I used the ports tree to install SA.

SA works in one of two ways. It can either run as a client/server application, or it can be a standalone program which is called each time a message is delivered. The client/server model supposedly reduces cpu overhead, so this is the method I chose.

After SA is installed, you need to start the spamd SpamAssassin processing daemon. When installing through ports, a start/stop script is installed as /usr/local/etc/rc.d/ Rename the file to /usr/local/etc/rc.d/ then start the daemon by executing the command /usr/local/etc/rc.d/ start.

The SpamAssassin filter
SA works by running each email through a filter script. The simple filter example included in the postfix documentation (/usr/local/share/doc/postfix/FILTER_README) makes a good starting point. There are a few steps that need to be taken:

The filter script I made is named /usr/local/bin/astrofilt. The contents are as follows:

The filter uses the spamc client, but if you wish to run SpamAssassin in non-client/server mode, you would need to change spamc to spamassassin.

When you have the SA filter installed, you can test it out by using the sample spam messages provided with SA. This can be done by issuing the command:

You will need to change sender to the email address that the message should be 'from', and recipient should be the address of who the mail should be delivered to -- most likely your own. If all goes correctly, in a few minutes you should receive one message with the subject of *****SPAM***** something and one without.

You can display the full header of the message to find out some more information on the SA weighting. This is useful for tweaking SA as time goes on. By changing the weighting of certain fields you can reduce false-negatives and false-positives. Sample SA headers from a message tagged as spam are included here:

This particular spam message scored a 10.4. 5.0 is the current spam threshold on our system. You can tweak the weighting and thresholds with SpamAssassin (more on this later).

Making SpamAssassin work with postfix
Making SA work with postfix is as simple as making two lines worth of changes to the file configuration file. If you installed postfix via ports, the configuration file is /usr/local/etc/postfix/

The first change is to change the line that read:

To read:

The next change is to add a filter statement into the Interfaces section of your file. It should read something like this:

You will probably want to change the filter command from /usr/local/bin/astrofilt to the name of your filter script (from above).

****IMPORTANT**** - The changes to must be on one line each, not wordwrapped into multiple lines. If you use PICO as your editor, you need to be aware that it will wordwrap, and these changes won't work.

Once you've made the changes to, you can issue the command postfix reload to restart postfix.

Now, you should have a generic default installation of SA running. You can verify it's running by emailing yourself copies of the sample-spam.txt and sample-nonspam.txt files.

Tweaking SpamAssassin
As time goes on, you may wish to tweak SA to either trap more spam that passes, or to reduce the false positives. You should only make your changes to the SA configuration file. The ports tree installs the SA file as /etc/mail/spamassassin/

After 12 hours of tweaking, I've found that SA is too generous and has allowed more spam to get through than I would like. I've gone ahead and increased the weighting for certain tests. My tweaks will undoubtably change during the next four weeks, but here's my initial configuration:

You can find more configuration options from the SpamAssassin online documentation.

Viral Scanning with Amavis

I used the '/usr/ports/security/amavis-perl' as a guideline. First I installed the following dependencies through the ports tree:

Next step was to download the McAfee Virus Scan for FreeBSD from the Soda Shoppe web-site and install it in /usr/local/uvscan on picasso. After installation, I used the '' example from the PDF documentation on the soda shoppe site to update the dat file. One thing to note, the function checkuvscanver did not work. My modification to it is as follows:

Last Updated: December 18, 2002, Ken Sallot