Dovecot 2.3.21 → 2.4.1への移行

先日Dovecot 2.4.1が出たので、Dovecot 2.3系から2.4.1を移行の検証?を渋々やりました。

Dovecot CE版のマニュアルは親切とは言い難く、どこをどう変えれば良いのかがわかりにくいです。私も結局はConfig変える度にservice dovecot restartで怒られたところをマニュアルやdovecotが配布しているsampleを見て直して修正するという、TAS作るようなやり方で移行しました。サンデーオペレータの私には割と苦痛な作業でした。

記事公開したのは、同じような環境で使っている方に、私が踏んだクソをもう一度回踏んでほしくは無いと思ったので私の例を紹介したいと思います。

環境

私の環境は下記のような感じです。

  • マシン: 38号機 (N100DC-ITX, DDR4 32GB, SATA SSDx2)
  • OS: FreeBSD 14.2-RELEASE-p2 (amd64)
  • コンパイラ: llvm19-19.1.7_1 (pkg版)
  • MTA: Postfix 3.9.1
  • MDA: Dovecot 2.3.21 → 2.4.1-4
  • DB/認証バックエンド: MySQL 8.0 / Cyrus SASL

MTAはPostfixでVirtual Domainを運用していて、バックエンドはMySQL (≠MariaDB)です。MTAもMDAもソースからのコンパイルです。

DovecotはMRA(Mail Retrieval Agent)としてのみ使っています。PostfixはSubmissionポートをListenしていますが、PostfixのSubmissionの認証バックエンドはCyrus SASL+MySQLで、Dovecotの認証機能は使っていません。そのためDovecotでSubmissionの認証をしている方は書き換えるべき設定がもっと増えると思います。

コンパイルオプション

コンパイルオプションは私の場合下記です。

zlib関係(ZLIB_CFLGS, ZLIB_LIBS)

前述のように私はバックエンドにMySQLを使っているので、--with-mysqlを入れています。

2.3.21の頃は--with-mysqlのみでconfigureが通ったのですがが、私の環境の2.4.1は後ろにZLIBのパラメータを入れないと下のような文句を言ってきて./configureが正しく終わらなかったため渋々入れました。

libbsd

--with-libbsd は証明書周りの挙動が不審(SNI別の設定を消すとSegmentation Faultする)だったので入れたらよくわかりませんがあ動くようになりました。まぁ現場猫クオリティで入れたので、もしかしたら--with-libbsd は付与しなくても大丈夫かもしれません。

configureが終わったらmake allでコンパイルします。

make install前にやること→旧バージョンのmake uninstall

コンパイルしたらインストール前に設定移行作業をすると思いますが、とりあえずここでは一旦これからインストールするという前提で話をすすめます。

このセクションは2.3系以前のDovecotが動いている方のみ該当します。

2.3系以前のDovecotが動いている場合、コンパイルが終了後、2.4系のインストール前にserviceコマンドでdovecotを停止し、今使っているバージョンのディレクトリでmake uninstallして既存のDovecotをアンインストールしてください。

私は雑にmake installで新バージョンを上書きしたのですが、下記のようなエラーログが出てIMAPSがまともに動きませんでした。

旧バージョンをmake uninstallしてから新バージョンを入れたら上記は出なくなったので2.3系以前のDovecotは一旦消すことをお勧めします。

make install後にやること→imap-hibernateのコピー

これはFreeBSDで、インストールは完了してて次はserviceコマンドでDovecot起動しようかなという状態での話です。

make installでインストールが終わったらcd src/imap-hibernateに移動して引数なしのmakeコマンドでimap-hibernateをコンパイルしてください。
コンパイルが通ったら出来上がったimap-hibernateをcp -pi でlibexec/dovecot(※)にコピーしてください。

※Dovecotは特にインストールディレクトリを指定しなければ/usr/localに入るので先述の「libexec/dovecot」は「/usr/local/libexec/dovecot」になるはずです。

この工程を省くと、dovecot起動時にimap-hibernateがねーぞ、ボケ、と怒られます。

