Published on (
 See this if you're having trouble printing code examples

Running Cyrus IMAP
Configuring virtual domains with Cyrus+Postfix in FreeBSD 5.4

by Francisco Reyes

Cyrus IMAP is an efficient IMAP server capable of handling a large number of accounts. Its biggest drawback is getting it installed and configured. This tutorial is a step-by-step guide on how to use Cyrus with the Postfix mail transfer agent (MTA). I tested these instructions with FreeBSD 5.4.

Postfix is a replacement for sendmail, the stock MTA that comes in FreeBSD. It is easier to configure and manage than sendmail. If you depend on sendmail, you can still look at the article for the Cyrus part, but you'll need to look elsewhere for the MTA configuration.

Unless otherwise instructed, perform all operations in this tutorial as root. You will need to use the port system. If you are new to it, check Chapter 4 of the FreeBSD Handbook.

Process Overview

Installing Cyrus and Postfix on FreeBSD requires three ports:

The SASL2 component acts as the authentication method. Any program that will connect to read email will go through SASL2 to authenticate. All users who have mailboxes need an account in the SASL2 database. In addition, any IDs you plan to use to manage Cyrus need IDs in SASL, but they don't need an ID in the Cyrus IMAP server.

Cyrus will manage the mailboxes. Users need to have an ID in Cyrus in order to receive mail.

Postfix will deliver the emails to Cyrus. Postfix needs to know about each user through a virtual alias map file. This file determines which emails to deliver to which internal mailbox. It is possible to point multiple email addresses to the same mailbox.

The ports I used for this article were Postfix 2.23, Cyrus 2.2.12, and SASL 2.1.21

All three ports rely on Berkeley DB as a database. For this article, I chose the most recent version, 4.3; however, if you already have a Berkeley DB port installed, you can configure the ports to use that instead.

SASL2 Port

Install this port:

# cd /usr/ports/security/cyrus-sasl2
# make install clean

OTP, NTLM, and GSSAPI are different authentication mechanisms and aren't relevant to this article. If you know about those other authentication mechanisms or plan to use them, you can omit the part that excludes them. However, leaving them while the rest of that authentication mechanism is not operational may cause your setup to not work or to produce additional warnings in your log files.

WITH_BDB_VER=43 specifies to use Berkeley database 4.3.

To test the SASL2 installation, do this:

# rehash
# saslpasswd2 -c admin
# sasldblistusers2
admin@domain1: userPassword

saslpasswd2 with the -c parameter instructs SASL2 to create the user. sasldblistusers2 shows the list of users. If the creation of the user admin was successful, the output should match the display above.

Cyrus Port

After you run make, a menu appears. Click on OK. This port needs no options besides Berkeley DB 4.3.

# cd /usr/ports/mail/cyrus-imapd22
# make USE_BDB_VER=43
# mail install clean

As with the SASL2 port, choose Berkeley DB 4.3 by using USE_BDB_VER=43.

Cyrus needs a directory to hold the IMAP files:

# mkdir /var/imap
# mkdir /var/imap/spool
# chown -R cyrus:mail /var/imap
# chmod -R 750 /var/imap

The default directories for Cyrus are /var/imap and /var/spool, but I prefer /var/imap and /var/imap/spool to facilitate backups. You can point these directories somewhere else, as long as all configuration files point to the same place.

To start Cyrus at boot time, change /etc/rc.conf by adding:


Postfix and Cyrus will communicate with a socket. The /usr/local/etc/cyrus.conf contains the name and location of the socket. Comment the line with lmtp and add:

lmtpunix cmd="lmtpd" listen="/var/imap/socket/lmtp" prefork=0
Linux Server Security

Related Reading

Linux Server Security
By Michael D. (Mick) Bauer

The primary configuration file for Cyrus is /usr/local/etc/imapd.conf. Replace your imapd.conf with the following. (The bracketed numbers refer to footnotes; remove those.)

configdirectory: /var/imap [1]
partition-default: /var/imap/spool
sievedir: /var/imap/sieve
admins: user1@domain1 user2@domain2 admin [2]
allowanonymouslogin: no
autocreatequota: 10240
reject8bit: no
quotawarn: 90
timeout: 30
poptimeout: 10
dracinterval: 0
drachost: localhost
sasl_pwcheck_method: auxprop
lmtp_overquota_perm_failure: no
unixhierarchysep: no
virtdomains: userid
defaultdomain: domain1 [3]
loginrealms: domain1,domain2 [4]

[1] To use a different location for your email storage, change the configdirectory, partition-default, and sievedir to point to your preferred location. The partition-default doesn't have to be inside the same directory as the configdirectory, but it makes it easier to back up if it is.

[2] If you want an ID to manage all domains, create it without a domain. IDs created with domains can manage only their own domain.

[3] This is the domain the system will add if you create a user without adding a domain.

[4] List all the domains for which you plan to host email. For an explanation of the options in imapd.conf, see /usr/local/etc/imapd.conf.original and man imapd.conf.

Now you must create several directories and files to prepare Cyrus for operation. Become user cyrus and run mkimap:

# su cyrus

As root, start Cyrus:

# /usr/local/etc/rc.d/ start

To test whether Cyrus is running, use this:

#telnet localhost 143
Escape character is '^]'.
* OK Cyrus IMAP4 v2.2.12 server ready

To exit, type a1 logout

For each mailbox you will host, you must create an ID in SASL2 and in Cyrus. For example, here's how to create the user test. Replace domain1 with a valid domain you plan to host. First, create the user in SASL2:

#saslpasswd2 -c test@domain1
Again (for verification):

# sasldblistusers2 userPassword

Then create it in Cyrus. You will need the password you used for user admin. If you don't recall the password, reset it using saslpasswd2 admin:

#cyradm --user admin localhost
cm user.test@domain1
test@domain1 (\HasNoChildren)

Postfix Port

A menu will appear when you make this port. Select the options Cyrus SASL v2 and Berkeley DB4.3. The script will ask whether you want to add the postfix user to the mail group and whether you want to activate Postfix in /etc/mail/mailer.conf. Answer yes to both.

# cd /usr/ports/mail/postfix
# make install clean
# rehash

Enable Postfix at startup by adding the following to your /etc/rc/conf:


Also create a symbolic link in the startup folder so that Postfix will start when the system boots:

# cd /usr/local/etc/rc.d
# ln -s /usr/local/sbin/postfix

Then disable some Sendmail-specific daily maintenance routines in your /etc/periodic.conf file:


With Postfix configured, create a needed file called alias.db, and then start it.

# newaliases
# ls -l /etc/aliases.db
# postmap /usr/local/etc/postfix/virtual
# postfix start

Although the setup described in this article does not use this file, Postfix looks for it anyway. You may need this file depending on your future needs.

To test whether Postfix is running:

telnet localhost 25
You should see a prompt
Connected to < your host name >
Escape character is '^]'.

There is one final file to edit, /usr/local/etc/postfix Change the entire as follows. (Again, bracketed numbers refer to footnotes, so remove them.)

command_directory = /usr/local/sbin
daemon_directory  = /usr/local/libexec/postfix
mailq_path        = /usr/local/bin/mailq
manpage_directory = /usr/local/man
newaliases_path   = /usr/local/bin/newaliases
queue_directory   = /var/spool/postfix
sample_directory  = /usr/local/etc/postfix
sendmail_path     = /usr/local/sbin/sendmail

mail_owner  = postfix
soft_bounce = no

myhostname           = domain1 [1]
myorigin             = $mydomain
relay_domains        = $mydestination
local_recipient_maps = $virtual_mailbox_maps
recipient_delimiter  = +
debug_peer_level     = 2

unknown_local_recipient_reject_code = 550

setgid_group       = maildrop
html_directory     = no
readme_directory   = no
masquerade_domains = $mydomain
smtpd_recipient_restrictions =
smtpd_helo_restrictions = reject_invalid_hostname
smtpd_require_helo      = yes

mailbox_transport       = lmtp:unix:/var/imap/socket/lmtp
virtual_transport       = lmtp:unix:/var/imap/socket/lmtp
virtual_mailbox_domains = domain1, domain2 [2]
virtual_alias_maps      = hash:/usr/local/etc/postfix/virtual

[1] The primary domain for email purposes.

[2] A list of all domains you plan to manage, including your primary domain.

For details on the options listed above, see /usr/local/etc/postfix/dist/

Now restart Postfix to make it read the new configuration files:

# postfix reload

In addition to having users listed in SASL and Cyrus, Postfix needs to know about them. Add each user to /usr/local/etc/postfix/virtual in the format:

user@domain     user@domain

You may also want to have a single address to receive all mail not designated to a valid address. Add the line:

@domain1 valid_user@domain1

Be aware that doing this will cause all the spam to that domain to go to that user. On the bright side, doing this will make your setup more compliant with the Internet standards that require the existence of addresses such as postmaster.

Finally, run postmap /usr/local/etc/postfix/virtual. Remember to run postmap every time you change that file.

Testing Your Setup

If you already have an IMAP client, you can connect to your newly configured Cyrus server using the test user. Remember to append the domain name when you log in.

If you don't have an IMAP client, you can use a text-based mail client, called Cone, in the ports system for your test. You can install Cone in the same server in which you have installed Cyrus, or on a different machine as long as it can connect to the Cyrus IMAP server.

# cd /usr/ports/mail/cone
# make install clean

For the rest of the test, you do not need to be the root superuser.

Once you are able to connect to the IMAP server with your own client or with Cone, try sending an email. If the machine is the one responsible for handling email for the given domain (that is, if your DNS MX records point to it), you can send an email to your test user from any machine.

If the IMAP server doesn't yet have MX records pointing to it, you can still test your setup by setting the machine you configured as your Cyrus server as the SMTP server. If you're using Cone from the same machine, you don't need to do anything extra. Just write an email and send it to your test user. By default, Cone will use the current machine as the delivery SMTP server.


Francisco Reyes is an independent consultant in New York.

Return to the BSD DevCenter.

Copyright © 2009 O'Reilly Media, Inc.