[HOWTO] Mirgration von Courier auf Dovecot unter Debian (incl. Umstellung von maildrop auf sieve)

Die Kollegen Baumann und Lehr nerven mich schon seit Wochen, dass ich doch bitte mal meine Migration von Courier auf Dovecot dokumentiere. Jetzt soll es also soweit sein. Hierbei betrachte ich auch die Umstellung von maildrop auf sieve, sowie die Integration des postfixadmin und des Squirellmail Filterplugins.

(!) Diese Doku ist natürlich auf eigene Gefahr und ohne jegliche Garantie meinerseits. (!) (nono)

Meine Ausgangslage: postfix, courier, maildrop, postfixadmin (zur Userverwaltung)

Auf Los gehts los:
Als Erstes würde ich empfehlen den Mailer mit allem drum und dran zu stoppen um Inkosistenzen zu vermeiden.
nightshift:~# /etc/init.d/postfix stop
Stopping Postfix Mail Transport Agent: postfix.
nightshift:~#

Ein Wegschreiben der aktuellen Mailerconfig in /etc/courier und /etc/postfix kann sicher auch nicht schaden.

Also… her mit den dovecot-Paketen

nightshift:~# apt-get install dovecot-common dovecot-pop3d dovecot-imapd

(!) Bitte bedenken, dass hierbei die Courier-Pakete deinstalliert werden. (!)

Jetzt gehts an die Config in /etc/dovecot. Da das default-configfile extrem lang aber auch gut kommentiert ist, beschränke ich mich auf die für uns wichtigen Stellen:

# Protocols we want to be serving: imap imaps pop3 pop3s
# If you only want to use dovecot-auth, you can set this to "none".
#protocols = imap imaps
protocols = imaps imap pop3s pop3

...

# Location for users' mailboxes. This is the same as the old default_mail_env
# setting. The default is empty, which means that Dovecot tries to find the
# mailboxes automatically. This won't work if the user doesn't have any mail
# yet, so you should explicitly tell Dovecot the full location.
#
# If you're using mbox, giving a path to the INBOX file (eg. /var/mail/%u)
# isn't enough. You'll also need to tell Dovecot where the other mailboxes are
# kept. This is called the "root mail directory", and it must be the first
# path given in the mail_location setting.
#
# There are a few special variables you can use, eg.:
#
# %u - username
# %n - user part in user@domain, same as %u if there's no domain
# %d - domain part in user@domain, empty if there's no domain
# %h - home directory
#
# See /usr/share/doc/dovecot-common/wiki/Variables.txt for full list. Some
# examples:
#
# mail_location = maildir:~/Maildir
# mail_location = mbox:~/mail:INBOX=/var/mail/%u
# mail_location = mbox:/var/mail/%d/%1n/%n:INDEX=/var/indexes/%d/%1n/%n
#
#
#
# !!! Das müsst Ihr auf euer Setup anpassen!!!
mail_location = maildir:/home/vmail/%d/%u

...

#namespace private {
# Hierarchy separator to use. You should use the same separator for all
# namespaces or some clients get confused. '/' is usually a good one.
# The default however depends on the underlying mail storage format.
#separator =

# Prefix required to access this namespace. This needs to be different for
# all namespaces. For example "Public/".
#prefix =

# Physical location of the mailbox. This is in same format as
# mail_location, which is also the default for it.
#location =

# There can be only one INBOX, and this setting defines which namespace
# has it.
#inbox = yes

# If namespace is hidden, it's not advertised to clients via NAMESPACE
# extension or shown in LIST replies. This is mostly useful when converting
# from another server with different namespaces which you want to depricate
# but still keep working. For example you can create hidden namespaces with
# prefixes "~/mail/", "~%u/mail/" and "mail/".
#hidden = yes
#}
# Da meine mailforders alle mit . Anfangen, muss das gesetzt sein
namespace private {
separator = .
prefix =
inbox = yes
}

...

