Skip to main content Help Control Panel

Rod Morison Software —  Technotes

Home «   Articles «  

Postfix & Cyrus Install

How to get email services up, configured and talking to each other

Ssh Access

Assuming you have a server up and responding on it's static IP as described in the Ubuntu Install section, you can continue to work on the console, or ssh into the server. In the long run you'll probably ssh most of the time, as you can do it from just about anywhere on the internet (with an ssh program, that is.)

If you've got a OS X Mac, BSD or Linux computer, ssh should already be available from the command line. If you're on Windows, get Putty or Cygwin (make sure you include the openssh package in the cygwin install.) I'll use the command line ssh in examples. You can peruse the Putty docs and achieve the same results.

ssh to the server (subbing your loginid and mailserver dns name, of course)
ssh -p 9999 loginid@mailserver.example.domain
This means of access has the plus of being able to copy/paste between windows, amongst others.

Postfix Install & Config

  1. Install the Postfix Package
    sudo apt-get install postfix
    The package installer will bring up 3 screens. Ok the first one, choose Internet Site for the second, and make sure the full name, with domain part (the FQDN) is in the 3rd screen.

    Postfix Package ConfigPostfix Package Config Postfix Config TypePostfix Config Type Postfix Mail NamePostfix Mail Name
  2. main.cf config
    sudo vi /etc/postfix/main.cf
    Find the "# TLS parameters" line and right underneath it add
    smtpd_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
    This file doesn't exist yet, but we'll install it later. It's not necessary for self-signed certs, like the snakeoil automatically generated cert, but getting this in place now makes referencing a CA signed cert a snap later.

    Next, add the following to the end of the file:
    # SASL parameters
    smtpd_sasl_local_domain =
    smtpd_sasl_auth_enable = yes
    smtpd_sasl_security_options = noanonymous
    broken_sasl_auth_clients = yes

    # Client & recipient restrictions
    smtpd_recipient_restrictions =
    permit_sasl_authenticated,
    permit_mynetworks,
    reject_unauth_destination,
    reject_invalid_hostname,
    reject_non_fqdn_hostname,
    reject_non_fqdn_sender,
    reject_non_fqdn_recipient,
    reject_unknown_sender_domain,
    reject_unknown_recipient_domain,
    reject_unauth_pipelining
    reject_rbl_client bl.spamcop.net,
    reject_rbl_client sbl-xbl.spamhaus.org,
    reject_rbl_client list.dsbl.org
    smtpd_client_restrictions = permit_mynetworks,
    check_client_access hash:/etc/postfix/access
    smtpd_sender_restrictions =
    reject_non_fqdn_sender,
    check_sender_access hash:/etc/postfix/access,
    check_sender_mx_access hash:/etc/postfix/access

    # LMTP
    message_size_limit = 20480000
    mailbox_transport = lmtp:unix:/var/run/cyrus/socket/lmtp
    virtual_transport = lmtp:unix:/var/run/cyrus/socket/lmtp

    Some things to look at and possibly modify in your setup:

    • The SASL setup is for authentication. We'll install SASL with Cyrus.
    • smtpd_recipient_restrictions settings are set to a strong anti-spam policy, e.g., rejecting anything from any of the 3 RBLs. It is definitely worth understanding this and the 2 following parameters which control whether Postfix accepts or rejects mail. See the Postfix docs on the subject. It's also worth reading up on RBLs if you're not familiar with how they work.
    • LMTP is how Postfix will hand off mail for delivery to mailboxes...the Cyrus LMTP service will listen on the other end. I use a large setting, 20MB, for message_size_limit because it suits my email user base. Choose your poison here.

  3. Copy in (or create an empty) access file - The references to /etc/postfix/access above are for an in-house blacklist. Up until 2006 I diligently fished out the sending mail IP from spam and added it to an access file. I'm providing my copy of this file; though no longer updated, it still manages to block a batch of spams every day, and I haven't had a complaint in years about a false positive. To use this file, copy it to your /etc/postfix directory and run. If you'd rather not, just use touch to create a blank file...you might want the feature someday.

    Postfix "blacklist" access db
    sudo touch /etc/postfix/access
    sudo cp access.txt /etc/postfix/access #skip if not using
    sudo postmap /etc/postfix/access
  4. master.cf config
    sudo vi /etc/postfix/master.cf
    Look for the first uncommented line starting with smtp and add a "-d" at the end. This flag will turn on debug messages in the log, useful at this stage of the game.
    smtp      inet  n       -       -       -       -       smtpd -d
    Then scroll down to the line beginning with lmtp and change the 3rd dash to read "n". This will make lmtp not run in chroot jail. As a security issue it's acceptably minor, as lmtp runs behind postfix, i.e., isn't exposed to outside access, plus we'll use unix sockets for the Cyrus interface.
    lmtp      unix  -       -       n       -       -       lmtp
  5. Add postfix user to mail group - I would have expected the installer package to do this. Needed so Cyrus and Postfix can share the LMTP socket, which will use group file access bits.
    sudo adduser postfix mail
  6. Restart Postfix
    sudo /etc/init.d/postfix restart

