Cyrus, SASL, and Multiple Domains

This took quite some time to figure out, but it was actually a lot simpler then I originally thought. Let me first give a huge thank you to Kevin M. Myer who originally had the foresight to see Cyrus' ability to do this, and who shared his knowledge with me. Now, lets start out with the advantages and disadvantages:



First thing we'll do is configure. In most cases this should be as simple as:
$ ./configure --with-auth=unix

You will need the --with-auth=unix, it doesn't mean you'll be using unix users for authentication, it means it CAN, and you'll need this for your first authentication and for testing.

After that do:
$ make depend
$ make all CFLAGS=-O

If you get problems with -lssl not being found and if your openssl installation is in /usr/local/ssl and it put your libraries in /usr/local/ssl/lib/openssl (default for source install), you may need to edit perl/sieve/acap/Makefile.PL and perl/sieve/managesieve/Makefile.PL and modify the LIBS line and add -L/usr/local/ssl/lib. The configure script was able to pick this up for most Makefiles (although I had LD_LIBRARY_PATH set, I'm sure if I needed to), not not the perl ones for some reason. Once you do this, run make clean; made depend; make all CFLAGS=-O and you should be set to go.


This part is easy. First make the necessary user and group:
# groupadd mail
# useradd -d /usr/cyrus -g mail cyrus
# passwd cyrus

And set a password for cyrus. When your done with that you can install with:
# make install

Additionally, there's a directory in the source called tools with necessary tools that don't get installed anywhere. These are good to keep around so I like to do the following, as root, from within the source directory:
# mkdir /usr/cyrus/bin/tools
# cp tools/* /usr/cyrus/bin/tools
# chown -R cyrus:mail /usr/cyrus/bin/tools

Now you will want to setup syslog to do some logging for you. We will start by doing lots of logging incase you run into trouble - but we'll drop down the level later. Edit /etc/syslog.conf and add these two lines:

local6.debug	/var/log/imapd.log
auth.debug	/var/log/auth.log

NOTE: Many systems already log auth stuff to a file (often auth.log) - look in your syslog.conf, if you already have a line like this, don't add it again. Either way you'll need the imapd line. Now we'll want to touch those files:
# touch /var/log/imapd.log /var/log/auth.log

Up until now, we've been following the included documentation almost word-for-word, but here's where we'll change a few things.

You'll need one IP address for each domain you want to host. For our examples, we'll use for and for Obviously these need to be real IP addresses in your address space. So setup a virtual interface for your IP addresses (set these in your system configuration files so they will stay on reboot, for example, on redhat-like systems, you'll use the files in /etc/sysconfig/network-scripts/). Then edit your /etc/hosts file so it's something like:         localhost localhost.localdomain 

This works equally well if you use subdomains instead of domains, by the way (i.e. and Now, make a directory /etc/cyrus like this (as root):
# mkdir /etc/cyrus
# chown cyrus:mail /etc/cyrus

Then create config files for your domains (note these will be used instead of /etc/imapd.conf):
# touch /etc/cyrus/ /etc/cyrus/

Now, edit each domain-specific configuration file giving it it's own configdirectory, partition-default, and servername. For example, domain1.conf would probably look like:
configdirectory: /var/imap/
partition-default: /var/spool/imap/
admins: cyrus
allowanonymouslogin: no
sasl_pwcheck_method: sasldb

Note the lack of a trailing slash... that's important. Here the servername attribute will determine the realm automatically. So when someone contacts the imapd daemons using this config file, it will allow the user to use just 'username' and realm is '' Additionally configdirectory and partitiondirectory specify a unique directory for this specific domain eliminating any problems with similarly named mailboxes.

Repeat the above for (changing domain1 to domain2 where necessary).

Next we need to make our directories:
# cd /var
# mkdir imap
# chown cyrus:mail imap
# chmod 750 imap
# for domain in; do
> mkdir $domain;
> chown cyrus:mail $domain;
> chmod 750 $domain;
> done
# cd /var/spool
# mkdir imap
# chown cyrus:mail imap
# chmod 750 imap
# for domain in; do > mkdir $domain;
> chown cyrus:mail $domain;
> chmod 750 $domain;
> done

Now the directories are almost done, a script from the source (that we copied to /usr/cyrus/bin/tools) can do the rest! So the next step is:
# su - cyrus
$ for domain in; do
> /usr/cyrus/bin/tools/mkimap /etc/cyrus/${domain}.conf;
> done;
$ exit

Although undocumented the mkimap script takes an arguement of the configuration file to use as a reference. One more directory related thing ONLY IF YOU ARE ON LINUX (all other unices, skip on down): We need to set the user, quota, and partition directories to update synchronously. This is fairly simple:

# cd /var/imap
# for domain in; do
> cd /var/imap/$domain;
> chattr +S user quota user/* quota/*;
> chattr +S /var/spool/imap/$domain /var/spool/imap/$domain/*;
> cd ..;
> done;
# chattr +S /var/spool/mqueue

Next ensure all of the following are in /etc/services:

pop3      110/tcp
imap      143/tcp
imsp      406/tcp
acap      674/tcp
imaps     993/tcp
pop3s     995/tcp
kpop      1109/tcp
sieve     2000/tcp
lmtp      2003/tcp
fud       4201/udp
Don't forget those need to be TABS and not SPACES! Also be sure to remove any entries from /etc/inetd.conf or /etc/xinetd.d/ for imap, imaps, pop3, pop3s, kpop, lmtp, or sieve.

Now we need to tell Cyrus about our domains and where to find their custom configuration files. First you'll want a base configration file to start with, so from the source directory do:
# cp master/conf/normal.conf /etc/cyrus.conf

Now, edit your /etc/cyrus.conf. Make one copy of everything for each domain you have. Make sure that the service names (the first word on the left) is ALWAYS UNIQUE! We will specify the specific configuration files we created above in this file, as well as specify an interface to bind to:

  # do not delete these entries!
  mboxlist-d1		cmd="ctl_mboxlist -C /etc/cyrus/ -r"
  mboxlist-d2		cmd="ctl_mboxlist -C /etc/cyrus/ -r"
  deliver-d1		cmd="ctl_deliver -C /etc/cyrus/ -r"
  deliver-d2		cmd="ctl_deliver -C /etc/cyrus/ -r"

  # this is only necessary if using idled for IMAP IDLE
  # idled		cmd="idled"

  # DOMAIN 1
  imap-d1		cmd="imapd -C /etc/cyrus/" listen="" prefork=1
  imaps-d1		cmd="imapd -s -C /etc/cyrus/" listen="" prefork=1
  pop3s-d1		cmd="pop3d -s -C /etc/cyrus/" listen="" prefork=1
  lmtpunix-d1		cmd="lmtpd -C /etc/cyrus/" listen="/var/imap/" prefork=0

  # DOMAIN 2
  imap-d2		cmd="imapd -C /etc/cyrus/" listen="" prefork=1
  imaps-d2		cmd="imapd -s -C /etc/cyrus/" listen="" prefork=1
  pop3s-d2		cmd="pop3d -s -C /etc/cyrus/" listen="" prefork=1
  lmtpunix-d2		cmd="lmtpd -C /etc/cyrus/" listen="/var/imap/" prefork=0

  ## I keep these here for refernce in case I ever want to use the services
  # pop3		cmd="pop3d" listen="pop3" prefork=1
  # pop3s		cmd="pop3d -s" listen="pop3s" prefork=1
  # sieve		cmd="timsieved" listen="sieve" prefork=0
  ## at least one LMTP is required for delivery
  # lmtp		cmd="lmtpd" listen="lmtp" prefork=0
  # lmtpunix		cmd="lmtpd" listen="/var/imap/" prefork=0


  # this is required
  checkpoint-domain1	cmd="ctl_mboxlist -C /etc/cyrus/ -c" period=30
  checkpoint-domain2	cmd="ctl_mboxlist -C /etc/cyrus/ -c" period=30

  # this is only necessary if using duplicate delivery suppression
  delprune-domain1	cmd="ctl_deliver -C /etc/cyrus/ -E 3" period=1440
  delprune-domain2	cmd="ctl_deliver -C /etc/cyrus/ -E 3" period=1440

Now two copies of all your services will be launched - one using each configuration file, and hence using the right directories. Additionally all maintenance stuff will now launch once for each domain. Notice here that I have all the services preforked. It is up to you whether or not you want services preforked, but I recommend preforking them for testing.

NOTE: In the configuration file above I have included imaps and pop3s, the secure versions of imap and pop3. I have not yet added the section on setting up Cyrus to do secure imap and pop (expect it very shortly), so you should comment those lines out unless you can configure them for yourself).

We're almost done! Lets set an sasl password for cyrus in each domain:
# saslpasswd -u cyrus
# saslpasswd -u cyrus

Once that's done, we'll want to a test user to each domain with the same username to ensure everything works:
# su - cyrus
$ cyradm> cm user.test> quit
$ cyradm> cm user.test> quit
$ ^D
# saslpasswd -u test
# saslpasswd -u test

Note that -u to saslpasswd signifies "realm" (why it's -u, I don't know). You can double check this did what you thought it did with sasldblistusers. I suggest using a different password for both users (while using the same username) to ensure you're seperate domains are setup properly.

Now we can fire up cyrus:
$ sdu -
# /usr/cyrus/bin/master &

Check everything is as you expect by doing netstat -an | grep LIST and looking for cyrus listening in pop3 (110), and imap (143).

You can test authentication with:
# imtest -a test -u test -p imap
# imtest -a test -u test -p imap

If that works you should be set! Note that you may want to change your syslog.conf file and turn the debugging level down on local6 once you have this working. Don't forget to enable SSL, and configure your MTA, desribed below.

Making Cyrus Start On Boot

Unfortunately, Cyrus doesn't come with a SYSV init script. But that's ok, we can make one easily enough. Create a file called /etc/init.d/cyrus, and make it look something like this:


# This script starts, stops, or restarts the
# Cyrus master.
# It was written by Phil Dibowitz

case "$1" in
                echo -n "Starting Cyrus IMAPd..."
                /usr/cyrus/bin/master &
                echo $! > /var/run/
                echo "done"
                echo -n "Stopping Cyrus IMAPd..."
                if [ -e /var/run/ ] ; then
                        kill `cat /var/run/`
                        rm /var/run/
                        echo "done"
                        echo "Sorry, can't find PID file, is it running?"
                $0 stop
                sleep 2
                $0 start
                echo "Usage: $0 {start|stop|restart}"

NOTE WELL: If you use postfix stop/restart will KILL postfix! You either need to modify this script, OR rename the postfix 'master' to 'pf_master' (or something like that), and change postfix's initscript, or some combination thereof.

So now you have an init script, lets make it active. Assuming your default runleve is 3, do:
cd /etc/rc3.d
ln -s ../init.d/cyrus S95cyrus

Adjust the number to taste. If you are on Solaris you should probably make a similar link to K05cyrus so the server stops when you leave runlevel 3.

Coming Soon

A patch for masssaslpasswd to support realms.

Adding SSL to Cyrus

I've put this on a different page.

Configuring SMTP

I've also moved this to it's own page.


Find troubleshooting info here.

Last Updated: 06/23/02

This page is © Phil Dibowitz 2001 - 2004