auth default {
# Space separated list of wanted authentication mechanisms:
# plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi
# NOTE: See also disable_plaintext_auth setting.
mechanisms = plain digest-md5 cram-md5 ntlm

#
# Password database is used to verify user's password (and nothing more).
# You can have multiple passdbs and userdbs. This is useful if you want to
# allow both system users (/etc/passwd) and virtual users to login without
# duplicating the system users into virtual database.
#
#
#
# By adding master=yes setting inside a passdb you make the passdb a list
# of "master users", who can log in as anyone else. Unless you're using PAM,
# you probably still want the destination user to be looked up from passdb
# that it really exists. This can be done by adding pass=yes setting to the
# master passdb.

# Users can be temporarily disabled by adding a passdb with deny=yes.
# If the user is found from that database, authentication will fail.
# The deny passdb should always be specified before others, so it gets
# checked first. Here's an example:

#passdb passwd-file {
# File contains a list of usernames, one per line
#args = /etc/dovecot.deny
#deny = yes
#}

# PAM authentication. Preferred nowadays by most systems.
# Note that PAM can only be used to verify if user's password is correct,
# so it can't be used as userdb. If you don't want to use a separate user
# database (passwd usually), you can use static userdb.
# REMEMBER: You'll need /etc/pam.d/dovecot file created for PAM
# authentication to actually work.
passdb pam {
# [blocking=yes] [session=yes] [setcred=yes]
# [cache_key=] []
#
# By default a new process is forked from dovecot-auth for each PAM lookup.
# Setting blocking=yes uses the alternative way: dovecot-auth worker
# processes do the PAM lookups.
#
# session=yes makes Dovecot open and immediately close PAM session. Some
# PAM plugins need this to work, such as pam_mkhomedir.
#
# setcred=yes makes Dovecot establish PAM credentials if some PAM plugins
# need that. They aren't ever deleted though, so this isn't enabled by
# default.
#
# cache_key can be used to enable authentication caching for PAM
# (auth_cache_size also needs to be set). It isn't enabled by default
# because PAM modules can do all kinds of checks besides checking password,
# such as checking IP address. Dovecot can't know about these checks
# without some help. cache_key is simply a list of variables (see
# /usr/share/doc/dovecot-common/wiki/Variables.txt) which must match for
# the cached data to be used. Here are some examples:
# %u - Username must match. Probably sufficient for most uses.
# %u%r - Username and remote IP address must match.
# %u%s - Username and service (ie. IMAP, POP3) must match.
#
# If service name is "*", it means the authenticating service name
# is used, eg. pop3 or imap (/etc/pam.d/pop3, /etc/pam.d/imap).
#
# Some examples:
# args = session=yes *
# args = cache_key=%u dovecot
#args = dovecot
}

# System users (NSS, /etc/passwd, or similiar)
# In many systems nowadays this uses Name Service Switch, which is
# configured in /etc/nsswitch.conf.
#passdb passwd {
# [blocking=yes] - See userdb passwd for explanation
#args =
#}

# Shadow passwords for system users (NSS, /etc/shadow or similiar).
# Deprecated by PAM nowadays.
#
#passdb shadow {
# [blocking=yes] - See userdb passwd for explanation
#args =
#}

# PAM-like authentication for OpenBSD.
#
#passdb bsdauth {
# [cache_key=] - See cache_key in PAM for explanation.
#args =
#}

# passwd-like file with specified location
#
#passdb passwd-file {
# Path for passwd-file
#args =
#}

# checkpassword executable authentication
# NOTE: You will probably want to use "userdb prefetch" with this.
#
#passdb checkpassword {
# Path for checkpassword binary
#args =
#}

# SQL database
passdb sql {
# Path for SQL configuration file
args = /etc/dovecot/dovecot-sql.conf
}

# LDAP database
#passdb ldap {
# Path for LDAP configuration file
#args = /etc/dovecot/dovecot-ldap.conf
#}

# vpopmail authentication
#passdb vpopmail {
# [cache_key=] - See cache_key in PAM for explanation.
#args =
#}

#
# User database specifies where mails are located and what user/group IDs
# own them. For single-UID configuration use "static".
#
#
#

# System users (NSS, /etc/passwd, or similiar). In many systems nowadays this
# uses Name Service Switch, which is configured in /etc/nsswitch.conf.
#
userdb passwd {
# [blocking=yes] - By default the lookups are done in the main dovecot-auth
# process. This setting causes the lookups to be done in auth worker
# proceses. Useful with remote NSS lookups that may block.
# NOTE: Be sure to use this setting with nss_ldap or users might get
# logged in as each others!
#args =
}

# passwd-like file with specified location
#
#userdb passwd-file {
# Path for passwd-file
#args =
#}

# static settings generated from template
#userdb static {
# Template for the fields. Can return anything a userdb could normally
# return. For example:
#
# args = uid=500 gid=500 home=/var/mail/%u
#
# If you use deliver, it needs to look up users only from the userdb. This
# of course doesn't work with static because there is no list of users.
# Normally static userdb handles this by doing a passdb lookup. This works
# with most passdbs, with PAM being the most notable exception. If you do
# the user verification another way, you can add allow_all_users=yes to
# the args in which case the passdb lookup is skipped.
#
#args =
#}
userdb static {
args = uid=5000 gid=5000 home=/home/vmail/%d/%n allow_all_users=yes
}

# SQL database
# userdb sql {
# Path for SQL configuration file
# args = /etc/dovecot/dovecot-sql.conf
# }

# LDAP database
#userdb ldap {
# Path for LDAP configuration file
#args = /etc/dovecot/dovecot-ldap.conf
#}

# vpopmail
#userdb vpopmail {
#}

# "prefetch" user database means that the passdb already provided the
# needed information and there's no need to do a separate userdb lookup.
# This can be made to work with SQL and LDAP databases, see their example
# configuration files for more information how to do it.
#
#userdb prefetch {
#}

# User to use for the process. This user needs access to only user and
# password databases, nothing else. Only shadow and pam authentication
# requires roots, so use something else if possible. Note that passwd
# authentication with BSDs internally accesses shadow files, which also
# requires roots. Note that this user is NOT used to access mails.
# That user is specified by userdb above.
user = root

# Directory where to chroot the process. Most authentication backends don't
# work if this is set, and there's no point chrooting if auth_user is root.
# Note that valid_chroot_dirs isn't needed to use this setting.
#chroot =

# Number of authentication processes to create
#count = 1

# Require a valid SSL client certificate or the authentication fails.
#ssl_require_client_cert = no

# Take the username from client's SSL certificate, using
# X509_NAME_get_text_by_NID() which returns the subject's DN's
# CommonName.
#ssl_username_from_cert = no

# It's possible to export the authentication interface to other programs:
#!!! STOLPERFALLE: Hier müssen die Rechte passen!!!!
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0666
user = vmail
}

