Ubuntu】22.04→24.04アップグレードでPHP8.3へ。

サーバー・インフラ

このブログは、ConoHa の VPS に自分で構築した WordPress で動いています。 構築したときの OS は Ubuntu 22.04 だったのですが、今回これを 24.04 にアップグレードしました。

いちばんの目的は、PHP のバージョンを上げることです。

なぜアップグレードしたのか:PHP 8.1 のサポート期間

Ubuntu 22.04 の apt で入る PHP は 8.1、24.04 で入る PHP は 8.3 です。

Ubuntu 22.04Ubuntu 24.04
PHP のバージョン8.18.3
Ubuntu の標準サポート2027年4月まで2029年4月まで

PHP 8.1 は、PHP 本家のサポートが 2025 年末で終わっています。Ubuntu がセキュリティ修正を取り込み続けてくれてはいますが、それも 22.04 のサポートが続く間だけです。 一方、24.04 の PHP 8.3 なら、あと数年は安心して使えます。

きっかけは、以前仕事で対応した PHP の脆弱性でした(1本目の記事で少し書きました)。PHP のバージョンとサポート期間を意識するようになり、自分のサーバーも早めに上げておこうと思いました。仕事でも VPS の Ubuntu を 22 系から 24 系に上げる作業が発生しそうなので、その練習も兼ねています。

環境

  • ConoHa VPS(メモリ 1GB)
  • Ubuntu 22.04 → 24.04
  • Apache + PHP(mod_php)+ MySQL 8.0
  • WordPress(WP-CLI で構築)、テーマは Cocoon
  • Let’s Encrypt で HTTPS 化済み

全体の流れ

  1. 今の状態を記録する
  2. WordPress のバックアップを取る
  3. 22.04 を最新にする
  4. ConoHa でイメージ保存(スナップショット)
  5. メンテナンス画面を出す
  6. do-release-upgrade を実行
  7. 再起動後の確認と修正
  8. 後片付け

作業時間は、アップグレード本体が 30 分くらい。ハマったところの対応を含めると、結局一晩またぐことになりました。


1. 今の状態を記録する

アップグレード後に「何が変わったか」を比べられるように、今の状態をファイルに書き出しておきます。

mkdir -p ~/pre-upgrade && cd ~/pre-upgradelsb_release -a > os.txtphp -v > php.txtphp -m > php-modules.txtsudo apache2ctl -M | sort > apache-modules.txtls /etc/php/8.1/apache2/conf.d/ > php-confd.txtdpkg -l > packages.txtsudo ufw status verbose > ufw.txtsudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication' > sshd.txtsudo certbot certificates > certs.txtsudo -u www-data wp core version --path=/var/www/wordpress > wp.txt

ちなみに最初、apache2ctl -M を sudo なしで実行したら「SSL 証明書のファイルがない」というエラーが出てドキッとしました。証明書は root しか読めない場所にあるので、一般ユーザーからは「ない」ように見えるだけでした。sudo を付けたら普通にモジュール一覧が取れました。

2. WordPress のバックアップを取る

スナップショットはサーバー丸ごと戻す用なので、それとは別に、DB と WordPress のファイルだけを取り出せる形でも残しておきます。

sudo mysqldump --single-transaction wordpress > ~/pre-upgrade/wordpress.sqlsudo tar czf ~/pre-upgrade/wp-files.tgz -C /var/www wordpress

これを scp で手元の Mac にもコピーしておきました。ConoHa 側で何かあっても、別のサーバーにブログだけ移せます。

3. 22.04 を最新にする

do-release-upgrade は、今の OS が最新になっていないと実行を断られます。

sudo apt update && sudo apt full-upgrade -ysudo apt autoremove -y

autoremove で、モデムや USB 関係などの VPS では使わないパッケージがたくさん消えました。アップグレードの前に減らしておくと、依存関係のトラブルや設定ファイルの質問が減るそうです。

4. イメージ保存(スナップショット)

ConoHa のコントロールパネルで、サーバーをシャットダウン → イメージ保存 → 起動しました。起動したままだと DB の書き込み途中の状態で保存されることがあるので、止めてから取ります。

ConoHa ではこれを「イメージ保存」と呼んでいますが、役割としては「この時点に戻せる保険」で、いわゆるスナップショットと同じものです。

5. メンテナンス画面を出す

アップグレード中は PHP が 8.1 から 8.3 に入れ替わるので、サイトが壊れて見える時間があります。そこで、メンテナンス画面を出すことにしました。

ポイントは、WordPress のメンテナンスモードではなく、Apache だけで出すことです。PHP が動かない間も表示できるからです。また、ステータスコード 503 を返すと、Google に「一時的な停止」だと伝わります。

