apt リポジトリの GPG 鍵が期限切れで apt update が失敗するときの対処法
現象
apt update 実行時に以下のようなエラーが出る。
W: GPG error: https://dl.yarnpkg.com/debian stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 62D54FD4003F6525 W: GPG error: https://oss-binaries.phusionpassenger.com/apt/passenger noble Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY D870AB033FB45BD1 Ansible の apt モジュールでは update_cache: yes を指定すると、この Warning を失敗として扱い Failed to update apt cache after 5 retries: で止まる。エラーメッセージの理由部分が空なので原因がわかりにくい。
原因
サードパーティ apt リポジトリ(yarn, Passenger 等)の GPG 署名鍵には有効期限がある(通常1〜3年)。Ubuntu 公式リポジトリの鍵は ubuntu-keyring パッケージで自動更新されるが、手動追加したリポジトリの鍵は手動で更新が必要。
対処法
1. 鍵の取得・登録
鍵を /usr/share/keyrings/ に dearmor 形式で保存する。
# yarn curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg \ | sudo gpg --dearmor -o /usr/share/keyrings/yarn.gpg # Passenger(2つの鍵を使用しているため、両方取得) (curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x561F9B9CAC40B2F7'; \ curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xD870AB033FB45BD1') \ | sudo gpg --dearmor -o /usr/share/keyrings/passenger.gpg 2. sources ファイルを Signed-By 形式に移行
旧形式(.list)から DEB822 形式(.sources)に移行し、Signed-By で keyring ファイルを指定する。
# /etc/apt/sources.list.d/yarn.sources Types: deb URIs: https://dl.yarnpkg.com/debian/ Suites: stable Components: main Signed-By: /usr/share/keyrings/yarn.gpg # /etc/apt/sources.list.d/passenger.sources Types: deb URIs: https://oss-binaries.phusionpassenger.com/apt/passenger Suites: noble Components: main Signed-By: /usr/share/keyrings/passenger.gpg 旧形式のファイルは削除する。
3. 検証
sudo apt update Warning が消えていれば成功。
ハマりポイント
Passenger は2つの GPG 鍵を使っている
Passenger 公式の auto-software-signing-gpg-key.txt が返す鍵(561F9B9CAC40B2F7)と、Release.gpg の署名に使われる鍵(D870AB033FB45BD1)が異なる。公式ドキュメント通りにやると片方しか登録されず apt update が失敗する。
keyserver の HTTP API から両方取得するのが確実。
root の ~/.gnupg が存在しない環境
sudo gpg --keyserver を使おうとすると No dirmngr エラーになることがある。keyserver の HTTP API(https://keyserver.ubuntu.com/pks/lookup)を curl で叩けば dirmngr に依存せず鍵を取得できる。
Ansible apt モジュールの挙動
update_cache: yes で Warning が出ると、Ansible はリトライ後に失敗として扱う。エラーメッセージに理由が表示されないため、サーバー上で直接 apt update を実行して原因を確認するのが早い。