Debian Mailman 2から3へのアップグレード フロントエンド編

Mailman 3は管理用ウェブフロントエンドにPostoriusというPython3とDjangoで稼働するサービスを利用している。Djangoのフレームワークが会員登録やログイン認証などの必要なインターフェースを提供してくれているわけだ。今時のユーザー登録をするとメールでアクティベーションURLが送られてくるというシステムなので、まずはPostoriusからメールが正しく送れることを確認しておく必要がある。

実は、この作業、一度でもMailman Coreからメールを送っておかないとメールの送信に必要なフォルダやデータベースが作成されないので、メーリングリストの移行とテスト送信を済ませてからでないとできないのだ。

実際にメールが送れるかどうかのテストは以下の通り。

/usr/share/mailman3-web/manage.py sendtestemail MYADDRESS@MYDOMAIN.COM

これでPostriusからのメールが受信できれば問題ない。

次にサイト全体を管理する権限を持つスーパーユーザーを作成する。

/usr/share/mailman3-web/manage.py createsuperuser

対話的なインターフェースでスーパーユーザーのユーザー名、メールアドレス、パスワードを設定する。ここまでで準備は完了。ここからはブラウザを使って設定を続行する。

まずはPostoriusにブラウザでアクセスする。

http://FQDN.COM/mailman3/

作成したスーパーユーザーのアカウントでログインすると設定したメールアドレスにアクティベーションするためのメールが送られてくるので指示に従ってアクティベーションすると晴れてスーパーユーザーが有効になってメーリングリストの設定等を変更できるようになる。

ここまででメーリングリスト運用に必要なすべての準備が整ってはいるのだが、最後にお化粧をする必要がある。というのも、Postriusのデフォルトのドメイン名がexample.comになっているので、格好悪いからだ。

Postriusにスーパーユーザーでログインした状態でツールバーのDomainsを選び、説明内のリンクからドメインを追加登録する。するとドメインがexample.comと新しく登録したドメインから選べるようになるので、新しく登録した正しいドメインを選ぶ。

ここで、元のexample.comを削除すればいいように思えるが、実はそれが大きな罠である。というのも、ここに登録されたドメインには順番にSITE_IDという内部識別IDが割り振られており、しかもmailman3-webは設定の中でSITE_ID = 1を絶対に利用するようにハードコードされており、このSITE_ID = 1がexample.comなのだ。というわけで、これをオーバーライドしておかないとexample.comを削除したとたんに、Postriusが動作不能になってしまうのだ。

というわけで、/etc/mailman3/mailman-web.pyに以下の記述を足して設定をオーバーライドしておく。

SITE_ID = 2

追加したドメインは自動的にSITE_ID = 2になっているはずなので、これでexample.comでなく新しいドメインが削除できない必須ドメインになった。

この状態でもう一度ドメイン一覧に戻り、example.comを削除すればよい。

以上でMailman 2から3へのアップグレード作業は全終了である。

Debian Mailman 2から3へのアップグレード リスト移行編

さて、基本的な設定が完了したら実際にMailman 2で利用していたメーリングリストを3にインポートする作業を行う。

ここからの作業もroot権限で行う必要があるためにsudo bashでrootのシェルを立ち上げて作業する。

まずは移行するメーリングリストをMailman 3に作成する。Mailman 3ではメーリングリスト名は投稿するアドレスそのものなのでFQDNまで含めて指定する必要があることに注意。

mailman create LISTNAME@FQDN.COM

次にMailman 2のメーリングリストの設定をインポートする。

mailman import21 LISTNAME@FQDN.COM /var/lib/mailman/lists/LISTNAME/config.pck

その後、Mailman 2のメーリングリストのアーカイブをインポートする。mailman3-webのDjangoプロジェクトのディレクトリに移動する。

cd /usr/share/mailman3-web

Python2と3の混在環境ではPython3を明示して実行する必要があるので以下のコマンドでインポート作業を実行する。

python3 manage.py hyperkitty_import -l LISTNAME@FQDN.COM /var/lib/mailman/archives/private/LISTNAME.mbox/LISTNAME.mbox

多少のエラーは出るかもしれないが気にしない。インポートが完了したらインデックスを作成する。

python3 manage.py update_index_one_list LISTNAME@FQDN.COM

最後にダイジェストを保管するディレクトリの所有者がrootで作成されてしまっているので所有者をMailman 3のユーザーIDであるlistに変更する。ディレクトリ名がLISTNAMEとFQDNの間を@ではなく.でつないでいることに注意。

