ビルドサーバーのセットアップ

F-Droidビルドサーバーは、各パッケージのビルドを、クリーンで分離された安全な使い捨て仮想マシン環境内に隔離します。数千ものアプリをビルドすることは、特に自動化されたプロセスや無人プロセスで行う場合、セキュリティの観点から危険な作業と見なされる可能性があります。ビルドの成果物が広く配布され、さらに半自動的な(「利用可能な更新があります」)形で配信される場合は、なおさらです。

上流のリポジトリがハッキングされたと仮定しましょう。その場合、攻撃者は以下のような事柄を行う可能性があります。

  1. ビルドを行っているユーザーとして、ビルドにおけるユーザー定義のステップで、実質的に何でも実行できます。
  2. キーストアにアクセスできます。
  3. リポジトリの他のアプリケーションの、ビルド済のAPKファイルまたはソースコードのファイルを改変できます。
  4. リポジトリにある他のアプリケーションのメタデータ(ここにはビルド用のスクリプトが含まれます。このスクリプトを使うことによっても、攻撃者は実質的に何でも実行することができます)を改変できます。

完全に隔離することで、その影響は少なくとも対象のアプリケーションに限定されます。ビルド環境は各ビルドごとに新しく用意され、完了後に破棄されるだけでなく、署名環境からも完全に隔離されています。

セキュリティ上の問題とは別に、古いバージョンのNDKなど、特殊な要件を持つアプリケーションもあります。多目的システム上でSDKを変更したり元に戻したりするのは現実的ではありません(少なくとも非常に煩雑です)が、使い捨ての単一用途仮想マシン内であれば、どのような対応も可能です。

これらはすべて、標準化され、完全に再現可能な環境でビルドを行えるという明らかな利点に加えて得られるものです。さらに、特定のアプリケーション向けに、専用のカスタムビルド環境を用意することもできます。

セットアップの概要

これは、完全にクリーンな最小構成のDebian/stableインストールから、動作するビルドサーバーをセットアップする方法です。このHOWTOでは、すでに fdroidserver をセットアップ していることを前提としています。ビルドサーバーのセットアップスクリプトは、まだ適切なパッケージ化に対応できる状態ではないため、当面は git から直接 fdroidserver ツールを実行する方法(例: ~/fdroidserver/fdroid build org.adaway)が、おそらく最も簡単です。また、F-DroidのインフラではDebianのみを使用しているため、Debian、Ubuntu、その他のDebian派生環境でしか動作しない可能性があります(移植への貢献を歓迎します!)。

ベースサーバーには最低でもDebian/trixieが必要です。そうでない場合は、大幅な調整が必要になります。Ubuntuまたは派生ディストリビューションを実行している場合は、vagrant-cachier など、お使いのバージョンに不足しているパッケージをこのPPAから取得できます: https://launchpad.net/~fdroid/+archive/ubuntu/buildserver/

まず、必要なパッケージをインストールし、この処理全体を実行するための新しいユーザー(例: fdroid)を作成します。これらはすべてのビルドで必要となるパッケージだけなので、アプリをビルドするには追加のパッケージ(たとえば mercurialsubversion)をインストールする必要がある場合があります。パッケージのインストールと fdroid ユーザーの作成が完了したら、この処理の残りの部分ではrootや sudo を使用しないでください。

root:~# apt-get install vagrant git python3-certifi \
        python3-libvirt python3-requestbuilder python3-yaml \
        python3-progress python3-vagrant python3-paramiko python3-pyasn1 \
        python3-pyasn1-modules python3-requests python3-git
        vagrant-mutate vagrant-libvirt ebtables dnsmasq-base \
        libvirt-clients libvirt-daemon-system qemu-kvm qemu-utils
root:~# adduser --disabled-password fdroid
root:~# su fdroid

fdroid のユーザーとして、ソースコードを複製しましょう。

fdroid:~$ cd ~
fdroid:~$ git clone https://gitlab.com/fdroid/fdroidserver.git

