Ubuntu Weekly Recipe

第419回長期サポート版で改めて見直す、PPAとのお付き合い

Ubuntu 16.04 LTSが無事にリリースされました。今回はUbuntuを使う上では欠かせない存在となったPPAについて、改めてその使い方を見直してみます。

そのPPAは本当に必要ですか?

2016年4月22日(地球のどこかのタイムゾーン)に、Ubuntu 16.04 LTSがリリースされました。さっそくアップグレード時の問題などが報告・修正されているので、Topicsでも言及されているように当分は本番環境のアップグレードを控えた方がいいでしょう[1]⁠。特に14.04のユーザーは、ある程度問題が洗い出されるポイントリリースまでは、アップグレードを控えるようにしてください。

さて2年ぶりのリリースということもあって、前回や前々回のLTSである14.04や12.04からのアップグレードを予定されている方も多いことでしょう。2年も使いつづけていると「秘伝のたれ」化が進行し、再インストールによって同じ環境を再現することが難しい状況になっているかもしれません。特にPPAを使っている場合は、⁠秘伝のたれ」度が高くなる傾向があります。

Ubuntuは、ディストリビューションのアップグレードの際にPPAを含むサードパーティのリポジトリを無効化します。アップグレードが完了した後に、ユーザーが必要に応じて個々のリポジトリを再度有効化する必要があるのです。よって、これを機に、そのPPAが本当に必要なのかどうか見直すことにしましょう。

この素晴らしいPPAに祝福を

PPA(Personal Package Archive)はUbuntuを使う上で非常に便利な機能です[2]⁠。主に以下の用途で使用します。

  • リポジトリには存在しないパッケージを提供する
  • リポジトリよりも新しいバージョンのパッケージを提供する
  • パッケージのCIを実現する

公式リポジトリからは提供されないソフトウェアをインストールしたい場合、ソースコードをダウンロードし、ビルドし、インストールするという手法が古くから使われてきました。しかしながらこの方法はあまりユーザーフレンドリーではありません。特に大きなプロジェクトだとビルドに時間がかかってしまいます。

そのため開発者があらかじめビルドしたバイナリパッケージを提供するという手法が出てきました。独立したソフトウェアであればこの方法で大体まかなえますが、自動的なアップグレードには対応できません。また、他のパッケージに依存する場合は、さらに一手間必要になります。

そこでUbuntuではPPAという形で、公式リポジトリと同じパッケージビルドサーバーとリポジトリを、ソフトウェアの開発者も使えるようにしました。ソフトウェア開発者から見れば、バイナリパッケージのビルド・リリースのためのインフラを構築・運用する手間が省けますし、一般ユーザーから見れば、一度PPAを登録してしまえば公式リポジトリと同じUIでソフトウェアのインストールやアップグレードを行えます。Ubuntu側としては、PPAでビルドできるソースパッケージをソフトウェア開発者が作成してくれれば、将来的に公式リポジトリにも取り込みやすくなります[3]⁠。

またUbuntuの公式リポジトリは、一度リリースしたら不具合の修正とセキュリティ対応がメインで、パッケージのバージョンをできるだけあげないというスタンスをとっています。よって特定のパッケージの新しいバージョンを使いたい場合は、どうしても新しいリリースを使わざるを得ません。これを回避するために個人がPPAを使うということもよくあります。PPAは公式リポジトリの別リリースや、他のユーザーのPPAからのパッケージのコピーに対応しています。これをうまく使えば、パッケージの構築知識がなくても自前のPPAを作れるのです。

さらに最近はGitやBazaarリポジトリのHooksに応じてパッケージをビルドする機能も公開されているため、パッケージのCI用途にもPPAが使われています。たとえばKubuntuチームのCIWaylandのデイリービルドもPPAを使っていますし、Ubuntu PhoneもPPAでビルドしたあとにテストを通ったものが、開発版リポジトリに投入される仕組みになっています。

このようにPPAはUbuntuの内外で深く使われているのです。

PPAはマシンの健康を害する恐れがあります

便利なPPAですが、当然のことながら万能ではなく、リスクも存在します。

  • 品質の問題
  • 信頼性の問題
  • 目的以外のパッケージがアップグレードされる

Ubuntuの公式リポジトリのパッケージは、基本的にそれなりにパッケージングの知識がある人がチェックしています。それでも「残念な」品質のパッケージが投入されたり、意図しない不具合が紛れ込むことが発生します。PPAは公式リポジトリのようなチェックは行われませんし、そもそもパッケージを作る人がパッケージングに詳しい保証もありません。インストールはできるけれども削除はできない、ましてやアップグレードなんて不可、そんなパッケージがPPAに紛れ込んでいる可能性も十分にあるのです。lintianやpiuparts、autopkgtestといったパッケージそのものやその内容をテストするツールはたくさんあります。しかしながらアップロードする人がそれを使っているとは限らないのです。