client {
path = /var/spool/postfix/private/auth
mode = 0600
user = postfix
group = postfix
}
}
## dovecot-lda specific settings
##
# socket listen {
# master {
# path = /var/run/dovecot/auth-master
# mode = 0600
# user = mail # User running Dovecot LDA
# #group = mail # Or alternatively mode 0660 + LDA user in this group
# }
# }

}

# If you wish to use another authentication server than dovecot-auth, you can
# use connect sockets. They are assumed to be already running, Dovecot's master
# process only tries to connect to them. They don't need any other settings
# than the path for the master socket, as the configuration is done elsewhere.
# Note that the client sockets must exist in the login_dir.
#auth external {
# socket connect {
# master {
# path = /var/run/dovecot/auth-master
# }
# }
#}

##
## Dictionary server settings
##

# Dictionary can be used by some plugins to store key=value lists.
# Currently this is only used by dict quota backend. The dictionary can be
# used either directly or though a dictionary server. The following dict block
# maps dictionary names to URIs when the server is used. These can then be
# referenced using URIs in format "proxy:name".

dict {
#quota = mysql:/etc/dovecot-dict-quota.conf
}

##
## Plugin settings
##

plugin {
# Here you can give some extra environment variables to mail processes.
# This is mostly meant for passing parameters to plugins. %variable
# expansion is done for all values.

# Quota plugin. Multiple backends are supported:
# dirsize: Find and sum all the files found from mail directory.
# Extremely SLOW with Maildir. It'll eat your CPU and disk I/O.
# dict: Keep quota stored in dictionary (eg. SQL)
# maildir: Maildir++ quota
# fs: Read-only support for filesystem quota
#quota = maildir

# ACL plugin. vfile backend reads ACLs from "dovecot-acl" file from maildir
# directory. You can also optionally give a global ACL directory path where
# ACLs are applied to all users' mailboxes. The global ACL directory contains
# one file for each mailbox, eg. INBOX or sub.mailbox.
#acl = vfile:/etc/dovecot-acls

# Convert plugin. If set, specifies the source storage path which is
# converted to destination storage (mail_location) when the user logs in.
# The existing mail directory is renamed to dir-converted.
#convert_mail = mbox:%h/mail
# Skip mailboxes which we can't open successfully instead of aborting.
#convert_skip_broken_mailboxes = no

# Trash plugin. When saving a message would make user go over quota, this
# plugin automatically deletes the oldest mails from configured mailboxes
# until the message can be saved within quota limits. The configuration file
# is a text file where each line is in format:
# Mails are first deleted in lowest -> highest priority number order
#trash = /etc/dovecot-trash.conf

# Lazy expunge plugin. Currently works only with maildirs. When a user
# expunges mails, the mails are moved to a mailbox in another namespace
# (1st). When a mailbox is deleted, the mailbox is moved to another namespace
# (2nd) as well. Also if the deleted mailbox had any expunged messages,
# they're moved to a 3rd namespace. The mails won't be counted in quota,
# and they're not deleted automatically (use a cronjob or something).
#lazy_expunge = .EXPUNGED/ .DELETED/ .DELETED/.EXPUNGED/
#!!! WO LIEGEN DIE FILTERREGELN DER USER???!!!
sieve = /home/vmail/%d/%u/.dovecot.sieve
}