これ、dovecotが上がらないので渋々入れたんですがなぜ起動時にimap-hibernateを求めるのかは謎です。そもそもIMAP Hibernate は 下図のようにFreeBSD(のようなkqueueベースのシステム)ではサポートしない。と明記されています。

Dovecotのマニュアルより引用
IMAP | Dovecot CE, https://doc.dovecot.org/2.4.0/core/config/imap.html , 2025.04.05閲覧

確かにimap-hibernateはFreeBSDではmake allではコンパイルされませんし、予めmakeでコンパイルしておいてもmake install時にインストールしてくれません。それなのに何故か起動時には存在していないとmasterプロセスが上がってこない不思議仕様なのでこのような対応を入れています。

正直意味不明なんですが、まぁDovecot CEにとってはFreeBSDはベストエフォート対応らしいので諦めです。

dovecot.conf

※新旧の設定は同一の筈です。

ここから先は設定関連です。私は2024年に25号機から38号機に移行した際にdovecotは25号機と2024年当時の最新のデフォルトの設定ファイルを比較して新しいファイルに設定を書き込んだので元設定はそんなに古くないと思います。

OX Dovecotでは「Example Configuration」で設定例を配布しているので、dovecot.confに限らず書き方に悩んだらこのファイルを参照すると良いと思います。まぁ後で出てくるんですがコメントが正しいとは限らないトラップがあったりしてそれでも面倒ですけどね。

ちなみにdovecot.confも含め、私が引っかかった部分しか書いていません。私より設定がもっと複雑な方はもっと書き換える部分が多いと思います。

設定ファイルのVersion定義

まずはdovecot.confです。以下、青緑が差分です。

2.3.x2.4.x
# --sysconfdir=/etc --localstatedir=/var
# Protocols we want to be serving.
# protocols = imap pop3 lmtp submission
protocols = imap


# --sysconfdir=/etc --localstatedir=/var
# Config header
dovecot_config_version = 2.4.0
dovecot_storage_version = 2.4.0

# Protocols we want to be serving.
# protocols = imap pop3 lmtp submission
protocols = imap

dovecot_config_versionとdovecot_storage_versionは2.4から新たに導入された設定値で、Dovecotの一連の設定はこの定義から始まらないと起動時に怒られます。設定ファイルの先頭にある必要まではありませんが、dovecotの設定はこの2つのパラメータから開始する必要があります。

私の場合2.3系の設定はprotocols = imapから始まっていたので、そこより上なら別にどこでもよかったのでテキトーにprotocls = imapの真上に入れました。

dictディレクティブ

2.3.x2.4.x
dict {
#quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
}
#dict {
#quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
#}

dictサービスは無くなったのですべてコメントアウトしました。

conf.d配下

次移行はconf.d配下です。conf.dは複数のファイルがありますが、ここで挙げてないファイルは私は/usr/local/etc/dovecot/conf.dに入れていません。

10-auth.conf

※新旧の設定は同一だと思います。

2.3.x2.4.x
# Disable LOGIN command and all other plaintext authentications unless
# SSL/TLS is used (LOGINDISABLED capability). Note that if the remote IP
# matches the local IP (ie. you're connecting from the same computer), the
# connection is considered secure and plaintext authentication is allowed.
# See also ssl=required setting.
# disable_plaintext_auth = yes
disable_plaintext_auth = no
# Disable LOGIN command and all other plaintext authentications unless
# SSL/TLS is used (LOGINDISABLED capability). Note that if the remote IP
# matches the local IP (ie. you're connecting from the same computer), the
# connection is considered secure and plaintext authentication is allowed.
# See also ssl=required setting.
# disable_plaintext_auth = yes
auth_allow_cleartext = yes

disable_plaintext_authは設定名が変わりました。設定名だけでなく設定の意味も変更され、2.3系以前は「無効をNo」でプレーンテキスト認証が有効でしたが、2.4系は「許容をYes」でプレーンテキスト認証が有効となりますので上記は設定としては同一です。