ANDROID_HOME 環境変数が正しく設定されていることも確認する必要があります。

必要に応じて、fdroid実行ファイルをPATHに追加できます:

fdroid:~$ echo "PATH=\$PATH:$HOME/fdroidserver" >> ~/.bashrc

fdroiddata リポジトリから、すべてのアプリビルドメタデータを取得します…

fdroid:~/fdroidserver$ cd ~
fdroid:~$ git clone https://gitlab.com/fdroid/fdroiddata.git
fdroid:~$ cp fdroidserver/examples/config.yml fdroiddata/
fdroid:~$ sed -i "s@^[# ]*build_server_always.*@build_server_always: true@" fdroiddata/config.yml

ビルドサーバーをセットアップする

前述の基本セットアップに加えて、’fdroid/bullseye64’ というVagrant互換のDebian/bullseyeベースボックスを提供しています。

私たちは、ビルドサーバー用のDebian Vagrantボックスを一からブートストラップしています。事前ビルド済みVagrantボックスの取得と検証は完全に自動化されています。(このプロセスに興味がある場合や、自分でそれらをブートストラップしたい場合は、F-Droid Base Box を参照してください)

F-Droidビルドサーバーボックスを作成する

次の内容を含むVagrant用の設定ファイルを ~/fdroidserver/buildserver/Vagrantfile.yaml として作成します:

vm_provider: libvirt

次に、ベースのbuildserverイメージを作成します…(baseboxとすべてのSDKプラットフォームのダウンロードには時間がかかる場合があります)。

fdroid:~$ cd fdroidserver
fdroid:~/fdroidserver$ ./makebuildserver --verbose

これには長い時間がかかり、多くの帯域幅とディスク容量を使用します。その大半は、さまざまなプラットフォームに必要なAndroid SDKの構成要素をインストールするために費やされます。幸い、これを行う必要があるのはときどきだけです。動作するビルドサーバーイメージができた後は、レシピが変更された場合(たとえばパッケージを追加する必要がある場合)でも、そのスクリプトをもう一度実行するだけで、既存のものがその場で更新されます。

完了すると、’buildserver’ という新しいベースボックスが作成され、アプリのビルド実行に使用されます。これで以前と同じようにパッケージをビルドできますが、fdroid build --verbose --server ... を実行すると、アプリのビルド実行は仮想マシン内に分離されます。

作成されたイメージには限られた数のCPUコアとメモリが割り当てられていますが、~/fdroiddata/builder/Vagrantfile を編集すると、実行時にそれらを動的に変更できます。例: libvirt.cpus = 6libvirt.memory = 12288。ただし、ホストマシンの上限を超えないようにしてください。超えるとVMが強制終了される可能性があります。

初めてビルドを行うときは、’buildserver’ ボックスをベースとして新しい仮想マシンが作成されます。パフォーマンスを向上させるため、このクリーンなマシン状態のスナップショットが保存され、以降のビルドで使用されます。スイッチを使用して、このスナップショットを破棄し、一から再ビルドするよう強制できます: fdroid build --resetserver ...

makebuildserverのキャッシュ調整(任意)

主なSDK/NDKのダウンロードは、次回以降の処理を高速化するために自動的にキャッシュされますが、SDKの android ツールを使用してプラットフォーム、アドオン、ツールをインストールする長い処理部分については、これを簡単に行う方法がありません。ただし、自動キャッシュに任せる代わりに、これらのダウンロードだけでなく、関連するすべての追加コンポーネントの .tar.gz ファイルも含む、事前に用意したキャッシュディレクトリを指定できます。プロビジョニングスクリプトがこれらを検出した場合、Androidツールを実行するよりも優先して使用されます。たとえば、buildserver/addons/cache/platforms/android-19.tar.gz がある場合、android-19プラットフォームのインストール時には、android update sdk --no-ui -t android-19 を使用して再ダウンロードする代わりに、そのファイルが使用されます。SDKのローカルインストールにこれらが含まれている場合、そこから追加コンポーネントのキャッシュファイルを作成できます:

