Guide to Installing Courier-IMAP on OpenBSD

Version 1.0, 26 December 2003

This is a writeup on how to turn your OpenBSD machine into an IMAP server with the help of the Courier-IMAP package.

Note: Courier-IMAP uses the Maildir format for mail boxes. That means in order to be able to use IMAP, the MTA on the server will have to be set up to deliver mail into Maildir mail boxes. I recommend qmail as an MTA. How to do this with the qmail MTA is described in the OpenBSD qmail Installation HOWTO.


Table of Contents


Installation

Courier-IMAP will need the following additional packages: postgresql-7.3.2.tgz, mysql-client-3.23.55.tgz, openldap-client-2.0.27.tgz and gdbm-1.8.3.tgz. If you don't have these already, we will install courier-imap directly from the packages directory of our local OpenBSD FTP mirror. This way, the package manager will automatically download the missing packages from the same server. If this is not already done, we will start with setting the PKG_PATH environment variable to our local OpenBSD mirror, as listed at http://openbsd.org/ftp.html. Then we install the packages.

# export PKG_PATH=ftp://sunsite.dk/mirrors/openbsd/3.3/packages/i386/
# pkg_add ${PKG_PATH}courier-imap-1.7.1.tgz

Now we will copy the sample configuration files provided into our /etc folder.

# cp -R /usr/local/share/examples/courier-imap/ /etc/

In order to be able to use IMAP over SSL (IMAPS) or with TLS, we will need to create a self-signed server certificate. To do this we need to edit the /etc/courier-imap/imapd.cnf file. Make sure you don't leave any fields empty and that CN is set to the exact domain name that the IMAP clients will use to refer to the server. Actually all fields except for CN are of little importance if your server is not a public IMAP server. If you have a valid SSL certificate, like from Thawte for example, you will want to use that one instead. For private and in-house uses, our self-signed certificate will usually suffice. Here is how I set it up:


RANDFILE = /usr/local/sbin/imapd.rand

[ req ]
default_bits = 1024
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type
prompt = no

[ req_dn ]
C=DK
ST=N/A
L=Copenhagen
O=ACME Inc.
OU=IT Department
CN=dogbert.danieltams.dyndns.org
emailAddress=postmaster@dogbert.danieltams.dyndns.org


[ cert_type ]
nsCertType = server

Now we can create the actual certificate.

# /usr/local/sbin/mkimapdcert

After taking care of the certificate, we're ready to make the Courier-IMAP server automatically start up every time we boot our system. /usr/local/libexec/imapd.rc starts and stops an ordinary IMAP daemon on the IMAP port 143. /usr/local/libexec/imapd-ssl.rc controls an IMAP daemon tunnelled through SSL, listening at the IMAPS port 993. In the following examples I will run both daemons. If you only want to run one of them, just leave out the other one. Add the following to your /etc/rc.local startup file:

if [ -x /usr/local/libexec/imapd.rc -a -x /usr/local/libexec/imapd-ssl.rc ]; then
        mkdir -p /var/run/courier-imap
        echo -n ' imapd';       /usr/local/libexec/imapd.rc start
        echo -n ' imapd-ssl';   /usr/local/libexec/imapd-ssl.rc start
fi

Also add the following to your /etc/rc.shutdown shutdown script file, so that the IMAP server gets shut down properly every time we shutdown our machine.

if [ -x /usr/local/libexec/imapd.rc -a -x /usr/local/libexec/imapd-ssl.rc ]; then
        echo -n ' imapd';       /usr/local/libexec/imapd.rc stop
        echo -n ' imapd-ssl';   /usr/local/libexec/imapd-ssl.rc stop
fi

echo '.'

User Setup

Now we are going to set up the mail users. For this we are going to create a virtual mail user account. This same system user account will be used for all IMAP accounts. We will call this account vmail.

# mkdir /var/vmail
# useradd -d /var/vmail -g =uid -s /sbin/nologin vmail
# chown vmail:vmail /var/vmail

So, the virtual mail account has now been created as a system user account. Now we will add it to the user database. Save the following two lines into the /etc/userdb file, replacing 1012 with the UID of the vmail account.

vmail   uid=1012|gid=1012|home=/var/vmail
1012=   vmail

Because /etc/userdb is going to contain the IMAP login passwords of your IMAP users, remove group and world rights from the file.

# chmod 600 /etc/userdb

Setting up new users and removing old ones involves several steps, so we are going to ease the job of user management by creating a script to add new users and one to remove old users. Save the following script into the file /usr/local/sbin/cour_userdb_mkuser.