sudo tee /etc/apache2/maintenance.conf <<'EOF'RewriteEngine OnRewriteCond /var/www/MAINTENANCE -fRewriteCond %{REMOTE_ADDR} !^(127\.0\.0\.1|::1)$RewriteCond %{REQUEST_URI} !=/maintenance.htmlRewriteRule ^ - [R=503,L]ErrorDocument 503 /maintenance.htmlEOF

これを HTTPS 側の VirtualHost で Include して、メンテ用の maintenance.html を WordPress のフォルダに置いています。 /var/www/MAINTENANCE というファイルがあるときだけメンテ画面になるので、切り替えは touch と rm だけです。サーバー自身(127.0.0.1)からのアクセスは通すので、メンテ中でもサーバー上の curl で中身を確認できます。

sudo touch /var/www/MAINTENANCE   # メンテ ONsudo rm /var/www/MAINTENANCE      # メンテ OFF

6. do-release-upgrade を実行

いよいよ本番です。SSH が切れたときの命綱として、ConoHa のコンソール(ブラウザから入れる画面)に事前にログインできるか試しておきました。

sudo do-release-upgrade

消えるパッケージは事前に確認する

「アップグレードを開始するか」の画面で d を押すと、削除・追加・更新されるパッケージの一覧が見られます。ここから先は止められないので、apache2、mysql-server、certbot などが削除の一覧に入っていないことを確認してから y を押しました。php8.1-... が消えて php8.3-... が入るのは予定どおりです。

設定ファイルの質問は「今のものを残す」

途中で何度か「設定ファイルを新しい版にしますか?」と聞かれました。sshd_config、時刻合わせの ntp.conf、cloud-init の cloud.cfg、起動まわりの grub です。

自分では触っていないファイルもあったのですが、ConoHa の初期設定が書き換えているので「変更あり」と判定されていたようです。新しい版にすると、ConoHa 向けの設定が消えてネットワークやコンソールがおかしくなる恐れがあるので、すべて今のものを残しました。迷ったら差分を表示して確認できます。

sshd_config の差分を見てみたら、ConoHa が最後に PasswordAuthentication yes を書き足していました。ただ、私は SSH をパスワード禁止にする設定を sshd_config.d/ の下の別ファイルに書いていて、そちらが先に読まれて優先されるので、実際にはパスワードでは入れない状態です。紛らわしいので、この行は後片付けで消しました。

ハマった①:アップグレード中に Apache が止まった

古いパッケージを削除するあたりで、こんなエラーが出ていました。

Syntax error on line 3 of /etc/apache2/mods-enabled/php8.1.load:Cannot load /usr/lib/apache2/modules/libphp8.1.so ... No such file or directory

PHP 8.1 が削除されたのに、Apache がまだ PHP 8.1 のモジュールを読み込もうとしてエラーになっています。これが、Apache + mod_php の環境で一番起きやすいトラブルだそうです。 途中で止めるほうが危ないので、そのまま最後まで進めて、再起動後に直すことにしました。

7. 再起動後:自宅から SSH できない

再起動して SSH でつなぎ直そうとしたら、

ssh: connect to host (サーバーのIP) port 22: Connection refused

と言われて入れません。

ハマった②:fail2ban に自宅の IP を BAN されていた

ConoHa のコンソールから入って調べると、サーバー側の SSH は正常に動いていました。 サーバーは SSH を待っているのに、自宅からは Connection refused。そこで別の回線から試したら、普通に入れました。自宅の IP だけが締め出されていたのです。

犯人は fail2ban でした。ログイン失敗が続いた IP を自動で BAN してくれる仕組みで、ConoHa の Ubuntu には最初から入っていました。

sudo fail2ban-client status sshd

Banned IP list を見ると、海外の IP にまじって自宅の IP が入っていました。

原因は Mac の SSH の動きです。Mac に鍵が複数あると、SSH は -i で指定した鍵の前に、ほかの鍵も順番に試すことがあります。サーバー側ではそれが「ログイン失敗」として数えられ、この日は何度もつなぎ直していたこともあって、BAN されてしまったようです。

別の回線から入って BAN を解除しました。

sudo fail2ban-client unban (自宅のIP)

再発防止に、Mac の ~/.ssh/config に IdentitiesOnly yes を書いて、指定した鍵しか使わないようにしました。

Host blog    HostName (サーバーのIP)    User (ユーザー名)    IdentityFile ~/.ssh/(このサーバー用の鍵)    IdentitiesOnly yes

これで ssh blog だけで入れるようになり、余計な鍵を試して BAN されることもなくなりました。