私はインターネット向けはIMAP over TLSしかLISTENしておらず、プレーンテキスト以外の認証は設定が面倒臭いのでプレーンテキストOKにしています。

10-logging.conf

※新旧の設定は同一ではない可能性があります。

2.3.x2.4.x
# mail_log plugin provides more event logging for mail processes.
plugin {
# Events to log. Also available: flag_change append
#mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
# Available fields: uid, box, msgid, from, subject, size, vsize, flags
# size and vsize are available only for expunge and copy events.
#mail_log_fields = uid box msgid size
}
# mail_log plugin provides more event logging for mail processes.
mail_plugins {
# Events to log. Also available: flag_change append
#mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
# Available fields: uid, box, msgid, from, subject, size, vsize, flags
# size and vsize are available only for expunge and copy events.
#mail_log_fields = uid box msgid size
}

pluginブロックの設定名が変更になりました。私はプラグインは特に使っておらず、こう変えたら動いたという感じなので設定としては新旧同一ではない可能性があります。

その他ログ関係

実運用の設定は上記のみなんですが、検証やトラブルシュート等でログを詳細(verbose)にしたい場合、下記のようにVerboseの指定方法が変更になっています。2.3系以前のno相当の設定はなさそうで、無効化する場合はコメントアウトです。(まぁ2.3.xもnoを入れずにコメントアウトで無効化していましたけど)

2.3.x2.4.x
auth_verbose = yes
auth_debug = yes
mail_debug = yes
verbose_ssl =
yes
log_debug=category=auth
log_debug=category=mail

log_debug=category=ssl

ログ系の細かい内容はマニュアルのLogging Verbosityのところにあります。

10-mail.conf

※新旧の設定はたぶん同等です。

Virtual DomainでMaildirを利用している場合の設定になります。

2.3.x2.4.x

# mail_location =
mail_location = maildir:/path/to/vmailbox/%d/%n

# mail_location =
# mail_location = maildir:/path/to/vmailbox/%d/%n
mail_driver = maildir
mail_path = /path/to/vmailbox/%{user | domain }/%{user | username }

mail_locationはなくなり、mail_driver / mail_path / mail_inbox_pathの3つに分割されました。また、プレースホルダ(%dとか%n)も変更になりました。

設定としてはmail_driverでMaildirの使用を明示したのち、mail_locationと同等の設定をmail_pathに書きます。

マニュアルには.INBOXを指定するmail_inbox_pathの例がありますが、mail_inbox_pathは省略するとmail_pathと同一になります。私はmail_inbox_pathは省略しています。

こうしている理由ですが、2.3系のmail_locationは、ここで指定されたパスを.INBOXとみなして、.INBOXに格納されるべきcurやnewをmail_locationで指定したディレクトリに散らかす構造になっています。本当は.INBOXは.INBOXディレクトリに入れたいのですが、mail_inbox_pathを明示すると今までmail_locationに散らかされた内容が見えなくなると怖いのでこのようにしました。

プレースホルダの末尾のスペースはマニュアルにそう書かれているのでコピペしました。

「/path/to/vmailbox」の部分はVitual Domainのメールボックスのルートとなるディレクトリで、MTAがPostfixの場合、virtual_mailbox_baseの設定と一致させる必要があります。

面倒なので検証していませんが、マニュアルによると(非Virtual Domainのように)どうもhomeディレクトリ配下にMaildirを設ける場合は下記のような書き方が必要っぽいです。

    home=/path/to/user/home/
mail_path=/path/to/user/home/Maildir/

10-ssl.conf

※新旧の設定は同一ではないかもしれませんが同等の筈です。
※SNI明示(local_name)のSSL証明書設定はFreeBSDのバイナリpkg版のcertbotで取得したLet’s Encryptの例です。ただしドメインは架空です。

2.3.x2.4.x