#!/bin/sh
#
# Original author: Matthew Farrellee < mafarrel <at> cs <dot> indiana <dot> edu >
# Date: Monday January 28, 2002
#
# Modified:
# Tuesday January 29, 2002: Made errors more readable.
#
# Modified by Darren Spruell < sancho <at> sancho2k <dot> net >:
# Friday January 10, 2003: Removed the stuff regarding the
# user's domain, etc. My mail host serves a single domain.
# Made some minor editions to the script.
#
# Modified by Daniel Tams < dantams <at> sdf-eu <dot> org >:
# Friday July 04, 2003: Changed binary variables to values that
# conform to a standard installation of courier-imap on OpenBSD.
# Changed password type to hmac-md5 for CRAM-MD5 secure 
# authentification.
 
##################################################################
# .: START CONFIGURABLE OPTIONS SECTION :.
##################################################################
 
# The following paths need to be set to reflect the location of
# the following commands, in order:
# maildirmake, makeuserdb, userdbpw, userdb
MAILDIRMAKE=/var/qmail/bin/maildirmake
MAKEUSERDB=/usr/local/sbin/makeuserdb
USERDBPW=/usr/local/sbin/userdbpw
USERDB=/usr/local/sbin/userdb
 
# These variables should reflect:
# VUSER -The name of your virtual user account
# VUSER_UID -The UID of your virtual user account
# VUSER_GID -The GID of your virtual user account (should be same as UID)
# VUSER_HOME -This account's home directory
VUSER=vmail
VUSER_UID=`id -u $VUSER`
VUSER_GID=`id -g $VUSER`
VUSER_HOME=~vmail
 
# Set this to qmail's home (usually /var/qmail):
QMAIL_HOME=/var/qmail
 
##################################################################
# .: END CONFIGURABLE OPTIONS SECTION :.
##################################################################
 
NEW_USER=$1
 
# Make sure the username argument was given.
if [ -z "$NEW_USER" ]
then
echo "Usage:" `basename $0` "<username>"
echo "Ex: `basename $0` bob"
exit 1
fi
 
# Make sure the user does not already exist.
if [ -d $VUSER_HOME/Maildir-$NEW_USER ]
then
echo "Error: Account" $NEW_USER "already exists."
exit 1
fi
 
# Create the user's home and mail directory.
echo "Creating a Maildir for" $NEW_USER
$MAILDIRMAKE $VUSER_HOME/Maildir-$NEW_USER
if [ $? != 0 ]; then
echo "Error creating Maildir..."
exit
fi
chown -R $VUSER.$VUSER $VUSER_HOME/Maildir-$NEW_USER
 
# Add the user to the proper userdb and set the user's password.
echo "Adding" $NEW_USER "to" /etc/userdb
echo "Enter the password for" $NEW_USER
$USERDBPW -hmac-md5 | $USERDB -f /etc/userdb $NEW_USER set \
	uid=$VUSER_UID gid=$VUSER_GID home=$VUSER_HOME \
	mail=$VUSER_HOME/Maildir-$NEW_USER hmac-md5pw
 
# Make sure the new user is noticed.
$MAKEUSERDB
 
# Create .qmail files for delivery to Maildir.
echo "vmail-$NEW_USER" > $QMAIL_HOME/alias/.qmail-$NEW_USER
echo "./Maildir-$NEW_USER/" > $VUSER_HOME/.qmail-$NEW_USER
echo "Created .qmail files for Maildir delivery to $NEW_USER."
 
# Finalize for user.
echo
echo " Done!!! $NEW_USER has been added to Courier-IMAP."
echo
exit 0

Beware: the above script will only work for adding users that do not already exist in /etc/passwd, i.e. virtual users that do not have any shell access, but will only have an email account on the server. If you want to set up IMAP access for a real user, let's say joe with UID 1000 and GID 1000, execute the following commands.

# sudo -u joe /var/qmail/bin/maildirmake /home/joe/Maildir
# /usr/local/sbin/userdbpw -hmac-md5 | /usr/local/sbin/userdb -f /etc/userdb joe \
	set uid=1000 gid=1000 home=/home/joe mail=/home/joe/Maildir hmac-md5pw
# /usr/local/sbin/makeuserdb

Save the following script into the file /usr/local/sbin/cour_userdb_rmuser.

#!/bin/sh
#
# Original author: Matthew Farrellee < mafarrel <at> cs <dot> indiana <dot> edu >
# Date: Monday January 28, 2002
#
# Modified:
# Tuesday January 29, 2002: Made errors more readable.
#
# Modified by Darren Spruell < sancho <at> sancho2k <dot> net >:
# Friday January 10, 2003: Removed the stuff regarding the
# user's domain, etc. My mail host serves a single domain.
# Made some minor editions to the script.
#
# Modified by Daniel Tams: < dantams <at> sdf-eu <dot> org >
# Saturday July 05, 2003: Fixed non-existant $VMAIL_HOME.
 
