さぁ超久しぶりの更新だ。

もう終焉が近いCentOS8でvsftpdを複数立ち上げる必要が出てきたのでその時にハマった事とそれの解決策を論じてみる。
「えーそんなにFTPサーバー複数立ち上げるか?」と思うかも知れないが実は結構需要がある。主な目的としてはFTPSのexplicit(21番ポート)とimplicit(990番ポート)を同時に立ち上げるだとか、chrootしないOSユーザー用のFTPとchrootしてなおかつ仮想ユーザーで運用するFTPなどを分ける(前者の方はSFTPにして欲しいところだが)などだ。implicit FTPSは正式のRFCからは外れたという事だが、実装としては存在するのでお客様の要件として対応する事があるのだ。
なお、ここではCentOS8のvsftpdにおいて複数の設定ファイルでそれぞれ独立したデーモンを制御する事に対してのみ論じ、個々の設定ファイルでImplicit FTPSを有効にするだとか、仮想ユーザーでvsftpdを運用するだとかの話は扱わない。

さて、CentOS8は各種デーモンの起動にsystemdという仕組みを利用している。vsftpdもsystemdで制御する事になる。

# systemctl enable vsftpd.service

で起動すると、/etc/vsftpd/vsftpd.confという設定ファイルを使うデーモンが立ち上がる。今回はこれをexplicitとし、implicit FTPS用に/etc/vsftpd/implicit.confという設定ファイルを用意する。
implicit.confを用いてデーモンを立ち上げるには、

# systemctl enable vsftpd.target
# systemctl enable vsftpd@implicit

という風にする。そうすると、/etc/systemd/system/multi-user.target.wantsの中にvsftpd.target、そして/etc/systemd/system/vsftpd.target.wantsの中にvsftpd@implicit.serviceというファイル(正確にはシンボリックリンク)が作成される。これで、2つのvsftpdが別々のポートで起動する、のだが、実際に開始してみると存在しないはずのvsftpd@vsftpd.serviceなるものが起動しており、なおかつさらに別の設定ファイルである/etc/vsftpd/others.confを置いておくと、/etc/systemd/system/vsftpd.target.wants内にvsftpd@others.serviceが無くても(つまり

# systemctl enable vsftpd@others

をしなくても)

# systemctl start vsftpd.target

をするとなぜかothers.confのvsftpdも立ち上がってしまう。設定ファイルは置いておきたいが、起動するサービスは制御したいというのができない。

正確に動きを追ったわけではないのだが、どうも/usr/lib/systemd/system-generators/vsftpd-generatorなるスクリプトファイルが悪さをしているようだ。これはおそらくsystemdから呼び出され、中身が/etc/vsftpd内にある*.confから/etc/systemd/system/vsftpd.target.wantsを勝手に作ってしまうものになっており、デフォルト設定ファイルであるvsftpd.confも検知しているのでvsftpd@vsftpd.serviceが作られるようだ。なのでこれが呼ばれないように

# cd /usr/lib/systemd/system-generators
# chmod -x vsftpd-generator

すると意図した動きになった。vsftpd@vsftpd.serviceという存在しないサービスが勝手に立ち上がってなおかつ起動に失敗するのは、前述のとおりvsftpd-generatorが/etc/vsftpd/vsftpd.confも検知して起動し、それがデフォルトのvsftpd.serviceとバッティングする事が原因なので/etc/vsftpd/*.confは全部立ち上がって良い場合はデフォルトのvsftpd.serviceを無効にするだけで良い。

# systemctl disable vsftpd.service
# systemctl enable vsftpd.target

これだけで/etc/vsftpd/vsftpd.confも含めた/etc/vsftpd/*.confが全てvsftpd.targetの有効化により全て有効になるようになる。ベストプラクティスとしては多分これで、起動したくない設定ファイルは/etc/vsftpd/others.conf.backなどと拡張子がconfにならないようにして、デフォルトのvsftpd.serviceは停止し、vsftpd.targetを開始して自動で複数の設定ファイルで別々にデーモンが起動するようにするのが良いと思われる。ただ、この方法を使うと設定ファイルのファイル名を調整した後に

# systemctl restart vsftpd.target

するだけではだめで、OSの再起動を行う必要がある。/usr/lib/systemd/system-generators/vsftpd-generatorが呼ばれるタイミングの問題だと思うのだが、この令和の時代にカーネルの更新以外でOSを再起動するなんてナンセンスな気もするので、それならやはりこのファイルの実行属性を消して全て個別に

# systemctl enable vsftpd@implicit.service

などとすべきかもしれない。