Alte Dovecot Konfiguration zu Dovecot 2.4 (Debian Trixie) migrieren

Seit einigen Wochen ist die neue Debian-Version “Trixie” zum Upgrade von Debian “Bookworm” erhältlich - und damit haben sich auch einige meiner Leser zu einer Aktualisierung ihres Mailserver-Setups aus meiner “Mailserver mit Dovecot, Postfix, MySQL und Rspamd unter Debian 10 Buster [v1.0]” Mailserveranleitung entschieden. Das für Debian Buster beschriebene Setup funktioniere nämlich genauso gut auch für Debian Bookworm - aber mit Debian Trixie kommt der Bruch:

Die neueste Debian Version macht bei der mitgelieferte Dovecot-Version einen Sprung auf Dovecot 2.4. Damit sind alte Dovecot-Konfigurationen nicht mehr kompatibel!

Die Konfigurations-Syntax hat sich an einigen Punkten stark geändert und alte Konfigurationen aus vorherigen Dovecot-Versionen können nicht mehr eingelesen werden. Dieser Beitrag geht auf die Änderungen in der neuen Version 2.4 ein und erklärt die Migration anhand des Beispiels der oben erwähnten Mailserveranleitung. Alle Änderungen spielen sich in der Datei /etc/dovecot/dovecot.conf ab. Weitere Änderungen (z.B. an Datenbankschema o.Ä.) sind nicht notwendig.

Eine vollständige Konfigurationsdatei findet ihr am Ende dieses Beitrags.

Insgesamt hat sich verändert:

  • Die Art und Weise, wie Konfigurationsparameter geschachtelt werden können
  • Namen einzelner Parameter
  • Variablennamen und -Funktionen

Alle Änderungen sind in der Dovecot-Dokumentation beschrieben. Wer beim Setup seines Mailservers meiner Anleitung gefolgt ist, kann jedoch einfach weiterlesen und die beschriebenen Schritte ausführen, um zu einer funktionierenden Konfiguration zu kommen.

Schritt 1: Config-Versionsnummern hinzufügen

Dovecot 2.4 führt eine Versionierung der Konfigurationssyntax ein. Deshalb müssen am Anfang der Datei folgende Zeilen unbedingt eingefügt werden:

# Dovecot config and storage versions
dovecot_config_version = 2.4.0
dovecot_storage_version = 2.4.0

Das Versäumnis aus der Vergangenheit scheint man nun nachgeholt zu haben ;-). Zukünftige Änderungen an der Syntax können dann von Dovecot selbst abgefangen werden bzw. bei Änderungen gewarnt werden.

SSL-Einstellungen

Die SSL-Einstellungen werden wie folgt umbenannt bzw. verändert:

  • ssl_cert => ssl_server_cert_file (und spitze Klammer zu Beginn weglassen)
  • ssl_key => ssl_server_key_file (und spitze Klammer zu Beginn weglassen)
  • ssl_dh => ssl_server_dh_file (und spitze Klammer zu Beginn weglassen)
  • ssl_prefer_server_ciphers => ssl_server_prefer_ciphers. Werte nicht “yes” oder “no”, sondern “client” oder “server”. Default: Client. Einstellung kann entfernt werden.
  • ssl_min_protocol: kann weggelassen werden, default ist bereits TLSv1.2
  • disable_plaintext_auth=yes => auth_allow_cleartext=no. Ist default - kann weggelassen werden.

Insgesamt ergibt sich also:

ssl = required
ssl_server_cert_file = /etc/acme.sh/mydomain.tld/fullchain.pem
ssl_server_key_file = /etc/acme.sh/mydomain.tld/privkey.pem
ssl_server_dh_file = /etc/dovecot/dh4096.pem
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384

PassDB / UserDB und auth_username_format

Die beiden PassDB und UserDB Abschnitte werden zu:

passdb sql {
    query = SELECT username AS user, domain, password FROM accounts WHERE username = '%{user | username | lower }' AND domain = '%{user | domain | lower}' and enabled = true;
}

userdb sql {
    query = SELECT concat(quota, 'M') AS quota_storage_size FROM accounts WHERE username = '%{user | username | lower }' AND domain = '%{user | domain | lower}' AND sendonly = false;
    iterate_query = SELECT username, domain FROM accounts where sendonly = false;
}