Cyrus Install & Config

  1. Install Cyrus Packages
    sudo apt-get install cyrus-admin-2.2 cyrus-clients-2.2 cyrus-imapd-2.2 sasl2-bin cyrus-pop3d-2.2
  2. Move & Fix Cyrus Dirs - Two things to change, one is a matter of taste, the other a show-stopper installer mistake. The matter of taste is the storage for Sieve, Cyrus's server side mail filtering technology (and one of the reasons I like Cyrus). Ubuntu puts that storage in /var/spool/sieve and mailbox storage in /var/spool/cyrus/mail. I like to keep it under one roof, so we'll move Sieve storage under cyrus and update the appropriate config file.

    The stopper is the perms on the cyrus dirs. Try ls -la /var/spool/cyrus and you'll see
    total 16
    drwxr-xr-x 4 cyrus mail 4096 2008-09-28 13:28 .
    drwxr-xr-x 6 root root 4096 2008-09-28 13:28 ..
    drwxr-x--- 29 root root 4096 2008-09-28 13:28 mail
    drwxr-x--- 29 root root 4096 2008-09-28 13:28 news
    The dirs under /var/spool/cyrus are all owned by root:root and 750. (If 750 doesn't ring a bell, it's worth reading some docs on Linux file perms.) Hence, the cyrus programs, which will run under cyrus:mail, can't write to the mail storage. I'd call that a bug. Same deal with /var/lib/cyrus: Once Cyrus tries to do something useful, like put mail in a mailbox, it barfs because it can't read/write it's working files.

    Oh, and because we're going to change perms to something only cyrus & root users can see, we'll go into "perma-root" mode temporarily. I recommend getting out of the root shell when done with this step.
    sudo bash
    cd /var/spool/cyrus/
    mv /var/spool/sieve/ .
    chown -R cyrus:mail .
    chmod -R o-rwx .
    ls -la
    cd /var/lib/cyrus/
    chown -R cyrus:mail .
    ls -la
    exit
  3. /etc/cyrus.conf - Cyrus, like Postfix, runs with a master daemon that dispatches other programs to handle different services. /etc/cyrus.conf is where the master is configured. (Fyi, once you're up and running try ps axu | grep master and you should see both master processes.)
    sudo vi /etc/cyrus.conf
    Move down to the SERVICES section, uncomment the imaps and pop3s services. These will give you secure pop3 and imap, over ssl. Comment out the nntp service (unless you want to run the old "netnews" service, not covered further here; anyone remember "alt"?.) Also, verify that the lmtpunix line is not commented, and the lmtp line is. The top of your SERVICES section should look like
    SERVICES {
    # --- Normal cyrus spool, or Murder backends ---
    # add or remove based on preferences
    imap cmd="imapd -U 30" listen="imap" prefork=0 maxchild=100
    imaps cmd="imapd -s -U 30" listen="imaps" prefork=0 maxchild=100
    pop3 cmd="pop3d -U 30" listen="pop3" prefork=0 maxchild=50
    pop3s cmd="pop3d -s -U 30" listen="pop3s" prefork=0 maxchild=50
    #nntp cmd="nntpd -U 30" listen="nntp" prefork=0 maxchild=100
    #nntps cmd="nntpd -s -U 30" listen="nntps" prefork=0 maxchild=100

    # At least one form of LMTP is required for delivery
    # (you must keep the Unix socket name in sync with imap.conf)
    #lmtp cmd="lmtpd" listen="localhost:lmtp" prefork=0 maxchild=20
    lmtpunix cmd="lmtpd" listen="/var/run/cyrus/socket/lmtp" prefork=0 maxchild=20
  4. Enable Squatter - This step is optional, depending on your application. Squatter is a full-text indexing daemon that will speed up "Search Entire Message" requests by 10x or more. If you run a smaller number of more demanding users (like I do), enable as shown. If you're running a horde of freebie accounts on limited resources, skip this step. It will add processing load to your system, but only if your mail and user activity is very high. If in doubt, try it, and disable it from this file if necessary.

    Again, in /etc/cyrus.conf move down to the "EVENTS" section and uncomment the two "squatter" lines to read
    # reindex changed mailboxes (fulltext) approximately every other hour
    squatter_1 cmd="/usr/bin/nice -n 19 /usr/sbin/squatter -s" period=120

    # reindex all mailboxes (fulltext) daily
    squatter_a cmd="/usr/sbin/squatter" at=0517
    With or without squatter, save and exit /etc/cyrus.conf
  5. /etc/imapd.conf - The service specific settings for imap, pop3, lmtp, sieve, etc. are in /etc/imapd.conf
    sudo vi /etc/imapd.conf
    First, find the "unixhierarchysep" line (approx line 28) and change the setting to "yes". Using this feature gives a more natural syntax which will correlate with how we config Web-Cyradm. The line should read
    unixhierarchysep: yes
    Continue down to the line that reads "#admins: cyrus". Web-cyradm will use this ID for privileged mailbox operations (like creating & deleting mailboxes). There is also a command line interface that can use this ID, cyradm, which should only be needed for debugging. The line should read:
    admins: cyrus
    On down to the line beginning "sievedir", which we change to correspond to the new location:
    sievedir: /var/spool/cyrus/sieve
    Now, look for "sasl_mech_list". This setting defines what imap, pop3 and smtp password formats are available. Uncomment, and set to "PLAIN LOGIN".

    Yes, these are both unencrypted formats. There are PAM issues upcoming that force this hand. That said, if you use the encrypted services: imaps, pop3s and smtp/tls with your email client, no readable passwords are exposed.

    The line should read
    sasl_mech_list: PLAIN LOGIN
    Continue to the line beginning "sasl_pwcheck_method". Change this to "saslauthd", a daemon which will, in turn, use pam authentication machinery. The line should read:
    sasl_pwcheck_method: saslauthd
    Next, go to "tls_cert_file" and uncomment this line and the "tls_key_file" line, leaving this setting pointing to the default, self signed "snakeoil" key for your machine. If you obtain a CA signed cert, change the .pem and .key file locations here. These lines should read.
    # File containing the global certificate used for ALL services (imap, pop3,
    # lmtp, sieve)
    tls_cert_file: /etc/ssl/certs/ssl-cert-snakeoil.pem

    # File containing the private key belonging to the global server certificate.
    tls_key_file: /etc/ssl/private/ssl-cert-snakeoil.key
    Finally, go to the line with "tls_ca_file" and uncomment. changing the value to "/etc/ssl/certs/ca-certificates.crt". This file isn't needed for self-signed certs. We'll install it later, though, so when CA'd certs come in, we just repoint the cert and key settings. This line should read:
    tls_ca_file: /etc/ssl/certs/ca-certificates.crt
    Save and exit /etc/imapd.conf and restart Cyrus
    sudo /etc/init.d/cyrus2.2 restart

Saslauthd Config

We installed sasl2-bin with Cyrus. Sasl will connect Cyrus & Postfix to Pam authentication, and Pam will be configured to ask a Mysql database, maintained by Web-Cyradm for password verification.
  1. /etc/default/saslauthd
    sudo vi /etc/default/saslauthd
    Change the "START=no" line to read
    START=yes
    And, down at the bottom of the file update the sasl unix socket to run inside Postfix jail. Change the last line to read
    OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"
  2. etc/postfix/sasl/smtpd.conf - Create a new file, /etc/postfix/sasl/smtpd.conf, i.e.,
    sudo vi /etc/postfix/sasl/smtpd.conf
    with the following contents:
    pwcheck_method: saslauthd
    mech_list: plain login
  3. Add postfix to the sasl group - For socket access
    sudo adduser postfix sasl
  4. Start saslauthd
    sudo /etc/init.d/saslauthd start

SSL Bits

Postfix and Cyrus's ssl configs are ready to go, except for a minor detail, read access to the private keys. While we're at it, we'll get that /etc/ssl/certs/ca-certificates.crt file installed:
sudo adduser cyrus ssl-cert
sudo adduser postfix ssl-cert
sudo apt-get install ca-certificates

If you do install a CA supplied cert, you'll probably have a .crt you need to convert to a .pem file mail apps. Here's the trick:

openssl x509 -in mydomain.crt -out mydomain.der -outform der
openssl x509 -in mydomain.der -inform der -out mydomain.pem -outform pem

Postfix Chroot Jail Fix

We're almost there, but we have a problem: Postfix needs to talk to two services via unix sockets, saslauthd and mysql (to be installed later), but the standard location for those sockets in /var/run are not in Postfix jail, i.e., /var/spool/postfix. We could move those sockets to /var/spool/postfix and use "ln -s" to put them back in /var/run, where other programs expect them. However, /var/run gets cleaned out on boot and we lose those links.

Solution: Add an /etc/init.d script that runs does the job after mysql and saslauthd startup and create their sockets. We already set saslauthd's config (above) to open it's socket in /var/spool/postfix. However, ASAIK Cyrus is hardwired to look in /var/run. Mysql presents a similar issue for other apps when we install it in the next section. Create /etc/init.d/postfix-fixchroot:
  1. Create /etc/init.d/fix-postfix-chroot
    sudo vi /etc/init.d/fix-postfix-chroot
    and add the lines:
    #!/bin/sh -e
    # Fixup socket paths in /var/run because of moves to postfix chroot @ /var/spool/postfix
    #

    # BEGIN INIT INFO
    # Provides: fixes in /var/run
    # Required-Start: $local_fs $remote_fs
    # Required-Stop: $local_fs $remote_fs
    # Should-Start: saslauthd mysql postfix
    # Should-Stop: saslauthd mysql postfix
    # Default-Start: 2 3 4 5
    # Default-Stop: 0 1 6
    # Short-Description: Fixup socket paths in /var/run because of moves to postfix chroot @ /var/spool/postfix
    # Description:
    # END INIT INFO

    PATH=/bin:/usr/bin:/sbin:/usr/sbin
    TZ=
    unset TZ

    . /lib/lsb/init-functions
    #DISTRO=$(lsb_release -is 2>/dev/null || echo Debian)

    case "$1" in
    start)
    log_daemon_msg "Try to fix sockets in postfix chroot"
    if [ ! -e "/var/run/mysqld" ] && [ -e /var/spool/postfix/var/run/mysqld ] ; then
    log_daemon_msg "ln -s /var/spool/postfix/var/run/mysqld /var/run"
    ln -s /var/spool/postfix/var/run/mysqld /var/run
    fi
    if [ ! -e "/var/run/saslauthd" ] && [ -e /var/spool/postfix/var/run/saslauthd ] ; then
    log_daemon_msg "ln -s /var/spool/postfix/var/run/saslauthd /var/run"
    ln -s /var/spool/postfix/var/run/saslauthd /var/run
    fi
    ;;

    stop)
    log_daemon_msg "Cleaning up sockets in postfix chroot"
    if [ -h "/var/run/mysqld" ]; then
    log_daemon_msg "rm /var/run/mysqld"
    rm /var/run/mysqld
    fi
    if [ -h "/var/run/saslauthd" ]; then
    log_daemon_msg "rm /var/run/saslauthd"
    rm /var/run/saslauthd
    fi
    ;;
    esac

    exit 0
  2. Setup fix-postfix-chroot - Remove the old /var/run/saslauthd and setup the init script:
    sudo rmdir /var/run/saslauthd
    sudo chmod +x /etc/init.d/fix-postfix-chroot
    sudo update-rc.d fix-postfix-chroot multiuser 90
    sudo /etc/init.d/fix-postfix-chroot start
    sudo ls -l /var/run/saslauthd/