##################################################################
# .: START CONFIGURABLE OPTIONS SECTION :.
##################################################################
 
# The following paths need to be set to reflect the location of
# the following commands, in order:
# makeuserdb, userdb
MAKEUSERDB=/usr/local/sbin/makeuserdb
USERDB=/usr/local/sbin/userdb
 
# These variables should reflect:
# -The virtual user account's home directory
# -The qmail base directory (generally /var/qmail)
VUSER_HOME=~vmail
QMAIL_HOME=/var/qmail
 
##################################################################
# .: END CONFIGURABLE OPTIONS SECTION :.
##################################################################
 
OLD_USER=$1
 
# Make sure the username argument was given.
if [ -z "$OLD_USER" ]
then
echo "Usage:" `basename $0` "<username>"
exit 1
fi
 
# Make sure the user already exists.
if [ ! -d $VUSER_HOME/Maildir-$OLD_USER ]
then
echo "Error: Account" $OLD_USER "doesn't exist."
exit 1
fi
 
# Give the user a chance to back out before destroying a Maildir.
echo -n "WARNING!! Are you sure you want to delete $OLD_USER's IMAP account? [y/n]: "
read DELANS
if [ $DELANS == "y" ]; then
:
else [ $DELANS != "y" ]
echo "Exiting. $OLD_USER's IMAP account unaffected."
exit 1
fi
 
# Remove the user's Maildir.
echo "Removing $OLD_USER's Maildir"
rm -Rf $VUSER_HOME/Maildir-$OLD_USER
# And the .qmail files
echo "Removing $OLD_USER's .qmail files"
rm $QMAIL_HOME/alias/.qmail-$OLD_USER
rm $VUSER_HOME/.qmail-$OLD_USER
 
# Remove the user's entry in the userdb.
echo "Removing" $OLD_USER "from" /etc/userdb
$USERDB -f /etc/userdb $OLD_USER del
 
# Make sure the deletion of the user is noticed.
$MAKEUSERDB
 
# Finalize for user.
echo
echo " Done!!! $OLD_USER has been removed from Courier-IMAP and the Maildir deleted."
echo
exit 0

Configuration

Authentication Modules

In this example we are only using the CRAM-MD5 authentication method. Therefore we can disable the other authentification methods. This is done in the /etc/courier-imap/authdaemonrc configuration file. Change the line

authmodulelist="authcustom authcram authuserdb authldap authpgsql authmysql authpwd"

to

authmodulelist="authcram"

Capabilities

In order for an IMAP client to know which features are supported by the server, the capabilities string is used. It quickly tells the client, amongst other things, which authentification methods it can use to login. It should reflect the authentification methods that have been setup. In the file /etc/courier-imap/imapd, add AUTH=CRAM-MD5 to the IMAP_CAPABILITY line, so that it comes to look like this:

IMAP_CAPABILITY="IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT \
	THREAD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 IDLE"

TLS

TLS enables SSL encryption over the standard IMAP port 143. If you want to enable this feature, simply set the IMAPDSTARTTLS variable to YES in the /etc/courier-imap/imapd-ssl file.

IMAPDSTARTTLS=YES

Plain authentification

If you should find that one of your users' email clients is not able to login with the HMAC-MD5 or STARTTLS authentication methods, you can add the following line to the first script. You will then have to enter the password one extra time every time you add a new user. But beware that using this login method will send the plain password unencrypted through the network and is therefore not encouraged.

$USERDB -f /etc/userdb $NEW_USER set imappw

We will need to add the plain userdb authentication module to our list of authentication modules to enable. We do that by adding authuserdb to the authentication modules list in our /etc/courier-imap/authdaemonrc file, so that it looks ike this:

authmodulelist="authcram authuserdb"

Also the ability to do plain authentification should be reflected in the capabilities string, so add AUTH=PLAIN to the IMAP_CAPABILITY line of /etc/courier-imap/imap so it looks like this:

IMAP_CAPABILITY="IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT \
	THREAD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 AUTH=PLAIN IDLE"

Test

Now lets add an IMAP user so we can test our system.

# cour_userdb_mkuser joedoe
Creating a Maildir for joedoe
Adding joedoe to /etc/userdb
Enter the password for joedoe
Password:
Reenter password:
Created .qmail files for Maildir delivery to joedoe.
 
 Done!!! joedoe has been added to Courier-IMAP.
 
#

Starting the Server

Now we will start up our IMAP server so we can test it out with an IMAP client.

# mkdir -p /var/run/courier-imap
# /usr/local/libexec/imapd.rc start
# /usr/local/libexec/imapd-ssl.rc start

Thanks go to Darren Spruell for the great stylesheet and the scripts.

Send any requests for correction, suggestions for improvement and comments to Daniel Tams