コンテンツへスキップ
← ブログ

Ubuntu 24.04 → 26.04 サーバー移行

アップグレード経路は8月27日、26.04.1とともに開く。足元では6つの既定値が入れ替わり、2つの条件はアップグレーダにきっぱり拒否させ、リリースノートにはサーバー側の実害ある劣化が2件埋もれている。

·約18分
  • Ubuntu
  • Linux
  • systemd
  • アップグレード

2026年8月27日(木)、CanonicalはUbuntu 26.04.1をリリースする。そしてそれと同時に、24.04からのLTS→LTSアップグレード経路がすべての利用者に対して開く。[schedule] その週に出てくる解説記事のほとんどは、do-release-upgradeの実行手順をなぞって終わる。けれども、難しいのはそのコマンドではない。本当に厄介なのは、Noble NumbatとResolute Raccoonのあいだで、サーバー運用の自動化が静かに依存しているベースシステムの部品が6つも差し替わり、アップグレーダがそもそも実行を拒否する条件が2つ加わり、そして文書化されているのにほとんど誰も触れないサーバー向けの劣化が2件そのまま出荷されていることだ。

Ubuntu 24.04 LTSと26.04 LTSのサーバー既定値を比較した図。sudoはsudo-rsへ、coreutilsはrust-coreutilsへ、systemd-timesyncdはchronyへ、initramfs-toolsはdracutへ置き換えられ、cgroup v1は削除されている。
サーバーで効いてくる変更は、カーネルのバージョン番号の側にはない。誰もリリースノートを読まない「既定値」の側にある。

以下は、実際の機械に対して私が使っているチェックリストである。想定読者はUbuntuをサーバーとして運用している人で、デスクトップもGNOMEもSnap Storeも出てこない。ここに書いた事実はすべて、Canonicalの公式リリースノートと上流プロジェクトのドキュメントに由来する。公式のノートがバージョン番号を明記していないところ ― OpenSSLがまさにそのケースだ ― については、それらしい数字をでっち上げるのではなく、機能として何ができるようになるのかを書いた。掲載しているコマンドは、コメントで「変更する」と断っていないかぎりすべて読み取り専用である。まずは何も壊さずに、自分の環境がどの分岐に該当するのかを確定させてほしい。判断材料が揃っていないまま作業窓を確保することが、この種の作業でいちばん高くつく。なお、この記事はdo-release-upgradeの画面遷移を追わない。そこはすでに十分に書かれているし、実際に人が困るのはコマンドを打つ前と、打ち終わったあとだからである。前半では「アップグレードしてよい状態かどうか」を判定し、後半では「本当に元通りになったかどうか」を判定する。その2つが揃えば、真ん中の40分は退屈な待ち時間になる。

8月27日という日付が重要な理由

Ubuntuは、次のLTSがリリースされた当日にそれを提案してくることはない。そのリリースの最初のポイントリリースを待つ。ポイントリリースはおよそ4か月後に登場し、初期の目立った不具合を吸収した状態で出てくる。26.04にとってのそれが2026年8月27日の26.04.1である。それまでは、標準のPrompt=ltsポリシーで運用している24.04サーバーは「アップグレード先はありません」と正しく答える。これはバグではないし、回避策を探すべき挙動でもない。むしろ、この待ち時間こそがLTS運用者に与えられている数少ない安全装置である。ポリシーは/etc/update-manager/release-upgradesPrompt行で決まる。サーバーでPrompt=normalになっていると、半年ごとの中間リリースを提案されることになり、これはほぼすべてのサーバーにとって誤った設定だ。逆に変更凍結期間中の機械群では、Prompt=neverを明示しておくほうが、「誰も上げないはず」という暗黙の了解に頼るより確実である。構成管理でこの1行を管理していないなら、アップグレードの計画より先にそこを直す価値がある。[schedule][upgradedoc]

# Ubuntu does NOT offer one LTS to the next until the first point release.
# For 26.04 that is 26.04.1, scheduled for Thursday 27 August 2026. Before that
# date `do-release-upgrade` on a 24.04 box correctly answers "No new release".

lsb_release -a
# Description:  Ubuntu 24.04.4 LTS
# Codename:     noble

# The policy that decides what you are offered. On servers it should be `lts`.
grep -v '^#' /etc/update-manager/release-upgrades
# [DEFAULT]
# Prompt=lts

# Prompt=lts     -> next LTS, but only after ITS point release. Correct for servers.
# Prompt=normal  -> every 6-month interim release. Wrong for almost all servers.
# Prompt=never   -> never offered. Use this to pin a fleet during a change freeze.

sudo do-release-upgrade -c          # -c = check only, changes nothing
# Checking for a new Ubuntu release
# No new release found.

# You CAN force it before 27 August with `-d`, which targets the development
# upgrade path. Do not do this on a production server: -d is how you end up
# being the person who finds the release-upgrader bug, and the point release
# exists precisely to absorb the first four months of regressions.

そして、これはカレンダーが体感ほど切迫していない理由でもある。Ubuntu 24.04 LTSの標準セキュリティメンテナンスは2029年4月まで続く。8月27日に崖から突き落とされるわけではなく、扉が一枚開くだけだ。実質的な期限は自分で決めたものだけであり、そして妥当な決め方は「次のリリースが出る」であって、「コンプライアンス監査の担当者に聞かれた週」ではない。組織として日付を先に決め、そこから逆算してパイロットと本番の作業窓を置くほうが、結果的に安く終わる。[releasecycle]

もっと長く据え置きたい場合、Ubuntu Proが24.04をExpanded Security Maintenanceで2034年4月まで延長する。意図的に凍結する機械群 ― アプライアンス、エアギャップ環境、退役予定のもの ― にとっては、これは正当な戦略である。逆に、いまも開発を続けているプラットフォームにとっては悪い戦略だ。自分たちのツールチェーンのほうが先に進んでしまい、最終的にすべてを自前でバックポートするはめになるからである。凍結は「時間を買う」判断であって、「作業をなくす」判断ではない、と理解しておきたい。実務上の落とし穴は、凍結を決めた人と、その環境の上で開発を続ける人が別だという点にある。ESMで延命した24.04の上に、2028年のPythonライブラリや2028年のコンテナランタイムを載せようとすると、結局は移行を後ろ倒しにしただけで、しかも移行先が26.04ではなく28.04になっているぶん跳躍幅が広がる。延命を選ぶなら、同時に「その環境では何を載せないか」も決めておくことだ。[pro]

状況8月27日があなたにとって意味すること妥当な対応
標準的な24.04サーバー、Prompt=ltsアップグレードが選択可能になる。押し付けられることはない。計画を立てる。パイロットのあと、9月か10月に。
変更凍結中の機械群何も変わらないが、担当者がテスト機を上げ始める可能性はある。惰性に頼らず、Prompt=neverを明示的に設定する。
アプライアンス/エアギャップ環境無関係である。24.04は2029年4月までサポートされる。留まる。凍結が長引くならUbuntu ProのESM(2034年まで)を検討。
前世代のクラウドインスタンスインスタンスを移行するまで、そもそもアップグレードできない。先に現行世代ファミリーへリサイズする。これはOSとは独立した作業である。
まだ22.04のまま直接の経路はない。22.04 → 24.04 → 26.04の順である。まず1ホップ目を実行する。2つのうち、退屈なほうだ。

事前棚卸し ― なぜ読み取り専用なのか

以下はすべて、何も触る前に24.04の機械上で実行する。書き込みは一切行わない。目的は見栄えのよいレポートを作ることではなく、アップグレード後に同じスクリプトを流して差分を取れる出力を作ることである。そうして初めて、「無事に戻ってきた」という言葉が、検証可能な主張になる。出力はチケットなりリポジトリなりに貼っておくこと。数か月後、原因不明の挙動を追うときに、アップグレード前後のどちらで壊れたのかを一行で判定できるようになる。台数が多いなら、この出力をホスト名付きで1か所に集めておきたい。全台ぶんのsystemctl list-unit-files --state=enabledを並べるだけで、「この1台にだけ有効なユニットがある」といった構成のばらつきが浮かび上がる。アップグレードで壊れるのはたいてい標準構成のホストではなく、何年か前に誰かが手で調整して、それきり忘れられた1台である。

#!/usr/bin/env bash
# noble-preflight.sh - read-only. Run it BEFORE the upgrade, save the output,
# and diff it against the same script run afterwards. Nothing here changes state.
set -uo pipefail
echo "=== identity ==="
lsb_release -ds; uname -r; systemctl --version | head -1

echo "=== 1. third-party repositories (the usual cause of a stuck upgrade) ==="
# do-release-upgrade disables these and does NOT re-enable them for you.
grep -rhs --include='*.list'    -E '^deb ' /etc/apt/sources.list /etc/apt/sources.list.d/
grep -rhs --include='*.sources' -E '^URIs' /etc/apt/sources.list.d/

echo "=== 2. packages not from the Ubuntu archive ==="
# Do NOT filter on the suite name: Docker's repo suite is literally `noble` and
# PGDG's is `noble-pgdg`, so grepping the codename hides exactly the two vendors
# you care about. Ask apt-cache policy where each package actually came from -
# in ONE invocation, because per-package calls reload the cache each time and
# turn this section into several minutes on a normal server.
#
# Set MIRROR to your own archive host if you run a local mirror, otherwise
# every package on the box gets reported as third-party and the output is noise.
# [.] rather than \. - awk processes escapes in a -v assignment and would warn.
MIRROR='archive[.]ubuntu[.]com|security[.]ubuntu[.]com|ports[.]ubuntu[.]com|archive[.]canonical[.]com'

apt-cache policy $(dpkg-query -f '${binary:Package} ' -W) 2>/dev/null | awk -v m="$MIRROR" '
  /^[a-zA-Z0-9]/ { pkg = $0; sub(/:$/, "", pkg) }
  /\*\*\*/     { getline; if ($2 !~ m && $2 != "/var/lib/dpkg/status")
                     printf "%-40s %s\n", pkg, $2 }'