Root & Postmaster Aliases

I recommend starting out you use an email address not on this server for root and postmaster messages. This setup anticipates some anti-virus/spam aliases. Once things are running smoothly, you might change to a local account.
  1. Add Admin Email Addresses - Edit /etc/aliases to read
    root:   myeverydaymailaddress
    postmaster: myeverydaymailaddress

    clamav: postmaster
    webmaster: postmaster
    maildebug: postmaster
    virusalert: postmaster
    spamalert: postmaster
  2. Run newaliases & reload Postfix
    sudo newaliases 
    sudo postfix reload

Test the Machinery

Two useful test tools are imtest and smtptest. Run them now, and auth with you Linux login to test that everything's working so far:
  1. IMAP
    imtest -a mylogin
    and you should get an imap handshake and a password prompt. Use your shell login password
    WARNING: no hostname supplied, assuming localhost

    S: * OK mailserver Cyrus IMAP4 v2.2.13-Debian-2.2.13-13ubuntu3 server ready
    C: C01 CAPABILITY
    S: * CAPABILITY IMAP4 IMAP4rev1 ACL QUOTA LITERAL+ NAMESPACE UIDPLUS ID NO_ATOMIC_RENAME UNSELECT CHILDREN MULTIAPPEND BINARY SORT THREAD=ORDEREDSUBJECT THREAD=REFERENCES ANNOTATEMORE IDLE STARTTLS
    S: C01 OK Completed
    Please enter your password:
    C: L01 LOGIN rod {8}
    S: + go ahead
    C: <omitted>
    S: L01 OK User logged in
    Authenticated.
    Security strength factor: 0
    ^C out of this and check the log file
    tail /var/log/mail.log
    for something like
    Sep 29 01:41:24 mailserver cyrus/imap[18380]: accepted connection
    Sep 29 01:41:28 mailserver cyrus/imap[18380]: login: localhost [127.0.0.1] rod plaintext User logged in
  2. smtptest - Do the same with smtptest. Stop here and get things working before going on.

