初めに
必要に迫られて既存のDebianパッケージをカスタマイズしたものを作成してみたので、その際の手順をまとめてみました。
背景
そもそものきっかけはDebian 11 (コードネーム bullseye)でpyspf-milterを利用しようとしたことでした。Bullseyeのpyspf-milterのバージョンは2.9.2なのですが、このバージョンには起動するとランタイムエラーが発生して異常終了するというバグがあります。この問題はDebianのバグ追跡システム(BTS)に報告されていて、そこでこのパッケージのメンテナは
- この問題はtesting(とunstable)では修正済
- stableでも修正する予定である
と回答していますが、この記事を書いている時点ではまだstableは修正されていません。
またこれとは別に、設定ファイルに特定のオプションを指定するとエラーが発生して異常終了するというバグがあります。これはupstreamの最新バージョンである2.9.3にもあるバグで、upstreamのバグ追跡システムに報告されていて、そこにこの問題を修正するためのパッチも添付されているのですが、まだ修正されていません。
そのためbullseyeでこの二つの問題を回避するためには
- 前者の問題が修正されているtesting/unstableのパッケージのソースを取得する
- 取得したソースに後者の問題を修正するパッチを追加する
- 変更したソースからbullseye用のパッケージを作成する
- 作成したパッケージをインストールして利用する
という手順が必要となるのですが、この記事では三番目のパッケージを作成するまでの手順を説明します。なお以下の説明では、全てはamd64なbullseyeの環境で行うものとします。
準備
自前でDebianパッケージを作成するには以下の3つの準備が必要となります。
- パッケージの作成に必要なDebianパッケージのインストール
- 作成したパッケージに署名するために用いるGnuPGの鍵の作成
- 環境設定
以下順に説明します。
パッケージの作成に必要なDebianパッケージのインストール
パッケージの作成には以下の4つパッケージをインストールする必要があります。
- build-essential
- devscripts
- git
- wget
build-essential
Debianパッケージに限らず、一般的にソフトウェアをビルドするにはコンパイラ、ライブラリ、ユーティリティなど様々なツールが必要になります。そして何が必要かはビルドするソフトウェアによって異なりますが、そのうちほとんどのDebianパッケージを作成する際に必要となるツールをインストールするためのパッケージがこのbuild-essentialです。Debianパッケージのソースには、そのパッケージを作成する際にインストールすべきパッケージを記述したファイルがあるのですが、build-essentialに含まれるパッケージについては、既にインストールされているものとみなして記述しなくてよいこととなっています。従ってDebianパッケージをし前で作成する際には、必ずこのパッケージをインストールする必要があります。
devscripts
名前が示すように、このパッケージにはDebianパッケージの開発(既存のパッケージのカスタマイズだけでなく新規にパッケージを作成する場合も含む)を行うのに便利なツールが含まれています。
git
既存のDebianパッケージをビルドするにはそのパッケージのソースを取得する必要があります。単純にそのままビルドするだけなら、/etc/apt/sources.list
に
deb-src http://deb.debian.org/debian/ bullseye main non-free contrib
のような行を追加したうえで
apt source (パッケージ名)
を実行すれば、カレントディレクトリの下に必要なすべてのソースがダウンロードされます。しかしながら今回はソースを変更する必要があり、そしてその変更内容を保存しておきたいので、gitを利用してDebianパッケージのソースのリポジトリからソースを取得することとしました。
wget
ソフトウェアのオリジナルのソースコードのアーカイブファイルを取得するのに使います。ファイルをダウンロードできるものなら、curlなどの別のツールやウェブブラウザでも構いません。
GnuPGの鍵の作成
パッケージに署名するのに必要なGnuPGの鍵を作成します。作成したパッケージをdpkg
コマンドを使って直接インストールするのなら必ずしも署名する必要はないのですが、今回は作成したパッケージをapt install
でリポジトリからインストール出来るようにしたいので、そうなるとセキュリティの観点からパッケージに署名することにしました。
署名にはGnuPGを用いるので、GnuPGの鍵が必要となります。既に自分用の鍵があるのならそれを用いることも出来ますが、なければ以下のコマンドを実行して作成します。
gpg --generate-key
実行すると名前とメールアドレスを尋ねられます。以後の説明では名前がTaro Yamadaでメールアドレスがtaro@examle.orgであるとします。名前とメールアドレスを入力すると確認を求められます。その後鍵のパスフレーズの入力が完了すると鍵が生成されます。
環境設定
パッケージの作成に用いるツールに必要な環境設定を行います。
環境変数
環境変数DEBEMAILにメールアドレスを、DEBFULLNAMEにフルネームを設定します。私はログインシェルとしてzshを使っているので、~/.zshenv
に以下の行を追加しました。
export DEBEMAIL="taro@example.org"
export DEBFULLNAME="Taro Yamada"
他のシェルを使っている場合は、そのシェルに応じた設定を行ってください。
devscripts
devscirpts関連の設定は~/.devscripts
で行います。以下の3行からなる~/.devscripts
を作成します。
DEBUILD_DPKG_BUILDPACKAGE_OPTS="-i -I -sa"
DEBUILD_LINTIAN_OPTS="-i -I --show-overrides"
DEBSIGN_KEYID="(署名に用いるGnuPGの鍵のIDの値)"
署名に用いるGnuPGの鍵のIDの値は、gpg --list-keys --keyid-format long
を実行して確認します。例えば出力が以下の通りだったとします。
ppub rsa3072/7F4DBC5AFC3010FF 2022-11-16 [SC] [expires: 2024-11-15]
F954C7608427047664E784FC7F4DBC5AFC3010FF
uid [ultimate] Taro Yamada <taro@example.org>
sub rsa3072/49AB5A578599DCA8 2022-11-16 [E] [expires: 2024-11-15]
この場合一行目の7F4DBC5AFC3010FF
が鍵のIDの値となるので、これを指定します。
git
コミットメッセージで用いられるメールアドレスとフルネームを設定します。
git config --global user.name "Taro Yamada"
git config --global user.email taro@example.com
ソースの取得と確認
ソースの取得
準備のところで説明した通り、今回はGitを使ってpyspf-milterのソースパッケージであるspf-engineのリポジトリからソースを取得します。作業を行うディレクトリに移動して以下のコマンドを実行します。
git clone https://salsa.debian.org/python-team/packages/spf-engine.git
完了するとカレントディレクトリの下のspf-engine
というディレクトリにソースがダウンロードされます。ソースはデフォルトのブランチであるdebian/master
の最新のコミットが取得されますが、現時点でこのコミットはtesting/unstableのpyspf-milterパッケージの最新バージョンである2.9.3-1より新しくなっています。なので2.9.3-1を基準にして新しいブランチを作成して、以降はそのブランチで作業をすることにします。
cd spf-engine
git switch -c custom debian/2.9.3-1
パッケージをビルドするにはこの他にSPF Engineのオリジナルのソースコードを含んだアーカイブファイルが必要なので、それをダウンロードします。
wget https://deb.debian.org/debian/pool/main/s/spf-engine/spf-engine_2.9.3.orig.tar.gz
結果として作業ディレクトリの下は以下のようになります。
% ls -F
spf-engine/ spf-engine_2.9.3.orig.tar.gz
%
これでソースの取得は完了です。
ソースがビルド出来るかの確認
今回取得したのは現時点でのtesting及びunstableのバージョンである2.9.3をビルドするためのソースですが、一般的に言ってtestingやunstabeのためのソースがstableの環境で正常にビルド出来る保証はありません。そこでまずその確認を行います。ソースをビルドするには以下のコマンドを実行します。
cd spf-engine
debuild
初めてこれを実行した際には、大抵の場合ビルドに必要なパッケージがインストールされていないというエラーメッセージが表示されてビルドは失敗します。何をインストールする必要があるかはビルドする環境によって変わりますが、エラーメッセージで不足しているパッケージが表示されるので、それらをインストールしたうえで再度コマンドを実行すると、今度は特に問題なく正常にビルドが完了します。ソースがstable環境でビルドできることが確認できたのでソースのディレクトリを元の状態に戻します。
rm -rf *.deb spf-engine_2.9.3-1*
cd spf-engine
git clean -dfx
git restore .
パッケージのカスタマイズ
パッチの追加
背景で説明した通り、stable(2.9.2-1)のpyspf-milterパッケージの二つのバグのうち、一つはtesting/unstable(2.9.3-1)で修正されていますが、もう一つはまだ修正されていません。そこで後者を修正するパッチを追加します。これも背景で説明した通り、この件に関するupstreamのバグ追跡システムへのバグ報告には問題を修正するパッチが添付されているのですが、Debianのspf-engineのソースには直接適用できないので、オリジナルを参考にして以下のようなパッチを作成しました。
diff --git a/spf_engine/policydspfsupp.py b/spf_engine/policydspfsupp.py
index 8ba8e6c..4ebca3f 100644
--- a/spf_engine/policydspfsupp.py
+++ b/spf_engine/policydspfsupp.py
@@ -153,9 +153,9 @@ def _readConfigFile(path, configData = None, configGlobal = {}):
'Socket': str,
'PidFile': str,
'UserID': str,
- 'UMask': 'int',
+ 'UMask': int,
'InternalHosts': str,
- 'IntHosts': 'bool',
+ 'IntHosts': bool,
'MacroListVerify': str,
}
これをspf-engine/debian/patches
の下に0901-fix-runtime-error.patch
というファイル名で置きます。
パッケージをビルドする際に適用するパッチの一覧はspf-engine/debian/patches/series
というファイルで管理されています。現時点でのこのファイルの内容は
0001-install-conf-fix.patch
となっているので、ここに追加したパッチのファイル名を
0001-install-conf-fix.patch
0901-fix-runtime-error.patch
のように追加します。
変更履歴の更新
次にDebianパッケージの変更履歴を管理しているファイルであるspf-engine/debian/changelog
を更新します。更新には専用のコマンドであるdch
を使用します。私はspf-engineパッケージのメンテナではないので、今回の更新はNMU(Non Maintainer Upload)に相当します。そこで
cd spf-engine
dch --nmu
のように、spf-engine
ディレクトリに移動した後にdch
を--nmu
オプションを指定して実行します。するとエディタが起動されてファイルの先頭に以下のような行が追加されます。
spf-engine (2.9.3-2.1) UNRELEASED; urgency=medium
* Non-maintainer upload.
*
-- Taro Yamada <taro@example.org> Thu, 17 Nov 2022 15:13:59 +0900
これを例えば以下のようにしてエディタを終了します。
spf-engine (2.9.3-2.1) UNRELEASED; urgency=medium
* Non-maintainer upload.
* Add patch to fix runtime error of pyspf-milter.
-- Taro Yamada <taro@example.org> Thu, 17 Nov 2022 15:13:59 +0900
パッケージのビルド
ビルドの確認の時と同様に
cd spf-engine
debuild
とするとビルドが正常に完了して、作業ディレクトリにカスタマイズされたパッケージが生成されます。
% ls -1F
pyspf-milter_2.9.3-1.1_all.deb
python3-spf-engine_2.9.3-1.1_all.deb
spf-engine/
spf-engine_2.9.3-1.1.debian.tar.xz
spf-engine_2.9.3-1.1.dsc
spf-engine_2.9.3-1.1_amd64.build
spf-engine_2.9.3-1.1_amd64.buildinfo
spf-engine_2.9.3-1.1_amd64.changes
spf-engine_2.9.3.orig.tar.gz
%
変更内容の保存
変更が正しく動作されることが確認されたので、変更内容をコミットします。
cd spf-engine
git add debian/changelog debian/patches/0901-fix-runtime-error.patch debian/patches/series
git commit
パッケージのバックポート
作成されたパッケージをそのまま利用しても問題ないのですが、testing/unstableのバージョンをstableに移植したことを明確にするために、バックポートの処理を行います。ソースがstableでビルド出来るかを確認した後と同じ手順で作業ディレクトリを片付けた後に以下のコマンドを実行します。
cd spf-engine
dch --bpo
するとエディタが起動されてファイルの先頭に以下のような行が追加されます。
spf-engine (2.9.3-1.1~bpo11+1) bullseye-backports; urgency=medium
* Rebuild for bullseye-backports.
*
-- Taro Yamada <taro@example.org> Thu, 17 Nov 2022 16:35:19 +0900
今回は単純にビルドしなおすだけなので、以下のように編集します。
spf-engine (2.9.3-1.1~bpo11+1) bullseye-backports; urgency=medium
* Rebuild for bullseye-backports.
-- Taro Yamada <taro@example.org> Thu, 17 Nov 2022 16:35:19 +0900
エディタを終了して再度debuild
を実行してパッケージをビルドします。ビルドが完了すると作業ディレクトリの下にバックポートされたパッケージが生成されます。
% ls -1F
postfix-policyd-spf-python_2.9.3-1.1~bpo11+1_all.deb
pyspf-milter_2.9.3-1.1~bpo11+1_all.deb
python3-spf-engine_2.9.3-1.1~bpo11+1_all.deb
spf-engine/
spf-engine_2.9.3-1.1~bpo11+1.debian.tar.xz
spf-engine_2.9.3-1.1~bpo11+1.dsc
spf-engine_2.9.3-1.1~bpo11+1_amd64.build
spf-engine_2.9.3-1.1~bpo11+1_amd64.buildinfo
spf-engine_2.9.3-1.1~bpo11+1_amd64.changes
spf-engine_2.9.3.orig.tar.gz
生成されたパッケージが2.9.3-1.1~bpo11+1となっているので、バックポートされたものであることがわかります。
バックポートに成功したので、変更内容の更新をコミットしておきます。
cd spf-engine
git add git add debian/changelog
git commit
まとめ
既存のDebianパッケージをカスタマイズする方法についてまとめました。これから同様のことを行おうとする方の参考になれば幸いです。