chown list:list /var/lib/mailman3/lists/ LISTNAME.FQDN.COM

以上で移行作業は完了。この時点で正しく配送されているかどうかを実際にメーリングリストにメールを投げてみて確認しよう。うまくいけばMailman Coreは問題なく動いている。あとは管理フロントエンドの設定を残すのみ。

Debian Mailman 2から3へのアップグレード インストール編

さて、問題はMailman 2から3へのアップグレードだ。Mailman 2と3は根本的に設計が異なるので、そのまますんなりパッケージをインストールするだけでアップグレードしてくれたりはしない。どころか、GNU本家であるDebianのパッケージですらインストールしただけではまともに動かないという体たらく。しかし、これを突破しないとBullseyeへのアップグレードはできないので、頑張ることにする。

さて、最初に移行作業中にMailman 2が働かないようにMailman 2のサービスを停止しよう。

sudo service mailman stop

Mailman 3のパッケージはさすがにMailman 2と共存できるようには配慮されているので、このままMailman 3をインストールする。

sudo apt install mailman3-full

インストール中にmailman3とmailman3-webのデータベースを自動作成するかどうか聞いてくるので<Yes>と答え、データベースの種類はsqlite3を選択する。このサーバーではMariaDBが稼働しているのでMySQLでもいけそうな気がするが、実際にやってみると設定に失敗して壊れたパッケージインストール状態になるので、おとなしくsqlite3で設定する。

インストールが完了するとmailman3とmailman3-webのサービスが起動しているはずである。

勇気がある人はこの時点でMailman 2をアンインストールしてしまおう。 🙂

ここからはMailman 3の設定。sudo bashでroot権限のシェルを起動してrootで作業をする。

まずはPostfixと連携するための設定をする。/etc/postfix/main.cfに以下のMailman 3用の設定を追加する。

owner_request_special = no
transport_maps = hash:/var/lib/mailman3/data/postfix_lmtp
local_recipient_maps = proxy:unix:passwd.byname $alias_maps hash:/var/lib/mailman3/data/postfix_lmtp
relay_domains = ${{$compatibility_level} < {2} ? {$mydestination} : {}} hash:/var/lib/mailman3/data/postfix_domains

次に/etc/mailman3/mailman.cfgのサイトオーナーの連絡先を書き換えておく。

site_owner: MYADDRESS@MYDOMAIN.COM

ここからmailman3-webが稼働できるように設定する。

まずはapache2のproxy_uwsgiを有効にする。

a2enmod proxy_uwsgi

次にapache2でPostorius(Mailman 3のウェブフロントエンド)のページを表示できるようにする。これはapache2で読み込まれる設定を置くディレクトリにMailman 3に付属する設定をシンボリックリンクで置く。

ln -s /etc/mailman3/apache.conf /etc/apache2/conf-enabled/mailman3-web.conf

現在のmailman3-webのパッケージでインストールされるこの設定ファイル/etc/mailman3/apache.confはバグがあるので手作業で修正しておく。

ProxyPass /mailman3 unix:/run/mailman3-web/uwsgi.sock|uwsgi://localhost/

という行のlocalhost/の最後の余分な/を削除するだけである。

最後に/etc/mailman3/mailman-web.pyのいくつかの設定を変更する。

EMAILNAME = ‘FQDN.COM’
ACCOUNT_DEFAULT_HTTP_PROTOCOL = “http”

本サーバーはHTTPSで接続することができないので、認証はHTTPでできるように二行目の設定変更が必要だ。

以上の設定が完了したらサーバーを再起動して変更した設定を反映させる。もちろん、コマンドラインで手動でapache2とmailman3, mailman3-webのサービスを再起動させてもいい。

もしサーバーを再起動したらMailman 2のサービスが起動してしまうので、忘れずに停止させておこう。

Debian パッケージの依存関係の逆方向探索

Debian Bullseyeがリリースされた。このサーバーはBusterで運用しているのでいずれアップグレードせねばならんなとリリースノートを読み込んでいたら衝撃の事実を発見。

なんとBullseyeではとうとうPython2.7が非推奨とな。これで一番困るのはMailman 2だ。Mailman 2はPython2.7で動いているので、Bullseyeではパッケージそのものが消滅しているらしい。Bullseyeに移行したければ、必然Mailman 3への乗り換えが必要になる。これはこれで大変だが、そもそもMailman 2自体がもうObsoleteでメンテナンスされていないみたいなので、しょうがないだろう。

これとは別にPython2.7を要求するパッケージが今のサーバーにインストールされているのかがどうにも気になる。そんなときは以下のコマンドで一発で解決できる。