Open the Firewall

At this point the server has no open relays and only on usable SMTP or IMAP login (albeit with no mailbox!), so let's open the firewalled ports for access.
sudo ufw allow smtp
sudo ufw allow pop3
sudo ufw allow pop3s
sudo ufw allow imap
sudo ufw allow imaps
sudo ufw status
Now, I recommend a reboot, to see if everything comes up clean, and an imtest from a remote machine:
sudo reboot

Epilogue

You've got a fully configured mail server, but you can't start sending/receiving email yet: Cyrus does not have any mailboxes. (Well, maybe send, but not receive.) If you want to create one, use the cyradm program (see man cyradm). However, don't bother if you're going to proceed with the Web-Cyradm setup.

You could stop here and just run the server like this: configure domains with a Postfix virtual map file (see www.postfix.org/VIRTUAL_README.html), mailboxes with cyradm and logins via shell accounts. This config is not covered here, but if you made it this far, you should have no trouble figuring it out. Fyi, it worked fine for me for 5 years. One hint: you'll need a login for a "cyrus" user as an admin in cyradm.

The Anti-Spam & Anti-Virus Install configurations should all work, even if you don't setup Web-Cyradm, though I haven't tested that config.

Next up: Web-Cyradm Install

Attached files

Postfix "blacklist" access db 70,775 bytes, 225 downloads
Up until 2006 I diligently fished out the sending mail IP from spam and added it to an access file. I'm providing my copy of this file; though no longer updated, it still manages to block a batch of spams every day, and I haven't had a complaint in years about a false positive.
Posted by Rod on Sep. 29 2008
Zoom

