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).


configdirectory
^^^^^^^^^^^^^^^

*This shows the default value: change it in imapd.conf to suit your
needs.*

   "configdirectory:" <none>

      The pathname of the IMAP configuration directory.  This field is
      required.

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 -f /var/run/saslauthd/mux

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, Exim). In Cyrus, this happens
via a protocol called LMTP, which is usually supported by your SMTP
server.


Integration with Sendmail
~~~~~~~~~~~~~~~~~~~~~~~~~


Objectives
""""""""""

This manual describes how to integrate Sendmail with Cyrus IMAP.  Open
Sendmail presents alternative approaches, but these do not integrate
well with email addresses from virtual domains, which are hosted by
Cyrus IMAP, but are not in the *virtuser* table.

Cyrus IMAP can manage many domains.  It has a default domain, and
other, virtual domains.

Sendmail can also manage many domains.  Its primary domains are stored
in the *w* class and are read from */etc/mail/local-host-names*.  The
rewritings for these domains are modified using the aliases database.
Sendmail handles unqualified email addresses and addresses from the
domains in the *w* class the same. Sendmail in addition can manage
further, virtual domains by defining the *VirtHost* class.  The
redirections for the virtual domains are controlled by
*virtusertable*.

This guide explains how to configure sendmail, so that it handles
unqualified email addresses in the same way, as if they were in the
default Cyrus IMAP domain.  It assumes, that the default Cyrus domain
is in the *w* class.  At the end it will be possible to have
destination addresses with domains in the *w* or *VirtHost* classes
and these addresses will be delivered to Cyrus IMAP after aliases and
*virtusertable* rewritings, if and only if Cyrus IMAP hosts them.

Sendmail will be configured to verify using *smmapd* if Cyrus does
have a mailbox, and reject the email during the SMTP dialog otherwise.
This avoids sending bounces.  Bounces reduce the IP reputation of a
mail server.  If a local for the server user does not have a Cyrus
IMAP account, this user will not get its emails in a folder on the
server.  If *smmapd* does not respond, sendmail will accept emails for
any address.

If a virtual mailbox exists in Cyrus IMAP and *virtusertable*
redirects the emails for that mailbox somewhere, the *virtusertable*
takes precedence, like the aliases database has precedence in such
cases.

The user database is not considered in this guide.

Plus addressing works, when the destination folder does exist and is
lowercased:  If *user1* has folders *abc* and *mNp*, emails for
*user1+abc* and *user1+aBc* will be accepted, emails for *user1+mNp*
and *user1+mnp* will be rejected.  The lowercase limitation comes from
*smmapd*.  Emails for *user1+def* will be rejected, if *user1* has no
mailbox *def*, even if a Sieve script would place such mails in
existing folders.

Plus addressing does not survive aliases rewriting.  If the aliases
table contains *user2: user1*, emails for *user2+abc* will be
rejected, while emails for *user2* or *user1+abc* will be accepted.
After inserting *user2+abc: user1+abc* in the aliases table, emails
for *user2+abc* will be accepted.


Install Sendmail
""""""""""""""""

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

   sudo apt-get install -y sendmail