apt-cache rdepends –installed python

これでPython2.7の本体パッケージであるpythonを依存関係で要求するインストール済みのパッケージがリストアップできるわけだ。

ざっと見る限りではPython2.7のサブパッケージしかないなと思ったら、nfs-commonがpythonに依存していたよ。Bullseyeのnfs-commonパッケージは依存先としてpython3を要求していたので、アップグレードすれば晴れてpythonに依存するパッケージは一つもなくなることになる。アップグレードしたら忘れずにPython2.7をシステムからパージすることにしよう。 🙂

Debian Consoleログインの文字化け解消

最近のLinuxディストリビューションはしっかり多言語対応しているのでグラフィカルなインストーラーでちゃんと日本語を選べるようになっていて、その状態でインストールするとしっかりとシェルの環境変数で言語が日本語になるように設定してくれる。

これ自体はありがたくてSSHなどでリモートのターミナルから接続した環境では様々なコマンドの出力結果が日本語化されてありがたいのだが、一つだけ問題がある。それはサーバー自身のコンソールからログインした場合だ。昔からコンソール画面の出力は多言語化されていないので、この状態でも言語が日本語になっていると出力が文字化けしてしまう。ついうっかりコンソールからパッケージのインストールとかをしてしまうとaptからのメッセージが文字化けして何を要求されているのかわからないまま全部の質問にYと答える羽目になる。

まあ、当たり前のことであるがログインシェルからはどのようなターミナルから接続されているのかを環境変数で認識できるわけだから、ログインシェルの設定でコンソールからログインしている時だけ環境変数の言語をデフォルトのCに戻してあげればよいだけである。そこで、bashをログインシェルにしている時には$HOME/.bashrcに以下の設定を書き加えておく。

case $TERM in
linux) LANG=C ;;
esac

これでログインした環境がコンソールだった場合に、環境変数TERMの内容がlinuxと設定されているので、システムの標準の言語設定をオーバーライドしてCに書き換えることができる。これで、コンソール環境での出力が強制的にデフォルトの英語に戻るというわけだ。

Transmissionの送受信バッファ不足エラー

Debianサーバーに入れてあるTransmission Daemonが突然全く送受信をしなくなった。PCに入れてあるBitTorrentクライアントでちゃんとダウンロードできることを確認したTorrentファイルを食わせてもPeerすら見つけられない。これは何かおかしいことが起きてそもそもDaemonが動いていないのだろうと思ったら、Daemon自体は起動している。しょうがないのでログをさらってみると謎のエラーが/var/log/daemon.log(と重複してsyslogにも)に記録されているのを発見。

UDP Failed to set receive buffer: requested 4194304, got 425984
UDP Failed to set send buffer: requested 1048576, got 425984

どうやらUDPの送受信でTransmissionが要求するバッファサイズに対してシステムが許可するバッファサイズが小さすぎるということで文句を言ってるようだ。なぜ突然このエラーが起きるようになったのかはよくわからないが、とにもかくにも最近何かのアップデートでUDP送受信バッファのサイズ制限がTransmissionの要求に合わなくなったことは間違いないようだ。確かに要求サイズに対してこれだけ可能サイズが小さければ拗ねてサボタージュされてもしょうがない。

で、これを解消するにはsysctl経由でkernelに送受信バッファサイズを大きくするように指示をしてあげればよい様なので、/etc/sysctl.dにTransmission用の設定ファイルを置くことにする。

/etc/sysctl.d/transmission.conf

net.core.rmem_max = 16777216
net.core.wmem_max = 4194304

これで再起動すれば自動的にこの設定がsysctlによって読み込まれてkernelの許可するバッファサイズが拡張されるはずだ。拡張されるバッファの数値はネットでこのエラーが出たときのおすすめサイズに合わせた。Transmissionが実際に要求しているサイズよりはでかいのでまあ問題はないだろう。

再起動後にはエラーは記録されていなかったが、あいかわらずPeerを見つけてくれない状態は続いている。稼働しない原因はほかにもあるようだ。引き続き調査を継続する。

Debianで古いパッケージの自動削除後にrc状態で残るゴミの大掃除

Debianのaptを使ってパッケージのアップデートを行っていると、パッケージが更新された場合に古いパッケージは自動的にremoveされる。しかし、purgeされるわけではないのでバージョン依存の設定情報があるパッケージなどは設定が削除されずに残ってしまう。そのため、dpkg –listでインストール済みのパッケージ一覧を取得すると先頭のパッケージの状態がrcとなっていつまでもゴミとして一覧に残り続けることになる。