信頼性は品質に内包される問題です。チェックが入らない以上、パッケージをアップロードする人がこっそりと悪さをするパッチを仕込むことも可能です。もちろん利用規約上許されないことですが、言い換えると利用規約でしか防げていないということです。本当にそのPPAを作った人を信用できるかどうか、PPAを導入する前に一考すべきです[4]⁠。

最後のリスクは、あまり話題にはならないかもしれません。PPAを導入すると、そのPPAに存在するパッケージと公式リポジトリのパッケージの優先度は同じ値になります。つまりPPAに存在するパッケージのバージョンが公式リポジトリのバージョンより高かったら、アップグレード時にPPA版のバージョンに更新されてしまうのです。

PPAに目的のパッケージしか存在しなければ、そこまで問題にはなりません。しかしながら新しいバージョンのパッケージをインストールするためには、他の依存するライブラリも更新しなくてはならないということはよくあります。そのため、そのようなパッケージを提供するPPAなら、新しいライブラリパッケージも提供していることが一般的です。しかしながらライブラリを更新すると、PPAとは関係ない他のパッケージが動かなくなってしまう可能性もあります。よってPPAを導入するには、どのパッケージが更新されるのかを把握しておくことが必要になります。

また個人用途のPPAには、複数の目的のパッケージを一つのPPAにまとめてしまっていることがよくあります。そのようなPPAを安易に導入してしまうと、芋づる式に他のパッケージまでアップグレードされてしまうのです。

一般的に、システムをより安定した状態で運用したいのであれば、PPAの導入はできるだけ避けるべきです。PPAを導入するごとにそのシステムの好感度は下がり、あまりに下がりすぎると突然別れを告げられる、それぐらいの覚悟はもっておきましょう。

コンテナもBackportsもあるんだよ

上記のリスクを避ける一つの解決策は、コンテナや仮想マシンを使うということです。目的の用途の隔離環境を一つ用意し、PPAはその環境でのみ使うことにします[5]⁠。コンテナや仮想マシンであれば、バックアップをとったり、他のホストに環境ごと移行することも簡単です。たとえホスト側のアップグレード時にPPAが無効化されたとしても、隔離環境内部への影響を考える必要はありません。若干手間がかかるという問題点をクリアできるなら、PPAは隔離環境でのみ使うというポリシーにしてしまうことをおすすめします[6]⁠。

「より新しいバージョン」が必要なのであれば、Backportsを使うという手もあります。Ubuntuは一度リリースすると、公式リポジトリのバージョンをあげることは原則行いません。しかしながらBackportsに限っては、このルールが若干緩い形で運用されます。ライブラリのような影響範囲の広いパッケージのアップグレードは行われませんが、単独のソフトウェアや少量の依存関係であればBackports上で新しいバージョンのパッケージを提供できます。

もしBackportsに、目的のバージョンのパッケージが存在するなら、PPAではなくBackportsを試してみましょう。

Backportsはインストール時点で有効化されています。ただし自動的にはインストールされません。たとえばUbuntu 14.04 LTSでlxcパッケージのバージョンを確認してみます[7]⁠。

$ apt-cache policy lxc
apt-cache policy lxc
lxc:
  インストールされているバージョン: (なし)
  候補:               1.0.8-0ubuntu0.3
  バージョンテーブル:
     1.1.5-0ubuntu3~ubuntu14.04.1 0
        100 http://jp.archive.ubuntu.com/ubuntu/ trusty-backports/main i386 Packages
     1.0.8-0ubuntu0.3 0
        500 http://jp.archive.ubuntu.com/ubuntu/ trusty-updates/main i386 Packages
     1.0.7-0ubuntu0.7 0
        500 http://security.ubuntu.com/ubuntu/ trusty-security/main i386 Packages
     1.0.3-0ubuntu3 0
        500 http://jp.archive.ubuntu.com/ubuntu/ trusty/main i386 Packages

1.0.3がリリース時のバージョンです。セキュリティアップデートに対応した結果、1.0.7や.1.0.8などがリポジトリに存在します。一番上にある1.1.5がBackportsにあるパッケージです。上記の「候補」が1.0.8になっていることからもわかるように、Backportsにあるパッケージはそのままではインストールされません。

Backportsのパッケージをインストールする方法は2種類存在します。

そのパッケージのみをBackportsから取得する方法
$ sudo apt-get install lxc/trusty-backports