echo "=== 3. held and manually installed packages ==="
apt-mark showhold
apt-mark showmanual | wc -l

echo "=== 4. locally modified config files you will be asked about ==="
# Every one of these produces a "keep or replace?" prompt mid-upgrade. Decide
# NOW, in writing, not at 02:00 with the package manager waiting on you.
debsums -ec 2>/dev/null || echo "install debsums to get this list"

echo "=== 5. services that must come back up ==="
systemctl list-unit-files --state=enabled --type=service --no-pager --no-legend | awk '{print $1}'

echo "=== 6. disk headroom - /boot is the one that bites ==="
df -h / /boot /var 2>/dev/null

echo "=== 7. cgroup hierarchy - a HARD upgrade blocker (see the cgroup section) ==="
stat -fc %T /sys/fs/cgroup/
# The parameter is a systemd boolean: 0/false/no/off all mean v1. Do not match
# only [01] or you will report "fine" on a host that is explicitly forced to v1.
grep -o 'systemd.unified_cgroup_hierarchy=[^ ]*' /proc/cmdline || echo "cmdline: default (v2)"

echo "=== 8. CPU capability for the AMD64v3 cloud images ==="
for f in avx avx2 bmi1 bmi2 f16c fma abm movbe osxsave; do
  grep -qw "$f" /proc/cpuinfo || echo "  MISSING: $f"
done

echo "=== 9. anything still using System V init scripts ==="
ls -1 /etc/init.d/ | grep -v README

このうち4つの節は、40分で終わるはずの作業を最悪の一晩に変える常連なので、特に書き出しておく。どれも事前なら数分で片付き、事後だと数時間かかる、という共通点がある。

  • サードパーティのリポジトリ。 do-release-upgradeは開始前にUbuntu以外のリポジトリをすべて無効化し、そして終わったあとも再有効化しない。これは正しい挙動だが、裏を返せば、ベンダーのリポジトリから入れたもの ― Docker、PostgreSQLのPGDG、Node、APMエージェントなど ― は、作業が終わった瞬間から更新を受け取らなくなるということである。しかも一切警告は出ない。あなたがresoluteスイートを指すように書き直すまで、静かに止まったままだ。しかも、リリース直後はベンダー側にresolute向けのスイートがまだ存在しないことがある。その場合の選択肢は「待つ」か「1つ前のスイートを暫定的に指す」かのどちらかで、後者を選ぶなら、いつ戻すのかを含めて記録に残しておくこと。
  • ローカルで書き換えた設定ファイル。 ひとつにつき、トランザクションの途中で「保持するか置き換えるか」の対話プロンプトが出る。事前に、文書として方針を決めておきたい。既定の答えは「自分のバージョンを保持」で、これはアプリケーション設定にとっては安全な選択だが、2年ぶんの上流ハードニングが入っているセキュリティ関連のファイルにとっては誤った選択である。debsums -ecの出力を事前に眺めておけば、判断すべき対象がたいてい10個から30個程度に収まることが分かる。その一覧に対して「保持」か「置き換え」かをあらかじめ書き込んでおけば、深夜にパッケージマネージャを待たせながら考える必要がなくなる。
  • ディスクの空き容量。 /には数GBの空きが必要である。古典的な失敗は、/bootを小さな別パーティションに切ってあるケースだ。dracutと複数のカーネルがそこを埋め、アップグレードは途中で失敗し、設定が半端に適用された状態のシステムが残る。作業前に古いカーネルを整理し、/var/cache/aptを掃除しておくだけで、この失敗の大半は避けられる。
  • cgroup階層とCPUフラグ。 どちらも後段で詳しく扱う。そして、どちらも「いま」知っておきたいことであって、シリアルコンソール越しに知りたいことではない。

2つのリリースの間で実際に動いたもの

まず見出しになる数字から見ていく。ここがその他すべての期待値を決めるからである。Ubuntu開発の2年ぶんというのは大きな跳躍で、これはサービスパックではない。ローカルでコンパイルしたもの、DKMSで組んでいるモジュール、pinしている言語ランタイムがあるなら、この表はそのまま作業リストになる。特にglibcとGCCの行は見落とされがちだ。ディストリビューションのパッケージだけで完結している環境なら何も起きないが、社内でビルドしたバイナリを配っている、あるいは古いベンダー製エージェントをコピーして回しているなら、そこが最初に軋む。[ltssummary]

コンポーネントUbuntu 24.04 LTSUbuntu 26.04 LTSサーバーで効いてくる理由
Linuxカーネル6.87.0新しいハードウェア対応。ツリー外モジュールとDKMSビルドを要確認。
systemd255259cgroup v1が削除。System Vスクリプトを扱う最後のリリース。
OpenSSH9.6p110.2p1ポスト量子鍵共有が既定に。DSAは完全に削除。
Python3.123.143.13と、そこで削除された19個の標準ライブラリをまたぐ。
APT2.73.1apt-keyが削除。新ソルバー。TLSはOpenSSL経由。
glibc / GCC2.39 / 142.43 / 15.2旧ツールチェーンでローカルビルドしたものは再ビルドが必要。
PostgreSQL1618メジャーバージョンの跳躍 ― pg_upgradeが必須で、自動ではない。
MySQL8.08.4 LTS非推奨オプションが削除。32ビットサーバーは廃止。
PHP8.38.5ホスティングしているものにとって、言語仕様2メジャーぶんの変化。
OpenJDK 既定2125明示的にpinすれば旧LTSのJDKも引き続き利用可能。

この表の中で、実は静かにいちばん興味深いのがOpenSSHの行である。9.6から10.2へ渡るということは、ハイブリッドのポスト量子鍵共有mlkem768x25519-sha256が利用可能になり、しかも既定で優先されるということだ ― 保証されるわけではない。相手側が9.6のままなら、従来型の鍵交換にネゴシエートされる。そしてDSAサポートは完全に消える。26.04のOpenSSLはML-KEM、ML-DSA、SLH-DSAというNIST標準に対応する。ポスト量子の話を先送りにしてきたのなら、このアップグレードにはその移行が、計画していようがいまいが同梱されている。悪い話ではない ― ただし、「いつの間にか有効になっていた」ではなく「意図して有効にした」と言えるように、後述の検証だけは通しておきたい。実務上の注意点は2つある。ひとつは、古いクライアントやネットワーク機器がDSA鍵を前提にしていないかの確認。もうひとつは、KexAlgorithmsをローカルで上書きしている設定が残っていないかの確認である。何年も前のハードニング設定が、せっかく既定になったポスト量子鍵共有を無効化している、というのは実際によく見かける状況だ。[openssh][openssl35][fips203]

足元で入れ替わった6つの既定値

ここが他のガイドに欠けている節であり、この記事が存在する理由である。Ubuntuは単にバージョンを上げただけではない。あなたが毎日打っている、あるいは毎日依存している6つのものについて、その実装そのものを差し替えた。ほとんどは改善である。そして、アップグレードそのものを止めてしまうのは、そのうちの1つだけだ。残りは、誰も書き残していなければ、午前3時にチームの誰かを確実に混乱させる、というだけである。ここで挙げる6つは、リリースノートの中では数行ずつしか割かれていない。にもかかわらず、障害対応中に「昨日まで動いていたコマンドの挙動が違う」という形で現れると、原因にたどり着くまでの時間が跳ね上がる。だからこそ、アップグレードの前に社内のWikiへ6行書いておくことに意味がある。[ltssummary]

打つコマンド24.04で動くもの26.04で動くもの取るべき対応
sudosudo(Todd C. Miller)sudo-rssudoersを監査する ― 未対応のディレクティブはfail closedで拒否される。切り戻しはsudo.wsの導入update-alternativesでの選択がセットである。
lssortdateGNU coreutilsrust-coreutils出力を解析しているスクリプトをテストする。GNU版はgnuls等で利用可能。cpmvrmはGNU実装のまま据え置かれている。
時刻同期systemd-timesyncdchrony(新規インストールのみ)アップグレード済みホストはtimesyncdのままである。手動で移行するか、既定から外れていると承知して運用する。
initramfsinitramfs-toolsdracutが既定にどちらも引き続きサポートされる。自分のホストが実際にどちらを使っているか確認すること。設定は/etc/dracut.conf.d/へ移る。
リポジトリの鍵apt-keySigned-Byのみapt-key addを呼んでいるプロビジョニングスクリプトをすべて書き直す。
cgroup階層v2が既定、v1もまだ可能v2のみv1で動いているホストはアップグレードを拒否される。先に24.04でカーネルパラメータを外すこと。

sudoはsudo-rsになった

26.04のリリースノートで最も驚かされる一行がこれである。sudo-rsが既定のsudoプロバイダになった。Todd C. Millerによるオリジナルのsudoはsudo.wsパッケージに改名されている。sudo-rsはメモリ安全な再実装で、ほぼ全員が実際に使っているsudoersのサブセットをカバーする。対応していないものに出会ったときの文書化された挙動は、明確なエラーを出して閉じる側に倒れる(fail closed)ことであって、黙って無視することではない。方向としては正しい。そして、それこそが事後ではなく事前に監査すべき理由でもある ― 未対応のディレクティブが1行あるだけでsudoが動かなくなる。sudoこそが物事を直す手段である機械の上で、である。例外として、受理したうえで無視される短い列挙集合がある ― env_resetvisiblepwverifypwmail_badpassalways_set_homelog_deniedとあと数個 ― が、そのいずれもアクセスを緩める方向には働かない。具体的に確認すべきなのは、umask、リソース制限、env_keep、独自のログ出力先、そしてSELinux関連のロールやタイプの指定だ。リソース制限とumaskはPAM側へ移ったし、sendmail連携はそもそもなくなった。監査ログを外部へ送っている環境では、sudoのログ形式が変わることでパーサやアラートのルールが空振りする可能性もあるので、SIEM側の検知ルールも合わせて見ておきたい。[sudors]

# 26.04 makes sudo-rs the default sudo provider. The original sudo by
# Todd C. Miller is still packaged, renamed to `sudo.ws`.