So sieht (bei mir) das Defaultfilterfile aus:

nightshift:/home/vmail# cat globalsieverc
require "fileinto";
if header :comparator "i;ascii-casemap" :contains "Subject" "***SPAM***" {
fileinto "Junk";
stop;
}

So… und nun gehts an die dovecot-sql.conf

nightshift:/etc/dovecot# cat dovecot-sql.conf
# This file is opened as root, so it should be owned by root and mode 0600.
#
# http://wiki.dovecot.org/AuthDatabase/SQL
#
# For the sql passdb module, you'll need a database with a table that
# contains fields for at least the userid and password. If you want to
# use the user@domain syntax, you might want to have a separate domain
# field as well.
#
# If your users all have the same uig/gid, and have predictable home
# directories, you can use the static userdb module to generate the home
# dir based on the userid and domain. In this case, you won't need fields
# for home, uid, or gid in the database.
#
# If you prefer to use the sql userdb module, you'll want to add fields
# for home, uid, and gid. Here is an example table:
#
# CREATE TABLE users (
# userid VARCHAR(128) NOT NULL,
# password VARCHAR(64) NOT NULL,
# home VARCHAR(255) NOT NULL,
# uid INTEGER NOT NULL,
# gid INTEGER NOT NULL,
# active CHAR(1) DEFAULT 'Y' NOT NULL
# );

# Database driver: mysql, pgsql, sqlite
driver = mysql

# Database connection string. This is driver-specific setting.
#
# pgsql:
# For available options, see the PostgreSQL documention for the
# PQconnectdb function of libpq.
#
# mysql:
# Basic options emulate PostgreSQL option names:
# host, port, user, password, dbname
#
# But also adds some new settings:
# client_flags - See MySQL manual
# ssl_ca, ssl_ca_path - Set either one or both to enable SSL
# ssl_cert, ssl_key - For sending client-side certificates to server
# ssl_cipher - Set minimum allowed cipher security (default: HIGH)
#
# You can connect to UNIX sockets by using host: host=/var/run/mysqld/mysqld.sock
# Note that currently you can't use spaces in parameters.
#
# sqlite:
# The path to the database file.
#
# Examples:
# connect = host=192.168.1.1 dbname=users
# connect = host=sql.example.com dbname=virtual user=virtual password=blarg
# connect = /etc/dovecot/authdb.sqlite
#
#!!!!ANPASSEN!!!
connect = host=127.0.0.1 dbname= user= password=

# Default password scheme.
#
# List of supported schemes is in
# http://wiki.dovecot.org/Authentication/PasswordSchemes
#
default_pass_scheme = CRYPT

# Query to retrieve the password.
#
# This query must return only one row with "user" and "password" columns.
# The query can also return other fields which have a special meaning, see
# http://wiki.dovecot.org/PasswordDatabase/ExtraFields
#
# The "user" column is needed to make sure the username gets used with exactly
# the same casing as it's in the database. Note that if you store username and
# domain in separate fields, you most likely want to return a combination of
# them as the "user" column, otherwise the domain gets stripped.
#
# Commonly used available substitutions (see
# http://wiki.dovecot.org/Variables for full list):
# %u = entire userid
# %n = user part of user@domain
# %d = domain part of user@domain
#
# Note that these can be used only as input to SQL query. If the query outputs
# any of these substitutions, they're not touched. Otherwise it would be
# difficult to have eg. usernames containing '%' characters.
#
# Example:
# password_query = SELECT concat(userid, '@', domain) AS user, password FROM users WHERE userid = '%n' AND domain = '%d'
# password_query = SELECT pw AS password FROM users WHERE userid = '%u' AND active = 'Y'
#
password_query = SELECT password FROM mailbox WHERE username = '%u'

# Query to retrieve the user information.
#
# The query must return only one row. Commonly returned columns are:
# uid - System UID
# gid - System GID
# home - Home directory
# mail - Mail location
#
# Either home or mail is required. uid and gid are required. If more than one
# row is returned or there are missing fields, the login will fail. For a list
# of all fields that can be returned, see
# http://wiki.dovecot.org/UserDatabase/ExtraFields
#
# Examples
# user_query = SELECT home, uid, gid FROM users WHERE userid = '%n' AND domain = '%d'
# user_query = SELECT dir AS home, user AS uid, group AS gid FROM users where userid = '%u'
# user_query = SELECT home, 501 AS uid, 501 AS gid FROM users WHERE userid = '%u'
#
#!!! UID und GID ANPASSEN!!!
user_query = SELECT maildir, 5000 AS uid, 5000 AS gid FROM mailbox WHERE username = '%u'