Achtet speziell auf die angepassten Variablen, z.B. %{user | username | lower }. Hinter dem concat(quota, 'M') AS quota_storage_size versteckt sich außerdem ein kleiner Bugfix, den ich hier direkt einbringen will. ;-)

Außerdem wird die Variable auch bei auth_username_format angepasst:

auth_mechanisms = plain login
auth_username_format = %{user | lower }

Damit die gerade definierten UserDB und PassDB Abschnitte überhaupt funktionieren, werden die Zugangsdaten zur MySQL-Datenbank in einem neuen SQL-Abschnitt definiert:

sql_driver = mysql
mysql /var/run/mysqld/mysqld.sock {
  user = vmail
  password = mypassword
  dbname = vmail
}

mypassword muss selbstverständlich angepasst werden!

Die Datei /etc/dovecot/dovecot-sql.conf kann vollständig gelöscht werden - sie wird nicht mehr benötigt.

Mail location

Die Definition des Mailspeicherorts mail_location wird in mehrere Parameter aufgeteilt und hierdurch ersetzt:

mail_driver = maildir
mail_path = ~/mail
mailbox_list_layout = fs

Außerdem bekommt der mail_home Parameter neue Variablennamen:

mail_home = /var/vmail/mailboxes/%{user | domain }/%{user | username }

Protocols

Die protocols Einstellung und die beiden protocol imap und protocol lmtp Sections werden zu diesem Block:

protocols {
    lmtp = yes
    imap = yes
    sieve = yes
}

protocol imap {
    mail_plugins {
        imap_quota = yes
        imap_sieve = yes
    }
    mail_max_userip_connections = 50
    imap_idle_notify_interval = 29 mins
}

protocol lmtp {
    mail_plugins {
        sieve = yes
        notify = yes
        push_notification = yes
    }
    postmaster_address = postmaster@mydomain.tld
}

Plugins Section

Das plugins Segment

plugins {
    ...
}

gibt es nicht mehr. Stattdessen wird der Inhalt direkt global.

Sieve Plugineinstellungen

  • sieve_plugins, sieve_before und sieve werden zu:
sieve_plugins {
    sieve_imapsieve = yes
    sieve_extprograms = yes
}

sieve_script spam-global {
    type = before
    path = /var/vmail/sieve/global/spam-global.sieve
}

sieve_script personal {
    type = personal
    path = /var/vmail/sieve/%{user | domain }/%{user | username }/scripts
    active_path = /var/vmail/sieve/%{user | domain }/%{user | username }/active-script.sieve
}

Alle imapsieve* Parameter werden insgesamt zu:

# From Mailbox to Spam
mailbox Spam {
    sieve_script spam {
        type = before
        cause = copy
        path = /var/vmail/sieve/global/learn-spam.sieve
    }
}

# From Spam to another folder (learn HAM)
imapsieve_from Spam {
    sieve_script ham {
        type = before
        cause = copy
        path = /var/vmail/sieve/global/learn-ham.sieve
    }
}

sieve_global_extensions wird zu:

sieve_global_extensions {
    vnd.dovecot.pipe = yes
}

Quota

quota und quota_exceeded_message werden zu:

quota "User quota" {
    driver = count
}
quota_exceeded_message = Benutzer %{user} hat das Speichervolumen ueberschritten. / User %{user} has exhausted allowed storage space.

Der alte “fs” Treiber für Quota soll nicht mehr genutzt werden. Stattdessen wird nun count genutzt. quota_exceeded_message bekommt außerdem neue Variablennamen.

Im neuen mail_plugins Blog wird das Quota-Plugin aktiviert:

mail_plugins {
    quota = yes
}

Im vorher bereits erwähnten protocol imap Block wurde außerdem noch imap_quota aktiviert.

Vollständige Beispielkonfiguration

Für den einfacheren Vergleich hier nochmal die vollständige Datei /etc/dovecot/dovecot.conf:

# Dovecot config and storage versions
dovecot_config_version = 2.4.0
dovecot_storage_version = 2.4.0


###
### Protocol settings
#############################

protocols {
    lmtp = yes
    imap = yes
    sieve = yes
}