ssl_cert = </etc/ssl/certs/dovecot.pem
ssl_key = </etc/ssl/private/dovecot.pem
ssl_dh = </usr/local/etc/dovecot/dh.pem
local_name mail.yuaiho.net {

ssl_cert = </usr/local/etc/letsencrypt/live/mail.yuaiho.net/fullchain.pem
ssl_key = </usr/local/etc/letsencrypt/live/mail.yuaiho.net/privkey.pem
}

ssl_server_cert_file = /etc/ssl/certs/dovecot.pem
ssl_server_key_file = /etc/ssl/private/dovecot.pem
ssl_server_dh_file = /usr/local/etc/dovecot/dh.pem
local_name mail.yuaiho.net {
protocol imap {
ssl_server_cert_file = /usr/local/etc/letsencrypt/live/mail.yuaiho.net/fullchain.pem
ssl_server_key_file = /usr/local/etc/letsencrypt/live/mail.yuaiho.net/privkey.pem
}
}

SSL証明書、鍵、DHパラメータの名前・指定方法が変わりました。名前だけでなく値の書き方も変更されて、内容もパスの指定のみでよくなりました。旧の方は「</path/to/ssl.pem」で中身を食わせていますが、新はパスのみの指定になっています。

ちなみに、食わせるという書き方自体は2.4系でも有効っぽいので単に%s/ssl_/ssl_server_/で置換するとリロード時に食うは食いますが、2.4系のssl_server_*_fileはファイルパスを文字列で設定する値であって、pemファイルの中身を食わせる設定ではありません。そのため雑に設定名だけ変えて不等号マークを残したままdovecotリスタートするとdovecotがバグります。というか、バグらせました。

あと、クライアントが送信するSNI(Server Name Indication)毎に、サーバが送信するサーバ証明書を変更する設定はlocal_nameのままです。ただ、直下にSSL証明書関係のファイルパスを直接指定することは出来ず、プロトコル指定が必要になったようです。直接書くとdovecotの起動時にCoreを吐いてSegmentation Faultで落ちます。

私の環境ではSegmentation Fault出たら真っ先に疑うのがこの部分です。

10-master.conf

このファイルは2.3時代には設置しておらず、2.4でチューニングが必要なことがわかったため、新規で「Example Configuration」から丸コピして(渋々)作りました。変更箇所は下記です。

service imap-login {
inet_listener imap {
#port = 143
}
inet_listener imaps {
#port = 993
#ssl = yes
}

# Number of connections to handle before starting a new process. Typically
# the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0
# is faster. <doc/wiki/LoginProcess.txt>
#service_restart_request_count = 1
service_restart_request_count = unlimited

# Number of processes to always keep waiting for more connections.
#process_min_avail = 0

# If you set service_restart_request_count=0, you probably need to grow this.
#vsz_limit = 256M # default
}

service_restart_request_countの設定を1から変更しています。それ以外はサンプルのままです。

1がどうもデフォルト値っぽくて最高のセキュリティらしいので1にしたいところですが、1のまんまだとdovecotのログに「anvil: Warning: conn unix:anvil (uid=0): Handshake with duplicate service=imap-login pid=-1 – replacing the old connection」が結構な量記録されて鬱陶しいです。

マニュアルには100や1000が良いだろうみたいなことが書かれています。確かに100にすると上記のログは減るは減るのですが、私一人しか使っていないような環境でも抑制しきれていないので渋々unlimitedにしました。

ちなみに、「Typically the only useful values are 0 (unlimited) or 1.」と書かれていますが、1は指定できても0は指定できません。0を指定すると下記のように起動時に0を超えた値にしろボケ、と怒られます。ただ、0と同じ意味らしいunlimitedは指定できます。

Starting dovecot ...
doveconf: Fatal: Error in configuration file /usr/local/etc/dovecot/dovecot.conf: service(imap-login): restart_request_count must be higher than 0 (did you mean "unlimited"?)

15-mailboxes.conf

このファイルは2.3のデフォルトのままなんです。特に変更しなくても動いています。

auth-sql.conf.ext/dovecot-sql.conf.ext