まあ残っていても別に実害はないのだが、linux-imageなどはどんどん古いバージョンがrc状態で積み重なってしまうため、dpkg –listが無駄に長くなることになり精神衛生上よくない。そこで、このrc状態のパッケージを簡単に一掃したくなる。そんなときはこのコマンド。

dpkg –list | grep “^rc” | cut -d ” ” -f 3 | xargs sudo dpkg –purge

これでインストール済みのパッケージの一覧からrc状態のパッケージだけを抜き出し、そのパッケージ名だけを切り出した後、すべてpurgeしてくれる。一応、念のために最後のパイプだけを外した状態でリストを出してみて、ほんとにrc状態のパッケージだけが抜き出されているかをチェックした方が安全である。

dpkg –list | grep “^rc”

でrc状態の一覧を取得し、

dpkg –list | grep “^rc” | cut -d ” ” -f 3

でそのパッケージ名だけがちゃんと抽出されていることを確認したのちに、purge実行だ。

Debianで古いkernelが溜まってしまった場合の対処

Debianでサーバーを運用していて生真面目にアップデートを当てていると、だいたいいつの間にか古いkernelが溜まってしまうことになる。Debian的お作法でいくとだいたい/bootパーティションは別に分けるので、あまりにもたくさんのkernelが溜まるにまかせるといつの間にか/bootパーティションが古いkernelでパンクして新しい更新されたkernelのインストールに失敗するなんてことになる。とはいえ、新しいkernelに問題があった場合に備えて古いkernelを少しは残しておきたいし、いちいち新しいkernelが降ってくるたびにインストールされたlinux-imageパッケージの一覧を取得してどのkernelを残すか考え、手動でpurgeする作業をしていたが、さすがに面倒になってきた今日この頃。そこで、とうとうbyobuスクリプトをインストールすることにした。byobuは本来はターミナルマルチプレクサをtmux上に実現するスクリプトだが、同梱されているスクリプトの中になぜかkernelを整理するスクリプトが存在する。tmuxを普段使わない身としてはそのスクリプトだけ別にパッケージ化してもらいたいものだが、そうもいかないのであきらめてbyobuと依存するtmux等も一緒にインストールする。インストールはDebianでも一発だ。

sudo apt install byobu

これで依存するtmuxやらなんやらと一緒にインストールされる。

さて、実際に古いカーネルをpurgeする場合は新しい順にいくつのkernelを残した状態にするかを指定してpurge-old-kernelsを実行する。例えば、今bootしている最新のkernelに加えて、一個前の古いkernelを安全のために残したい場合は、2個のkernelを残すということで以下のように実行する。

sudo purge-old-kernels –keep 2

あとはpurgeすべきkernelがあった場合は削除処理をしてくれるので、対話的に実行すればよい。このスクリプトは–keepオプション以外のオプションを単純にaptに渡すだけのwrapperなので、対話的にしたくなければaptですべての質問にyesと答える-qyオプションをつければいいだろう。

あとは、/bootが足りなくなってるなと思ったときにこれを実行するだけだが、毎日のサーバーのリポートメールでついついパーティションごとの空き容量をチェックするのを忘れちゃうんだよね。

Ubuntu19.10でAMDGPUドライバーを有効にする

予備機としてUbuntuをインストールして使っている予備機はグラボにAMD Radeon HD 7750が刺さっている。先日、このグラボが認識されなくなるトラブルが起き、原因はマザーボードの電池切れだったことが分かって電池を交換して組み立てなおしたのだが、そのついでにUbuntu19.10を入れたついでにAMD提供のLinux用ドライバーを入れようと思ったら、LTSバージョンのUbuntuにしか対応していない。どうすんの?と思ったら、どうやらこのドライバーのオープンソースバージョンはすでにLinux Kernel 5系列に取り込まれていて、それが単に有効化されていないだけだということが判明したので、有効化する方法を記録しておく。

HD 7750は命令セットがSouthern Islandsと呼ばれる世代である。通常のUbuntu19.10のKernelはradeonドライバーが有効になっているので、これを無効にして代わりにamdgpuドライバーをSouthern Islandsのグラボであることを明示して有効化する。有効化に必要な場所は二か所。一つはGRUB2の設定。これを有効にしておかないとブートが途中で止まってしまう。もう一つはKernelのmoduleの設定を変更する。