依存パッケージも含めてBackportsから取得する方法
$ sudo apt-get install -t trusty-backports lxc

前者については依存パッケージはBackportsではなく通常のリポジトリからしか導入しません。よって依存パッケージもBackportsから取得したい場合は後者を利用してください。逆に依存パッケージはBackportsのバージョンに更新したくない場合は、前者を利用することになります。

このようにBackportsを使えば、PPAを導入しなくても良い場合がしばしば存在します。ただしBackportsは公式リポジトリではあるものの、セキュリティアップデートを保証しているわけではないことに注意してください。

よろしい、ならば確認だ

Backportsには存在しないパッケージを使いたい場合は、どうしてもPPAに頼らざるを得ません。より品質の高いPPAを見つけるために必要な知識を説明しましょう。

あなたのPPAはどこから?

PPAを導入する場合、まずどのPPAを使うのかという問題が発生します。

あるソフトウェアの公式サイトでPPAを使ったパッケージの導入を紹介している場合は、それに従うのが一番安全でしょう。それ以外の場合は、⁠ソフトウェア名 PPA」で検索すると大抵見つかります。

特定のパッケージのより新しいバージョンを提供するPPAがないか調べる確実な方法は、LaunchpadのWeb UIを使うことです。まずあるパッケージ「foo」のソースパッケージの名前を調べます。

$ apt-cache showsrc foo
Package: srcfoo
(以下略)

この場合、⁠srcfoo」がソースパッケージの名前です。パッケージ名とソースパッケージ名が同じ場合もあります。

次にソースパッケージ名を元に、以下のURLにアクセスします。

https://launchpad.net/ubuntu/+source/srcfoo/

ページ左下に「Other versions of 'srcfoo' in untrusted archives.」という項目がありますので、それを展開します。そこの表示されるものが、そのソースパッケージと「同じ名前の」ソースパッケージを提供しているPPAのリストになります。

図1 lxcパッケージの場合
画像

表示される数は限定されているので、すべてをリストアップしたかったら「other untrusted versions of 'srcfoo'.」を選択してください。

図2 lxcパッケージを提供するPPAのリスト
画像

数が多いと、どれから選んでいいかわからないかもしれません。そこでいくつか選択のポイントを紹介しましょう。

PPA name
PPA nameにはそのPPAの名前が書いてあります。きちんとした人が作ったPPAであれば、ここに「stable」「develop⁠⁠、⁠nightly」といった用途にあわせた単語が入っています。逆に「PPA for ユーザー名」のような初期値を使っているPPAは、他のユーザーが使うことを考慮していない可能性が高いので、避けたほうが良いでしょう。
Description
Descriptionには、そのPPAに対するより長い説明が記述されています。ここの記述がしっかりしていれば、その内容を読むことで 自分の用途にあっているか把握できるはずです。もし空だったら、個人目的のPPAの可能性が高いので避けましょう。
SourcesとBinaries
アップロードされたソースパッケージとビルドされたバイナリパッケージの数です。単純に数字を見るだけで可否を判断することはできませんが、目的と比較してあまりに数が多いようなら避けたほうが無難です。

リストアップのページで確認できるのはこれくらいです。ここで絞り込んだ上で、さらに個別のPPAのページを見ていきましょう。

図3 ⁠LXC: stable」のページ
画像

ページ上部には、このPPAを管理するユーザー名ないしはチーム名が表示されます。名前をクリックするとそのユーザーないしチームのトップページに飛びますので、作成者がどのような人物なのかを把握しておきましょう。

「Overview of published packages」には、このPPAが提供するソースパッケージのリストとその作成者、作成日時がリストアップされています。⁠Published in」で、リリースごとにフィルタリングできます。使っているリリースのパッケージが提供されるか確認してください。PPAを導入すると、ここに表示されるパッケージはすべて更新される可能性があるということです。そのPPAの目的に対して、あまりに数が多いようであれば、なるべく使わないようにしましょう。

Versionフィールドに「Newer version available」と表示されることがあります。PPAで提供しているバージョンよりも新しいパッケージが、公式リポジトリから提供されていることを意味します。この場合、バージョン指定せずにインストールしたら公式リポジトリのパッケージがインストールされてしまうので注意してください。

「View package details」をクリックすれば、個々のソースパッケージの内容が表示されます。目的のパッケージの目的のアーキテクチャの「Build Status」が成功(緑色のチェックマーク)になっていることを確認しておきましょう。当然のことながらビルドに失敗しているパッケージは、インストールできません。

「Available diffs」には前のバージョンや公式リポジトリのバージョンからの差分が表示されます。変更点に問題がないか確認しておきましょう。

