Ubuntuのパッケージリポジトリのスナップショットを作成したり、独自パッケージリポジトリを作成したいならaptlyが便利です。今回はこのaptlyの使い方について紹介します。
パッケージリポジトリの管理ツールである「aptly」
aptlyは「パッケージリポジトリの管理ツール」と題した、独自パッケージのリポジトリや部分的なミラーリポジトリを作成・管理するためのCLIツールです。具体的には次のような機能を提供します。
- 公式パッケージリポジトリのパッケージすべてもしくは一部のミラーリング
- パッケージリポジトリのスナップショットの作成
- ローカルパッケージリポジトリの作成
- リポジトリ間のマージ・更新
- HTTP経由で作成したリポジトリを公開
- REST APIを使ったリポジトリの操作
フルミラーも可能ではありますが、リポジトリのメタデータを署名するために使用するGPG鍵は公式リポジトリと異なる鍵を生成・利用します。このため「jp.archive.ubuntu.com」のような公式のミラーリポジトリとは異なり、作成したリポジトリを利用する場合は、PPAのような非公式リポジトリのようにGPG鍵をapt-key
コマンドで取り込まなければならないことに注意が必要です。
リポジトリのスナップショット機能は、多数のマシンに構成管理ツールなどを用いて環境を構築する際に真価を発揮するでしょう。一般的に通常のUbuntuリポジトリは、ディストリビューション側(リポジトリ側)の都合にあわせて任意のタイミングでパッケージが更新されます。つまり同じようにインストールしたとしてもタイミングによってインストールされるパッケージのバージョンが異なってしまう可能性が存在します。構成管理ツールを用いてバージョン指定でパッケージをインストールする方法もありますが、そのバージョンのパッケージファイルがいつまでリポジトリに存在するかはリポジトリのポリシー次第です。よって複数台のマシンの環境を完全に合わせるのであれば、ローカルにパッケージのスナップショットを作成する必要があります。aptlyを使えば、これを簡単に実現できるのです。
ローカルパッケージリポジトリの作成は、独自にDebianパッケージを作成しそれを特定のネットワーク環境内部にのみ公開したい場合に便利です。Ubuntuの場合はPPAを使うという手が存在するものの、アーキテクチャに縛りがあったり、非公開リポジトリを作る場合は有料だったりと、いくつかの制約が存在します。マシン内で閉じた簡易的なリポジトリでよければdpkg
コマンドやapt-ftparchive
コマンドを使って構築することも可能ではありますが、提供するパッケージ数が増えてきたり、ネットワーク越しに公開したい場合に手間がかかります。aptlyを使えば、ミラーやスナップショットと同じ要領でローカルパッケージの提供が行えますし、部分的に公式リポジトリの内容をマージすることも可能です。
まだ実験的ではありますが、REST APIを用いてリポジトリの操作を行えます。CIツールと組み合わせてテストが通ったパッケージを自動的にリポジトリに追加する際に役に立つことでしょう。
単に公式パッケージのミラーサイトを作りたいだけであれば、第47回の後半で紹介しているapt-mirrorが存在します。こちらはフルミラーですのでストレージのリソースをそれなりに使用するものの、リポジトリのメタデータやパッケージの署名は公式の状態をそのまま維持するため、apt-key
による鍵の追加は不要になるというメリットがあります。また、実際にインストールするパッケージのみキャッシュしたいということであれば、第315回で紹介したapt-cacher-ngが便利です。こちらはsources.list
を変更する必要すらなく、プロキシサーバーを指定する要領で構築したキャッシュを利用できます。
どちらのツールもaptlyほど柔軟な管理は行えませんが、設定や環境構築がシンプルというメリットがあります。目的・用途に応じて使い分けるとよいでしょう。
aptlyのインストール
aptlyのパッケージは公式リポジトリにも存在しますが、Ubuntu 16.04 LTSで0.9.6、開発中の17.10で1.0.1と最新の1.1.1に比べると若干古いです。特に16.04上で運用するとなると、1.x系にあげておきたいところでしょう。そこで今回は公式サイトのリポジトリからインストールすることにします。
DebianとUbuntuで同じパッケージなので、リポジトリのURL部分はUbuntuであっても「squeeze
」のままでかまいません。
aptlyを運用するためにはリポジトリ用のGPG鍵が必要になります。普段使っているGPG鍵でも実装上は問題ありませんが、リポジトリ用に別の鍵を作るほうが無難です。またリポジトリ用のデータベースはaptlyを実行したユーザーのホームディレクトリに作られるため、aptly専用のユーザーを作ることも考えたほうがいいでしょう[1]。可能であればLXDのようにコンテナの中に閉じ込めてしまいましょう。今回はaptlyユーザーを作って、その中で作業を行います。
aptlyユーザーに切り替えて、GPG鍵を生成します。標準的な選択肢をそのまま選んでいけば問題ありません。
これでaptlyを使う準備が整いました。
特定パッケージのミラーリポジトリを作る
例としてUbuntu 16.04 LTSのfcitxパッケージとmozc関連のパッケージのミラーリポジトリを作ってみましょう。aptlyはaptコマンドを経由せず、自分自身の信頼する鍵のリストからリポジトリのメタデータを検証します。これはシステムのリポジトリ公開鍵リストとは独立して管理できるようにするためです。
そこであらかじめUbuntu公式リポジトリの公開鍵を信頼する鍵として取り込んでおきます。公式リポジトリの公開鍵リストはubuntu-keyringパッケージとして提供されています。一般的なインストール方法なら最初からインストールされているはずです。Debianのリポジトリの公開鍵が必要なら、debian-archive-keyringパッケージやdebian-keyringパッケージをインストールしてください。
では適当なミラーリポジトリを作成してみましょう。「-architecutres
」でミラーするアーキテクチャを制限します。「-filter
」オプションはミラーするパッケージを制限します。いずれも指定しない場合は、フルミラー相当になりますので、かなりのパッケージをダウンロードすることになります。今回の場合、パッケージ名が「fcitx」のパッケージもしくは「mozc-」で始まるパッケージを指定しています。他にも「-filter
」では、Debianパッケージのフィールドを使ったフィルタリングもできます。たとえば特定のソースパッケージから生成されるバイナリパッケージをミラーしたい場合は「$Source (foo)
」と指定します。詳細は公式ドキュメントの「PACKAGE QUERIES」を参照してください。
「-filter-with-deps
」は依存するパッケージも一緒にインストールするオプションです。一通りオプションを指定した後ろに任意のリポジトリ名(今回は「ange」)を指定した上で、ミラー元のURLやコンポーネント(/etc/apt/sources.list
に記載している内容)を記述します。今回はxenialコンポーネントのみを指定しています。
ミラーリポジトリを作成したら、「aptly mirror update
」コマンドで最新のパッケージをダウンロードしましょう。
xenial以外にもリリース後のアップデートパッケージが格納されるxenial-updatesや、より新しいリリースからのバックポートパッケージが格納されるxenial-backportsのパッケージもミラーしたい場合は、個別に「aptly mirror create
」を実行する必要があります。後ほど説明するスナップショット機能を用いて、作成した複数のミラーリポジトリをひとつのリポジトリに統合する機能もあります。
取得したパッケージは「~/.aptly/pool/
」以下にハッシュを元にした接頭辞付きで保存されます。これでリポジトリのミラーが完了しました。なお、このままだとパッケージリポジトリとしては使えません。後述の「リポジトリを公開する」の手順を行う必要があります。
リポジトリの状態を確認する
リポジトリの状態は「aptly mirror show
」で確認できます。
また各リポジトリに格納されているパッケージは「aptly mirror search
」で検索できます。作成したすべてのリポジトリを検索する場合は「aptly package search
」です。
「aptly package show
」を使うと、一致するパッケージの詳細を表示できます。
リポジトリのスナップショットを作成する
「aptly mirror update
」はミラー元のリポジトリの内容と同期します。つまりリポジトリ内部のパッケージが更新される可能性があるわけです。aptlyにはミラーリポジトリを更新したかどうかに関わらず特定のタイミングの状態を保持するスナップショットリポジトリを作成する機能があります。
先ほど作ったangeとange-updatesのスナップショット(ange-20170817)をそれぞれ作成してみましょう。
これでangeやange-updatesが更新されたとしても、スナップショットをとったタイミングのリポジトリの状態を参照できます。
複数のスナップショットをマージして、ひとつのリポジトリにすることも可能です。先程作ったスナップショット「ange-20170817」と「ange-updates-20170817」をひとつにまとめた新しいスナップショット「princess-20170817」を作るには次のようなコマンドを実行します。「-latest
」オプションを付けると、重複するパッケージのうちバージョンが新しいパッケージのみを取り込みます。
ちなみにスナップショット間での差分も表示できます。
リポジトリを公開する
作成したスナップショットはパッケージリポジトリとして公開できます。
リポジトリのメタデータに署名を行うため、最初に作成したGPG鍵のパスフレーズの入力が必要になります。
「-distribution
」に指定する値(上記のケースなら「princess」)は公開時のディストリビューション名であり、Ubuntuのリポジトリでいうところの「xenial」や「zesty」です。省略するとスナップショット名がそのまま使われます。将来的に同じディストリビューション名でより新しいスナップショットにスイッチする可能性があることを考えると、スナップショット名よりは汎用的な名前にしておくべきでしょう。
パッケージリポジトリは「~/.aptly/public/
」以下に作られます。いわゆる一般的なパッケージリポジトリの構成になっています。個々のパッケージはダウンロードしたパッケージファイルへのハードリンクとなっています。ちなみに「~/.aptly.conf
」を設定すれば、ファイルシステム上の別のディレクトリはもとより、Amazon S3やOpenStack Swiftといったストレージサービス上にリポジトリを構築できます。またUbuntuで言うところのmain・universeのようにマルチコンポーネントなリポジトリも構築できます。
「aptly publish
」による「公開」は、実際は「リポジトリとして公開するためのディレクトリ構成を作る」ところまでしか行いません。外部からネットワーク越しにリポジトリとして使うためには、このディレクトリにアクセスし、ファイルを取得できるような何か別のサービスを立ち上げる必要があります。端的に言うとHTTPサーバーが必要です。手っ取り早いのは、「~/.aptly/plubic/
」ディレクトリが外部から見えるようにHTTPサーバーの設定を行うことでしょう。
実験的にHTTPサーバーを立てたければ、「aptly serve
」コマンドが使えます。
「aptly serve
」コマンドを実行するとaptlyに組み込まれたHTTPサーバーが起動して、公開済みのリポジトリへ8080番ポート経由でアクセスできるようになります。あとはこのリポジトリを利用したいクライアント側で、リポジトリの設定を行うだけです。
クライアント側の操作に移る前に、まずaptly側の公開鍵をエクスポートしておきましょう。
あとはこのリポジトリ鍵を登録し、sources.list
を設定します。ここでaptlyが動いているマシンのアドレスを「aptly.example.com
」だとしています。
最後のコマンドでfcitxの候補としてaptlyで作ったリポジトリのパッケージが表示されたら成功です。
もちろん「aptly serve
」は簡易的な機能しかもっていないので、プロダクション用途であれば一般的なHTTPサーバーを用意したほうがよいでしょう。
ローカルパッケージのリポジトリを作る
ここまではすでに存在するリポジトリからパッケージを取得していました。aptlyでは単なるミラーだけでなく、独自のリポジトリを作ることも可能です。
「-distribution
」は「リポジトリを公開する」の項でも指定した公開時のディストリビューション名であり、Ubuntuのリポジトリで言うところの「xenial」や「zesty」です。「-component
」はUbuntuで言うところのmain・universeのようにパッケージの種別ごとに別のディレクトリにしたいときに使用します。最後の「chise-repo」が内部的なリポジトリの名前になります。
さて、作ったリポジトリにパッケージファイルを追加しましょう。
「beatrice/
」の部分にはいくつかの指定方法が存在します。まず拡張子が「.deb
」や「.udeb
」「.dsc
」のファイルを指定すると、そのパッケージファイルをリポジトリに追加します。ソースパッケージである「.dsc
」の場合は、その中で指定されている他のソースアーカイブも一緒に追加してくれます。今回の例のようにディレクトリを指定した場合は、再帰的に拡張子が「.deb
」や「.udeb
」「.dsc
」のファイルを探しすべて追加します。pbuilderやcowbuilderのようにビルドしたパッケージを一定の場所に集めている場合に便利です。「-remove-files
」オプションを付けると、取り込みが成功したら元のファイルを削除してくれます。
dput
コマンドのように「.changes
」ファイルベースで取り込みたい場合は、「aptly repo include
」を使います。こちらは原則としてGPG鍵で署名済みである必要があります。詳しい使い方はmanページを参照してください。
「aptly repo copy
」や「aptly repo move
」コマンドを使うと、複数のローカルリポジトリ間でパッケージの移動を行えます。テストリポジトリから本番リポジトリに移動したい場合に使えるでしょう。ミラーリポジトリからパッケージを取得したい場合は「aptly repo import
」コマンドを使います。
ローカルリポジトリはミラーリポジトリと異なり、「aptly repo publich
」コマンドを使って直接リポジトリを公開することが可能です。もちろん一度スナップショットを取ってから公開する方法も使えます。スナップショット化しておけば、他のミラーリポジトリの依存パッケージ群をマージした独自のリポジトリを作れるため便利です。
社内開発リポジトリにaptlyはいかが?
ここまで紹介したように、aptlyを使えば独自のDebianパッケージリポジトリをとても簡単に運用できます。社内インフラ用に独自にパッチを当てたパッケージを配布したい、Ubuntu公式リポジトリの一部のパッケージのスナップショットを取りたいなどの用途に最適です。また、パッケージの作成・ビルド・テストリポジトリへのアップロード・各種CIツールによるテスト・本番リポジトリへの移動までのサイクルを機械的に行えるというメリットもあります。
社内開発用にパッケージリポジトリが欲しいと考えているのであれば、aptlyを試してみるのはいかがでしょうか?