Ubuntu Weekly Recipe

第812回aptの新機能あれこれ [Ubuntu 24.04 LTS版]

「apt」は言わずとしれたUbuntuの基本を担うパッケージ管理システムです。今回はUbuntu 24.04 LTSに搭載されたapt 2.8.0に関して、前回のLTSである22.04の「apt 2.4.12」以降に実装されたり、さらには古いLTSにもバックポートされたりした機能について紹介しましょう。

ちなみにaptの機能紹介は本連載でも何度か行っています。より古いバージョンからアップグレードする場合は、そちらも参照してください。

これらの記事では公開当時最新の2.3.6までしか紹介できていなかったので、2.3.6から2.4.12までの機能についてもまとめて紹介する予定です。

「apt 2.8.0」とは?

もう既にUbuntu 24.04 LTSをインストールし、aptのバージョンを確認しているのであれば、⁠24.04のaptは2.7.14では?」と思われたかもしれません。実はこれは24.04のリリースノートにも記述されていることなのですが、4月末時点において、apt 2.8.0はまだ正式なアップデートとしては提供されていない状態です。

Ubuntu 24.04 LTSではセキュリティ対策の一貫として、rsa2048、ed25519、ed448以上の鍵で署名されたリポジトリしか許容しないことになりました[1]。これはたとえばrsa1024の鍵で署名されたリポジトリを使う場合、aptコマンドで「エラーになってしまう」ことを意味します。apt 2.7.14まででは一時的な措置として「エラーではなく警告扱いとする」対応が取られていましたが、apt 2.8.0でエラーとするよう処理が変更されました。

しかしながら、Ubuntuにおいてサードパーティのリポジトリとしてよく使われるPPAにおいて、2014年より前に作られたアカウントのリポジトリ鍵はrsa1024となるという問題が存在しています。これは同じアカウントで新規にPPAリポジトリを作成してもrsa1024となってしまいます。具体的にはそのようなリポジトリを追加すると次のような警告が表示されます。

W: https://ppa.launchpadcontent.net/(略)/InRelease: Signature by key (略) uses weak algorithm (rsa1024)

これがapt 2.8.0だと警告ではなくエラーになってしまうのです。過去にユーザー側でリポジトリ鍵を再生成するインターフェースを用意することも検討されましたが、今のところ実装されているわけではありません。そこでPPA側の鍵については、Launchpad側で自動的にrsa4096で再署名する処理が進んでいる状況のようです[2]。ただし2024年4月末時点でもこの対応は完了しておらず、古くから存在する多くのリポジトリがrsa1024のままとなっています。

apt 2.8.0は、これらの対応が一通り完了されてから取り込まれる見込みです。ちなみに2.7.14と2.8.0の差分はこの警告をエラーにする変更と、ドキュメント上のURIやテストの修正にとどまっており、本件以外の機能的な違いはほとんどありません。

deb822形式への移行

利用者にとっての一番大きな変更点はやはりリポジトリ情報がdeb822形式になったことでしょう。これは第810回Ubuntu 24.04 LTSの変更点でも言及しているとおり/etc/apt/sources.listがコメントアウトされ、/etc/apt/sources.list.d/ubuntu.sourcesという形の新しいフォーマットで記録されたというものです。

deb822形式だと複雑なオプションが人間にも機械にも読みやすくなっている
$ cat /etc/apt/sources.list.d/ubuntu.sources
## Ubuntu distribution repository
(中略)
## See the sources.list(5) manual page for further settings.
Types: deb
URIs: http://jp.archive.ubuntu.com/ubuntu
Suites: noble noble-updates noble-backports
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

## Ubuntu security updates. Aside from URIs and Suites,
## this should mirror your choices in the previous section.
Types: deb
URIs: http://security.ubuntu.com/ubuntu
Suites: noble-security
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
従来のsources.listファイルはただのコメントアウトとなっている
$ cat /etc/apt/sources.list
# Ubuntu sources have moved to the /etc/apt/sources.list.d/ubuntu.sources
# file, which uses the deb822 format. Use deb822-formatted .sources files
# to manage package sources in the /etc/apt/sources.list.d/ directory.
# See the sources.list(5) manual page for details.

実はこの機能(deb822形式)そのものは古くから存在し、apt 1.1からは*.sources形式として使えるようになったため、第677回でも部分的に紹介していました。従来の1行フォーマットだと、多少の設定を追加することは可能ではありましたが、いかんせん一行での記述はいろいろと無理が生じていました。そこでdeb822形式では、空行でブロックを区切り、各ブロックをキー・バリューのフォーマットにすることで、読みやすさと拡張性を両立させています。