パッケージのバージョンも重要です。あるPPAのパッケージを導入したあとに、より新しいリリースのUbuntuにアップグレードするとしましょう。その時、新しいリリースのUbuntuで提供しているパッケージに更新されるかどうかは、PPAのパッケージのバージョンフィールドとの比較で決まります。

バージョンフィールドの大小についてはいくつかの決まりがあります。一般的に数字が大きい方が新しくなります。⁠~(チルダ⁠⁠」は「前の文字列よりも古い」ことを意味します。Backportsなどは「バックポート元のバージョン~バックポート元のUbuntuリリース」といったバージョン名をつけることが多いです。これにより、そのバージョンフィールドはバックポート元のバージョンよりも古くなることを保証できます。

ルールを覚えることが面倒であれば、dpkgコマンドでバージョンを比較できます。

$ dpkg --compare-versions 1.0 gt 0.9 && echo "ok"
ok
$ dpkg --compare-versions 1.0~ppa1 gt 1.0 && echo "ok"
$

「gt」は左のバージョンが右のバージョンよりも大きい場合に成功となります。1.0と0.9なら1.0の方が大きいので「ok」が表示されます。⁠1.0~ppa1」「1.0より小さいバージョン」なので、⁠ok」は表示されません。⁠gt」以外にも演算子がありますので、詳しいことは「dpkg --help」を参照してください。

add-apt-repositoryかapt-add-repositoryか、それが問題だ

使用するPPAを決めたら、次はそのリポジトリをシステムに追加します。第314回にもあるように、CUIならadd-apt-repositoryコマンド、GUIならsoftware-properties-gtkから導入しましょう。またAnsibleのように書式の中でリポジトリの追加をサポートしているツールも存在します。

ちなみに「apt-add-repository」「add-apt-repository」へのシンボリックリンクになっていますので、どちらを使っても問題ありません。問題なんて何もないのです。

追加するリポジトリ名はPPAページの「Adding this PPA to your system」を参照してください。⁠ppa:ユーザー名/PPA名」という書式のはずです。

$ sudo add-apt-repository ppa:ユーザー名/PPA名
$ sudo apt update

なおadd-apt-repositoryコマンドはPPAだけでなく、他のリポジトリにも対応しています。指定できる書式については、⁠add-apt-repository --help」を参照してください。

$ add-apt-repository --help
(中略)
  Examples:
    apt-add-repository 'deb http://myserver/path/to/repo stable myrepo'
    apt-add-repository 'http://myserver/path/to/repo myrepo'
    apt-add-repository 'https://packages.medibuntu.org free non-free'
    apt-add-repository http://extras.ubuntu.com/ubuntu
    apt-add-repository ppa:user/repository
    apt-add-repository multiverse

add-apt-repositoryコマンドを使うと、最初にPPAのDescriptionの内容を表示します。問題なければEnterキーで追加します。

追加する際は、PPAの公開鍵を自動的に登録します。PPAのパッケージリポジトリのメタデータは、PPAごとに作成された秘密鍵を使って署名を行っています。ユーザーはそのPPAの公開鍵を安全な経路でダウンロードし、その公開鍵で署名を検証することで、パッケージの正当性を検証するというわけです[8]⁠。

さらにリポジトリのURL(apt line)を、⁠/etc/apt/sources.list.d/」以下に追加します。ファイル名は「ユーザー名-PPA名-リリース.list」です。ここでの「ユーザー名」はPPAを作成した人のLaunchpad上でのユーザーIDになります。

PPAを削除したい場合は、add-apt-repositoryに「--remove」オプションをつけて実行します。リポジトリの状態を変更するので「apt update」も必要です。

$ sudo add-apt-repository --remove ppa:ユーザー名/PPA名
$ sudo apt update

これにより先ほど追加された公開鍵とlistファイルが削除されます。なおインストールされたパッケージはそのままですので、別途ppa-purgeなどのコマンドを使う必要があります。

PPAで導入されるパッケージのバージョンを固定したい場合は、第331回を参考にAptPinの設定を行ってください。

Ubuntu 16.04 LTSの話は?

4月18日に発売されたSoftware Design 2016年5月号の第2特集では「2年ぶりのLTS 安定のUbuntu 16.04の新機能」と題して、Ubuntu Japanese Teamのメンバーが新機能やらフレーバーやらサーバーやらの解説を行っています。SORACOM AirのSIMカードのおまけでUbuntu 16.04 LTSの情報が得られると思っていただけると、お得感があるのではないでしょうか。

ちなみに付録のSIMカード、アクティベーションの期限が5月18日までなので、とりあえず試してみたい場合は早めに書店にGoです。

おすすめ記事

記事・ニュース一覧