- Home
- Download
- Contribute
- Support
- Cyrus SASL

# Cyrus IMAP

# Installing Cyrus

This guide assumes you have already compiled Cyrus.

## Install Cyrus

The `--prefix` option given to `configure` (during compilation) sets where Cyrus is installed to.

If unspecified, it will go to whatever destination is your system default (often `/usr/local`). To check: the final output of the configure step will display where a `make install` will install to.

    make install  # optional if you're just developing on this machine

    make install-binsymlinks    # Only needed if you're testing older Cyrus versions

## Optional Components

- HTTP modules
  - About http module support
  - HTTPD Configuration
  - Module-specific information
  - For end users
- Virus Scanner
  - About virus scan support
  - Virus Scanner Configuration

## Setting up syslog

A lot of Cyrus’s debugging information gets logged with `syslog`, so you’ll want to be able to capture it and find it later (especially when debugging cassandane tests)

1. Find the correct place to edit syslog config for your system (for me, I needed to create `/etc/rsyslog.d/cyrus.conf`)

2. Add lines like

   > `local6.* /var/log/imapd.log`

   > `auth.debug /var/log/auth.log`

3. Restart the rsyslog service

   > `sudo /etc/init.d/rsyslog restart`

4. Arrange to rotate `/var/log/imapd.log` so it doesn’t get stupendously large. Create `/etc/logrotate.d/cyrus.conf` with content like:

       /var/log/imapd.log
       {
           rotate 4
           weekly
           missingok
           notifempty
           compress
           delaycompress
           sharedscripts
           postrotate
           invoke-rc.d rsyslog rotate > /dev/null
           endscript
       }

## Create Cyrus environment

### Set up the cyrus:mail user and group

Now let’s create a special user account just for the Cyrus server to sandbox Cyrus: called `cyrus`. We’ll also create a `mail` group as well. This allows Cyrus to give other programs some permissions if they are run under the `mail` group, again, without causing a Cyrus bug to delete all of your cat pictures. Disaster!

If you have installed from packages, your package vendor may have already done this for you. To check, use these commands:

    $ getent group mail
    mail:x:8:

    $ getent passwd cyrus
    cyrus:x:999:8:Cyrus IMAP Server:/var/lib/imap:/bin/bash

Example group and user creation commands for GNU/Linux:

    groupadd -fr mail
    useradd -c "Cyrus IMAP Server" -d /var/lib/imap -g mail -s /bin/bash -r cyrus

The `var/lib/imap` directory above is an example. Use the same directory specified in the `configdirectory` option in imapd.conf(5).

If your installation uses system locations for things like SSL certificates (i.e. `/etc/ssl/certs /etc/ssl/private`), then you should also add the `cyrus` user to the appropriate group to gain access to the PKI files. On Debian/Ubuntu systems, for example, this group is `ssl-cert`:

    usermod -aG ssl-cert cyrus

### Authentication with SASL

Now, let’s set up SASL. This will allow you to connect to your local IMAP server and login, just like any IMAP user would before checking for new emails.

Create a `saslauth` group and add the `cyrus` user to the group, so Cyrus can access SASL. (on Debian, this group is called ‘sasl’: adjust the following commands to suit.)

    groupadd -fr saslauth
    usermod -aG saslauth cyrus

Change the default SASL configuration in `/etc/default/saslauthd`.
  1. Make sure that the `START` option is set to yes `(START=yes)` and
  2. Set the``MECHANISMS`` option to sasldb `(MECHANISMS="sasldb")`.

Start the SASL auth daemon:

    /etc/init.d/saslauthd start

Now, we’ll create the IMAP user inside SASL. This is the user you’ll use to login to the IMAP server later on.

    echo 'secret' | saslpasswd2 -p -c imapuser

You can replace `secret` with a more suitable password you want and `imapuser` with the username you want. Once this is done, check that the user exists and is set up correctly:

    testsaslauthd -u imapuser -p secret

You should get an `0: OK "Success."` message.

### Mail delivery from your MTA

Your Cyrus IMAP server will want to receive the emails accepted by your SMTP server (ie Sendmail, Postfix, etc). In Cyrus, this happens via a protocol called LMTP, which is usually supported by your SMTP server.

#### Install Sendmail

We’ll set up LMTP with the Sendmail SMTP server.

    sudo apt-get install -y sendmail