sudo --version
update-alternatives --display sudo    # which implementation is actually selected

# sudo-rs implements the sudoers subset that essentially everyone uses:
# user/group specs, host specs, NOPASSWD, Cmnd_Alias, %group, includedir.
# Its documented behaviour on something it does NOT support is to fail closed
# with a clear error, not to ignore it. That is the safe direction - but it
# means an unsupported directive stops sudo from working rather than quietly
# degrading it, so you want to find those directives before the upgrade, not
# from a locked-out root account afterwards. A short enumerated set is accepted
# and ignored instead (env_reset, visiblepw, verifypw, mail_badpass,
# always_set_home, log_denied among them); none of those loosen access.

# Resource limits and umask move to PAM; sendmail integration is simply gone.
grep -rEn 'Defaults.*(umask|rlimit|mailto|mailerpath|env_keep|logfile|SELinux|role|type)' \
     /etc/sudoers /etc/sudoers.d/ 2>/dev/null

# Whatever you change, validate with the checker that matches your provider.
# visudo uses it automatically; run it by hand after any scripted edit.
sudo visudo -c

# --- If you find something sudo-rs will not honour ---
# Both implementations coexist; the provider is chosen through alternatives,
# so installing the package is only half the job:
sudo apt install sudo.ws
sudo update-alternatives --config sudo
# Treat this as a migration window rather than a destination: fix the sudoers
# file so you do not depend on the fallback staying available.

# --- One removal has no fallback ---
# The `sudo-ldap` package is gone. If your sudoers rules live in LDAP you must
# move that authorisation to PAM before upgrading, not after:
dpkg -l sudo-ldap 2>/dev/null | grep '^ii' && echo "ACTION REQUIRED: sudo-ldap is removed in 26.04"

実務的な注意が2つある。ひとつめ。2つの実装は共存しており、どちらを使うかはupdate-alternativesで選択される。つまりsudo.wsをインストールしただけでは、切り戻しは半分しか終わっていない。sudo update-alternatives --config sudoまで実行して、初めてプロバイダが入れ替わる。ふたつめ。代替手段がまったく用意されていない削除がひとつある。sudo-ldapパッケージが消えた。sudoの認可ルールをLDAPに置いているなら、アップグレードの前にPAMベースのLDAP認証へ移す必要がある。そうしないと、ルールが単に存在しないシステムに着地することになり、権限昇格の経路をどう組んでいるかによっては、コンソールに触れないかぎり直せない状態になりかねない。これは実行順序が結果を決める、数少ない項目のひとつである。そして、切り戻しはあくまで退避先であって目的地ではない。sudoersファイルのほうを直しておけば、次のLTSで同じ問題を解き直さずに済む。

ls・sort・dateがRust実装になった

2つ目の驚きである。コアユーティリティがRust実装のrust-coreutilsになった。GNU版のバイナリも引き続きインストールされており、gnuという接頭辞が付く ― gnulsgnudategnusortといった具合だ。注目すべきなのは、cpmvrmはrust-coreutilsパッケージの中身としては依然GNU実装だという点で、未解決のバグを理由に据え置かれている。これは正しい判断である。つまり、データを破壊する能力が最も高いユーティリティ群こそが、変わっていない側だということになる。意見を固める前に知っておく価値のある事実がもうひとつある。26.04のリリースノートは、rust-coreutilsに対する既知のCVEを20件開示している。隠されているよりは開示されているほうがはるかに良いし、慌てるような話でもない ― ただしそれは、コアユーティリティを「決して動かない部分」という頭の引き出しに入れておくのではなく、パッチ適用の監視対象として扱うべきだ、ということを意味している。実際に問題が出るのは、対話的な利用ではなく、出力を解析しているスクリプトのほうだ。ls -lの桁揃え、dateのフォーマット指定子の細かい違い、sortのロケール依存の挙動、そして何よりエラーメッセージの文言 ― このあたりは「ほぼ同じ」であって「同一」ではない。監視スクリプトやログのパイプラインがstderrの文字列を見て分岐しているなら、そこは事前にテストしておく価値がある。どうしてもGNUの挙動が必要なら、パッケージ単位でまるごと戻すこともできるが、coreutilsはEssentialなので操作にはフラグが要るし、SSHセッション越しではなく復旧可能なコンソールから実行すること。[uutils]

# Core utilities now come from rust-coreutils (the uutils project). The GNU
# binaries are still installed, prefixed with `gnu`: gnuls, gnudate, gnusort...

ls --version | head -1        # uutils
gnuls --version | head -1     # GNU

# Worth knowing before you decide: the 26.04 release notes ship a list of
# twenty known CVEs against rust-coreutils (CVE-2026-35341 through -35377).
# That is disclosed, not hidden, and none of it is a reason to panic - but it
# is a reason to keep this package on your patching radar rather than assuming
# core utilities are the boring part of the system.

# cp, mv and rm are STILL the GNU implementations inside rust-coreutils, held
# back over unresolved bugs. So the utilities most likely to destroy data are
# the ones that did not change - which is the right call, and worth knowing
# before you go hunting for a regression in the wrong place.

# Where this actually bites: scripts that parse output, or lean on a GNU-only
# flag. Behaviour is close, not identical, and error text differs.
# Test the parsers, not the interactive use:
sort --help | grep -c . ; date --help | grep -c .

# --- Reverting, if a script you cannot change depends on GNU behaviour ---
sudo apt install coreutils-from-gnu --allow-remove-essential
# ...and back again:
sudo apt install coreutils-from-uutils --allow-remove-essential
# `--allow-remove-essential` is required because coreutils is Essential:yes.
# Read that flag as the warning it is: run it from a console you can recover,
# not over the SSH session you are about to need.

chronyがsystemd-timesyncdを置き換える ― ただしあなたの機械では違う

3つ目、そして私の経験上いちばん見落とされているのがこれである。既定の時刻同期デーモンがsystemd-timesyncdからchronyに変わった ― ただし新規インストールに限る。アップグレードしたサーバーはtimesyncdを保持し、そのまま動き続け、そして静かにドキュメントとも、ハードニングのベースラインとも、26.04を前提に書かれたあらゆる手順書とも一致しなくなる。Canonicalは手動移行の手順を文書化しているが、それを実行してくれるものは何もない。この差分は、単体では実害を生まない。実害が出るのは、新規構築したホストとアップグレードしたホストが同じクラスタに混在し、監視の期待値や構成管理のテンプレートがどちらか一方しか想定していないときだ。移行するにせよしないにせよ、「うちは全台timesyncdで統一する」または「全台chronyへ寄せる」のどちらかを明示的に選び、構成管理に落とすこと。いちばん悪いのは、選ばないまま両方が混ざることである。[chrony]

# Chrony replaces systemd-timesyncd as the default time daemon - but ONLY for
# fresh installs. An upgraded 24.04 server keeps timesyncd and will not tell
# you it is now off the default path. This is the change most likely to be
# missed, because nothing breaks: you just quietly stop matching the docs.

timedatectl show --property=NTP --property=NTPSynchronized
systemctl is-active systemd-timesyncd chrony 2>/dev/null

# --- The migration Canonical documents for upgraded systems ---
sudo apt-mark auto systemd-timesyncd     # demote it to an automatic dependency
sudo apt install chrony                  # installing chrony displaces timesyncd

# Verify you have exactly one time daemon running, not zero and not two:
systemctl is-active chrony
chronyc tracking
chronyc sources -v

# --- The trap, if you had ever edited chrony.conf ---
# Ubuntu's NTS-authenticated pool now lives in a separate drop-in file. If your
# old chrony.conf still lists servers, you will poll the same pool twice.
grep -E '^(server|pool)' /etc/chrony/chrony.conf
cat /etc/chrony/sources.d/ubuntu-ntp-pools.sources
# Keep the drop-in, comment out the duplicates in chrony.conf, then:
sudo systemctl restart chrony && chronyc sources -v

移行には向こう側に罠がある。UbuntuのNTS認証付きプールは、いまや/etc/chrony/sources.d/ubuntu-ntp-pools.sourcesに置かれている。過去にchrony.confを編集してpool行やserver行を残していた場合、同じサーバーを二重にポーリングすることになる。致命的ではないが、半年後に誰かが時刻のずれを調べたときに、意味の読み取りづらいchronycの出力を生む種類の問題である。

dracutがinitramfs-toolsを置き換える

4つ目である。既定のinitramfs基盤がinitramfs-toolsからdracutに変わった。ここはリリースノートの書き方が慎重で、こちらも同じく慎重であるべきところだ ― initramfs-toolsは引き続きサポートされ、2つの実装は相互に切り替えられる。アップグレードを終えたホストが実際にどちらを使っているかは、ブログ記事から推測してよい種類の事実ではない。この記事も含めて、である。まず確認し、そのうえで、分かったことに応じて動くこと。[dracut][dracutconf]

  • 推測せず、機械に聞くこと。 dpkg -l dracut initramfs-toolsで何が入っているかが分かり、dracut --versionでそれが実際に使える状態かが分かる。注意点がひとつある。lsinitrdには--versionフラグが存在しない。そのため、dracutの有無を判定するつもりで書かれたよくあるワンライナーは、誤った答えを返す。dracut --versionのほうを使うこと。
  • 設定の置き場所が変わる。 実際に乗り換えるのなら、/etc/initramfs-tools/はもう出番がない。dracutは/etc/dracut.conf.d/を読む。独自のフック、モジュール一覧、強制的に含めているドライバの指定は、すべてdracut向けに書き直す必要がある。そして、この書き直しこそが実際の作業であり、誰も代わりにやってはくれない。
  • イメージは中身を見る。再生成しない。 内容を一覧し、ストレージとネットワークのドライバが実際に入っていることを確認する ― NVMe、virtio、megaraid、mpt3sasなど、そのハードウェアやハイパーバイザが必要とするものだ。リリースアップグレードの直後、まだ2回の再起動を通していないホストの上でinitramfsを作り直すことは、このページに書かれている中で最も危険な行為である。

