自宅サーバーのUbuntu 22.04をそろそろ24.04にアップグレードしようと思い立った。今まで割とすんなりアップグレード出来たのに、今回は何度か中断してしまった…
事前準備
まずシステムを最新化してからバックアップを取る。ログとキャッシュは容量が大きいので除外した。今思えばdockerのイメージも除外しておけば良かった。
sudo apt update && sudo apt upgrade -y && sudo apt dist-upgrade -y
sudo tar -czf /mnt/middle/etc_home_var_$(date +%Y%m%d).tar.gz \
--exclude=/var/log \
--exclude=/var/cache \
/etc /home /var
念のため、現在インストールされているパッケージの一覧もバックアップしておく。
dpkg --get-selections | grep -v deinstall > ~/package-list-backup.txt
次に、アップグレード中に邪魔しそうなものを片付ける。WireGuardは使わなくなっていたので削除し、DockerはユーザーサービスとしてDockerを停止する。外部ストレージ(/mnt/hdd1、/mnt/xfs、/mnt/middle)は全部アンマウントしておく。
# WireGuard停止・削除
sudo systemctl stop wg-quick@wg0
sudo systemctl disable wg-quick@wg0
sudo apt remove wireguard wireguard-tools
sudo apt autoremove
sudo rm -rf /etc/wireguard/
# Dockerを停止
systemctl --user stop docker
systemctl --user disable docker
# 外部ストレージをすべてアンマウント
sudo umount /mnt/hdd1 /mnt/xfs /mnt/middle
/etc/fstabの外部ストレージのエントリ(/mnt/hdd1、/mnt/middle、/mnt/xfs)もコメントアウトしておく。アップグレード後の再起動が終わったら戻す。
最後に、リポジトリ設定を確認する。/etc/apt/sources.list.d/docker.listについて、Claudeが自動置換されないのでnobleに変更しておけといっていたが、アップグレード後にすれば良い。そうしないと、OSアップグレードで再実行するときにアップデートしておくものが残っていると実行できなくなる。
byobuで実行する必要はなかった
sudo do-release-upgradeを実行する時は、セッションが切れても大丈夫なようにbyobuを起動してから実行した。しかし、実はdo-release-upgrade自体がscreenを内部で自動起動してセッションを保護してくれるため、byobuでの実行不要だった。
ログにも re-exec inside screen: '['screen', '-e', '\\0\\0', '-c', 'screenrc', '-S', 'ubuntu-release-upgrade-screen-window', '/tmp/ubuntu-release-upgrader-i_2szg_4/noble', '--mode=server', '--frontend=DistUpgradeViewText']'と記録されており、SSH接続が切れてもアップグレードが中断されない仕組みが最初から備わっていた。
アップグレード失敗後であってもbyobuセッションの中にいたため、再度byobuを起動しようとして「セッションがネストしますよ」と警告が出た。tmux list-sessionsで確認しても別な操作は不要で、そのままsudo do-release-upgradeを再実行すれば良かった。
/boot の空き容量が足りない
実行してみると早速エラーが出て止まった。
アップグレードには '/boot' に空き領域が 258 M 必要です
df -h /bootで見ると空き186M。dpkg -l | grep linux-imageを叩くと、4.15系カーネルがrcステータスのまま大量に残っていた。設定ファイルだけ残った状態なので、一括で掃除する。そして、rcステータスのカーネルを一括削除した。
dpkg -l | grep '^rc.*linux-image' | awk '{print $2}' | xargs sudo dpkg --purge
# 古いカーネルイメージを削除(使用中の5.15.0-176は残す)
sudo apt remove --purge linux-image-5.15.0-174-generic
sudo apt autoremove --purge
これで/bootの空きが186Mから312Mに回復した。
do-release-upgradeを再実行すると、今度はaptやdpkgが別のプロセスにロックされているというエラーが出た。念のため、裏でパッケージ操作を邪魔しそうなunattended-upgradesも止めておくことにする。
sudo systemctl stop unattended-upgrades
sudo systemctl disable unattended-upgrades
nginxのパッケージ競合
続けて以下のエラーも出た。
'/usr/sbin/nginx' を上書きしようとしています。これはパッケージ nginx-core 1.23.2-1+ubuntu20.04.1+deb.sury.org+1 にも存在します
以前sury.orgのサードパーティリポジトリからインストールしたnginxが残っていたのが原因だ。完全に削除してから入れ直す。
sudo apt remove --purge nginx nginx-core nginx-common libnginx-mod-stream-geoip libnginx-mod-http-geoip
sudo apt update
sudo apt install nginx
これで、解消するかと思いきや…直らなかった。sudo apt --fix-broken installで解消されて一気にアップグレードが進んだ。
アップグレード前に設定を確認・修正
アップグレードが進むとSambaのsmb.conf、ネットワーク設定のsysctl.confなどのリリースメンテナンスとの差分確認が発生する。差分を確認したら、メモしておき、リリースメンテナンスのままインストールして、後で変更点を手動で追加していった。
SSHのsshd_configだけは、下手に修正するとリモート接続できなくなる可能性がある。
-#Port 22
+Port 12345
-#PermitRootLogin prohibit-password
+PermitRootLogin no
一旦はそのままにしようと思ったが、ポートの変更、rootログインの禁止の修正分だけなので、マージ機能で綺麗に反映することができた。
アップグレード完了
これで一気に最後までいくかと思いきや、/etc/locale.aliasのインストールでいきなり中断。
新バージョンの設定ファイル /etc/locale.alias をインストールしています ...
Generating locales (this might take a while)...
en_AG.UTF-8... done
・・・中略・・・
ja_JP.UTF-8... done
Generation complete.
libc-dev-bin (2.39-0ubuntu8.7) を設定しています ...
libc6-dev:amd64 (2.39-0ubuntu8.7) を設定しています ...
man-db (2.10.2-1) のトリガを処理しています ...
未解決のクラッシュレポートはありません。詳しくは --help を試してみてください。
アップグレードをインストールできません
アップグレードを中断しました。システムが不安定な状態の可能性があります。今からリカバリーを実行します。(dpkg --configure -a)
中断原因は分からなかったが、中断された直後の自動リカバリー(dpkg --configure -a)も失敗していた。
E:Could not get lock /var/lib/dpkg/lock. It is held by process 2018306 (dpkg), W:Be aware that removing the lock file is not a solution and may break your system., E:管理用ディレクトリ (/var/lib/dpkg/) をロックできません。これを使う別のプロセスが動いていませんか?
既にunattended-upgradesは止めていたため、Geminiに言わせると、恐らくアップグレード処理自体が異常終了した際にdpkgのロックを掴んだまま(ゾンビプロセス化して)残ってしまい、自分自身のリカバリー処理をブロックしてしまったのだろう。
アップグレードの中断、リカバリー処理もブロックされたとはいえ、lsb_release -aで確認するとUbuntu 24.04.4 LTSになっていた。
そのままsudo apt upgrade、sudo apt autoremove、sudo apt dist-upgradeを実行すると、問題なく全てのパッケージが更新された。最後にsudo rebootをして再起動する。
再起動後の後片付け
再起動後はまずsystemctl --failedで問題のあるサービスを確認。postfixが動いていたが使っていないので無効化した。
systemctl --failed
sudo systemctl disable --now postfix
/etc/fstabの外部ストレージを有効化して、再マウント。
sudo systemctl daemon-reload
sudo mount -a
次にDockerを有効化・起動し、各サービスを順番に立ち上げた。
systemctl --user enable docker.service
systemctl --user start docker
systemctl --user restart immich.service
systemctl --user restart seafile.service
Nginx Proxy Managerが起動しない
npmのサービスを起動しようとしたが、コンテナがDNS解決をループして起動できなかった。npmはリバースプロキシとしてimmich、seafileなどのコンテナに接続するため、これらが揃っていないとDNS解決に失敗してループしてしまう。
immichとseafileはsystemdユーザーサービスとして管理しているので先に立ち上げていたのだが、Dockerのcomposeで管理しているコンテナ群がまだ上がっていなかった。このcomposeコンテナはDockerサービス起動時に自動で立ち上がる想定で、個別にsystemdサービスを登録していなかったため、揃っていないことに気付くのが遅れた。
docker compose up -d
これでcompose側のコンテナが揃い、npmも正常に起動した。
リポジトリをnobleに更新して仕上げ
Sambaの文字コード設定(dos charset = CP932 / unix charset = UTF-8)、そして共有フォルダ設定を追記してアップグレード前状態に戻す。続けて外部リポジトリのコードネームをnobleに更新し、諸々の後片付けをして完了とした。
grep -h "^deb" /etc/apt/sources.list.d/*.list # jammy が残っているリポジトリを確認
sudo sed -i 's/jammy/noble/' /etc/apt/sources.list.d/cloudflared.list
sudo sed -i 's/jammy/noble/' /etc/apt/sources.list.d/docker.list
sudo apt update && sudo apt upgrade
sudo rm /etc/apt/sources.list.d/*.distUpgrade
sudo apt dist-upgrade
sudo apt autopurge
sudo systemctl enable unattended-upgrades
sudo systemctl start unattended-upgrades
できれば不要なパッケージとか削除しておきたいが、もう手動インストールパッケージ(apt-mark showmanual)が396件あるの、どうしたものか?
Ubuntu 16.04からアップグレードしてきたが、今回は、中断が3回とトラブルが多かったが、大きなエラーはなくアップグレードできたので良かった。