We need to make Sendmail aware of the fact we are using the Cyrus IMAP server: modify the `/etc/mail/sendmail.mc` file. Add this line before the `MAILER_DEFINITIONS` section:

    define(`confLOCAL_MAILER', `cyrusv2')dnl

And right below `MAILER_DEFINITIONS`, add this:

    MAILER(`cyrusv2')dnl

This enables the cyrusv2 mailer for local mail delivery. This is a sendmail property that tells sendmail it’s talking to Cyrus. (Cyrus 3.x works with this property, despite the naming confusion.)

Next, we run a script that takes the `/etc/mail/sendmail.mc` file and and prepares it for use by Sendmail. This may take some time.

    sudo sendmailconfig

#### Sendmail communication

One last thing we need to do for LMTP to work with Sendmail is to create a folder that will contain the UNIX socket used by Sendmail and Cyrus to deliver/receive emails:

    sudo mkdir -p /var/run/cyrus/socket
    sudo chown cyrus:mail /var/run/cyrus/socket
    sudo chmod 750 /var/run/cyrus/socket

### Protocol ports

The Cyrus IMAP server provides service interfaces via either TCP/IP ports or Unix domain sockets. For the former, Cyrus requires that there are proper entries in the host’s `/etc/services` file. The following are required for any host using the listed services:

    pop3      110/tcp  # Post Office Protocol v3
    nntp      119/tcp  # Network News Transport Protocol
    imap      143/tcp  # Internet Mail Access Protocol rev4
    imsp      406/tcp  # Internet Message Support Protocol (deprecated)
    nntps     563/tcp  # NNTP over TLS
    imaps     993/tcp  # IMAP over TLS
    pop3s     995/tcp  # POP3 over TLS
    kpop      1109/tcp # Kerberized Post Office Protocol
    lmtp      2003/tcp # Lightweight Mail Transport Protocol service
    smmap     2004/tcp # Cyrus smmapd (quota check) service
    csync     2005/tcp # Cyrus replication service
    mupdate   3905/tcp # Cyrus mupdate service
    sieve     4190/tcp # timsieved Sieve Mail Filtering Language service

Make sure that these lines are present or add them if they are missing.

### Cyrus config files

Set up a simple directory structure for Cyrus to store emails, owned by the `cyrus` user and group `mail`:

    sudo mkdir -p /var/lib/cyrus /var/spool/cyrus
    sudo chown -R cyrus:mail /var/lib/cyrus /var/spool/cyrus
    sudo chmod 750 /var/lib/cyrus /var/spool/cyrus

The `/var/spool/cyrus` directory is the partition where Cyrus will store mail and must be allocated sufficient storage. The exact location can be configured in imapd.conf(5) in the partitions options.

Let’s add some basic configuration for the Cyrus IMAP server. Two files have to be added: `/etc/imapd.conf` and `/etc/cyrus.conf`. There are several examples included with the software, in `doc/examples/`. Pick one each from the `imapd_conf` and `cyrus_conf` directories, or create your own.

For imapd.conf(5), let’s start with the `normal.conf` example:

    # Suggested minimal imapd.conf
    # See imapd.conf(5) for more information and more options

    # Space-separated users who have admin rights for all services.
    # NB: THIS MUST BE CONFIGURED
    admins: cyrus

    ###################################################################
    ## File, socket and DB location settings.
    ###################################################################

    # Configuration directory
    configdirectory: /var/lib/cyrus

    # Directories for proc and lock files
    proc_path: /run/cyrus/proc
    mboxname_lockpath: /run/cyrus/lock

    # Locations for DB files
    # The following DB are recreated upon initialization, so should live in
    # ephemeral storage for best performance.
    duplicate_db_path: /run/cyrus/deliver.db
    ptscache_db_path:  /run/cyrus/ptscache.db
    statuscache_db_path: /run/cyrus/statuscache.db
    tls_sessions_db_path: /run/cyrus/tls_sessions.db

    # Which partition to use for default mailboxes
    defaultpartition: default
    partition-default: /var/spool/cyrus/mail

    # If sieveusehomedir is false (the default), this directory is searched
    # for Sieve scripts.
    sievedir: /var/spool/sieve

    ###################################################################
    ## Important: KEEP THESE IN SYNC WITH cyrus.conf
    ###################################################################

    lmtpsocket: /run/cyrus/socket/lmtp
    idlesocket: /run/cyrus/socket/idle
    notifysocket: /run/cyrus/socket/notify

    # Syslog prefix. Defaults to cyrus (so logging is done as cyrus/imap
    # etc.)
    syslog_prefix: cyrus

    ###################################################################
    ## Server behaviour settings
    ###################################################################

    # Space-separated list of HTTP modules that will be enabled in
    # httpd(8).  This option has no effect on modules that are disabled at
    # compile time due to missing dependencies (e.g. libical).
    #
    # Allowed values: caldav, carddav, domainkey, ischedule, rss
    httpmodules: caldav carddav

    # If enabled, the partitions will also be hashed, in addition to the
    # hashing done on configuration directories. This is recommended if one
    # partition has a very bushy mailbox tree.
    hashimapspool: true

    # Enable virtual domains
    # and set default domain to localhost
    virtdomains: yes
    defaultdomain: localhost

    ###################################################################
    ## User experience settings
    ###################################################################

    # Minimum time between POP mail fetches in minutes
    popminpoll: 1

    ###################################################################
    ## User Authentication settings
    ###################################################################

    # Allow plaintext logins by default (SASL PLAIN)
    allowplaintext: yes

    ###################################################################
    ## SASL library options (these are handled directly by the SASL
    ## libraries, refer to SASL documentation for an up-to-date list of
    ## these)
    ###################################################################

    # The mechanism(s) used by the server to verify plaintext passwords.
    # Possible values are "saslauthd", "auxprop", "pwcheck" and
    # "alwaystrue".  They are tried in order, you can specify more than one,
    # separated by spaces.
    sasl_pwcheck_method: saslauthd

    # If enabled, the SASL library will automatically create authentication
    # secrets when given a plaintext password. Refer to SASL documentation
    sasl_auto_transition: no

    ###################################################################
    ## SSL/TLS Options
    ###################################################################

    # File containing the global certificate used for ALL services (imap,
    # pop3, lmtp, sieve)
    #tls_server_cert: /etc/ssl/certs/ssl-cert-snakeoil.pem

    # File containing the private key belonging to the global server
    # certificate.
    #tls_server_key: /etc/ssl/private/ssl-cert-snakeoil.key

    # File containing one or more Certificate Authority (CA) certificates.
    #tls_client_ca_file: /etc/ssl/certs/cyrus-imapd-ca.pem

    # Path to directory with certificates of CAs.
    tls_client_ca_dir: /etc/ssl/certs

    # The length of time (in minutes) that a TLS session will be cached for
    # later reuse.  The maximum value is 1440 (24 hours), the default.  A
    # value of 0 will disable session caching.
    tls_session_timeout: 1440

Note that configdirectory and partition-default are set to the folders we just created.

Note

The admin user is the `imapuser` created earlier for authentication against sasl. Change this value if you named your user something different.

For cyrus.conf(5), again we’ll start with the `normal.conf` example:

    # standard standalone server implementation

    START {
      # do not delete this entry!
      recover       cmd="ctl_cyrusdb -r"
    }

    # UNIX sockets start with a slash and are put into /run/cyrus/socket
    SERVICES {
      # add or remove based on preferences
      imap          cmd="imapd" listen="imap" prefork=0
      imaps         cmd="imapd -s" listen="imaps" prefork=0
      pop3          cmd="pop3d" listen="pop3" prefork=0
      pop3s         cmd="pop3d -s" listen="pop3s" prefork=0
      sieve         cmd="timsieved" listen="sieve" prefork=0

      # these are only necessary if receiving/exporting usenet via NNTP
    #  nntp          cmd="nntpd" listen="nntp" prefork=0
    #  nntps         cmd="nntpd -s" listen="nntps" prefork=0

      # these are only necessary if using HTTP for CalDAV, CardDAV, or RSS
      http          cmd="httpd" listen="http" prefork=0
      https         cmd="httpd -s" listen="https" prefork=0

      # at least one LMTP is required for delivery
    #  lmtp          cmd="lmtpd" listen="lmtp" prefork=0
      lmtpunix      cmd="lmtpd" listen="/run/cyrus/socket/lmtp" prefork=0

      # this is requied if using socketmap
    #  smmap         cmd="smmapd" listen="/run/cyrus/socket/smmap" prefork=0

      # this is required if using notifications
    #  notify        cmd="notifyd" listen="/run/cyrus/socket/notify" proto="udp" prefork=1
    }

    EVENTS {
      # this is required
      checkpoint    cmd="ctl_cyrusdb -c" period=30

      # this is only necessary if using duplicate delivery suppression,
      # Sieve or NNTP
      delprune      cmd="cyr_expire -E 3" at=0400

      # Expire data older than 28 days.
      deleteprune   cmd="cyr_expire -E 4 -D 28" at=0430
      expungeprune  cmd="cyr_expire -E 4 -X 28" at=0445

      # this is only necessary if caching TLS sessions
      tlsprune      cmd="tls_prune" at=0400
    }

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

Before you launch Cyrus for the first time, create the Cyrus directory structure: use mkimap(8).

    sudo -u cyrus ./tools/mkimap

### Optional: Setting up TLS certificates

Obtain a certificate, e.g. from Let’s Encrypt. You need a file with the full chain and a private key in X.509 format. Adjust the file owner on these files with `sudo chown cyrus:mail`. Set the options `tls_server_cert` and `tls_server_key` in imapd.conf(5) to point to these files.

Open `/etc/cyrus.conf` and in the SERVICES section, add (or uncomment) this line:

    imaps        cmd="imapd" listen="imaps" prefork=0

Notice the s at the end of imaps. This says we are using TLS. Similar such lines may be used for pop3s, lmtps and other protocols. See Protocol Ports, above, for more information on these.

If you now restart (or start) your Cyrus server, you should have Cyrus listening on port 993 (the IMAPS port) with the STARTTLS IMAP extension enabled. You can check that TLS works as expected with the following command:

    imtest -t "" -u imapuser -a imapuser -w secret localhost

Make sure to replace imapuser with whatever user you set up with saslpasswd2 before, and to replace secret with the actual password you set for that user.

### Prepare ephemeral (run-time) storage directories

If you will be using ephemeral (run-time) storage locations on an OS or distro on which the directory skeleton does not persist over reboots, you will need to use your distro’s standard method to ensure that any such directories your installation depends upon exist prior to launching the daemon.

Here’s how to do so for Debian/Ubuntu. Use the provided `statoverride` facility to manage the ownership and permissions of these directories:

    sudo dpkg-statoverride cyrus mail 755 /run/cyrus
    sudo dpkg-statoverride cyrus mail 750 /run/cyrus/socket

Then you can use something like this in your init script (like those packaged by Debian team):

    dir=$(dpkg-statoverride --list /var/run/cyrus)
    [ -z "$dir" ] || createdir $dir

where the `createdir()` shell function looks like this:

    createdir() {
    # $1 = user
    # $2 = group
    # $3 = permissions (octal)
    # $4 = path to directory
        [ "$VERBOSE" = "yes" ] && OPT="-c"
        [ -d "$4" ] || mkdir -p "$4"
        chown $OPT -h "$1:$2" "$4"
        chmod $OPT "$3" "$4"
    }

Putting it all together, this blob from the stock Debian packaging would go between pre-flight checks (checking for config sanity, file locations, etc.) and initialization:

    createdir() {
    # $1 = user
    # $2 = group
    # $3 = permissions (octal)
    # $4 = path to directory
        [ "$VERBOSE" = "yes" ] && OPT="-c"
        [ -d "$4" ] || mkdir -p "$4"
        chown $OPT -h "$1:$2" "$4"
        chmod $OPT "$3" "$4"
    }

    missingstatoverride () {
        echo "$0: You are missing a dpkg-statoverride on $1.  Add it." >&2
        exit 1
    }

    fixdirs () {
        dir=$(dpkg-statoverride --list /run/cyrus) \
            || missingstatoverride /run/cyrus
        [ -z "$dir" ] \
            || createdir $dir
        dir=$(dpkg-statoverride --list /run/cyrus/socket) \
            || missingstatoverride /run/cyrus/socket
        [ -z "$dir" ] \
            || createdir $dir
    }

## Launch Cyrus

    sudo ./master/master -d

Check `/var/log/syslog` for errors so you can quickly understand any problems.

When you’re ready, you can create init scripts to start and stop your daemons. This https://www.linux.com/learn/managing-linux-daemons-init-scripts is old, but has a good explanation of the concepts required.

## Send a test email

We will send a test email to our local development environment to check if:

- The SMTP server* accepts the incoming email,
- LMTP transmits the email to Cyrus IMAP,
- You can see the email stored on your filesystem.

Note

*SMTP servers are also often called an “MTA,” for Mail Transport Agent

But first, create a mailbox to send the test email to. We’ll call this test mailbox example@localhost.

    echo 'createmailbox user/example@localhost' | cyradm -u imapuser -w secret localhost

We seem to be creating a mailbox named `user/example@localhost`. In fact, Cyrus understands this to be a user called `example@localhost`. As usual, adjust the password via the `-w` option to the password you set above.

If you have explicitly disabled `unixhierarchysep` in `/etc/imapd.conf` (it is enabled by default in 3.0+), you should replace `user/example@localhost` with `user.example@localhost`. You can read more about `unixhierarchysep` in imapd.conf(5).

The command will produce the following output:

    localhost> localhost>

This happens because cyradm is normally used interactively, with a prompt. We aren’t using a prompt, so this output is expected.

Now that the mailbox exists, we can send an email using telnet with raw SMTP commands.

First, connect to the MTA:

    telnet localhost smtp

You should see a prompt appear:

    Trying ::1...
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    220 ... ESMTP Sendmail ...

Now, we’ll send the SMTP commands to the server. These are responsible for ordering the MTA to store an email:

    EHLO localhost
    MAIL FROM:<hello@localhost>
    RCPT TO:<example@localhost>
    DATA
    Hello world!
    .
    QUIT

If you are using Sendmail as your SMTP server, you should be able to safely copy and paste this bit into the terminal before hitting your ENTER key. If not, you may want to paste these commands one by one (or make sure you enable PIPELINING in the SMTP config).

If you see a message like 250 2.0.0 … Message accepted for delivery, you did it! You should now have a file called 1. in the /var/spool/cyrus/user/example directory, with the content of the email you sent just before.

If not, you may want to check syslog to see if any error messages show up and go through the previous steps again.

To let the example user log in via IMAP on a normal mail client, you need to add them to SASL (as before):

    echo 'mypassword' | saslpasswd2 -p -c example

Check your two users are there:

    sasldblistusers2

You can now configure a mail client to access your new mailserver and connect to the mailbox for example@localhost via IMAP and see the message.

## Checking CardDAV and CalDAV

Modify `/etc/cyrus.conf` and add (or uncomment) this line in the SERVICES section:

    http        cmd="httpd" listen="http" prefork=0

Modify `/etc/imapd.conf` and add (or uncomment) this line:

    httpmodules: caldav carddav

Running the following commands should return you sample entry addressbook and calendar entry for the sample example user:

    curl -u example@[hostname]:mypassword -i -X PROPFIND -H 'Depth: 1' http://localhost:8080/dav/addressbooks/user/example@[hostname]/Default

    curl -u example@[hostname]:mypassword -i -X PROPFIND -H 'Depth: 1' http://localhost:8080/dav/principals/user/example@[hostname]/

## Troubleshooting

Some common issues are explained below.

I have all kinds of weird Perl errors when running cyradm

The solution is to set the Perl library path right. To be honest, I was too lazy to figure out exactly which path was right, so I added this snippet to my `~/.bashrc` file:

    export PERL5LIB="$PERL5LIB:$(find path/to/cyrus/perl -type d | tr "\\n" ":")"

Just make sure to change path/to/cyrus to the actual path to the Cyrus source code directory. This should be something like `/home/jack/cyrus-src/perl`.

I can’t connect to the IMAP server

Make sure that the SASL auth daemon is running. You can start it with this command:

    /etc/init.d/saslauthd start

You can safely run this command even if you don’t know whether the SASL auth daemon is already running or not.

Emails are not being delivered to Cyrus

Make sure that you have started Sendmail, which you can do like this:

    /etc/init.d/sendmail start

My IMAP server (master) can’t authenticate users to SASL

Check that the groups setting on your cyrus user is correct.

Ubuntu uses saslauth group, Debian uses sasl group.

Check the output of groups cyrus to see what groups it currently belongs to.

Incorrect groups settings results in saslauthd reporting permission failures:

    SASL cannot connect to saslauthd server: Permission denied
    SASL unable to open Berkeley db /etc/sasldb2: Permission denied

Master will need to be restarted if you needed to change the groups.

Something is not working but I can’t figure out why

More information is almost always logged to syslog. Make sure you start syslog with this command before starting the Cyrus server:

    /etc/init.d/rsyslog start

My question isn’t answered here

Join us on the mailing lists if you need help or just want to chat about Cyrus, IMAP, etc.