protocol imap {
    mail_plugins {
        imap_quota = yes
        imap_sieve = yes
    }
    mail_max_userip_connections = 50
    imap_idle_notify_interval = 29 mins
}

protocol lmtp {
    mail_plugins {
        sieve = yes
        notify = yes
        push_notification = yes
    }
    postmaster_address = postmaster@mydomain.tld
}


##
## TLS Config
## Quelle: https://ssl-config.mozilla.org/#server=dovecot&version=2.3.9&config=intermediate&openssl=1.1.1d&guideline=5.4
##

ssl = required
ssl_server_cert_file = /etc/acme.sh/mydomain.tld/fullchain.pem
ssl_server_key_file = /etc/acme.sh/mydomain.tld/privkey.pem
ssl_server_dh_file = /etc/dovecot/dh4096.pem
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384


###
### Dovecot services
################################

service imap-login {
    inet_listener imap {
        port = 143
    }
}


service managesieve-login {
    inet_listener sieve {
        port = 4190
    }
}

service lmtp {
    unix_listener /var/spool/postfix/private/dovecot-lmtp {
        mode = 0660
        group = postfix
        user = postfix
    }

    user = vmail
}


service auth {
    ### Auth socket für Postfix
    unix_listener /var/spool/postfix/private/auth {
        mode = 0660
        user = postfix
        group = postfix
    }

    ### Auth socket für LMTP-Dienst
    unix_listener auth-userdb {
        mode = 0660
        user = vmail
        group = vmail
    }
}


###
### SQL settings
###

sql_driver = mysql
mysql /var/run/mysqld/mysqld.sock {
  user = vmail
  password = mypassword 
  dbname = vmail
}

###
### Client authentication
#############################

auth_mechanisms = plain login
auth_username_format = %{user | lower }

passdb sql {
    query = SELECT username AS user, domain, password FROM accounts WHERE username = '%{user | username | lower }' AND domain = '%{user | domain | lower}' and enabled = true; 
} 

userdb sql {
    query = SELECT concat(quota, 'M') AS quota_storage_size FROM accounts WHERE username = '%{user | username | lower }' AND domain = '%{user | domain | lower}' AND sendonly = false;
    iterate_query = SELECT username, domain FROM accounts where sendonly = false; 
}


##
### Address tagging
###
recipient_delimiter = +

###
### Mail location
#######################

mail_uid = vmail
mail_gid = vmail
mail_privileged_group = vmail


mail_home = /var/vmail/mailboxes/%{user | domain }/%{user | username }
mail_driver = maildir
mail_path = ~/mail
mailbox_list_layout = fs


###
### Mailbox configuration
########################################

namespace inbox {
    inbox = yes

    mailbox Spam {
        auto = subscribe
        special_use = \Junk
    }

    mailbox Trash {
        auto = subscribe
        special_use = \Trash
    }

    mailbox Drafts {
        auto = subscribe
        special_use = \Drafts
    }

    mailbox Sent {
        auto = subscribe
        special_use = \Sent
    }
}



###
### Mail plugins
############################

mail_plugins {
    quota = yes
}


sieve_plugins {
    sieve_imapsieve = yes
    sieve_extprograms = yes
} 

sieve_script spam-global {
    type = before
    path = /var/vmail/sieve/global/spam-global.sieve
}

sieve_script personal {
    type = personal
    path = /var/vmail/sieve/%{user | domain }/%{user | username }/scripts
    active_path = /var/vmail/sieve/%{user | domain }/%{user | username }/active-script.sieve 
}


# From Mailbox to Spam
mailbox Spam {
    sieve_script spam {
        type = before
        cause = copy
        path = /var/vmail/sieve/global/learn-spam.sieve
    }
}

# From Spam to another folder (learn HAM)
imapsieve_from Spam {
    sieve_script ham {
        type = before
        cause = copy
        path = /var/vmail/sieve/global/learn-ham.sieve
    }
}



# Sieve extensions only allowed in global context
sieve_global_extensions {
    vnd.dovecot.pipe = yes
}
sieve_pipe_bin_dir = /usr/bin


###
### IMAP Quota
###########################

quota_exceeded_message = Benutzer %{user} hat das Speichervolumen ueberschritten. / User %{user} has exhausted allowed storage space.

quota "User quota" {
        driver = count
}