ちなみに BAN リストのほかの IP は、本物の攻撃でした。再起動してから短い時間の間に、SSH へのログイン失敗が 100 回以上記録されていました。fail2ban がちゃんと仕事をしていたわけですが、自分まで巻き込まれたのは予想外でした。

Apache の PHP を 8.1 → 8.3 に切り替える

やっと SSH で入れたので、止まっていた Apache を直します。

sudo a2dismod php8.1sudo a2enmod php8.3sudo apache2ctl configtestsudo systemctl restart apache2

Syntax OK が出て、Apache が PHP 8.3 で動き出しました。

アップロード上限を 8.3 側にも設定する

前の記事で「アップグレードしたら確認しよう」と書いていたアップロード上限です。予想どおり、/etc/php/8.1/ に置いた設定は 8.3 には引き継がれていなかったので、8.3 側に作り直しました。

sudo tee /etc/php/8.3/apache2/conf.d/99-upload.ini <<'EOF'upload_max_filesize = 64Mpost_max_size = 64MEOFsudo systemctl restart apache2

確認

lsb_release -dphp -v | head -1dpkg -l php8.3-common | tail -1systemctl is-active apache2 mysqlsudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication'sudo certbot renew --dry-runsudo -u www-data wp core verify-checksums --path=/var/www/wordpress
  • OS:Ubuntu 24.04.5 LTS
  • PHP:8.3.6
  • Apache と MySQL:どちらも active
  • SSH:root 禁止・パスワード禁止のまま
  • 証明書の自動更新:リハーサル成功
  • WordPress のファイル:改ざん・破損なし

メンテ画面を外して、ブラウザでトップページ、記事ページ、管理画面へのログイン、画像のアップロードまで確認して完了です。

PHP 8.3.6 は古くない?

php -v を見ると 8.3.6 と出ます。PHP 8.3 の最新版はもっと先まで出ているので、古いのでは?と思いました。

見るべきは、dpkg -l で出てくる後ろの部分です。

php8.3-common  8.3.6-0ubuntu0.24.04.13

Ubuntu は PHP 本体の番号を 8.3.6 のまま固定して、セキュリティ修正だけを取り込んでいます(バックポート)。修正のたびに、後ろの ubuntu0.24.04.13 の数字が増えていきます。 仕事で対応した脆弱性も、Ubuntu のセキュリティ情報のページで「24.04 の php8.3 は 8.3.6-0ubuntu0.24.04.13 で修正」とされていて、ちょうどこの版でした。

8. 後片付け

最後に、古いものを片付けました。

sudo apt autoremove -ydpkg -l | grep php8.1

php8.1-... が rc という状態で 13 個残っていました。rc は「本体は削除済み、設定ファイルだけ残っている」という意味だそうです。まとめて完全削除(purge)しました。

sudo apt purge -y $(dpkg -l | awk '/^rc/ && /php8\.1/ {print $2}')

それでも /etc/php/8.1 のフォルダが残りました。apt は自分が入れたファイルしか消さないので、私が手で作った 99-upload.ini が残っていたからです。中身がそれだけなのを確認して、フォルダごと消しました。

ほかにやったこと:

  • サーバー上に置いたバックアップ(DB の中身入り)を削除(Mac にコピー済み)
  • sshd_config に残っていた紛らわしい PasswordAuthentication yes の行を削除
  • 数日問題がなければ、ConoHa のアップグレード前イメージを削除する予定

まとめ

  • PHP 8.1 から、サポート期間の長い 8.3 にするために Ubuntu を 22.04 → 24.04 にアップグレードした
  • 事前の記録、アプリ単位のバックアップ、イメージ保存をしてから実行した
  • Apache だけで出すメンテ画面(503)は、PHP が壊れている間も表示できて便利
  • 設定ファイルの質問は、基本「今のものを残す」
  • Apache + mod_php だと、アップグレード後に a2dismod php8.1 → a2enmod php8.3 が必要
  • /etc/php/8.1/ に置いた自分の設定は、8.3 側に作り直す
  • SSH が切れたときの命綱(ConoHa のコンソール)は、事前にログインできるか試しておく
  • 鍵が複数ある Mac から何度もつなぎ直すと、fail2ban に BAN されることがある。IdentitiesOnly yes で防げる

手順だけ見ればコマンドを何行か打つだけなのですが、実際にやってみると、Apache が止まったり、自分の防御策に自分が締め出されたりと、思わぬところでつまずきました。仕事で本番サーバーを上げる前に、自分のサーバーで一度経験できて本当によかったです。

同じように Ubuntu のアップグレードを考えている方の参考になればうれしいです。

タイトルとURLをコピーしました