- Überblick über die Einrichtung
- Einrichten eines Build-Servers
- Builds ausführen
- Optionale Verwendung von QEMU/KVM/libvirt statt VirtualBox
Der F-Droid-Build-Server isoliert die Herstellung eines jeden Pakets in einer sauberen, abgeschirmten und sicheren Wegwerfarbeitsumgebung einer virtuellen Maschine. Das Herstellen tausender Apps, insbesondere mit automatisierten und/oder unbeaufsichtigten Prozessen, muss vom Sicherheitsaspekt her als eine gefahrbringende Beschäftigung angesehen werden. Das ist umso mehr der Fall, wenn die hergestellten Produkte zudem weit verbreitet werden und dies in einer halbautomatischen Weise geschieht (“Es stehen Aktualisierungen bereit”).
Nehmen wir an, ein einspielendes Quell-Repository ist beschädigt. Dann finden wir hier eine kleine Auswahl an Maßnahmen, die ein Angreifer in einer solchen Situation ergreifen könnte:
- Eigene Build-Schritte anwenden, die faktisch alle ausgeführt werden, als würde der Benutzer den Build erstellen.
- Auf den Schlüsselspeicher zugreifen.
- Die erstellten APK-Dateien oder Quelltexttarballs für andere Anwendungen im Repository ändern.
- Verändern von Metadaten (zu denen auch Build-Skripte gehören, die wiederum ebenfalls die Fähigkeit mitbringen, alles auszuführen) für andere Anwendungen im Repository.
Durch die vollständige Isolierung bleiben die Auswirkungen zumindest auf die jeweilige Anwendung beschränkt. Die Build-Umgebung wird nicht nur frisch für jeden Build geschaffen und danach verworfen, sie wird auch komplett von der Signatur-Umgebung abgeschirmt.
Abgesehen von Sicherheitsproblemen gibt es einige Anwendungen, die seltsame Anforderungen haben, wie z.B. alte Versionen des NDK. Es wäre nicht praktikabel (oder zumindest extrem chaotisch), damit zu beginnen, das SDK auf einem Mehrzwecksystem zu modifizieren und wiederherzustellen, aber innerhalb der Grenzen einer Virtual Machine zum einmaligen Gebrauch ist alles möglich.
Hinzu kommt der offensichtliche Vorteil, eine standardisierte und vollständig reproduzierbare Umgebung zu besitzen, in der gebaut wird. Darüber hinaus schafft sie die Voraussetzungen für spezialisierte, maßgeschneiderte Build-Umgebungen für besondere Anwendungsfälle.
Überblick über die Einrichtung
Ausgehend von einer komplett sauberen minimalen Debian/Stable-Installation
richten Sie so einen funktionierenden Build-Server ein. Diese Anleitung
geht davon aus, dass Sie bereits den fdroidserver aufgesetzt
haben. Das Ausführen der
fdroidserver-Werkzeuge direkt aus
git heraus
(z. B. ~/fdroidserver/fdroid build org.adaway
), wird wahrscheinlich fürs
Erste am einfachsten sein, da die Build-Server-Setup-Skripte noch nicht
wirklich fertig sind, um sie sauber zusammenzupacken. Außerdem wird es
wahrscheinlich nur auf Debian, Ubuntu und anderen Debian-Derivaten
funktionieren, da F-Droid nur Debian in seiner Infrastruktur verwendet (wir
begrüßen Portierungsbeiträge!).
Der Basisserver braucht mindestens Debian/Jessie oder es müssen einige schwierige Anpassungen vorgenommen werden. Wenn Sie Ubuntu oder eine abgeleitete Distribution nutzen, können Sie alle Pakete, die in Ihrer Version fehlen, wie vagrant-cachier, von diesem PPA beziehen: https://launchpad.net/~fdroid/+archive/ubuntu/buildserver/
Installieren Sie zunächst die notwendigen Pakete und legen Sie einen neuen Benutzer an, der den gesamten Prozess hier ausführen soll, z. B. fdroid. Dies sind nur die Pakete, die von allen Builds benötigt werden. Möglicherweise müssen Sie zusätzliche Pakete installieren, um Apps herzustellen, z. B. mercurial oder subversion. Sobald die Pakete installiert sind und der Benutzer fdroid erstellt wurde, sollte in diesem Prozess nichts mehr mit root oder sudo ausgeführt werden.
root:~# apt-get install vagrant virtualbox git python3-certifi \
python3-libvirt python3-requestbuilder python3-yaml \
python3-clint python3-vagrant python3-paramiko python3-pyasn1 \
python3-pyasn1-modules python3-requests python3-git
root:~# adduser --disabled-password fdroid
root:~# su fdroid
Klonen Sie den Quellcode und konfigurieren Sie die Buildserver-Einstellungen, was als Benutzer fdroid ausgeführt wird:
fdroid:~$ cd ~
fdroid:~$ git clone https://gitlab.com/fdroid/fdroidserver.git
fdroid:~$ cp fdroidserver/examples/makebuildserver.config.py fdroidserver/
Sie müssen außerdem sicherstellen, dass die
Einrichtung Ihrer
ANDROID_HOME
-Umgebungsvariable korrekt ist.
Der Einfachheit halber können Sie optional die ausführbare Datei „fdroid“ zu Ihrem Pfad hinzufügen:
fdroid:~$ echo "PATH=\$PATH:$HOME/fdroidserver" >> ~/.bashrc
Erstellen Sie das Basis-Buildserver-Image…. (das Herunterladen der Basebox und aller SDK-Plattformen kann lange dauern).
fdroid:~$ cd fdroidserver
fdroid:~/fdroidserver$ ./makebuildserver
Holen Sie sich alle App-Metadaten aus dem 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
Einrichten eines Build-Servers
Zusätzlich zum zuvor beschriebenen Basis-Setup liefern wir eine Vagrant-kompatible Debian/Stretch-Basebox namens „fdroid/basebox-stretch64“ aus.
Das Bootstrapping der Debian-Vagrant-Boxen für unseren Buildserver erfolgt von Grund auf. Der Bezug und die Überprüfung unserer vorgefertigten Vagrant-Boxen ist voll automatisiert. (Sollten Sie Interesse an diesem Prozess haben oder das Bootstrapping selbst in die Hand nehmen wollen, sollten Sie sich das hier ansehen: F-Droid Base Box)
Erstellen der F-Droid-Buildserver-Box
Navigieren Sie zu Ihrem Klon des F-Droid Server
git und beginnen Sie mit der
Erstellung von makebuildserver.config.py
, wofür
./examples/makebuildserver.config.py
als Referenz verwendet wird - schauen
Sie sich die Einstellungen und die Dokumentation dort an, um zu entscheiden,
ob etwas an Ihre Umgebung angepasst werden muss. Es gibt einen Pfad zum
Abrufen der Basisbox, falls sie nicht existiert, sowie eine passende
Proxy-Definition, die beide evtl. für Ihre Umgebung angepasst werden
müssen. Sie können dann in das Verzeichnis fdroidserver
wechseln und
makebuildserver
ausführen.
# navigieren Sie zu Ihrem Klon des F-Droid-Servers
cd .../fdroidserver
# kopieren Sie die Beispiel-Konfigurationsdatei
cp examples/makebuildserver.config.py makebuildserver.config.py
# starten Sie den Build Ihres Basebox-Images
./makebuildserver
Dies wird lange dauern, viel Bandbreite und Speicherplatz beanspruchen - der größte Teil davon wird für die Installation der notwendigen Teile des Android-SDKs für die verschiedenen Plattformen aufgewendet. Zum Glück müssen Sie das nur gelegentlich tun. Sobald Sie ein funktionierendes Build-Server-Image haben, können Sie, wenn sich Rezepte ändern (z.B. wenn Pakete hinzugefügt werden müssen), dieses Skript einfach erneut ausführen, dann wird das vorhandene an Ort und Stelle aktualisiert.
Sobald es fertig ist, haben Sie eine neue Basis-Box namens „buildserver“,
die für die eigentlichen Builds verwendet wird. Sie können dann Pakete wie
gewohnt erstellen, aber bei Ausführung von fdroid build --server ...
erfolgt die App-Erstellung nun isoliert innerhalb der virtuellen Maschine.
Beim ersten Build wird eine neue virtuelle Maschine erstellt, die die
„Buildserver“-Box als Basis verwendet. Ein Snapshot dieses sauberen
Maschinenzustandes wird für zukünftige Builds gespeichert, um die Leistung
zu verbessern. Sie können das Verwerfen dieses Snapshots und den Neuaufbau
von Grund auf erzwingen, indem Sie den Schalter fdroid build --resetserver
...
verwenden.
Cache-Anpassungen für makebuildserver (optional)
Die wichtigsten SDK/NDK-Downloads werden automatisch zwischengespeichert, um
den nächsten Durchgang zu beschleunigen. Aber es gibt keine einfache
Möglichkeit, dies für längere Abschnitte zu tun, die das android
-Tool des
SDK verwendet, um Plattformen, Add-ons und Tools zu installieren. Anstatt
jedoch ein automatisches Caching zu erlauben, können Sie ein vorgefülltes
Cache-Verzeichnis angeben, das nicht nur diese Downloads, sondern auch
.tar.gz-Dateien für alle relevanten Ergänzungen enthält. Wenn die
Provisionierungsskripte diese erkennen, werden sie anstelle der
Android-Tools verwendet. Haben Sie zum Beispiel
buildserver/addons/cache/platforms/android-19.tar.gz
, wird sie für die
Installation der Android-19-Plattform verwendet, anstatt sie mit android
update sdk --no-ui -t android-19
erneut herunterzuladen. Es ist möglich,
aus einer lokalen Installation des SDK die Cache-Dateien dieser Ergänzungen
zu erstellen, diese eingeschlossen:
cd /pfad/zum/android-sdk/platforms
tar czf android-19.tar.gz android-19
mv android-19.tar.gz /path/to/buildserver/addons/cache/platforms/
Wenn Sie bereits einen Buildserver erstellt haben, ist es auch möglich, diese Dateien direkt vom Buildserver zu beziehen:
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' > /pfad/zum/fdroidserver/buildserver/cache/platforms/android19.tar.gz
Builds ausführen
Bei Verwendung des Buildservers ist es am einfachsten, fdroid
direkt von
einem Git-Checkout von fdroidserver aus zu starten. Wenn Sie die
fdroidserver-Tools noch nicht installiert und eingerichtet haben, müssen
Sie das als nächstes tun: Server und Repo-Werkzeuge
installieren. Das liefert alle
Abhängigkeiten, die benötigt werden, um fdroidserver von git auszuführen.
Jetzt sind Sie bereit, Builds auszuführen. Testen Sie die neueste Version von fdroid:
fdroid:~/fdroidserver$ cd ~/fdroiddata
fdroid:~/fdroiddata$ ~/fdroidserver/fdroid build org.fdroid.fdroid -l --server
Optionale Verwendung von QEMU/KVM/libvirt statt VirtualBox
Es ist auch möglich, QEMU/KVM-Gast-VMs über libvirt anstelle des
standardmäßigen VirtualBox zu laden. VirtualBox ist immer noch das
empfohlene Setup, da auch von f-droid.org verwendet wird, aber es gibt
Fälle, in denen es nicht möglich ist, VirtualBox auszuführen, wie z.B. auf
einer Maschine, auf der bereits QEMU/KVM-Gäste laufen. Um die
libvirt-Bilddateien direkt mit vagrant package
lesbar zu machen, muss QEMU
von libvirt so konfiguriert werden, dass es immer auf libvirt.libvirt
gesetzt wird.
root:~# apt-get install vagrant vagrant-mutate vagrant-libvirt ebtables dnsmasq-base \
python3-libvirt libvirt-clients libvirt-daemon-system qemu-kvm qemu-utils git \
python3-yaml python3-clint python3-vagrant python3-pyasn1 python3-pyasn1-modules \
python3-requests python3-git
root:~# cat << EOF >> /etc/libvirt/qemu.conf
user = "libvirt"
group = "libvirt"
dynamic_ownership = 1
EOF
root:~# service libvirtd restart
Erstellen Sie dann neben makebuildserver eine makebuildserver.config.py und fügen Sie hinzu:
vm_provider = 'libvirt'
Debian/stretch und Ubuntu/xenial
root:~# adduser fdroid libvirt
root:~# adduser fdroid libvirt-qemu
älteres Debian und Ubuntu
root:~# adduser fdroid libvirtd
root:~# adduser fdroid kvm
Erweitertes verschachteltes KVM Setup:
Dieser Abschnitt ist nicht relevant für die Verwendung von F-Droid in einem
normalen Setup. Wenn Sie das Flag fdroid build --server
in einem KVM
laufen lassen wollen, hilft Ihnen dieses Kapitel beim Start.
Beachten Sie die folgenden grundlegenden Schachtelungseinstellungen:
bare metal host (l0)
\- F-Droid VM (l1)
\- F-Droid builder VM (l2)
Die obigen Schritte beschreiben, wie man (l1) und makebuildserver einrichtet (l2).
Zuerst müssen Sie prüfen, ob die CPU den Befehlssatz vmx (oder svm auf amd) unterstützt. Mit diesem Befehl können Sie Details über Ihre CPU auflisten:
root:~# cat /proc/cpuinfo
Bei (l0) müssen Sie prüfen, ob die Verschachtelung aktiviert ist:
root:~# cat /sys/module/kvm_intel/parameters/nested
Wenn es nicht aktiviert ist, können Sie es einschalten durch Ausführen von:
echo "options kvm-intel nested=Y" > /etc/modprobe.d/kvm-intel.conf
Sie müssen einen Neustart durchführen, damit dies wirksam wird.
Als nächstes müssen Sie sicherstellen, dass Ihre (l1) VM-Konfiguration die zum Verschachteln benötigten CPU-Funktionen weiterleitet. Öffnen Sie also Ihre Konfiguration für die VM /etc/libvirt/qemu/my-vm.xml und fügen Sie einen CPU-Block in Ihr Domain-Tag ein. (virt-manager bietet auch eine Benutzeroberfläche für diese Tätigkeit.)
<cpu mode='custom' match='exact'>
<model fallback='allow'>SandyBridge</model>
<vendor>Intel</vendor>
<feature policy='require' name='vmx'/>
</cpu>
Die tatsächlich benötigte Konfiguration hängt von Ihrer CPU ab. Details finden Sie im libvirts Handbuch. Das wichtigste ist vmx (oder svm auf amd) an das Gastsystem weiterzuleiten.
Dies ist das Setup, das in den Continuous Integration-Builds als Teil der reproduzierbaren Builds verwendet wird. Sie können dies auf dem Jenkins-Setup des Debian-Projekts in Aktion sehen:
* https://jenkins.debian.net/job/reproducible_setup_fdroid_build_environment_profitbricks7/