cd /path/to/android-sdk/platforms
tar czf android-19.tar.gz android-19
mv android-19.tar.gz /path/to/buildserver/addons/cache/platforms/

すでにbuildserverをビルドしている場合は、これらのファイルをbuildserverから直接取得することもできます:

vagrant ssh -- -C 'tar -C ~/android-sdk/platforms czf android-19.tar.gz android-19'
vagrant ssh -- -C 'cat ~/android-sdk/platforms/android-19.tar.gz' > /path/to/fdroidserver/buildserver/cache/platforms/android19.tar.gz

ビルドを実行する

buildserverを使用する場合、fdroidserver のgitチェックアウトから直接 fdroid を実行するのが最も簡単です。fdroidserver ツールをまだインストールしてセットアップしていない場合は、次にそれを行う必要があります: サーバーとrepoツールのインストール。これにより、gitから fdroidserver を実行するために必要な依存関係がすべて提供されます。

これでビルドを実行する準備が整いました。最新のfdroidバージョンをビルドしてテストします:

fdroid:~/fdroidserver$ cd ~/fdroiddata
fdroid:~/fdroiddata$ ~/fdroidserver/fdroid build org.fdroid.fdroid -l --server

QEMU/KVM/libvirtのセットアップ

以前はVirtualBoxが使用されていましたが、libvirt経由のQEMU/KVMゲストVMが現在も推奨セットアップです。これはf-droid.orgで使用されている構成だからです。libvirtイメージファイルを vagrant package で直接読み取れるようにするには、libvirt のQEMUで所有権が常に libvirt.libvirt に設定されるよう構成する必要があります。

root:~# cat << EOF >> /etc/libvirt/qemu.conf
user = "libvirt"
group = "libvirt"
dynamic_ownership = 1
EOF
root:~# service libvirtd restart
Debian/bullseyeとUbuntu/xenial
root:~# adduser fdroid libvirt
root:~# adduser fdroid libvirt-qemu
それより古いDebianとUbuntu
root:~# adduser fdroid libvirtd
root:~# adduser fdroid kvm

高度なネストKVMセットアップ:

このセクションは、通常のセットアップでF-Droidを使用する場合には関係ありません。KVM内で fdroid build --server フラグを実行したい場合、この章が始めるための助けになります。

次の基本的なネスト構成を考えます:

bare metal host (l0)
\- F-Droid VM (l1)
   \- F-Droid builder VM (l2)

上記の手順では、(l1) のセットアップ方法を説明しており、makebuildserver は (l2) をセットアップします。

まず、お使いのCPUが vmx(AMDでは svm)命令セットをサポートしているか確認する必要があります。次のコマンドを使用して、CPUの詳細を一覧表示できます:

root:~# cat /proc/cpuinfo

(l0) では、ネストが有効になっていることを確認する必要があります:

root:~# cat /sys/module/kvm_intel/parameters/nested

有効になっていない場合は、次を実行して有効にできます:

echo "options kvm-intel nested=Y" > /etc/modprobe.d/kvm-intel.conf

有効にするには再起動してください。

次に、(l1) VMの設定で、ネストに必要なCPU機能が転送されるようにする必要があります。VMの設定ファイル /etc/libvirt/qemu/my-vm.xml を開き、domainタグ内にcpuブロックを挿入します。(virt-manager でも、この操作用のユーザーインターフェイスが提供されています。)

<cpu mode='custom' match='exact'>
    <model fallback='allow'>SandyBridge</model>
    <vendor>Intel</vendor>
    <feature policy='require' name='vmx'/>
</cpu>

ここで実際に必要な設定は、お使いのCPUによって異なります。詳細は libvirtのマニュアル で確認できます。重要なのは、vmx(AMDでは svm)をゲストシステムへ転送することです。