# If you wish to avoid two SQL lookups (passdb + userdb), you can use
# userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll
# also have to return userdb fields in password_query prefixed with "userdb_"
# string. For example:
#password_query = SELECT userid as user, password, home as userdb_home, uid as userdb_uid, gid as userdb_gid FROM users WHERE userid = '%u'
#

Im Anschluss müssen die bestehenden Mailboxen migriert werden. Das wird hier sehr schön beschrieben. Nachdem man das script courier-dovecot-migrate.pl hat laufen lassen ist man hier auch schon fertig.

In der master.cf des Postfix muss man nun kund tun, dass man die Mails gerne über den lda von dovecot zustellen möchte. Und das geht durch Hinzufügen folgender Zeilen:
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}

In der main.cf habe ich folgende Zeilen angepasst:

smtpd_sasl_type=dovecot

virtual_transport = dovecot

dovecot_destination_recipient_limit=1

In der config.php des postfixadmins sollte sichergestellt sein, dass folgendes stimmt:


// Encrypt
// In what way do you want the passwords to be crypted?
// md5crypt = internal postfix admin md5
// system = whatever you have set as your PHP system default
// cleartext = clear text passwords (ouch!)
$CONF['encrypt'] = 'md5crypt';

So, und da wir (und unsere user) die Filter auch schön pflegen können, brauchen wir den pysieved. Auch gibt es ein paar Anpassungen zu tätigen:

nightshift:/usr/local/lib/pysieved# cat /usr/local/etc/pysieved.ini
[main]
# Authentication back-end to use
auth = Dovecot

# User DB back-end to use
userdb = Virtual

# Storage back-end to use
storage = Dovecot

# Bind to what address? (Ignored with --stdin)
#bindaddr = 127.0.0.1

# Listen on what port? (Ignored with --stdin)
port = 2000

# Write a pidfile here
pidfile = /tmp/pysieved.pid

[SASL]
# How do we identify ourself to saslauthd?
service = managesieve

# Where's the magic mux file?
#mux = /var/run/dovecot/auth-master

[PAM]
# How do we identify ourself to PAM?
service = pysieved

[Virtual]
# Append username to this for home directories
base = /home/vmail

# What UID and GID should own all files? -1 to not bother
uid = 5000
gid = 5000

# Switch user@host.name to host.name/user?
hostdirs = True

[Dovecot]
# Path to Dovecot's auth socket (do not set unless you're using Dovecot auth)
mux = /var/spool/postfix/private/auth

# Path to Dovecot's master socket (if using Dovecot userdb lookup)
master = /var/run/dovecot/auth-master

# Path to sievec
sievec = /usr/lib/dovecot/sievec

# Where in user directory to store scripts
scripts = .pysieved

# What user/group owns the mail storage (-1 to never setuid/setgid)
uid = -1
gid = -1

Und damit das auch mit meinem setup (maildirformat: /home/vmail//@) tut habe ich folgende Datei editiert:

nightshift:/usr/local/lib/pysieved/plugins# cat virtual.py
#! /usr/bin/python

import __init__
import os

class new(__init__.new):
def init(self, config):
self.uid = config.getint('Virtual', 'uid', None)
self.gid = config.getint('Virtual', 'gid', None)
self.base = config.get('Virtual', 'base', None)
self.hostdirs = config.getboolean('Virtual', 'hostdirs', False)
assert (self.uid and self.gid and self.base)

def lookup(self, params):
username = params['username']
adress = params['username']
if self.hostdirs:
parts = username.split('@', 1)
username = os.path.join(parts[1], parts[0])
domain = parts[1]
if self.gid >= 0:
os.setgid(self.gid)
if self.uid >= 0:
os.setuid(self.uid)
return os.path.join(self.base, domain, adress)

Jetzt sollte pysiebed auch starten.

nightshift:/usr/local/lib/pysieved# python pysieved.py

Um für die Regelverwaltung noch ein schönes UI zu haben, bietet dich das Squirrelmail plugin avelsieve an. Hier habe ich nicht mehr gemacht, als es nach Doku zu installieren.

So, und wenn alles geklappt hat, dann sollte euer postfix und dovecot völlig lässig hochfahren und alles im Lack sein.

VIEL GLÜCK!!! (grin3)

Anregungen, Verbesserungen bitte über die Kommentarfunktion.