cgroup v1は消えた。アップグレードは拒否される

26.04のsystemd 259にはcgroup v1が一切ない。上流はsystemd 258でレガシー階層とハイブリッド階層を削除しており、起動時にマウントされるのはcgroup v2だけである。Canonicalはこれを不意打ちではなく明示的な関門にした ― 公式の表現では、「cgroup v1で動作しているUbuntuのインストールは、Ubuntu 26.04 LTSへのアップグレードを許可されない」。つまりここでの失敗の形はアップグレードの拒否であって、ホストが起動不能になることではない。これは良い結末のほうであり、この点は正確に書いておく価値がある。この変更を扱った記事の少なくない数が、そうではないかのような書き方をしているからだ。Ubuntu 24.04はすでにv2が既定なので、圧倒的多数のサーバーはこの線を何も気づかずに越えていく。問題になるのは例外のほうで、そしてその例外は痛い。確認に1分しかかからない項目のために、確保した作業窓を丸ごと失うことになるからである。[systemd258][cgroupv2]

# systemd 259 in 26.04 has NO cgroup v1. The legacy and hybrid hierarchies
# were removed upstream in systemd 258; only cgroup v2 is mounted at boot.
#
# Canonical turned that into a hard gate rather than a surprise: "Ubuntu
# installations running cgroup v1 will not be allowed to upgrade to Ubuntu
# 26.04 LTS." So the failure mode is a REFUSED upgrade, not a bricked host -
# which is the good outcome, and the reason to check now is that you would
# otherwise discover it inside your maintenance window.

stat -fc %T /sys/fs/cgroup/
# cgroup2fs   -> v2, the upgrade will proceed
# tmpfs       -> v1 or hybrid, the upgrader will refuse. Fix it first.

# The parameter is a systemd boolean: 0, false, no and off all select v1.
grep -o 'systemd.unified_cgroup_hierarchy=[^ ]*' /proc/cmdline
grep -o 'systemd.legacy_systemd_cgroup_controller=[^ ]*' /proc/cmdline

# --- Fix it on 24.04, reboot, and confirm the workload still works ---
sudoedit /etc/default/grub
#   remove systemd.unified_cgroup_hierarchy=0 from GRUB_CMDLINE_LINUX*
sudo update-grub && sudo reboot
# after the reboot:
stat -fc %T /sys/fs/cgroup/     # must print cgroup2fs

# Two related consequences that are easy to miss, both from the release notes:
#   - a 26.04 CONTAINER will not run on a host still booted with cgroup v1
#   - a 26.04 HOST will not run containers that require v1 (e.g. images based
#     on Ubuntu older than 18.04). Check your base images, not just your hosts.

# --- The other systemd deadline, and it is closer than you think ---
# 26.04 is the LAST release that runs System V init scripts. systemd 260 has
# already dropped the support upstream, so the release that loses it is 26.10
# - October 2026, not some comfortable date in 2028.
ls -1 /etc/init.d/ | grep -v README
systemctl list-units --type=service --no-pager | grep -i 'LSB:'

探すべきパターンは、カーネルのコマンドラインパラメータ、たいていはsystemd.unified_cgroup_hierarchy=0である。何年も前に、古いDockerや古いKubernetesノード、あるいはJVMの監視エージェントを動かすために追加され ― そして、その存在を誰にも思い出させるものがなかったために、そのまま残っている。当日ではなくいま見つけておくべき理由は単純で、作業窓の中で拒否されたところで、失った窓は返ってこないからだ。まず24.04の側でこのパラメータを外し、再起動し、ワークロードが問題なく動くことを確認してから、初めてアップグレードすること。見落としやすい副作用が2つある。cgroup v1で起動したままのホストの上では、26.04のコンテナが動かない。そして26.04のホストの上では、v1を必要とするコンテナ ― たとえば18.04より古いUbuntuをベースにしたイメージ ― が動かない。ホストだけでなく、ベースイメージのほうも確認すること。別件として、26.04はSystem V initスクリプトを実行できる最後のUbuntuリリースであり、その期限は見た目より近い。systemd 260はすでに上流でこのサポートを落としているので、実際にそれを失うリリースは26.10、2026年10月である。2028年のどこか余裕のある日付ではない。棚卸しはいまなら5分で終わる作業だ。/etc/init.d/の中身を一覧し、systemctl list-unitsの出力からLSB:を含む行を拾えば、残っているSystem Vスクリプトはすぐ分かる。たいていは商用エージェントか、10年前に誰かが書いた社内スクリプトである。26.04にいるあいだに本来のユニットファイルへ書き換えておけば、この先のリリースは何も考えずに越えられる。[since2510][mobycgroup][systemd260]

APT 3とapt-keyの廃止

APTが2.7から3.1に上がり、自動化を壊す変更はapt-keyの削除である。何年も前から非推奨だったが、互換のためのシムは用意されていない。署名検証はgpgvへ直接向かうようになり、各リポジトリは自分の鍵を明示的に指定しなければならない。apt-key addをまだ呼んでいるプロビジョニングスクリプトは26.04で失敗する。しかもその呼び出しはたいていブートストラップの早い段階にあるので、有用なことが何ひとつ起きないうちに失敗する。影響範囲はサーバー本体だけではない。Dockerfile、cloud-initのuser-data、Ansibleのロール、Packerのテンプレート、CIのジョブ定義 ― apt-keyという文字列は、想像より多くの場所に散らばっている。26.04のイメージを1つ作る前に、リポジトリ全体をgrepしておくこと。書き換え自体は機械的で、鍵を/etc/apt/keyrings/配下の独立したファイルへ置き、.sources側でSigned-Byとしてパスを指すだけである。[aptsecure][aptsources]

# APT 3 in 26.04 removes `apt-key` entirely. Verification goes straight to
# gpgv, and every repository must name its key explicitly.

apt --version                       # apt 3.1.x
command -v apt-key || echo "apt-key: gone, as expected"

# Find repositories that still rely on the deleted trusted keyring. These are
# what break: not the tool, the repositories that assumed it.
ls -l /etc/apt/trusted.gpg /etc/apt/trusted.gpg.d/ 2>/dev/null

# --- The replacement: one key per repository, referenced by path ---
# Create the directory explicitly. It exists on a normal install and does NOT
# on a minimal container image, which is exactly where bootstrap scripts run.
sudo install -m 0755 -d /etc/apt/keyrings
# Dearmor the key into its own file (note .gpg for binary, .asc for armoured):
curl -fsSL https://example.com/repo.asc \
  | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg
sudo chmod 0644 /etc/apt/keyrings/example.gpg

# Then point the repository at it. Modern deb822 format, /etc/apt/sources.list.d/example.sources:
#   Types: deb
#   URIs: https://example.com/apt
#   Suites: resolute
#   Components: main
#   Signed-By: /etc/apt/keyrings/example.gpg
#
# Or the one-line form, if you still use it:
#   deb [signed-by=/etc/apt/keyrings/example.gpg] https://example.com/apt resolute main

sudo apt update                     # any repo you missed fails loudly here

# --- Worth knowing about, not worth planning around ---
# APT 3 adds transaction history. It replays package operations; it does not
# restore data, and it cannot undo a release upgrade.
apt history-list
sudo apt history-undo <ID>

APT 3は新しい依存関係ソルバーも持ち込む。従来のソルバーが解を見つけられないときに自動的に働くもので、加えてapt history-undoapt history-rollbackによるトランザクション履歴が入った。ただし、この履歴機能に頼る前に仕様をよく読んでほしい。これはパッケージ操作を再生するものである。データを復元するわけではなく、あなたのデータベースのことを知っているわけでもなく、リリースアップグレードを取り消すこともできない。日常的なパッケージ操作の巻き戻しには便利だが、これをバックアップ戦略の代わりに数えてはいけない。新しいソルバーについても同様で、従来なら解けずに止まっていた状況を通してくれるぶん、意図しない大量の入れ替えが提案されることがある。aptの出力は、確認する前にyを押さず、削除されるパッケージの一覧を必ず読むこと。

Python 3.12から3.14へ ― 「死んだ電池」をまたぐ

Ubuntu 24.04はPython 3.12を、26.04は3.14を同梱する。つまりこのアップグレードは3.13、標準ライブラリのモジュールを19個削除したリリースをまたぐということだ。PEP 594に基づく削除で、捕まえるべき非推奨警告はもう残っていない。警告期間は3.11と3.12だったからである。代わりに手に入るのは実行時のImportErrorで、しかもそのimportに最初に到達したcronジョブ、フック、あるいはリクエストハンドラの中で起きる。厄介なのは、この失敗がアップグレード直後に出るとはかぎらないことだ。月次のバッチや、四半期に一度しか走らないレポート生成の中に該当するimportが埋まっていると、発覚は数週間後になる。だからこそ、アップグレード前に静的なgrepをかけておく価値がある。実行してみるのではなく、コードを読んで探すのがここでは正しい順序である。[py313][pep594]

# 24.04 shipped Python 3.12. 26.04 ships 3.14 as the system interpreter - so
# this upgrade crosses 3.13, the release that deleted nineteen standard-library
# modules under PEP 594. Nothing warns you: the import simply fails at runtime,
# in whichever cron job or handler happens to reach that line first.

python3 --version                   # Python 3.14.x

# Scan everything you own for the removed modules, before the upgrade. Note
# the module name is matched anywhere on an import line, not just directly
# after the keyword - otherwise `import os, cgi` slips straight through.
grep -rInE '^[[:space:]]*(import|from)[[:space:]].*\b(aifc|audioop|cgi|cgitb|chunk|crypt|imghdr|mailcap|msilib|nis|nntplib|ossaudiodev|pipes|sndhdr|spwd|sunau|telnetlib|uu|xdrlib)\b' \
  --include='*.py' /opt /srv /usr/local/lib /home 2>/dev/null

