Cyrus IMAP Server

If you're sure you really want to do this, download the latest Cyrus IMAP Server source from http://cyrusimap.web.cmu.edu/imapd/ or, more specifically, ftp://ftp.andrew.cmu.edu/pub/cyrus/. Once you have downloaded the source tarball, unzip it in the top level directory where you wish the source/build tree to reside.

     tar -xvzf cyrus-imapd-2.3.9.tar.gz
     cd cyrus-imapd-2.3.9

If you haven't already done so or are not reusing pre-existing ones, create a userid and group for cyrus:

     su
     /usr/sbin/groupadd -g 12 -r mail
     /usr/sbin/useradd -c "Cyrus IMAP Server" -d /var/lib/imap -g mail -M -n -r \
       -s /bin/bash -u 76 cyrus
     passwd cyrus

By setting the password for the cyrus userid, you will be able to log in as that user to do administration for cyrus, since the admin will be set to "cyrus" in the config file (below). If you don't care about this feature, you can use "/sbin/nologin" for the shell when you create the user and skip setting their password. But, trust us, you're probably going to need it so its best to set the userid up with a login shell and password.

Build cyrus, per the instructions in the INSTALL file. If you used different names than the ones suggested above, you will want to choose the user and group that Cyrus will run under by setting --with-cyrus-user=user and --with-cyrus-group=group. By default, the user chosen is "cyrus" and the group chosen is "mail":

     ./configure
     make depend
     make all CFLAGS=-O

As super user, install the software:

     su
     make install

Create the file "/etc/imapd.conf". Here is a sample "imapd.conf":

     configdirectory: /var/lib/imap
     partition-default: /var/spool/imap
     admins: cyrus
     sievedir: /var/lib/imap/sieve
     sendmail: /usr/sbin/sendmail
     hashimapspool: true
     sasl_pwcheck_method: saslauthd
     sasl_mech_list: PLAIN
     tls_cert_file: /etc/pki/cyrus-imapd/cyrus-imapd.pem
     tls_key_file: /etc/pki/cyrus-imapd/cyrus-imapd.pem
     tls_ca_file: /etc/pki/tls/certs/ca-bundle.crt

The last three lines are common in the pre-installed versions of Cyrus, because the OS winkies thought you'd like one more layer of bogus, annoying security to fu*k with instead of just setting something up that works. So, they set Cyrus up to talk to the SASL daemon using TLS. Earlier versions of the config file don't have these three lines.

Create all of the directories needed to run Cyrus:

     su
     mkdir /var/lib
     mkdir /var/lib/imap
     chown cyrus /var/lib/imap
     chgrp mail /var/lib/imap
     chmod u=rwx,g=rx,o= /var/lib/imap
     mkdir /var/lib/imap/sieve
     chown cyrus /var/lib/imap/sieve
     chgrp mail /var/lib/imap/sieve
     chmod u=rwx,go= /var/lib/imap/sieve
     mkdir /var/spool/imap
     chown cyrus /var/spool/imap
     chgrp mail /var/spool/imap
     chmod u=rwx,go= /var/spool/imap

Now, use the tool "tools/mkimap" to create the rest of the subdirectories below the directories you just created:

     su cyrus
     tools/mkimap

Next, make sure you remove any old imap, imaps, pop3, pop3s, kpop, lmtp and sieve lines from /etc/[x]inetd.conf (the Cyrus daemon will be taking over these functions). Once this is done, [x]inetd needs to be restarted to make the changes permanent.

Read and follow the install notes as to how to set Cyrus up to respond to IMAP and POP requests, and how to have your MTA deliver email to Cyrus using LMTP.

/etc/rc.d/init.d/cyrus-imapd:

You will need a startup script to start Cyrus when your system boots up. The following script (for RedHat) can be added as /etc/rc.d/init.d/cyrus-imapd:

     #!/bin/sh
     #
     # chkconfig: - 65 35
     # description: The Cyrus IMAPD master serves as a master process for the \
     #              Cyrus IMAP and POP servers.
     # config: /etc/cyrus.conf
     # config: /etc/imapd.conf
     # pidfile: /var/run/cyrus-master.pid
     # author:     Simon Matter, Invoca Systems <simon.matter@invoca.ch>
     # version:    2005111100
     # changed:    Add quickstart/stop option to init script to bypass db
     #             import/export
     # Source function library
     if [ -f /etc/init.d/functions ]; then
       . /etc/init.d/functions
     elif [ -f /etc/rc.d/init.d/functions ]; then
       . /etc/rc.d/init.d/functions
     else
       exit 0
     fi
     # Source networking configuration.
     . /etc/sysconfig/network
     # Check that networking is up.
     [ ${NETWORKING} = "no" ] && exit 0
     # check if the config files are present
     [ -f /etc/cyrus.conf ] || exit 0
     [ -f /etc/imapd.conf ] || exit 0
     # This is our service name
     BASENAME=$(basename $0)
     if [ -L $0 ]; then
       BASENAME=$(find $0 -name $BASENAME -printf %l)
       BASENAME=$(basename $BASENAME)
     fi
     # Source service configuration.
     if [ -f /etc/sysconfig/$BASENAME ]; then
       . /etc/sysconfig/$BASENAME
     else
       echo "$BASENAME: configfile /etc/sysconfig/$BASENAME does NOT exist !"
       exit 1
     fi
     # get_config [config default]
     # extracts config option from config file
     get_config() {
       if config=$(grep "^$1" /etc/imapd.conf); then
         echo $config | cut -d: -f2
       else
         echo $2
       fi
     }
     # where to find files and directories
     CONFIGDIRECTORY=$(get_config configdirectory /var/lib/imap)
     CYRUSMASTER=/usr/lib/cyrus-imapd/cyrus-master
     CYRUS_PROC_NAME=$(basename $CYRUSMASTER)
     ALWAYS_CONVERT=1
     # fallback to su if runuser not available
     if [ -x /sbin/runuser ]; then
       RUNUSER=runuser
     else
       RUNUSER=su
     fi
     RETVAL=0
     RETVAL2=1
     QUICK=0
     start() {
       if [ $(/sbin/pidof -s $CYRUSMASTER) ]; then
         echo -n $"$BASENAME already running."
         false
         echo
       else
         if [ $QUICK -eq 0 ]; then
           echo -n $"Importing $BASENAME databases: "
           cd $CONFIGDIRECTORY
           $RUNUSER - cyrus -c "umask 166 ; \
             /usr/lib/cyrus-imapd/cvt_cyrusdb_all \
               > ${CONFIGDIRECTORY}/rpm/db_import.log 2>&1" </dev/null
           RETVAL=$?
           if [ $RETVAL -eq 0 ]; then
             success $"$BASENAME importing databases"
           else
             failure $"$BASENAME error importing databases, check \
               ${CONFIGDIRECTORY}/rpm/db_import.log"
           fi
           echo
         fi
         if [ $RETVAL -eq 0 ]; then
           echo -n $"Starting $BASENAME: "
           daemon $CYRUSMASTER -d $CYRUSOPTIONS
           RETVAL2=$?
           echo
         fi
       fi
       [ $RETVAL -eq 0 -a $RETVAL2 -eq 0 ] && touch /var/lock/subsys/$BASENAME
       return $RETVAL
     }
     stop() {
       echo -n $"Shutting down $BASENAME: "
       killproc $CYRUSMASTER
       RETVAL=$?
       if [ $QUICK -eq 0 ]; then
         if [ ! $(/sbin/pidof -s $CYRUSMASTER) ]; then
           echo
           echo -n $"Exporting $BASENAME databases: "
           cd $CONFIGDIRECTORY
           $RUNUSER - cyrus -c "umask 166 ; \
             /usr/lib/cyrus-imapd/cvt_cyrusdb_all export \
               > ${CONFIGDIRECTORY}/rpm/db_export.log 2>&1" </dev/null
           RETVAL2=$?
           if [ $RETVAL2 -eq 0 ]; then
             success $"$BASENAME exporting databases"
           else
             failure $"$BASENAME error exporting databases, check \
               ${CONFIGDIRECTORY}/rpm/db_export.log"
           fi
         fi
       fi
       echo
       [ $RETVAL -eq 0 -a $RETVAL2 -eq 0 ] && rm -f /var/lock/subsys/$BASENAME
       return $RETVAL
     }
     restart() {
       stop
       start
     }
     reload() {
       echo -n $"Reloading cyrus.conf file: "
       killproc $CYRUSMASTER -HUP
       RETVAL=$?
       echo
       return $RETVAL
     }
     condrestart() {
       [ -e /var/lock/subsys/$BASENAME ] && restart || :
     }
     rhstatus() {
       status $CYRUSMASTER
       RETVAL=$?
       return $RETVAL
     }
     case "$1" in
       start)
         start
         ;;
       stop)
         stop
         ;;
       restart)
         restart
         ;;
       reload)
         reload
         ;;
       condrestart)
         condrestart
         ;;
       status)
         rhstatus
         ;;
       quickstart)
         QUICK=1
         start
         ;;
       quickstop)
         QUICK=1
         stop
         ;;
       *)
         echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart\
           |status|quickstart|quickstop}"
         RETVAL=1
     esac
     exit $RETVAL