Add cf/feature/anfi_vcyrus.m4
"""""""""""""""""""""""""""""

Create the file cf/feature/anfi_vcyrus.m4:

   divert(-1)
   dnl
   dnl By using this file, you agree to the terms and conditions set
   dnl forth in the LICENSE file which can be found at the top level of
   dnl the sendmail distribution (sendmail-8.12).
   dnl
   dnl     Contributed by Andrzej Filip and Dilyan Palauzov
   LOCAL_CONFIG
   # cyrus - map for checking cyrus mailbox presence
   Kcyrus socket -T<TMPF> -a<OK> local:/var/imap/socket/smmapd

   LOCAL_RULESETS
   SLocal_localaddr
   R$+     $: $1 $| $(cyrus $1 $: $)
   R$+ $|                $#error $@ 5.1.1 $: "550 User unknown."
   R$+ $| $*<TMPF>       $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
   R$+ $| $*<OK>         $#cyrusv2 $@ $: $1
   R$+ $| $*             $: $1

Many spaces in a row stand for the tabulator character.

Despite the naming confusion, Cyrus 3 works with the *cyrusv2* mailer.

This file creates a map called *cyrus*, which connects to the Cyrus`
*smmapd* service.

The file extends the *localaddr=5* and *Local_localaddr* rulesets to
verify whether an address is known to Cyrus IMAP.  The rulesets are
called from the *local* mailer, as the *local* mailer has the *5*
mailer flag set.  The ruleset changes the mailer to *cyrusv2* and the
email is accepted if and only if the address is known to Cyrus IMAP.

The temporary rejections do not work in practice.  If *smmapd* is
down, the email is queued instead of being rejected.  The 451 line
above is there to encourage discussion.


Patching m4/proto.m4
""""""""""""""""""""

   diff --git a/cf/m4/proto.m4 b/cf/m4/proto.m4
   --- a/cf/m4/proto.m4
   +++ b/cf/m4/proto.m4
   @@ -1147,6 +1147,10 @@ dnl if no match, change marker to prevent a second @domain lookup
    R<@> $+ + $* < @ $+ . >      $: < $(virtuser @ $3 $@ $1 $@ $2 $@ +$2 $: ! $) > $1 + $2 < @ $3 . >
    dnl without +detail
    R<@> $+ < @ $+ . >           $: < $(virtuser @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
   +dnl If a virtual address is not in the virtusertable, but cyrus knows about the address, deliver it.
   +R< error : $-.$-.$- : $+ > $+ < @ $={VirtHost} . >           $: < error : $1.$2.$3 : $4 > $5 < $6 . > $| $(cyrus  $5@$6 $: $)
   +R< error : $-.$-.$- : $+ > $* < $* . > $| $*<OK>             $#cyrusv2 $@ $: $5@$6
   +R< error : $-.$-.$- : $+ > $* $| $*<TMPFS>           $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
    dnl no match
    R<@> $+                              $: $1
    dnl remove mark

Where many spaces in a row stand for the tabulator key.

If an address from a virtual domain is not found in the
*virtusertable*, ask *smmapd* if the address is known to Cyrus IMAP.
If it is known, deliver it to Cyrus IMAP.


Patching mailer/cyrusv2.m4
""""""""""""""""""""""""""

   diff --git a/cf/mailer/cyrusv2.m4 b/cf/mailer/cyrusv2.m4
   --- a/cf/mailer/cyrusv2.m4
   +++ b/cf/mailer/cyrusv2.m4
   @@ -11,7 +11,7 @@ PUSHDIVERT(-1)
    #

    _DEFIFNOT(`_DEF_CYRUSV2_MAILER_FLAGS', `lsDFMnqXz')
   -_DEFIFNOT(`CYRUSV2_MAILER_FLAGS', `A@/:|m')
   +_DEFIFNOT(`CYRUSV2_MAILER_FLAGS', `8m')
    ifdef(`CYRUSV2_MAILER_ARGS',, `define(`CYRUSV2_MAILER_ARGS', `FILE /var/imap/socket/lmtp')')
    define(`_CYRUSV2_QGRP', `ifelse(defn(`CYRUSV2_MAILER_QGRP'),`',`', ` Q=CYRUSV2_MAILER_QGRP,')')dnl

The *8* flag means, that Cyrus LMTPd can accept 8bit data and sendmail
will not convert 8bit data to 7bit before passing it to Cyrus IMAP.
The *A@/:|* functionality will be performed by the *local* mailer,
before the *cyrusv2* mailer is called.  The *cyrus2v* mailer is used
only to pass data to Cyrus IMAP, after it is verified, that Cyrus IMAP
hosts a particular mailbox.  Thus the *cyrus2v* mailer does not call
the *localaddr=5* rule set in order to avoid loops. (If the *cyrusv2*
mailer calls the *localaddr=5* ruleset and the *localaddr=5* ruleset
calls the *cyrusv2* mailer, there is an endless loop).

The patch to *m4/proto.m4* also requires a mailer, which does not call
the *localaddr=5* ruleset.  Because of this, substituting the *local*
mailer by *define(`confLOCAL_MAILER', `cyrusv2')dnl* will not work.
The proposed setup needs one mailer calling the *localaddr=5* ruleset
(here the *local* mailer) and one mailer not calling the *localaddr=5*
ruleset (the *cyrusv2* mailer).


Sendmail communication
""""""""""""""""""""""