# The three that actually turn up on servers, and what to do about each:
#   cgi / cgitb -> old WSGI shims and form parsing. Move to the framework's
#                  parser, or `pip install standard-cgi` as a stopgap.
#   crypt       -> /etc/shadow hashing in provisioning scripts.
#                  Replace with `passlib` or a libxcrypt binding.
#   telnetlib   -> network-device automation. Replace with `netmiko`/`pexpect`,
#                  or better, stop using telnet.
# Pure-Python removals are republished on PyPI under `standard-*` names, which
# buys you a release cycle. It does not fix the code.

# Do not forget the interpreter under your virtualenvs: a venv created against
# 3.12 keeps pointing at a binary the upgrade removes. -xdev keeps this out of
# /proc, /sys and network mounts; -print0 survives paths with spaces.
find / -xdev -name pyvenv.cfg -print0 2>/dev/null \
  | xargs -0 -r grep -H 'version'   # rebuild every one of these afterwards

19個のうち3つは、サーバー上で本当によく見かける。古いWSGIシムやフォーム解析ヘルパーの中のcgicgitb/etc/shadowのハッシュを書くプロビジョニングスクリプトの中のcrypt、そしてネットワーク機器の自動化に使われるtelnetlibである。純Python実装のものはPyPIにstandard-接頭辞付きの名前で再公開されており、コードをきちんと直すためのリリースサイクル1本ぶんの猶予を稼げる。そしてvirtualenvを忘れないこと。3.12のバイナリに対して作られたものは、アップグレードが削除するインタプリタを指し続ける。pyvenv.cfgを探して回れば、忘れていた環境がいくつか出てくるはずだ。作り直し自体はrequirements.txtがあれば数分で終わるが、それが無い環境こそが本当の作業になる。アップグレードの前に、いま動いている状態でpip freezeを取っておきたい。これは事前棚卸しに追加する価値のある、たった一行の保険である。[py314]

そのクラウドインスタンスは、もうサポート対象外かもしれない

Ubuntu 26.04のAMD64向けクラウドイメージは、x86-64-v3というマイクロアーキテクチャレベル向けにビルドされている。この語は注意して読む必要がある ― 多くの解説がここを取り違えているからだ。動いたのはあらかじめ用意されたイメージのほうであって、アーカイブではない。x86-64-v3はv2のベースラインに、AVX、AVX2、BMI1、BMI2、F16C、FMA、LZCNT、MOVBE、OSXSAVEを加えたものである。これらを持たないCPUは、そもそもその命令を実行できない ― 性能設定ではなくハードウェアの下限であり、カーネルパラメータで和らげられる類のものでもない。判定はきわめて簡単だ。/proc/cpuinfoにAVX2があるかどうかを見れば、実用上はほぼ答えが出る。厳密にやるならフラグを1つずつ確認すること。所要時間は1台あたり数秒で、機械群全体でも構成管理から一括で流せる。アップグレードの計画に着手する前に、この1項目だけは全台ぶん集めておくことを勧める。該当ホストが1台でも見つかったなら、それはOSの作業ではなくインフラの移設案件であり、必要なリードタイムがまったく違うからである。[ltssummary][x86levels]

# Ubuntu 26.04 cloud IMAGES for AMD64 are built for the x86-64-v3
# microarchitecture level. Read that word carefully: it is the prebuilt images
# that moved, not the archive. The archive stays baseline x86-64, so an
# in-place upgrade still pulls baseline packages. What you lose on an old
# instance family is SUPPORT and a launchable image - not, by itself, the boot.
# That is a smaller problem than "it will not come back", and still one you
# want to solve before you build anything else on top of it.

# x86-64-v3 is the v2 baseline plus AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT,
# MOVBE and OSXSAVE. AVX2 is a decent proxy; the loop is the real check.
# Note `abm`: Linux exposes LZCNT under that capflag, and there is no `lzcnt`
# string in /proc/cpuinfo - grep for the obvious name and every host on earth
# reports a missing feature it actually has.
for f in avx avx2 bmi1 bmi2 f16c fma abm movbe osxsave; do
  grep -qw "$f" /proc/cpuinfo && echo "  $f yes" || echo "  $f MISSING"
done

# --- AWS: previous-generation families are out ---
# M1 M2 M3 M4 / C1 C3 C4 / R3 R4 / I2 / G3 / P2 P3 P3dn are no longer supported
# from 26.04. Note the [a-z]* before the dot: without it you miss p3dn and g3s,
# which are precisely two of the families you are hunting for.
aws ec2 describe-instances \
  --query 'Reservations[].Instances[].{Id:InstanceId,Type:InstanceType}' \
  --output text | grep -E '^\S+[[:space:]]+(m[1-4]|c[134]|r[34]|i2|g3|p[23])[a-z]*\.'
# The fix is a migration, not a config change: resize onto a current family
# (m6i/m7i, c6i/c7i, r6i/r7i) FIRST, then upgrade the OS.

# --- Google Cloud: N1 on Sandy Bridge or Ivy Bridge is out ---
gcloud compute instances list --format='table(name,zone,machineType,cpuPlatform)'

# --- Bare metal / on-prem: opt in only after you have checked every host ---
# The archive itself stays baseline x86-64; the v3 build is opt-in:
echo 'APT::Architecture-Variants "amd64v3";' | sudo tee /etc/apt/apt.conf.d/99enable-amd64v3
sudo apt update && sudo apt upgrade
プラットフォーム26.04以降サポートされないもの必要な対応
AWS EC2M1、M2、M3、M4/C1、C3、C4/R3、R4/I2/G3/P2、P3、P3dnこれらのための26.04イメージはビルドされない。先に現行世代ファミリー(m6i/m7i、c6i/c7i、r6i/r7i)へ移行する。
Google Compute EngineIntel Sandy BridgeおよびIntel Ivy BridgeのCPUプラットフォーム上のN1先にインスタンスを新しいCPUプラットフォームかマシンタイプへ移す。
ベアメタル/オンプレミス何もない ― アーカイブはベースラインのx86-64のままである対応不要。v3ビルドはapt.conf.dに1行加えるオプトインである。
IBM Z(s390x)z14世代(LinuxONE II)以前z15以降が新しい最低要件であり、ubuntu-release-upgraderがアップグレードそのものを差し止める。
RISC-VRVA23S64 ISAプロファイル未満のものRVA20ボード向けには24.04が引き続き対象リリースである。

実務上の帰結は、パニック版よりずっと狭い ― それでも手を打つ価値はある。AWSの前世代インスタンスファミリーは26.04以降サポートされず、それらのための26.04イメージもビルドされない。ただし、その場で実行するdo-release-upgradeはアーカイブからベースラインのamd64パッケージを取ってくるので、これは自動的に起動の問題になるわけではなく、まずサポートの問題である。とはいえ、誰もテストしていないハードウェアの上で、サポート対象外の組み合わせを本番の負荷にさらすというのは、意図して選ぶ立場ではない。重要な何かをM3で動かしているなら ― そして、10年間問題なく動いてきたという理由でそうしている人は驚くほど多いのだが ― まず現行世代ファミリーへリサイズし、そのあとにOSをアップグレードすること。ベアメタルでは、そもそも手を強制されることが何もない。アーカイブはベースラインのx86-64のままで、v3ビルドはあくまでオプトインである。オンプレミスでv3を有効化したい場合も、先に全ホストのCPUフラグを確認してからにしたい。同じラックの中に1世代古いサーバーが混じっているというのは、珍しくもなんともない話だ。そしてs390xとRISC-Vにも同種の下限が引かれている。IBM Zはz15以降が最低要件になり、しかもこちらはubuntu-release-upgraderがアップグレードそのものを差し止める。RISC-VはRVA23S64プロファイルが前提である。該当する環境では、これはリリースを選ぶ話ではなくハードウェアを選ぶ話になる。[awsprev]

サービス別 ― 本当に移行作業が必要なもの

バージョンが上がるだけなら、たいていは何事もなく終わる。以下に挙げるのは、メンテナ側が何かを変えたためにこちら側の作業が必要になるものである。放置した場合の被害が大きい順に並べている。上の3つは、OSのアップグレードとは切り離して、それぞれ独立した変更として計画すべきものだ。同じ作業窓に詰め込むと、何が原因で落ちているのかの切り分けができなくなる。なお、表のうちPostgreSQLとapache2の行は、Canonicalが公開している既知の問題(known issues)の一覧に由来するもので、この直後の節で詳しく扱う。

サービス変更点工数
RabbitMQフィーチャーフラグの都合で、この跳躍を直接アップグレードできない。 ― 手動手順が必要。独立したメンテナンスとして計画を。
Dovecot2.4で設定フォーマットが書き直された。 ― 設定移行を別プロジェクトとして扱うこと。
Samba AD/DCsamba-ad-dcパッケージをアップグレードの前に入れる必要がある。 ― 見落とすと実務上は取り返しがつかない。今日確認を。
PostgreSQL16 → 18はpg_upgradeが必要。加えてhuge_pages=onにしないとLinux 7.0の劣化を受ける。 ― 劣化は無言で進む。切り替える前にhuge pageのプールを見積もること。
apache2 + mod-phpユニットのMemoryDenyWriteExecute=yesがPHPのJITを壊す。中 ― php-fpmへ移るか、承知のうえで指定を上書きする。
HAProxy2.x → 3.2:URI解釈の厳格化、enabledの拒否、tune.ocsp-updateへの改名。中 ― 設定の修正のみ。事前にテストしやすい部類である。
Squid7.2でclient_delay_accessftp_epsv、持続接続系ディレクティブが削除。中 ― 削除済みディレクティブが残っているとデーモンが起動しない。
MySQL8.0 → 8.4 LTS。非推奨オプションが削除、32ビットサーバーも廃止。中 ― 設定の見直しは事後ではなく事前に。
SSSDrootではなくsssdユーザーとして動作するようになった。小 ― シークレットとkeytabへのアクセスを確認する。
Postfix既定でchroot内にインストールされなくなった。小 ― ただしchrootをカスタマイズしていたならパスを再確認すること。
OpenSSH9.6 → 10.2:DSAが削除、ポスト量子鍵共有が既定に。小 ― 通常は対応不要。DSAを必要とするクライアントがないか確認を。