/etc/rc.d/init.d/saslauthd:

You will need a startup script to start the SASL authorization daemon, used by Cyrus to authorize mail users at login time, when your system boots up. The following script (for RedHat) can be added as /etc/rc.d/init.d/saslauthd:

     #! /bin/bash
     #
     # saslauthd      Start/Stop the SASL authentication daemon.
     #
     # chkconfig: - 95 05
     # description: saslauthd is a server process which handles plaintext \
     #              authentication requests on behalf of the cyrus-sasl library.
     # processname: saslauthd
     # Source function library.
     . /etc/init.d/functions
     # Source our configuration file for these variables.
     SOCKETDIR=/var/run/saslauthd
     MECH=shadow
     FLAGS=
     if [ -f /etc/sysconfig/saslauthd ] ; then
         . /etc/sysconfig/saslauthd
     fi
     RETVAL=0
     # Set up some common variables before we launch into what might be
     # considered boilerplate by now.
     prog=saslauthd
     path=/usr/sbin/saslauthd
     # Ugh. Switch to a specific copy of saslauthd if there's one with $MECH
     # in its name, in case it wasn't included in the base cyrus-sasl package
     # because it would have dragged in too many undesirable dependencies.
     if test -x ${path}.${MECH} ; then
         path=/usr/sbin/saslauthd.$MECH
     fi
     start() {
         echo -n $"Starting $prog: "
         daemon $path -m $SOCKETDIR -a $MECH $FLAGS
         RETVAL=$?
         echo
         [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
         return $RETVAL
     }
     stop() {
         echo -n $"Stopping $prog: "
         killproc $path
         RETVAL=$?
         echo
         [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
         return $RETVAL
     }
     restart() {
           stop
         start
     }
     case "$1" in
       start)
           start
         ;;
       stop)
           stop
         ;;
       restart)
           restart
         ;;
       status)
         status $path
         ;;
       condrestart)
           [ -f /var/lock/subsys/$prog ] && restart || :
         ;;
       *)
         echo $"Usage: $0 {start|stop|status|reload|restart|condrestart}"
         exit 1
     esac
     exit $?

Install both scripts and turn them on:

     su
     chkconfig --add cyrus-imapd
     chkconfig cyrus-imapd on
     chkconfig --add saslauthd
     chkconfig saslauthd on

Once you've installed the scripts, start the daemons:

     su
     /etc/init.d/saslauthd start
     /etc/init.d/cyrus-imapd start

Now, before you can use Cyrus for IMAP, you must create mail boxes. Good thing you set the cyrus password so you can now logon to the administrator:

     cyradm --user cyrus --auth login localhost

You'll be prompted for the cyrus user's password. Enter it and continue with building mailboxes. For each user, do the following:

     cm user.joeuser
     lam user.joeuser

You should see something like this:

     joeuser lrswipkxtecda

The list of letters following the user's name are their permissions. A nice, long string (like that shown) is good. They need 'c' for sure, if SquirrelMail is to work. If things are not as they should be, try "man cyradm" for a list of commands, such as "sam", that may be useful.

Incidentally, should you ever wish to delete a mailbox, you can't do it. That's right. The cyrus user doesn't have permissions to delete a mailbox (what a crock). But, they can give themselves the permissions (see, I told you it was a crock). So, deletion becomes a two-step process:

     sam joeuser cyrus x                                         
     dm joeuser

After you've set up a new mailbox, you can test that the user at least has permissions to log in by doing this:

     imtest -m login -p imap -a joeuser localhost
     . logout

You should see a message about them being authenticated, etc.