まずはGRUB2の設定。/etc/default/grubにパラメーターを追加する。追加するのはGRUB_CMDLINE_LINUX_DEFAULTの項目。すでに書いてあるであろうパラメーターの前に以下のパラメーターを追加する。

radeon.si_support=0 radeon.cik_support=0 amdgpu.si_support=1 amdgpu.cik_support=0

これでradeonドライバーが起動時に無効になり、amdgpuドライバーのSouthern Islands用が有効になる。

次はKernelモジュールの設定。/etc/modprobe.d/に二つファイルを追加する。

一つはradeonドライバーの無効化。/etc/modprobe.d/radeon.confというファイルを以下の内容で作成する。要root権限。

options radeon si_support=0
options radeon cik_support=0

もう一つはamdgpuドライバーのSouthern Islands用の有効化。/etc/modprobe.d/amdgpu.confというファイルを以下の内容で作成する。もちろんこちらも要root権限。

options amdgpu si_support=1
options amdgpu cik_support=0

GURB2の設定のアップデートとinitramfsのアップデートが必要。要root権限。

update-grub2
update-initramfs

これで再起動すれば読み込まれるディスプレイドライバーがradeonドライバーからamdgpuドライバーに切り替わる。

Debian 9から10へのアップグレード

Debian 9 Stretchで運用してきたこのサーバーをまだ当分この状態で運用したいので、この機会にDebian 10 Busterにアップグレードすることにした。

まずはDebian 9 Stretchにアップグレードした時に放置していたネットワークインターフェースの名称変更を実施。Debian 8までは伝統的なeth*というインターフェース名が使われていたが、10ではこれがデバイスのハードウェア的な接続場所に応じた固定的な名前しか使えなくなる。だから、移行措置期間の9のうちにインターフェース名を変えておく必要がある。

公式のリリースノートに従って新しい名前を調べ、/etc/network/interfacesにあるインターフェース名を変更し、新しい名前を有効にしてinitramfsを再構築させたが、実際は起動したら全然違うインターフェース名だった。どうやらUSB接続されているインターフェースの命名規則はMACアドレスを使う命名法になるので、リリースノートの手順では正しい名前が得られないらしい。というわけで、冷静に/sbin/ifconfig -aで新しいインターフェース名を一覧から取得し、これで設定しなおして無事にインターフェース名の変更が終了。

あとはパッケージリポジトリをStretchからBusterに変更してインストール済みパッケージをroot権限になって更新する。

apt update

apt-get upgrade

apt full-upgrade

途中、コンソールのLANGをen_US.UTF-8に戻しておくのを忘れてコンソールのメッセージが全く読めなくて焦ったが、9から10へのアップグレードは予想以上に何も聞いてこなかったので助かった。エラーもなく全パッケージのアップデートが完了したので再起動。最初、ネットワークインターフェースが上がらなくて起動しないトラブルが起きたが、一度電源を切ってから再起動したら問題なく起動したので良しとする。

バージョンが確かに10に上がってることを確認したのちに、サーバーのサービスがちゃんと動いているか調べたところ、WordPressだけが正しく動いていなかった。調べてみると、php7.0とphp7.3が重複インストールされた状態になっていたので、php7.0をアンインストール。それにともなってapache2のphp7.3モジュールがアンロードされた状態になっていたので、a2enmodコマンドで明示的に有効化。これで大丈夫と思ったらアクセスしても何も表示されなくて焦ったが、単にブラウザのキャッシュの問題だったので、リロードしたら無事に表示された。

最後にobsoleteになったパッケージを以下のコマンドでチェック。

aptitude search ‘~o’

ほとんどのパッケージが移行のためのダミーパッケージか、もっと新しいバージョンがすでにインストールされているかなので問題なく削除できるのだが、phpmyadminがobsoleteになってしまったのは困った。これは非常に多くのphpやmariaDBがらみのパッケージが依存関係で入っているので、普通にremoveするとおそらくWordPressに必要なパッケージまでautoremoveされてしまう。そこで、この記事を参照してBuster環境でWordPressを手動でインストールするときに推奨されているパッケージを手動でインストールして、パッケージをautoremoveされないように「手動でインストールしました」フラグを立てておいた。その後、phpadminが依存関係で自動的に入れた状態になっているパッケージをphpadminごとautoremoveで取り除いた。

で、その状態でもWordPressが正しく動いているのを確認できたので、無事にBusterにサーバーのアップグレードを完了。

唯一心残りだったのが、Debian 10に至っても内蔵のRTL8111Gのドライバがおかしくてネットワークが使えないことか。結局、USB2-Gigabitという情けないアダプターをこれからも使い続けることに。