RabbitMQが最上段にあるのは実力どおりである。フィーチャーフラグの都合で、この跳躍を直接アップグレードすることはできず、Canonicalも手動手順を文書化している。Dovecot 2.4は設定フォーマットそのものを書き直した ― OSアップグレードの副作用としてではなく、独立した変更として計画してほしい。HAProxyは2.x系から3.2へ移り、動的サーバーに対するenabledキーワードを拒否し、標準外のURIをより厳格に解釈し、tune.ssl.ocsp-updatetune.ocsp-updateに改名した。HAProxyについては幸い、事前検証が簡単である。3.2のバイナリを別環境に用意して既存の設定ファイルを構文チェックにかければ、拒否される項目がその場で列挙される。Squidも同様で、7.2で削除されたディレクティブが残っていると、警告ではなくデーモンの起動失敗として現れる。どちらも「設定ファイルを事前に通してみる」という30分の作業で、当日の不確実性がほぼ消える。[rabbitmq][dovecot24][haproxy32]

残りは平凡だが、自動的に終わるわけではない。PostgreSQL 18は16からのpg_upgradeが必要である。MySQLは8.0から8.4 LTSへ移り、長く非推奨だったオプションが削除され、32ビットサーバーのサポートもなくなった。SSSDはrootではなく非特権のsssdユーザーとして動くようになったので、シークレットやkeytabを引き続き読めるか確認しておきたい。Postfixは既定でchrootされなくなった。そしてSamba Active Directoryドメインコントローラを運用していてsamba-ad-dcパッケージを明示的に入れていない場合は、アップグレードの前にインストールすること。さもないとドメインコントローラの機能が生き残らず、しかもそれを直すために必要なコンポーネントが、まさにインストールされなかったものになる。データベースを持つサービスについては、もうひとつ原則がある。pg_upgradeにせよMySQLの8.4移行にせよ、実行前のダンプは「取ってあること」ではなく「復元してみたことがあること」に意味がある。取得しただけのバックアップは、統計的にはかなりの割合で復元できない。作業窓の見積もりには、この確認の時間も入れておくこと。[postgres18][mysql84][sssd]

サーバーに実際に噛みついてくる2つの既知の問題

Canonicalはリリースノートと並べて既知の問題の一覧を公開しており、そのうちの2件は、26.04について書かれたほとんどの記事より具体的である。どちらもアップグレードを止めはしない。どちらも、その後のサーバーの振る舞いを静かに変える。そして、探すべき場所を知らなければ、あなたはその変化を別の何かのせいにすることになる。1つ目はapache2だ。そのsystemdユニットは、ハードニングの一環としてMemoryDenyWriteExecute=yesを設定するようになった。これは書き込み可能かつ実行可能なメモリを禁じる指定であり ― まさにJITコンパイラが必要とするものである。libapache2-mod-phpの下ではこれがPHPのJITを壊し、ログにはAllocation of JIT memory failedが並び、誰もOSのアップグレードと結び付けない性能低下が残る。推奨される対処はphp-fpmへ移ることだ。そちらは影響を受けない。どうしてもmod-phpに留まるのなら、systemctl edit apache2で意図的にこの指定を上書きすること ― ただし、それはバグを直しているのではなく、緩和策をひとつ切っているのだと理解したうえで。[since2510][apachebug]

# Both of these are in Canonical's own known-issues list for 26.04, and both
# are more concrete than most of what gets written about this release. Neither
# stops the upgrade; both change how your server behaves afterwards.

# --- 1. apache2 + mod-php: the PHP JIT stops working ---
# The apache2 systemd unit now sets MemoryDenyWriteExecute=yes as hardening.
# That forbids memory that is writable and executable at once, which is exactly
# what a JIT needs. Symptom:
#   Warning: preg_match(): Allocation of JIT memory failed, PCRE JIT will be disabled.
dpkg -l 'libapache2-mod-php*' 2>/dev/null | grep '^ii'

# Recommended fix: move to php-fpm, which is not affected. Note the a2dismod -
# without it apache2 keeps loading mod_php and the JIT stays broken, which is
# the most common way this "fix" gets applied and then reported as not working.
sudo apt install php-fpm
sudo a2dismod php8.5 && sudo a2dismod mpm_prefork
sudo a2enmod mpm_event proxy_fcgi setenvif && sudo a2enconf php8.5-fpm
sudo systemctl restart apache2 php8.5-fpm

# If you must stay on mod-php, override the hardening deliberately - and
# understand that you are turning off a mitigation, not fixing a bug:
sudo systemctl edit apache2
#   [Service]
#   MemoryDenyWriteExecute=no
sudo systemctl restart apache2

# --- 2. PostgreSQL on the 7.0 kernel: throughput and latency regression ---
# A Linux 7.0 change can cost PostgreSQL significant throughput and latency.
# Systems using huge pages are NOT affected, so this is a configuration
# question rather than a wait-for-a-patch question.
sudo -u postgres psql -tAc 'SHOW huge_pages;'      # want: on

# huge_pages=try (the default) silently falls back to normal pages, which is
# how you end up affected without any error telling you so.
#
# Size the pool FIRST. PostgreSQL will compute the number for you - no
# arithmetic, no guessing at shared_buffers overhead:
sudo -u postgres postgres -D /var/lib/postgresql/18/main \
     -C shared_memory_size_in_huge_pages
# 3170
grep -E 'Hugepagesize|HugePages_Total' /proc/meminfo
sudo sysctl -w vm.nr_hugepages=3170                # use YOUR number, then
                                                   # persist it in /etc/sysctl.d/
# ...and only now turn it on:
sudo -u postgres psql -c "ALTER SYSTEM SET huge_pages = 'on';"
sudo systemctl restart postgresql
# huge_pages=on means PostgreSQL REFUSES TO START if the pages are not
# available. That is the point - it fails loudly instead of quietly slowly -
# but it means you size the pool before you flip the setting, not after.

2つ目はPostgreSQLで、こちらは誤診されるほうに賭けてもいい類の問題である。Linux 7.0での変更が、スループットとレイテンシに無視できない劣化を引き起こしうる ― ただし、huge pagesを使っているシステムは影響を受けない。つまりこれは、パッチを待つ問題ではなく設定の問題だということだ。厄介なのは、PostgreSQLの既定であるhuge_pages=tryが、通常のページへ黙ってフォールバックすることである。そのため、影響を受けているサーバーは何も報告しない。エラーも警告も出ず、ただ先週より数字が悪いだけだ。huge_pages=onを意図して設定すること。そして、その前にhuge pageのプールを見積もっておくこと。onは、ページが確保できないならPostgreSQLは起動を拒否するという意味だからである。これは正しい取引だ ― 静かに遅くなるより、大きな音を立てて落ちるほうがよい ― が、長い作業窓の最後に切り替えるような設定ではない。[pghugepages][pgkernel][systemdexec]

アップグレードを実行する

ここに賢いことは何もない。価値はすべて順序の中にあり、そしてステップ0を飛ばさないという一点にある。所要時間は環境にもよるが、20分から60分を見込んでおきたい。そのあいだ接続が切れてもプロセスが死なないよう、tmuxかscreenの中で実行するのは必須である。do-release-upgrade自身も1022番ポートに予備のsshdを立ち上げるが、それはあくまで最後の砦であって、最初から頼るべき仕組みではない。[upgradedoc]

# Nothing below is clever. The value is entirely in the order and in refusing
# to skip step 0.

# --- 0. A rollback you have actually tested ---
# Snapshot the VM, or take a filesystem-level backup you have restored from at
# least once. `do-release-upgrade` has no undo, and neither does apt history.
# If you cannot roll back, you are not upgrading, you are gambling.

# --- 1. Land on a fully patched 24.04 first ---
sudo apt update && sudo apt full-upgrade
sudo apt --purge autoremove
sudo reboot                        # boot the newest 24.04 kernel BEFORE upgrading
uname -r

# --- 2. Survive a dropped connection ---
# The upgrade takes 20-60 minutes and will kill your shell if the link drops
# mid-transaction. do-release-upgrade opens a standby sshd on 1022 by itself;
# run it inside tmux or screen anyway.
sudo apt install tmux
tmux new -s upgrade
# detach with Ctrl-b d, reattach after a disconnect with: tmux attach -t upgrade

# --- 3. Run it ---
sudo do-release-upgrade
# Answer the config-file prompts from the list you produced in the pre-flight.
# Default is "keep your currently-installed version" (N). For sshd_config and
# anything security-relevant, take the maintainer's version and re-apply your
# changes as a drop-in afterwards - your 2019 hardening file is not better
# than the 2026 defaults.

# --- 4. Reboot and verify, in this order ---
sudo reboot
lsb_release -ds                    # Ubuntu 26.04.1 LTS
uname -r                           # 7.x
systemctl --failed                 # must be empty
journalctl -p err -b --no-pager | head -50
ss -tlnp                           # every listener you expect, and nothing new

# --- 5. Clean up what the upgrade left behind ---
sudo apt --purge autoremove        # read the list before confirming
ls /etc/apt/sources.list.d/        # re-enable third-party repos, resolute suites
dpkg -l | grep '^rc' | wc -l       # removed-but-not-purged leftovers

ひとつだけ、声に出して言っておく価値のある判断がある。既定の答えがつねに正しいとはかぎらないからだ。設定ファイルの変更について尋ねられたとき、自分のバージョンを保持するのはアプリケーション設定にとっては安全な選択だが、セキュリティに関わるものにとってはたいてい誤った選択である。2019年に書いたあなたのsshd_configハードニングは、2026年の既定値より優れてはいない。ただし、この助言には明白な但し書きが付く。メンテナ版のsshd_configを受け入れるということは、そのファイルの中に置いていた独自のPortAllowUsersPermitRootLoginMatchブロックも一緒に捨てるということであり、しかもsshdは、あなたがそれらを再適用し終える前に再起動する ― いままさにアップグレードに使っている、その接続の上で、である。1022番ポートの予備セッションは開いたままにしておくこと。そのうえで、本当に必要なローカルの変更だけをsshd_config.d/のドロップインとして再適用し ― そこなら次回のアップグレードも手を出さない ― そこまで済ませてから、最初のシェルを閉じること。この原則はsshd_config以外にも当てはまる。PAMの設定、login.defs、監査ルール、TLSのポリシーファイル ― 上流が2年かけて更新してきたものは、たいていあなたが2019年に書いたものより良くなっている。逆に、アプリケーション固有の設定 ― nginxのvhost、アプリのユニットファイル、DBのチューニング ― は、あなたの側が正しい。この2つを区別できていれば、対話プロンプトは怖くない。