For LMTP and SMMAP to work with Sendmail, it is necessary 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

Do the same for the *smmapd* socket.


Adjustments for the *.mc* files
"""""""""""""""""""""""""""""""

In your *.mc* files add:

   FEATURE(`anfi_vcyrus')dnl
   MAILER(`cyrusv2')dnl

and recompile them, e.g. by calling *make file.cf* to convert
*file.mc* to *file.cf*.  Test with:

   # ggg is unqualified address, which exists both in Cyrus’ default domain and in sendmails’ w class
   $ sendmail -C file.cf -bv ggg
   ggg... deliverable: mailer cyrusv2, user ggg

   # verify that ggg and ggg@your-primary-domain resolve in the same way, your-primary-domain is the default Cyrus IMAP domain
   $ sendmail -C file.cf -bv ggg@your-primary-domain
   ggg... deliverable: mailer cyrusv2, user ggg

   # as above, but here another-domain belongs to class `w` and it is not the default domain for Cyrus IMAP
   $ sendmail -C file.cf -bv ggg@another-domain
   ggg... deliverable: mailer cyrusv2, user ggg

   # for an address, which exists in Cyrus IMAP, and is not overwritten in virtusertable.
   # domain1.org belongs to class VirtHost and does not belong to class w.
   $ sendmail -C sendmail-mail.cf -bv zzz@domain1.org
   zzz@domain1.org... deliverable: mailer cyrusv2, user zzz@domain1.org


Postfix
~~~~~~~


Install Postfix
"""""""""""""""

We'll set up LMTP with the Postfix SMTP server (consider which other
Postfix related packages you may also desire):

   sudo apt-get install -y postfix postfix-doc postfix-pcre postfix-ldap ...

We need to make Postfix aware of the fact we are using the Cyrus IMAP
server and engineer delivery via LMTP.  The following examples show
the "postconf" commands to run to add the necessary configuration to
"/etc/postfix/main.cf", these are not complete configurations.

Note:

  Postfix supports a great many configurations for mail delivery
  transport, so these settings will depend on whether you're planning
  to use the "local", "virtual" or "lmtp" destination definitions.
  For our examples we'll be using "virtual".  Adjust as needed for
  your purposes, and please consult the Postfix documentation at
  http://www.postfix.org/postconf.5.html

1. Setup your recipient maps, thus defining for which recipients the
   "virtual" destination will be used:

      postconf -e "virtual_mailbox_domains=hash:/etc/postfix/virtual_recipient_domains"
      postconf -e "virtual_mailbox_maps=hash:/etc/postfix/virtual_recipients"

   or, if you have enabled smmapd you can automatically track
   mailboxes with:

      postconf -e "virtual_mailbox_domains=hash:/etc/postfix/virtual_recipient_domains"
      postconf -e "virtual_mailbox_maps=socketmap:unix:/run/cyrus/socket/smmap:smmapd"

2. Optional: Set the concurrency and recipient limits for LMTP
   delivery to the "virtual" destination:

      postconf -e "virtual_destination_concurrency_limit=300"
      postconf -e "virtual_destination_recipient_limit=300"

   The purpose of those two settings is to allow for a large number of
   simultaneous delivery threads between the MTA (Postfix) and the MDA
   (Cyrus), and to allow for a large number of recipients to be listed
   for any given message, thus avoiding splitting up delivery of
   messages with lots of recipients into many separate deliveries.

3. Send mail for those recipients to Cyrus via LMTP.  This first
   example is for delivery via TCP to a different host:

      postconf -e "virtual_transport=lmtp:inet:lmtp.example.org:2003"

   If your Postfix and Cyrus are on the same host, then use some
   version of this, where the socket patch matches what's set in the
   "lmtpsocket" option in imapd.conf(5):

      postconf -e "virtual_transport=lmtp:unix:/run/cyrus/socket/lmtp"


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
   nntps     563/tcp  # NNTP over TLS
   imaps     993/tcp  # IMAP over TLS
   pop3s     995/tcp  # POP3 over TLS
   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.
