- はじめに — 遅延はなくせませんが、管理はできます
- まず確認すること — updateinfo は生きているか
- 何が滞留しているかを数えます
- 適用します
- 2 つのスナップショットの差分を審査資料にします
- ミラー容量を管理します
- ロールバック — 戻せるものと戻せないもの
- 持ち込み周期を設計します
- 運用チェックリスト
- おわりに — 遅延を隠さないでください
- 自分で試す
- シリーズ全体
- 参考資料
はじめに — 遅延はなくせませんが、管理はできます
接続網サーバーのセキュリティ対応はこうです。勧告が出て、その日に dnf update --security を回して、終わりです。
閉域網はこうです。勧告が出て、次の持ち込み周期を待ち、外側でパッケージを取得し、審査に上げ、媒体を持ち込み、リポジトリを更新し、サーバーに適用します。速くて数日、普通は数週間です。
この遅延は構造から出てきます。手順をどれだけ磨いても 0 にはなりません。ですから今回の目標は遅延をなくすことではなく、測定可能にし、緊急経路を別に用意し、その事実を組織に知らせること です。
まず確認すること — updateinfo は生きているか
運用編の大部分は dnf updateinfo から出発します。ところが閉域網では、このコマンドが何も出力しないことが非常によくあります。
# 何が滞留しているかを数えてみる
dnf updateinfo --summary
# 何も出てこないなら、たいていはリポジトリ側の問題です
理由は第 5 回のモジュール問題と同じ構造です。どのパッケージがどの勧告に属するかは、rpm ファイルの中ではなくリポジトリメタデータに あります。createrepo_c が rpm から生成するのは primary、filelists、other であり、勧告情報は rpm の中にないので作り出すことができません。createrepo_c の man ページに --keep-all-metadata("Keep additional metadata during update (default)") が別途あるのも、この付加メタデータが別個の存在だからです。
そこでこう分かれます。
dnf reposync --download-metadataで取得したなら勧告情報も一緒に来ます。この場合、持ち込み後にcreaterepo_cを再実行しないでください。作り直すと失われますdnf downloadで rpm だけを集めてcreaterepo_cでリポジトリを作ったなら勧告情報はありません。このリポジトリでは--security系がすべて無意味になります
2 番目の状態で dnf update --security を回すと、エラーなしで「やることなし」と出ます。静かに何もしないという点が危険です。持ち込み手順の検証段階に、この 1 行を入れておいてください。
# 持ち込みリポジトリが勧告情報を持っているか確認 — 0 なら手順が間違っている
dnf updateinfo --summary | tail -5
何が滞留しているかを数えます
勧告情報が生きているなら、現状把握はコマンド数行です。RHEL 9 公式セキュリティドキュメントの表記をそのまま使います。
# まだ適用していないセキュリティ更新の一覧
dnf updateinfo list updates security
# すでに適用済みのセキュリティ更新 (監査対応用)
dnf updateinfo list security --installed
# 特定の勧告の詳細 (CVE 番号と説明を含む)
dnf updateinfo info RHSA-2019:0997
# CVE を参照する勧告だけを絞り込む
dnf updateinfo list --with-cve
ドキュメント基準で --with-cve は "print only advisories referencing a CVE"、--with-bz は "print only advisories referencing a bugzilla" です。可用性の指定子は --available(デフォルト)、--installed、--updates、--all の 4 つです。
RHEL 9 セキュリティドキュメントにある dnf updateinfo list updates security の出力はこういう形です。
RHSA-2019:0997 Important/Sec. platform-python-3.6.8-2.el8_0.x86_64
RHSA-2019:0997 Important/Sec. python3-libs-3.6.8-2.el8_0.x86_64
RHSA-2019:0990 Moderate/Sec. systemd-239-13.el8_0.3.x86_64
2 列目が深刻度です。これで持ち込みの優先順位を決められます。
適用します
# 利用可能なセキュリティ更新をすべて適用
sudo dnf update --security
# 特定の勧告だけを適用
sudo dnf update --advisory=RHSA-2019:0997
# 特定の勧告を最小のバージョン変更だけで適用
sudo dnf upgrade-minimal --advisory=RHSA-2019:0997
# 特定の CVE だけを指定して適用
sudo dnf update --cve=CVE-2019-9636
# 深刻度で範囲を絞る
sudo dnf update --sec-severity=Important
dnf ドキュメントの定義では、--security が "Includes packages that provide a fix for a security issue"、--advisory=<advisory> が "Include packages corresponding to the advisory ID"、--cve=<cves> が "Include packages that fix a CVE ID"、--sec-severity=<severity> が "Includes packages that provide a fix for an issue of the specified severity" です。
upgrade-minimal は閉域網で特に有用です。ドキュメントの説明は "Updates each package to the nearest available version that provides a bugfix, enhancement or a fix for security issue" です。セキュリティ修正は受け取りつつ、バージョンの変化を最小に保つ ので、変更範囲が狭くなって審査を通しやすく、回帰のリスクも減ります。閉域網の定期パッチのデフォルトにする価値があります。
適用のあとに残る作業が 1 つあります。
# 再起動が必要なプロセスを確認
dnf needs-restarting
RHEL 9 ドキュメントはこのコマンドに重要な但し書きを付けています。このコマンドはプロセスだけを列挙し、サービスではないので "you cannot restart processes listed using the systemctl utility" です。出力に出たものをそのまま systemctl に渡してはいけない、という意味です。
2 つのスナップショットの差分を審査資料にします
定期持ち込みでいちばん面倒なのが、「今回は何が変わりますか」という質問に答えることです。dnf repodiff がその仕事をします。ドキュメントの定義は "repodiff is a program which will list differences between two sets of repositories" です。
# 前回の持ち込みスナップショットと今回のものを比較する
dnf repodiff \
--repofrompath=old,/srv/repo-snapshots/2026-07-14/baseos \
--repofrompath=new,/srv/repo-snapshots/2026-08-15/baseos \
--repo-old=old --repo-new=new \
--archlist=x86_64 \
--size
# 1 行の要約形式で (審査文書に添付しやすい)
dnf repodiff \
--repofrompath=old,/srv/repo-snapshots/2026-07-14/baseos \
--repofrompath=new,/srv/repo-snapshots/2026-08-15/baseos \
--repo-old=old --repo-new=new \
--archlist=x86_64 --simple --downgrade
ここで必ず知っておくべきデフォルトがあります。ドキュメントは "Note that by default only source packages are compared" と明記しています。--archlist を指定しなければバイナリパッケージは比較されません。ドキュメントは --archlist、-a を "Add architectures to change the default from just comparing source packages. Note that you can use a wildcard * for all architectures" と説明しています。
残りのオプションは、--size、-s が "Output additional data about the size of the changes"、--simple が "Output a simple one line message for modified packages"、--downgrade が "Split the data for modified packages between upgraded and downgraded packages"、--compare-arch が名前だけでなくアーキテクチャまで比較対象に入れるオプションです。
この出力を持ち込み審査の添付にそのまま使えば、審査する側が「何が変わるのか」を根拠を持って判断できます。
ミラー容量を管理します
持ち込みを繰り返すとリポジトリは大きくなり続けます。かといって古いバージョンをすべて消せばロールバックが不可能になります。dnf repomanage がこの均衡を取ってくれます。ドキュメントの説明は "repomanage prints newest or older packages in a repository specified by <path> for easy piping to xargs or similar programs" です。出力するだけで削除はしないという点が重要です。
# 各パッケージの最新 2 バージョンだけ残し、残りを確認する
dnf repomanage --old --keep 2 /srv/repo/rhel9-baseos
# 実際に削除する (一覧を先に目で確認したあとだけ)
dnf repomanage --old --keep 2 /srv/repo/rhel9-baseos | xargs -r rm -v
# 整理後にメタデータを作り直す
sudo createrepo_c --update /srv/repo/rhel9-baseos
ドキュメント基準で --old は "Show older packages (for a package or a stream show all versions except the newest one)"、--new は "Show newest packages"、-k、--keep は "Limit the resulting set to newest <keep-number> packages" です。
いくつ残すかが、そのままロールバック可能な範囲になります。持ち込み周期が月 1 回で 3 つ残すなら、およそ 3 か月分のロールバックが可能です。容量とロールバック範囲を同じ天秤に載せて決めてください。
ロールバック — 戻せるものと戻せないもの
パッチ後に問題が起きたときの手順です。
# トランザクション履歴を確認
dnf history
# 特定のトランザクションの内容を確認
dnf history info 42
# そのトランザクション 1 つだけを戻す
sudo dnf history undo 42
# 指定時点以降をすべて戻す (指定したトランザクション自体は維持)
sudo dnf history rollback 41
RHEL 9 ドキュメントは undo の動作をこう説明します。トランザクションがパッケージをインストールしていれば削除し、削除していれば再インストールし、更新されたパッケージについては以前のバージョンが まだ利用可能な場合にかぎり ダウングレードを試みます。そして "If an older package version is not available, the downgrade by using the dnf history undo command fails" と明記しています。
閉域網では、この一文がそのまま前節の保管ポリシーにつながります。古いパッケージを消していればロールバックは失敗します。
そして必ず守るべき境界が 1 つあります。RHEL 9 ドキュメントはこう警告しています。
"Downgrading RHEL system packages to an older version by using the
dnf history undoanddnf history rollbackcommand is not supported. This concerns especially the selinux, selinux-policy-*, kernel, and glibc packages, and dependencies of glibc such as gcc."
つまりカーネル、glibc、SELinux ポリシーは履歴の巻き戻しで扱ってはいけません。こうしたものの回帰対応は、ロールバックではなく 別の経路 で準備しておく必要があります。カーネルなら以前のカーネルで起動する方法があり、それ以外はスナップショットやシステムイメージのレベルでの復旧が現実的な答えです。この境界を手順書に明記しておけば、事故が起きた時点での判断が速くなります。
持ち込み周期を設計します
ここが今回の核心となる設計です。経路を 1 つしか用意しないと必ず失敗します。2 つ用意します。
| 区分 | 定期持ち込み | 緊急持ち込み |
|---|---|---|
| 周期 | 月 1 回など固定 | 事由が発生したとき |
| 発動条件 | スケジュール | 深刻度 Critical の勧告、または組織が定めた CVE 基準 |
| 範囲 | リポジトリ全体のスナップショット | 該当勧告に関係するパッケージのみ |
| 適用コマンド | dnf upgrade-minimal --security | dnf update --advisory=<ID> |
| 審査 | 標準手順 | 事前に合意された短縮手順 |
| 検証 | 全体の回帰テスト | 該当サービスのみ |
緊急経路の核心は 平時にあらかじめ合意しておくこと です。事故が起きたあとで短縮手順を作ろうと言い出すと、その議論だけで数日かかります。
遅延を測ることも忘れないでください。
#!/usr/bin/env bash
# patch-lag.sh — 滞留しているセキュリティ勧告を深刻度別に数える
set -euo pipefail
echo "== 調査時刻: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "== リポジトリスナップショット"
grep -h '^name=' /etc/yum.repos.d/airgap-*.repo || true
echo "== 滞留しているセキュリティ勧告の要約"
if ! dnf updateinfo --summary 2>/dev/null | grep -q .; then
echo "警告: updateinfo メタデータがありません。持ち込み手順を確認してください。"
exit 2
fi
dnf updateinfo --summary
echo "== 深刻度別の詳細"
for sev in Critical Important Moderate Low; do
n="$(dnf updateinfo list updates security 2>/dev/null | grep -c "${sev}/Sec." || true)"
printf '%-10s %s\n' "${sev}" "${n}"
done
この出力を定期報告に入れれば、パッチ遅延は「感覚」ではなく数字になります。数字になれば、持ち込み周期を短くしようという議論が可能になります。
Red Hat 公式セキュリティドキュメントの手順は、その多くが前提条件として "A Red Hat subscription is attached to the host" を明記しています。閉域網サーバーはこの条件を満たさない場合が多いので、勧告情報は持ち込みリポジトリのメタデータを通して入ってこなければなりません。前の第 1 節が重要な理由がここにあります。
サブスクリプションなしに Red Hat コンテンツを再配布することは契約違反になりうるので、組織のライセンス条件を先に確認してください。勧告メタデータも Red Hat コンテンツに含まれます。
運用チェックリスト
手順書のいちばん前に貼っておいて使う用途のものです。
持ち込み準備 (接続網)
- リリースバージョンを固定したか (
--releaseverまたは/etc/dnf/vars/releasever) - 空の
--installrootで依存関係を解決したか - モジュールを使うシステムなら
module_platform_idを指定したか -
reposyncに--download-metadataを付けたか (勧告とモジュール情報の保存) -
dnf repoclosureが通ったか -
MANIFEST.tsvを生成したか (NEVRA、チェックサム、スナップショット日付、releasever) - GPG 公開鍵をバンドルに含めたか
- 生成コマンドを
PROVENANCE.txtに記録したか -
dnf repodiffの出力を審査資料として添付したか
持ち込み後 (閉域網)
- マニフェストとチェックサムを突き合わせたか
-
rpmkeys --checksigがすべて通ったか - マニフェストにないファイルが媒体にないか確認したか
- リポジトリメタデータを作り直す必要があるか判断したか (
--download-metadataで取得したなら再生成は禁止) -
.repoファイルにgpgcheck=1が明記されているか -
dnf clean expire-cacheのあとdnf repolist -vでパッケージ数を確認したか -
dnf updateinfo --summaryが空になっていないか -
dnf repoclosureを実際のリポジトリ構成で改めて回したか
適用と事後
-
dnf upgrade-minimal --securityで変更範囲を最小化したか -
dnf needs-restartingの結果を処理したか -
dnf historyのトランザクション ID を運用記録に残したか - ロールバック可能な範囲 (
repomanage --keepの値) を確認したか - カーネル・glibc・SELinux を履歴ロールバックの対象から外したか
- パッチ遅延の数値を定期報告に反映したか
おわりに — 遅延を隠さないでください
閉域網の運用でいちばん危険な態度は、パッチ遅延を恥じて報告から外すことです。遅延は閉域網を選んだ対価であり、その選択はたいてい技術ではなく規制がしたものです。
やるべきことは、遅延を 数字にし、緊急経路をあらかじめ開けておき、その数字を定期的に見せること です。そうしてはじめて「持ち込み周期を月 1 回から隔週に短縮しよう」という議論が、勘ではなく根拠の上で行われます。
7 回分の結論は 1 つに集まります。閉域網では反復可能なものだけが生き残ります。マニフェストとチェックリストがその反復を作ります。
コマンドとオプションは 2026-08-15 に公式ドキュメントで確認しました。RHEL のバージョンによって異なるので、使用中のバージョンのドキュメントで改めて確認してください。
自分で試す
- Linux ターミナル — パッチ遅延の測定スクリプトを組み立ててみる
- Linux コマンドクイズ — dnf の運用コマンドを復習する
- コンテナラボ — イメージの更新周期をパッケージの周期と併せて設計してみる
シリーズ全体
- 閉域網インストールが難しい本当の理由
- 外側で取得する — dnf download, reposync, yumdownloader
- ローカルリポジトリを作る — createrepo_c と GPG 鍵
- 持ち込み手順と完全性 — 再現可能なバンドル
- モジュールとバージョン固定
- コンテナイメージの持ち込み
- 運用プレイブック (この記事)
閉域網 Kubernetes の運用は Day 2 運用編 に続きます。
参考資料
현재 단락 (1/139)
接続網サーバーのセキュリティ対応はこうです。勧告が出て、その日に `dnf update --security` を回して、終わりです。