事後の検証を、きちんとやる

「起動しました」は検証ではない。これは事前棚卸しスクリプトの対になるものである ― ただし、使い方については正確を期しておきたい。2つのスクリプトは意図的に異なる節を出力するので、片方をもう片方に対してまるごとdiffしてはいけない。直接比較する価値があるのは、有効なサービスの一覧とss -tlnpの2つのブロックである。同じユニットが有効で、同じポートが待ち受けていること。以前は有効だったサービスがいま無効になっているとしたら、それに気づくのはここであるべきだ ― 月曜日に誰かがチケットを起票したときではない。それ以外に見るべきものも決まっている。systemctl --failedが空であること、ss -tlnpに見覚えのないリスナーが増えていないこと、そしてjournalctl -p err -bの先頭50行である。これらが揃えば、「起動しました」は「同じ役割を果たしています」に格上げされる。

#!/usr/bin/env bash
# noble-postflight.sh - the counterpart to the pre-flight script. The two print
# DIFFERENT sections on purpose, so do not diff them against each other
# wholesale. The blocks that are directly comparable are the enabled-services
# list and `ss -tlnp`: same units enabled, same ports listening.
# "It booted" is not a verification; "the same 41 services are enabled and
# listening on the same ports" is.
set -uo pipefail

echo "=== the defaults that changed under you ==="
sudo --version | head -1                    # sudo-rs, unless you reverted
update-alternatives --display sudo | head -2
ls --version | head -1                      # uutils, unless you reverted
systemctl is-active chrony systemd-timesyncd 2>/dev/null   # exactly one active
stat -fc %T /sys/fs/cgroup/                 # cgroup2fs

echo "=== which initramfs generator is this host ACTUALLY using? ==="
# Both are supported in 26.04 and either can be in place after an upgrade, so
# do not assume - ask. (lsinitrd has no --version; dracut does.)
dpkg -l dracut initramfs-tools 2>/dev/null | grep '^ii' || true
command -v dracut >/dev/null && dracut --version

echo "=== crypto, which moved a long way in two years ==="
ssh -V                                      # OpenSSH 10.2p1 in 26.04, from 9.6p1
ssh -Q kex | grep -c mlkem                  # post-quantum key agreement offered
# OpenSSL spells these with hyphens - ML-KEM-768, not mlkem - so grep for both
# or you will "prove" that a correctly configured box has no PQ support.
openssl list -kem-algorithms | grep -ciE 'ml-?kem'

echo "=== DSA host keys are gone; make sure nothing still expects one ==="
ls /etc/ssh/ssh_host_*_key 2>/dev/null
sudo sshd -t && echo "sshd config: valid"

echo "=== services ==="
systemctl --failed --no-pager
systemctl list-unit-files --state=enabled --type=service --no-pager --no-legend | awk '{print $1}'
ss -tlnp

echo "=== rebuild every virtualenv that pointed at python3.12 ==="
find / -xdev -name pyvenv.cfg 2>/dev/null

echo "=== the two server known-issues from the release notes ==="
# 1. apache2 now sets MemoryDenyWriteExecute=yes, which breaks the PHP JIT
#    under libapache2-mod-php. php-fpm is unaffected and is the recommendation.
dpkg -l libapache2-mod-php\* 2>/dev/null | grep -q '^ii' && \
  echo "mod-php present -> move to php-fpm, or: systemctl edit apache2 (MemoryDenyWriteExecute=no)"
# 2. A Linux 7.0 change can cost PostgreSQL significant throughput and latency.
#    Systems using huge pages are not affected.
command -v psql >/dev/null && sudo -u postgres psql -tAc 'show huge_pages'
#    Anything other than `on` here is worth fixing before you call this done.

echo "=== boot integrity: inspect, do not regenerate ==="
# READ ONLY on purpose. Regenerating the initramfs immediately after a release
# upgrade is the riskiest thing you could do on this page; look first.
# /boot/initrd.img-* is mode 0600 root:root, hence the sudo on both branches.
if command -v lsinitrd >/dev/null; then
  sudo lsinitrd | grep -E 'nvme|virtio|megaraid|mpt3sas' | head
elif command -v lsinitramfs >/dev/null; then
  sudo lsinitramfs /boot/initrd.img-"$(uname -r)" | grep -E 'nvme|virtio|megaraid|mpt3sas' | head
else
  echo "neither lsinitrd nor lsinitramfs present - install the tool matching your generator"
fi

スクリプトでは代われない確認が2つある。ひとつはnetplanの設定である。26.04はNetplan 1.2を同梱し、ルーティング可能なインターフェースを待つ独自のsystemd-networkd-wait-onlineを含む。そのため、NICの立ち上がりが遅いホストは以前とは違う起動の仕方をする可能性がある。もうひとつは、事前棚卸しで洗い出したサードパーティのリポジトリすべてだ。Signed-Byで鍵を指定したうえでresoluteスイートへ向け直し、apt updateがクリーンに通ることを確認すること。ベンダーのセキュリティ更新を静かに受け取らなくなった機械群こそ、このアップグレードが失敗したことに最も気づきにくい形である。もうひとつ、済ませておくと安心なのがinitramfsの確認だ。ただし、ここでやるのは中身を見ることであって、作り直すことではない。lsinitrd(initramfs-toolsのままならlsinitramfs)でイメージの内容を一覧し、NVMe、virtio、megaraid、mpt3sasといった必要なドライバが実際に含まれていることを確かめておきたい。この2分の確認は、次に再起動が必要になったとき ― それはたいてい、あなたが選んだタイミングではない ― に効いてくる。[netplan]

結論:いまか、11月か、2027年か

丁寧な現場でも雑な現場でもこれをやってきた立場からの、正直な助言である。結論だけ先に言えば、急ぐ理由はどこにもなく、しかし準備を先送りする理由もない。作業そのものは後ろ倒しにしてよいが、調査は今日始めるべきだ。

  1. 8月27日にアップグレードしないこと。 ポイントリリースは不具合を吸収するために存在するが、そこで捕まえきれなかったものは続く2週間のうちに表面化する。見つけるのは、本番環境が持つべきよりも高いリスク許容度を持った人たちである。
  2. 9月上旬に、重要でないサーバーを1台だけアップグレードすること。 興味深い程度には現実的な機械 ― ビルドエージェントや社内ツールなど ― で、それでいて誰からも呼び出しがかからないもの。事前・事後のスクリプトを実行し、その差分を保管しておく。その差分が、残り全部に対する移行ドキュメントになる。
  3. アップグレードを拒否させる2つの条件を、先に、全台で潰すこと。 cgroup v1で起動したままのホストと、IBM Z z14以前で動いているもの ― この2つはアップグレーダにきっぱり拒否される。作業を段取りする前に、まず見つけておくこと。同じ棚卸しにAMD64v3のインスタンスファミリーも入れておきたい。こちらは拒否こそされないが、サポート対象外の組み合わせで動かすというのはひとつの選択であり、それは意図された選択であるべきだ。3つとも、アップグレードの意思決定とは無関係に、今日、24.04の上で確認できる。
  4. 残りは10月から11月にかけてまとめて処理すること。 その頃には、依存しているサードパーティのリポジトリにもresoluteスイートが揃い、残っていた摩擦のほとんどが消えている。

そして、サマリだけでなく既知の問題(known issues)のページを読んでほしい。これはリリース後に更新されるもので、まさにその性質こそが欲しいものである。サマリは「何を意図したか」を教えてくれるが、既知の問題の一覧は「実際に何が起きたか」を教えてくれる。そして、パイロット機で見つけた差分は必ず文書に残すこと。2台目以降は、その文書があるかどうかで所要時間が桁違いに変わる。移行は1回きりの出来事ではなく、24.04のときも同じことをしたはずだし、28.04のときも同じことをする。毎回ゼロから始めないための投資として、これほど安いものはない。[since2510]

どのみちinitと定期実行まわりに手を入れるのなら、systemdタイマーとcronの比較がこのリリースで先送りできなくなった移行を扱っている。アップグレードのSSHとTLSの側面はポスト量子SSHとTLSの主題で、パッケージではなく接続の側で何を検証すべきかを掘り下げている。そしてこの記事を読んで、そもそもアップグレードすべき可動部を減らしたくなったのなら、それがまさに退屈なクラウドアーキテクチャの主張である。

よくある質問

2026年8月27日より前に、Ubuntu 24.04から26.04へアップグレードできますか?

技術的には可能です。開発版のアップグレード経路を対象にするdo-release-upgrade -dを使えば実行できます。ただし本番サーバーでやるべきではありません。ポイントリリースは、リリース後4か月ぶんの不具合を吸収するためにこそ存在します。前倒しで強行するということは、リリースアップグレーダ自体のバグを最初に踏む人になるということです。1時間で復元できるノートPCなら妥当な行為ですが、実トラフィックを抱えたサーバーでは違います。どうしても早く検証したいのであれば、本番と同じ構成のステージング機を1台用意し、そこで-dを使ってください。得られる情報は同じで、失うものがありません。

そもそもアップグレードは必要ですか?24.04はいつまでサポートされますか?