おそらくdeb822形式における現時点での最大の利点はメタデータにリポジトリ鍵を埋め込めるようになったということでしょう。詳しい事情は第675回apt-keyはなぜ廃止予定となったのかを参照してほしいのですが、aptにおいて「リポジトリを追加する」というのは、⁠リポジトリの公開鍵を取得する」⁠リポジトリのメタデータを追加する」の2段階の手順を意味していました。これによりそのリポジトリの所有者(公開鍵と対になる秘密鍵を持っている人)が、リポジトリで配布しているパッケージを作成した(署名した)ことを検証できるわけです。

1段階目の手順として、過去には「apt-key」コマンドが使われていたものの、このコマンドで登録した鍵は、他のリポジトリの検証でも参照されてしまうという問題がありました。そこでUbuntu 22.04 LTS以降ではリポジトリの公開鍵を/usr/local/share/keyrings以下に配置し、それをsources.list等からdeb [signed-by=/usr/local/share/keyrings/foo.gpg] ...のように参照することが従来スタイルにおける定番の手順となっていたのです[3]

これがdeb822形式を使うと、次のように記述できます。

Types: deb
URIs: https://ppa.launchpadcontent.net/cosmos-door/build/ubuntu/
Suites: noble
Components: main
Signed-By:
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 .
 mI0ESXT/dwEEAK5ZJF7rYtDdYJQakL+Jp1TmQS6H/6s36NQQl5ppvqqRmkegjqVx
 vjf27ksZWFkwNu/K+4gj3QPNQa/f8uZhIk7USqS3vplgx3V2MI5IyOmF5mL6ndNQ
 vvsjm7zBQB7qfnDVBdshBzty4J6DpiqIebn5puDVWC89EzoVFuytgdctABEBAAG0
 IUxhdW5jaHBhZCBQUEEgZm9yIE1pdHN1eWEgU2hpYmF0YYi2BBMBAgAgBQJJdP93
 AhsDBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQZa/sBpluxTwzUQQAmMgMxLTN
 4YSAEuRhgQpE5u8BkcTekKuxkEw8UM3TRfid8cbtxLqnpSyNrg3hCh8LcnofPy63
 3wXqEu1u+V5f1jxzAgI0ajtg7aprnDWdl4TjIavuz5R8zRXmcxs6ajQr8BXww4G/
 yt/ZsVTWo7xK+QWLFxdrOLxg7A1E8kV/uZI=
 =eid5
 -----END PGP PUBLIC KEY BLOCK-----

Signed-By:キーの値としてASCII形式の公開鍵をそのまま書けてしまうのです。これによりdeb822形式を使えば、リポジトリを追加する際の手順は「リポジトリのメタデータを追加する」のワンステップで完了します[4]

ちなみに*.sourcesファイルならdeb822形式で、*.listなら従来形式で解釈されるため、引き続き併用可能です。しかしながら既に「deb822形式でしか使えないオプション」も存在し、今後もそれは増えていくことになるでしょう。もし比較的新しいUbuntu向けの自家製のリポジトリを公開しているのであれば、deb822形式に変換することをおすすめします。

apt installやupgrade時にapt updateを実行するオプション

これまでパッケージをインストールするステップはsudo apt updateしてからsudo apt install FOOsudo apt upgradeするのが定番でした。これが24.04のaptでは、sudo apt install FOO -Usudo apt upgrade -Uだけで、sudo apt update相当の処理も実行してくれるようになります。つまりコマンド1回でリポジトリ情報の更新とパッケージのアップグレードやインストールが行えるようになったわけです。

もう少し詳しく説明すると、最初のsudo apt updateはリポジトリ情報の更新を意味しています。つまりリポジトリにあるパッケージのリスト、提供している最新のバージョンなどが含まれているデータです。リポジトリの情報を更新しなくてもインストールが可能なことは多いのですが、その場合は必ずしも最新版がインストールされるわけではありませんし、運が悪いと「リポジトリから削除されたバージョン」をインストールしようとしてエラーになってしまいます。そのため、何かパッケージをインストールする場合は、⁠あらかじめsudo apt updateする」ことが一般的だったのです。

apt 2.7.0ではapt installapt upgradeなどを含むapt-get系のコマンドに-U--updateオプションを付けると、この「あらかじめsudo apt updateする」ことを肩代わりしてくれるのです。別にこれまでもワンライナーを書けばできていたことではありますが、タイプ量が減るのはうれしいことでしょう。

ちなみにupdateとその他の処理はアトミックに行われるわけではありません。つまりAPT関連のファイルのロックはupdate処理と、その他の処理で別々に取得しようとします。update完了後、その他の処理を開始する前に他のプロセスがAPTのロックを取ってしまうと、他の処理はエラー終了してしまうので注意してください。

snapshot.ubuntu.comで特定日時のリポジトリにアクセスできるようになった

一般的にUbuntuのパッケージリポジトリは「その時点での最新の状態」のみが提供されます。また、そのリポジトリの更新は任意のタイミングで行われます。その結果として、次のような問題が発生しうるのです。

  • ステージング環境でapt update && apt upgradeを実行した状態でデプロイした
  • その状態で特に問題ないことが確認できた
  • 本番環境でapt update && apt upgradeを実行した状態でデプロイした
  • 実はステージング環境に対していくつかのパッケージが更新されていたため、ステージング環境と本番環境で中身が異なってしまっていた

