构建服务器设置

F-Droid 构建服务器将每个软件包的构建隔离在一个干净、隔离和安全的一次性虚拟机环境中。构建数以千计的应用,特别是使用自动化和/或无人值守的流程,从安全角度来看,可以被认为是一种危险游戏。当构建的产物也是以半自动化(”你有更新可用”)的方式广泛传播时,情况就更糟糕了。

假定上游源代码存储库已被攻击。攻击者在这种情况下可以执行的一小部分操作:

  1. 使用自定义的构建步骤,作为进行构建的用户执行几乎任何东西。
  2. 访问密钥库。
  3. 修改存储库中其他应用构建的 APK 文件或源代码包。
  4. 修改存储库中其他应用的元数据(包括构建脚本,其中还包括执行任何内容的功能)。

通过完全隔离,影响至少局限于有关的应用。构建环境不仅在每次构建时是新鲜的,之后就会被扔掉,而且它也与签名环境完全隔离。

除了安全问题,还有一些应用有奇怪的要求,比如旧版本的 NDK。在一个多用途系统上开始修改和恢复 SDK 是不切实际的(或者至少是极其混乱的),但是在一个一次性虚拟机的范围内,一切都有可能。

除此以外,还有一个明显的优势,那就是有一个标准化的、完全可重复的环境来进行构建。此外,它还允许为特定的应用提供专门的定制构建环境。

设置概述

这是从完全干净的最小 Debian/stable 安装开始如何设置一个有效的构建服务器的方法。 本指南假设你已经设置了 fdroidserver。直接从 git 运行 fdroidserver 工具(例如 ~/fdroidserver/fdroid build org.adaway)可能是目前最容易,因为构建服务器设置脚本尚未真正准备好进行正确的打包。此外,它可能只适用于 Debian、Ubuntu 和其他 Debian 衍生产品,因为 F-Droid 只在其基础设施中使用 Debian(我们欢迎移植贡献!)。

基础服务器至少需要 Debian/bullseye,否则需要进行一些繁重的调整。如果你运行 Ubuntu 或衍生发行版,你可以从这个 PPA 中获得任何缺少的软件包,比如 vagrant-cachierhttps://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-clint 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 可执行文件添加到你的路径中:

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

从 fdroiddata repo 中获取所有的应用构建元数据…

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

设置一个构建服务器

除了前面描述的基本设置之外,我们还提供了一个与 Vagrant 兼容的 Debian/bullseye 基础系统,称为 ‘fdroid/bullseye64’。

我们正在为我们的构建服务器从头引导 Debian Vagrant 盒子。获取和验证我们预先构建的 Vagrant 盒子是完全自动化的。(如果你对这个过程感兴趣或者想自己引导这些盒子,你应该看看:F-Droid Base Box

创建 F-Droid 构建服务器系统

创建一个 Vagrant 配置文件,位于 ~/fdroidserver/buildserver/Vagrantfile.yaml,包括内容有:

vm_provider: libvirt

接着是基本构建服务器镜像…(下载 basebox 和所有 sdk platforms 可能需要很长的时间)。

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

这将需要很长的时间,使用大量的带宽和磁盘空间 - 其中大部分用于安装所有不同平台的 Android SDK 的必要部分。幸运的是,你只需要偶尔这么做。一旦你有了一个工作的构建服务器镜像,如果配方发生变化(例如需要添加软件包时),你只需再次运行该脚本,现有镜像将原地更新。

一旦完成,你就会有一个新的基础系统叫做 ‘buildserver’,用于你的应用构建运行。现在你可以像以前一样构建软件包,但是当你运行 fdroid build -- verbose -- server ... 时应用构建运行将被隔离在一个虚拟机内。

创建的映像分配到的 CPU 核心数和内存有限,但你可以编辑 ~/fdroiddata/builder/Vagrantfile在运行时动态修改它们。比如,ibvirt.cpus = 6libvirt.memory = 12288,但请注意,所设的值不能超过物理主机硬件的上限,否则可能会杀死虚拟机。

第一次构建时,会以“构建服务器”系统为基础创建一个新的虚拟机。这个干净的机器状态的快照被保存下来,以便在未来的构建中使用,从而提高性能。你可以使用选项强制丢弃该快照并从头开始重建: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/

如果你已经建立了一个构建服务器,也可以直接从构建服务器中获取这些文件:

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

运行构建

当使用构建服务器时,直接从 fdroidserver 的 git 签出运行 fdroid 将是最容易的。如果你还没有安装和设置 fdroidserver 工具,接下来你将需要做这个:安装服务器和存储库工具。这提供了从 git 运行 fdroidserver 所需的所有依赖项。

现在你已经准备好运行构建了。通过构建最新的 fdroid 版本进行测试:

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

设置 QEMU/KVM/libvirt

虽然过去曾使用 VirtualBox,QEMU/KVM guest VMs via libvirt 仍旧是推荐的设置,因为 f-droid 用的就是这个。为了让 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(或 _svm_amd)指令集。你可以使用这个命令来列出关于你的 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) 虚拟机配置转发嵌套所需的 cpu 功能。所以打开你的虚拟机配置 /etc/libvirt/qemu/my-vm.xml,在你的 domain-tag 里面插入一个 cpu 块。(virt-manager 也为这个操作提供了一个用户接口。)

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

这里实际需要的配置取决于你的 cpu。你可以在 libvirts 手册中找到细节。重要的部分是你把 vmx(或 svm 在 amd 上)转发给客户系统。