Ubuntu 24.04 LTSの標準セキュリティメンテナンスは2029年4月まで、Ubuntu Proを使えばESMで2034年4月まで延長されます。2026年8月の時点で切迫している事情は何もありません。アップグレードする理由は、あなた自身のツールチェーンが先に進むからです ― 新しいPython、新しいPostgreSQL、新しい言語ランタイム。留まり続けると、最終的にすべてを自分でバックポートすることになります。凍結はアプライアンスや退役予定の環境にとっては正当な選択であり、いまも構築を続けているプラットフォームにとっては悪い選択です。判断の軸は「サポート期限」ではなく「自分たちが何を載せ続けるつもりか」です。

メンテナンスの作業枠をいちばん失いやすい変更はどれですか?

残置されたsystemd.unified_cgroup_hierarchy=0というカーネルパラメータです。systemd 259にはcgroup v1が一切なく、Canonicalはこれを明確な関門にしました。cgroup v1で起動したままのホストは、アップグレードを許可されません。壊れた機械が手に入るわけではありません ― ダウンタイムを1時間見積もった、まさにその時点で拒否が返ってくるのです。2位はLinux 7.0カーネル上でのPostgreSQLの劣化です。1位と違ってエラーがまったく出ず、ただ数字が悪くなるだけだからです。どちらも24.04の上で、今日、1分もかからずに確認でき、日付を決める前に片付けられます。

sudo-rsは本番環境で使って安全ですか?

圧倒的多数のシステムが実際に持っているsudoers設定 ― ユーザーとグループの指定、ホスト指定、NOPASSWD、コマンドエイリアス、includedir ― に関しては安全です。注意が必要なのは周辺部です。sudo-rsはDefaultsエントリの全種類を実装しているわけではなく、リソース制限とumaskはPAM側へ移り、sendmail連携はなくなりました。未対応のディレクティブに出会ったときの文書化された挙動は、黙って無視することではなく、明確なエラーを出して拒否する(fail closed)ことです。安全な方向ではありますが、確認していなかったディレクティブが1行あるだけで、sudoこそが物事を直す手段である機械の上でsudoが動かなくなる、という意味でもあります。なお、受理したうえで無視される短い列挙集合が例外として存在し、そのいずれもアクセスを緩める方向には働きません。アップグレードの前にsudoersファイルを監査してください。切り戻しが必要になった場合、2つの実装は共存しています。sudo.wsをインストールし、update-alternatives --config sudoで選択してください ― パッケージを入れるだけではプロバイダは切り替わりません。

アップグレード後もDockerコンテナは動きますか?

ほぼすべてのケースで動きます。Ubuntu 24.04はすでにcgroup v2が既定で、モダンなDockerは何年も前からv2に対応しているからです。例外は、古いDockerやKubernetesノードを動かすためにカーネルコマンドラインへsystemd.unified_cgroup_hierarchy=0を設定したことがあるホストです。systemd 259はcgroup v1を完全に削除しており、そうしたホストはアップグレード自体をきっぱり拒否されます。stat -fc %T /sys/fs/cgroup/を確認してください ― cgroup2fsと表示される必要があります。関連して見落としやすい制約が2つあります。cgroup v1で起動したままのホストの上では26.04のコンテナが動きません。そして26.04のホストの上では、v1を必要とするコンテナ ― たとえば18.04より古いUbuntuをベースにしたイメージ ― が動きません。ホストだけでなく、ベースイメージのほうも確認してください。

アップグレード後にPythonスクリプトが動かなくなったのはなぜですか?

ほとんどの場合、Python 3.13で削除されたモジュールに対するImportErrorです。Ubuntu 24.04はPython 3.12を、26.04は3.14を同梱するため、このアップグレードはPEP 594に基づいて19個の標準ライブラリモジュールを削除したリリースをまたぎます。サーバー上で最も頻繁に現れる3つはcgicrypttelnetlibです。純Python実装の削除分はPyPIにstandard-接頭辞付きの名前で再公開されており、当面のしのぎになります。別件として、3.12のバイナリに対して作られたvirtualenvは作り直しが必要です。指しているインタプリタがもう存在しないからです。

systemd-timesyncdからchronyへ移行する必要はありますか?

厳密には必要ありません。timesyncdは引き続き動作し、アップグレードしたサーバーはそれを保持します。ただしchronyは26.04の新規インストールでの既定です。何もしなければ、アップグレードしたホストと新規構築したホストが分岐し、26.04を前提に書かれた手順書やハードニングのベースラインが一致しなくなります。Canonicalは移行手順をapt-mark auto systemd-timesyncdのあとにapt install chronyと文書化しています。移行する場合は、chrony.confに残っているサーバー指定が/etc/chrony/sources.d/ubuntu-ntp-pools.sourcesのドロップインと重複していないか確認しておいてください。

アップグレードが失敗した場合、ロールバックできますか?

Ubuntuのツール群にその手段はありません。do-release-upgradeにundoはなく、新しいapt history-undoもパッケージ操作を再生するだけでシステムを復元するものではありません ― あなたのデータのことを知らず、リリースアップグレードを巻き戻すこともできません。ロールバック手段はVMのスナップショットか、少なくとも一度は実際に復元してみたことのあるファイルシステムレベルのバックアップです。それがないのであれば、あなたがやっているのはアップグレードではなく、期待値は高いが下振れが青天井の賭けです。

その下で動くコンテナランタイムも動いている。API の下限、イメージストア、そしてエラーも出さずに変わったファイルディスクリプタ上限についてはDocker Engine 29 に上げると何が壊れるかを参照。

参考資料

上記の主張はすべて、以下のいずれかに遡ることができる。Ubuntu固有の事柄についてはCanonicalのリリースノートとスケジュールが典拠であり、それ以外は上流プロジェクトのドキュメントである。公式のノートがバージョンを明記していない箇所については、数字を推測せず、機能として記述している。

  1. Canonical — Ubuntu 26.04 LTS (Resolute Raccoon) release notes; released 23 April 2026, supported until April 2031
  2. Canonical — Ubuntu 26.04 LTS summary for LTS users: the authoritative list of changes since 24.04, and the source for every default swap described here
  3. Canonical — Ubuntu 26.04 LTS changes since 25.10, including the known-issues list and the cgroup v1 removal detail
  4. Canonical — Resolute Raccoon release schedule; the 26.04.1 point release is listed for Thursday 27 August 2026
  5. Ubuntu Server documentation — How to upgrade your release (do-release-upgrade, the -d flag, and the LTS-to-LTS point release rule)
  6. Canonical — Ubuntu 24.04 LTS (Noble Numbat) release notes, the baseline this article upgrades from
  7. Canonical — Ubuntu release cycle: LTS cadence, five years of standard support, ESM through Ubuntu Pro
  8. Canonical — Ubuntu Pro documentation (ESM, Livepatch, and the ten-year maintenance window on 24.04)
  9. Trifecta Tech Foundation — sudo-rs, the memory-safe sudo and su implementation that is now Ubuntu's default sudo provider
  10. uutils/coreutils — the Rust reimplementation of the GNU core utilities shipped as rust-coreutils
  11. systemd v258 release notes — removal of cgroup v1 (legacy and hybrid hierarchies) and the raised kernel baseline
  12. systemd NEWS — the upstream changelog covering v256 through v259, including the System V compatibility deprecation
  13. Linux kernel documentation — Control Group v2, the only hierarchy systemd still mounts
  14. moby/moby #51111 — Docker's cgroup v1 deprecation discussion and support timeline
  15. apt-secure(8) — repository signing after the removal of apt-key, and the Signed-By mechanism that replaces it
  16. sources.list(5) — the deb822 .sources format and the Signed-By field
  17. dracut(8) — the initramfs infrastructure that replaces initramfs-tools as Ubuntu's default
  18. dracut.conf(5) — configuration in /etc/dracut.conf.d/, including hostonly and the drivers to force-include
  19. chrony.conf(5) — the configuration file, source directories and NTS options for Ubuntu's new default time daemon
  20. What's New In Python 3.13 — the release that removed the nineteen PEP 594 'dead battery' standard-library modules
  21. PEP 594 — Removing dead batteries from the standard library; the full list of removed modules and their replacements
  22. What's New In Python 3.14 — the interpreter Ubuntu 26.04 ships as the system Python
  23. OpenSSL 3.5 series release notes — ML-KEM, ML-DSA and SLH-DSA support and the default hybrid TLS groups
  24. OpenSSH release notes index — covers the 9.6 to 10.2 range that this upgrade crosses, including DSA removal
  25. NIST FIPS 203 — Module-Lattice-Based Key-Encapsulation Mechanism Standard (ML-KEM), the algorithm behind the new OpenSSL and OpenSSH defaults
  26. AWS — previous generation EC2 instances; the families that lose Ubuntu support because of the AMD64v3 cloud image baseline
  27. x86-64 microarchitecture levels — what x86-64-v3 requires (AVX2, BMI1/2, FMA, MOVBE)
  28. RabbitMQ — upgrade documentation and feature flags, the reason RabbitMQ is not directly upgradable across this release
  29. Dovecot — upgrading from 2.3 to 2.4, the release that rewrote the configuration format (26.04 ships 2.4.2)
  30. HAProxy 3.2 configuration manual — the breaking changes since the 2.x series shipped in 24.04
  31. PostgreSQL 18 release notes — the major version 26.04 ships, requiring pg_upgrade from 16
  32. MySQL 8.4 LTS release notes — the series replacing 8.0, including removed deprecated options
  33. Netplan 1.2 documentation — the series shipped in Ubuntu 26.04
  34. SSSD 2.10 release notes — the change that makes the daemon run as the unprivileged sssd user rather than root
  35. systemd v260 release notes — System V service script support already dropped upstream, which is why 26.10 is the release that loses it
  36. PostgreSQL documentation — the huge_pages configuration parameter, the documented mitigation for the Linux 7.0 regression
  37. PostgreSQL documentation — configuring Linux huge pages for the server
  38. LP #2144455 — apache2's MemoryDenyWriteExecute hardening breaking the PHP JIT under libapache2-mod-php
  39. systemd.exec(5) — MemoryDenyWriteExecute=, the hardening directive apache2 now sets by default

Was this useful?