もちろんコンテナのイメージを配布するなどの対策を取れば回避できますが、それでもベアメタルなマシンには使えません。そこで出てくるのがAptlyなどを利用して自前のミラーサーバーを用意し、そこで随時リポジトリスナップショットを取って活用することになるでしょう。大規模な数の運用である場合は、自前のミラーサーバーはほぼ必須であるためスナップショットの用意もそこまで大変ではありませんが、規模が小さくなると手間のほうが上回ってしまいます。

そこで登場したのがsnapshot.ubuntu.comです。これは何かと言うと、指定した日時のリポジトリの状態を返してくれるUbuntuパッケージリポジトリです。たとえばhelloパッケージは、4月末時点での最新版は「2.10-3build1」です。よってapt install helloすると、このバージョンがインストールされます。

$ apt policy hello
hello:
  インストールされているバージョン: (なし)
  候補:               2.10-3build1
  バージョンテーブル:
     2.10-3build1 500
        500 http://jp.archive.ubuntu.com/ubuntu noble/main amd64 Packages

これを「2024年4月1日01時23分45秒(UTC⁠⁠」時点でのリポジトリからhelloパッケージをインストールしたい場合は次のように実行します。

$ sudo apt install hello --update --snapshot 20240401T012345Z
(中略)
取得:6 https://snapshot.ubuntu.com/ubuntu/20240401T012345Z noble InRelease [255 kB]
取得:7 https://snapshot.ubuntu.com/ubuntu/20240401T012345Z noble-updates InRelease [89.7 kB]
取得:8 https://snapshot.ubuntu.com/ubuntu/20240401T012345Z noble-backports InRelease [90.8 kB]
取得:9 https://snapshot.ubuntu.com/ubuntu/20240401T012345Z noble-security InRelease [90.7 kB]
(中略)
取得:1 https://snapshot.ubuntu.com/ubuntu/20240401T012345Z noble/main amd64 hello amd64 2.10-3 [26.2 kB]
26.2 kB を 2秒 で取得しました (14.2 kB/s)
以前に未選択のパッケージ hello を選択しています。
(データベースを読み込んでいます ... 現在 180207 個のファイルとディレクトリがインストールされています。)
.../hello_2.10-3_amd64.deb を展開する準備をしています ...
hello (2.10-3) を展開しています...
hello (2.10-3) を設定しています ...
man-db (2.12.0-4build2) のトリガを処理しています ...
install-info (7.1-3build2) のトリガを処理しています ...

--updateオプションによってリポジトリ情報の更新が行われ、--snapshot 20240401T012345Zオプションで指定した日付のリポジトリを参照した結果、一個古いバージョン(2.10-3)のhelloパッケージがインストールされています。ちなみに初めて指定するリポジトリ日時は、それなりの量のリポジトリ情報がダウンロードされる--updateの実行に時間がかかる)点に注意してください。

特定の日時はYYYYMMDDThhmmssZで指定します。UTCで指定する必要があるため、たとえばdate -u -d "$(date -u -Iseconds)" +'%Y%m%dT%H%M%SZ'などで変換すると良いでしょう[5]

--snapshot-S⁠」オプションは、apt installだけでなくapt policyのようなapt-cache系のコマンドの一部でも指定可能です。恒常的に特定のスナップショットを参照したい場合は、.sourcesファイルに次のように記述します。

Types: deb
URIs: http://jp.archive.ubuntu.com/ubuntu
Suites: noble noble-updates noble-backports
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Snapshot: 20240401T012345Z

ちなみにこの機能自体はUbuntu 20.04 LTS、22.04 LTSにもバックポートされています。手順としては上記と同じで良いのですが、あらかじめsources.listにsnapshot=yesを記述しなくてはなりません。

deb [snapshot=yes] http://archive.ubuntu.com/ubuntu/ jammy main restricted

また、過去にたどれるのは「2023年3月1日」までです。今後「最大2年間分はサポートする」とのことですが、利用状況次第では変わる可能性はありそうです。冒頭ではデプロイ時の用途のみに言及していましたが、不具合追求などでもかなり役に立つことでしょう[6]

他にも、環境変数NO_COLORに任意の値を設定したり、/etc/apt/apt.conf.d/などでbinary::apt::APT::Color "0";と記述すれば、aptコマンドの色付けを無効化できるとか、apt install時にdebファイルを指定した際の補完方法が賢くなったとか、apt検索時のパターンマッチングが強化されなど、細かい変更点はいろいろ存在します。

Ubuntu 24.04 LTSに更新する際は、ぜひ新しいaptの機能にも着目してください。

おすすめ記事

記事・ニュース一覧