Your comments

Gordon on May 21 2009
Hi there I have a ubuntu machine (Hardy Heron). It does not have smtptest and imaptest.

Can't seem to use apt-get to install them. I have googled for info on how to install them but no luck. How do I install them?

thanks
 on May 28 2009
Very good! One of the very few howtos that actually work One minor addition: the login test didn't work, I had to manually modify access right (sudo chmod g+r /etc/ssl/private) to get rid of "unable to get private key from '/etc/ssl/private/ssl-cert-snakeoil.key'"
Tithtola on Sep. 4 2009
Hi sir,

I have an Error in IMAP test. I suddenly don't know what my password shell login is. Thus, I cannot test it whether it is working or not. Please answer me what is the shell login password?

thank,

Tola
Nick Atkins on Feb. 19
Excellent how-to, I installed on Debian 5 which is of course close to Ubuntu, the only other package I needed to install was libsasl2-modules because I was getting the following errors:

When trying to connect with smtptest:

failure: prot layer failure

And the resultant lines in /var/log/mail.info:

Feb 19 12:01:18 sfps postfix/smtpd[10474]: warning: xsasl_cyrus_server_get_mechanism_list: no applicable SASL mechanisms Feb 19 12:01:18 sfps postfix/smtpd[10474]: fatal: no SASL authentication mechanisms Feb 19 12:01:19 sfps postfix/master[10390]: warning: process /usr/lib/postfix/smtpd pid 10474 exit status 1 Feb 19 12:01:19 sfps postfix/master[10390]: warning: /usr/lib/postfix/smtpd: bad command startup -- throttling

Other than this it worked for me right away, thanks very much!

Stay tuned
recent comments
podcasted files
AddThis.com