※同等だと思うけどdovecot-sql.conf.extの設定の一部は移植しておらず。

2.3.x2.4.x
passdb {
driver = sql
# Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
#args = /etc/dovecot/dovecot-sql.conf.ext
args = /usr/local/etc/dovecot/dovecot-sql.conf.ext
}


userdb {
driver = sql
#args = /etc/dovecot/dovecot-sql.conf.ext
args = /usr/local/etc/dovecot/dovecot-sql.conf.ext
}

mysql 127.0.0.1 {
user = DBのユーザ名
password = DBのパスワード
dbname = DB名
}


sql_driver = mysql


passdb sql {
#driver = sql
# Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
#args = /etc/dovecot/dovecot-sql.conf.ext
query = dovecot-sql.conf.extのpassword_queryの値を入れる。
}


userdb sql {
#driver = sql
#args = /etc/dovecot/dovecot-sql.conf.ext

#args = /usr/local/etc/dovecot/dovecot-sql.conf.ext
query = dovecot-sql.conf.extのuser_queryの値を入れる。
}

このファイルですが、SQLの設定の外出しができなくなり直書きが必要になりました。そのため「dovecot-sql.conf.ext」は不要になった・・・と思います。

mysqlディレクティブ

2.3系以前ではSQLの設定はdovecot-sql.conf.extとかいうファイルを作って、そこにconnect = host=/tmp/mysql.sock dbname=DB名とかでSQLの設定を書き、auth-sql.conf.ext側ではargsでdovecot-sql.conf.extのファイルパスを指定すればよかったのですが、この方法はNGになったっぽいです。

そのため2.4系でMySQLバックエンドを使用するには本ファイルのmysql <接続先>ディレクティブでDBの接続先定義と、sql_driverでSQLエンジンを選択します。代わりに、passdb/userdbからはdriverを消します。ただ、passdb/userdbからdriverは消さなくても文句は言ってこないです。

127.0.0.1はドメインソケット接続ではなくTCPで接続している可能性があります。が、これは個人的にはどっちでもいいので未検証です。

passdb/userdb

passdbとuserdbは名前を定義する必要があります。この部分の名前はテキトーではダメらしく、SQLの場合は「sql」で固定なようです。mainとかhogeとかのテキトーな名前だと、dovecot起動時に「中にqueryとか意味わからん設定があるんだけど?」と怒られます。passdbやuserdbが複数ある場合はsqlN(Nは数字)が許容されるっぽいです(未検証)。

argsは無くなりました。代わりにqueryにSQLを直書きします。

queryに書くSQLはargsで指定していたファイル(dovecot-sql.conf.ext)をプレースホルダだけ気をつけてそれ以外はそのまま移植すれば大丈夫です。移植元はuserdbディレクティブのqueryは「user_query」の設定値を、passdbディレクティブの場合は「password_query」の設定値を移植します。

これ、dovecot-sql.conf.extにあった「iterate_query」をどこにも移植していない気がしなくも無いんですが、とりあえず動いているっぽいので今回は見なかったことにします。

前述の通り、driver = sqlは消しても消さなくても動きます。謎です。

所感

2.4系への移行は、DovecotからのアナウンスではMigration Guideを見て注意深くやれ(Please carefully review before https://doc.dovecot.org/main/installation/upgrade/2.3-to-2.4.html installing new packages.)のようなことが書かれていますが、まともに検証しないで導入するいい加減なサンデーオペレーターの私の環境ですら上記の如くトラップだらけです。

そのためガイドを熟読するよりも、通り一遍見て、service dovecot startで文句言ってきたところを一つづつ潰していくのが実務としては効率的ではないかなと思います。まぁ、要するにゴリ押しなんですが、そう言っても2.4系は設定によっては起動時にログを出すこともなくSegmentation Faildで簡単に死んじゃうので、この戦法も確実では無いのが非常に面倒なところです。

まぁCoreダンプ読める人なら関係ないんでしょうけど私には無理です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


This site uses Akismet to reduce spam. Learn how your comment data is processed.