Erstellen eines „simple binary F-Droid Repos“
In diesem Artikel möchte ich zeigen, wie man ein einfaches binäres Repo für die Verwendung mit jedem F-Droid-Client einrichtet. Es wird nicht so bequem sein wie Repomaker (statt einer grafischen Benutzeroberfläche müssen wir etwas Kommandozeilenarbeit leisten), aber auf der anderen Seite bist Du immer auf dem neuesten Stand mit den Werkzeugen, die das F-Droid-Projekt selbst verwendet, und kannst so leicht Hilfe bekommen. Meine Anleitung hier zielt auf Debian-basierte Systeme ab; wer etwas anderes verwendet, muss entsprechende Anpassungen vornehmen (z. B. bei den Befehlen des Paket-Installers).
FdroidServer
fdroidserver ist, was das F-Droid Projekt auch selbst verwendet. Und dessen Konfiguration als „simple binary repo“ ist, was z. B. bei IzzyOnDroid repo zum Einsatz kommt.
Es gibt zwar ein fdroidserver
-Paket in den Repos unserer Linux-Distribution, aber das ist normalerweise ziemlich veraltet1. Wir hätten das nehmen können (apt install fdroidserver
) und wären mit der Einrichtung schon fertig – aber damit hätten wir eine alte Version, mit der das F-Droid-Team uns nur schwer unterstützen könnte. Außerdem würden wir viele der neueren Funktionen verpassen und wären nicht mehr mit der offiziellen Dokumentation synchron.
Daher wollen wir den manuellen Ansatz verwenden, der uns auch mehr Flexibilität bietet. Zum Beispiel ist es damit recht einfach, Korrekturen oder neue Funktionen einzubringen, sobald sie committed wurden: kein Warten auf die Packager unserer Distribution, einfach in das fdroidserver
-Verzeichnis wechseln und einen git pull
ausführen.
Benötigte Abhängigkeiten installieren
Diese können sich im Laufe der Zeit ändern (und es kann z. B. ein neueres OpenJDK empfohlen werden). Zum Zeitpunkt, an dem ich dies schreibe, wird folgendes benötigt:
sudo apt install openjdk-11-jdk apksigner fastjar jarwrapper androguard
sudo apt install python3-yaml python3-pyasn1-modules python3-paramiko python3-ruamel.yaml python3-git
sudo apt install python3-qrcode python3-defusedxml
# optional:
# sudo apt install yamllint
Ein (fake) AndroidSDK bereitstellen
Hinweis: Mit der aktuellen Version von fdroidserver
(spätestens ab 12/2021) ist dies nicht mehr nötig, und der Schritt kann übersprungen werden.
Wir bräuchten auch Teile der Android-Buildtools. Die Installation des gesamten AndroidSDK ist ein bisschen übertrieben, wenn man nur ein einfaches Binary Repo betreiben (und nicht selbst Anwendungen kompilieren) möchte. Fdroidserver sucht (und braucht) für diesen Einsatzzweck nur sehr wenig davon (hauptsächlich aapt
), also können wir entweder android-tools-adb
(oder direkt adb
) und android-tools-fastboot
(oder direkt fastboot
) über apt install
installieren, damit unser Linux-System auch für Updates sorgt – oder die minimalen ADB- und Fastboot-Pakete von IzzyOnDroid herunterladen (Updates können damit verzögert werden, da ich sie nicht zu häufig vornehme) und platzieren die Binärdateien manuell; das vermeidet die Abhängigkeiten, die von den obigen Paketen eingeschleppt werden.
Mit diesen Tools müssen wir ein echtes AndroidSDK fälschen, damit fdroidserver glaubt, dass es vorhanden ist (und sich nicht mehr beschwert, dass es nicht gefunden wird). Im Folgenden wird dies im Unterverzeichnis bin/android-sdk
unseres Linux-Home-Verzeichnisses eingerichtet. Mein Beispiel hier verwendet die manuell heruntergeladenen Dateien von IzzyOnDroid, die ich in das Unterverzeichnis bin/
meines Linux-Home-Verzeichnisses installiert habe:
mkdir ~/bin/android-sdk
cd ~/bin/android-sdk
ln -s . build-tools
ln -s . platform-tools
ln -s . tools
ln -s ~/bin/adb .
ln -s ~/bin/aapt .
ln -s ~/bin/fastboot .
ln -s /etc/alternatives/keytool .
Zur Sicherheit noch einmal klargestellt: Wer das AndroidSDK komplett installiert hat, kann sich diesen Schritt sparen und verwendet einfach selbiges. Das ist zwar wesentlich umfangreicher – ermöglicht dann aber auch das Kompilieren von Apps.
Fdroidserver installieren und einrichten
Wir haben die Abhängigkeiten bereits manuell eingerichtet und verwenden nun den neuesten Code aus dem Development Repository. Dies setzt natürlich voraus, dass auch ein funktionierendes Git-System eingerichtet ist (wer das noch nicht hat: apt install git
). Im Folgenden wird von einer Installation in /opt/fdroidserver
ausgegangen (um es einfach zu halten) – es kann natürlich auch ein anderes Verzeichnis der Wahl verwendet werden (/opt
erfordert zudem, dass wir dort Schreibrechte haben).
cd /opt
# Hole die Software
git clone https://gitlab.com/fdroid/fdroidserver.git
# Erstelle einen Alias (am besten in der `.bashrc` integrieren)
alias fdroid=/opt/fdroidserver/fdroid
Das (erste) Repo erstellen
Wahrscheinlich möchtest Du Dein Repository (öffentlich) zugänglich machen, was normalerweise über einen Webserver geschieht. Auch hier kann das Verzeichnis frei gewählt werden. Gehen wir von „bekannten Strukturen“ aus und verwenden wir /var/www/fdroid
für unser Beispiel hier:
# Erstellen des Verzeichnisses, das unser Repo beinhalten soll
sudo mkdir /var/www/fdroid
# Es sollte dem Nutzer gehören, der es später auch bedienen soll (uns), aber auch der Webserver benötigt Zugriff (hier: über die Gruppe)
sudo chown <MyUser>:www-data /var/www/fdroid
sudo chmod 755
# Jetzt initialisieren wir das Repo
cd /var/www/fdroid
fdroid init
# trotz der Beschwerde "No Android SDK found" war die Initialisierung erfolgreich. Jetzt gilt es,
# die Konfiguration anzupassen – insbesondere auch den `keydname`. Die Anpassungen direkt unterhalb
# dieses Blocks durchführen, dann die Datei `keystore.p12` löschen, und weiter geht es mit
fdroid update --create-key
# Index und keystore verifizieren
jarsigner -verify -verbose repo/index-v1.jar
keytool -keystore keystore.p12 -list -v # das abgefragte Passwort findet sich in der Konfigurationsdatei
# Zum Abschluss sichern wir Konfiguration und Keystore gegen unbefugten Zugriff ab. Danach kann nur noch der
# Eigentümer (wir) F-Droid Aktionen in diesem Repo ausführen:
sudo chmod 0600 /var/www/fdroid/config.yml /var/www/fdroid/keystore.p12
Anpassungen der config.yaml
(die entsprechenden Sektionen gilt es in der Datei aufzusuchen und zu bearbeiten):
# Nur notwendig, wenn ein "Fake AndroidSDK" (s. o.) erstellt oder das "echte SDK" nicht gefunden wurde:
# Den sdk_path lassen wir auf unsere "Fake-Struktur" (siehe oben) bzw. das installierte komplette AndroidSDK
# zeigen. Das Beispiel hier geht davon aus, dass sich dieses im Home-Verzeichnis des Users befindet, der
# später die fdroid Befehle ausführt. Wer ganz sicher gehen will, setzt einfach einen absoluten Pfad:
sdk_path: ~/bin/android-sdk
# Details zu unserem repo_ und archive_ (in der Beispiel-Konfiguration sind diese auskommentiert.
# Diese den eigenen Bedürfnissen anpassen; URLs müssen dahin zeigen, wo der "echte Webserver"
# das Repo letztendlich öffentlich bereitstellt).
# Im Prinzip wird nur repo_ benötigt. Wer gar keine Archivierung älterer App-Versionen wünscht,
# setzt archive_older auf 0.
# Wie viele (ältere) APKs im Repo verbleiben sollen, wenn neuere Versionen einer App hinzukommen:
archive_older: 3
# wer keine SymLinks auf das jeweils aktuellste APK einer App benötigt ("keep it simple"):
make_current_version_link: false
# Der für alle Schlüssel verwendete eindeutige Name.
# Diese Anpassungen sollten vorgenommen werden, BEVOR das Repo öffentlich verfügbar gemacht wird
# und sollten danach besser NICHT mehr angefasst werden – denn dies definiert u. a., wie der Index
# signiert wird. Ändert man das später, werden die Nutzer des Repos Signtur-Fehler erhalten (der
# F-Droid Client wird die Index-Updates nicht mehr akzeptieren), was zu Verwirrung führt
# (dies ist auch der Grund dafür, dass mein Repo nach wie vor mit dem "example keydname" läuft,
# da ich das seinerzeit zu spät bemerkt hatte).
# keydname (syntax): CN=myDomain.com, O=MyOrganisationName, OU=MyDevelopmentUnit, L=MyTown, C=MyCountry
# In der folgenden Zeile die Werte bitte entsprechend anpassen :-)
keydname: CN=acme.com, O=ACME, OU=ACMEDev, L=Berlin, C=DE
#--=[ wer keinen separaten "Remote Server" für die Publikation verwendet, kann folgendes überspringen: ]=--
# serverwebroot zeigt auf den SSH Counter-Part des öffentlichen Servers
serverwebroot: www.example.com:/var/www/fdroid
# soll/muss ein spezieller SSH-Schlüssel verwendet werden, wird er hier definiert:
identity_file: ~/.ssh/fdroid_id_rsa
Nachdem nun die Datei keystore.p12
gelöscht und per fdroid update --create-key
neu erstellt wurde, sollte jarsigner -verify -verbose repo/index-v1.jar
unsere keydname
Anpassungen bestätigen (was mit jar verified.
endet). Danach folgen noch einige Warnungen, die getrost ignoriert werden können:
- Einträge mit invalidem „certificate chain“ (äh… wir haben gar keinen „chain“, weil…)
- „signer certificate is self-signed“ (ähm – ja, stimmt, das haben wir gemacht)
- „SHA1 digest algorithm is considered a security risk“ (dagegen können wir nichts tun, das ist Sache der fdroidserver Entwickler)
- „SHA1withRSA signature algorithm is considered a security risk“ (gleiche Geschichte)
- „jar contains signatures that do not include a timestamp“ (auch das)
Befüllen des neuen Repos
Da es sich hier um ein simple binary Repo handelt, füllen wir es einfach mit Binaries. Dazu kopieren wir die entsprechenden .apk
Dateien in unser neues Repo (darauf achten, dass sie innerhalb des Verzeichnisses repo/
landen – was mit unseren obigen Beispieldaten /var/www/fdroid/repo/
wäre), und lassen fdroidserver ein Update durchführen bei welchem er auch die zugehörigen Metadaten erstellt, indem wir fdroid update -c
ausführen (das -c
steht hier für "createMeta"). Metadaten müssen nur einmalig pro Package (aka „App“) erstellt werden; stellen wir also jetzt Version 1 von com.example.app
bereit, muss dieser Schritt später für Version 2 nicht wiederholt werden. Bei folgenden Läufen, wenn nur Beschreibungen angepasst oder neue Versionen hinzugefügt wurden, genügt also ein einfaches fdroid update
.
Das empfohlene Namensschema für APK Daeien ist: <package_name>_<versionCode>.apk
– für unser Beispiel von gerade eben wäre das also /var/www/fdroid/repo/com.example.app_1.apk
.
fdroid update -c
hat nun (eine) initial(e) Metadaten-Datei(en) für unsere neue(n) App(s) erstellt, die wir im Unterverzeichnis metadata/
finden. Der Dateiname entspricht wieder unserem PackageName, und wäre damit für unser obiges Beispiel /var/www/fdroid/repo/com.example.app.yml
. Eine Auflistung aller in dieser Datei verfügbaren Felder findet sich in F-Droid’s Build Metadata Reference. Da wir hier von einem einfachen „binary repo“ sprechen, können wir alle Build-spezifischen Dinge auslassen. Für den Anfang sollte zunächst genügen, was folgendes reelle Beispiel aus meinem Repo zeigt:
Categories:
- Money
License: MIT
AuthorName: Zap
AuthorEmail: zap@jackmallers.com
AuthorWebSite: https://www.zaphq.io/
SourceCode: https://github.com/LN-Zap/zap-android
IssueTracker: https://github.com/LN-Zap/zap-android/issues
Translation: https://github.com/LN-Zap/zap-android/blob/master/docs/TRANSLATING.md
AutoName: Zap
Summary: Bitcoin Lightning Wallet
Description: |-
<p><i>Zap</i> Wallet makes Bitcoin usable for everyone. Trustlessly send and
receive Bitcoin instantly with minimal fees via the Lightning Network.
Manage your private keys, multiple wallets, and open channels, to get
connected with peers on the Lightning Network and start transacting today.
Zap is available on all platforms, so you can stay connected and transact
whether you are at home or on the move.</p>
<p><i>Zap</i> is also available for iOS, Mac, Linux and Windows.</p>
ArchivePolicy: 1 versions
Die Author*
Felder sind optional und können weggelassen werden; gleiches gilt für IssueTracker
, Translation
und AutoName
. Ich habe die ArchivePolicy
zur Veranschaulichung mit aufgenommen, da sie recht nützlich sein kann: hier gibt sie an, dass nur exakt 1 APK der App im repo/
Verzeichnis existieren soll. Ältere werden automatisch in das Verzeichnis archive/
verschoben, wo sie bequem mittels rm *.apk
entsorgt werden können (sofern man kein Archiv betreiben möchte).
Synchronisation mit dem öffentlichen Server
Bis hier hin haben wir uns auf unserem lokalen Rechner bewegt, der wahrscheinlich nicht öffentlich zugänglich ist. Um unser Repo öffentlich verfügbar zu machen, muss auch der eigentliche Webserver entsprechend vorbereitet werden:
# Das Verzeichnis erstellen, in welchem unser Repo "lebt":
sudo mkdir /var/www/fdroid
# Wir geben dem Webserver Rechte zum Lesen und Ausführen (hier: in Verzeichnisse wechseln),
# und unserem für die Synchronisation via rsync verwendeten User Vollzugriff:
sudo chown <MyUser>:www-data /var/www/fdroid
sudo chmod 755
Um unsere lokalen Anpassungen auf den Server zu bringen, rufen wir einfach fdroid deploy
auf, während wir uns in selbigem (/var/www/fdroid
) befinden.
Einige optionale, aber empfohlene Anpassungen zur Webserver-Konfiguration
Möchte ein Anwender einen App-Link aus der F-Droid Client App heraus teilen, weiß letzterer nichts über das Setup des jeweiligen Repositories. Es wird also anhand des Servernamens eine URL erstellt, die der Sturktur bei f-droid.org entspricht. Damit diese auch auf unserem Server funktioniert, müssen ggf. „Redirects“ eingerichtet werden. Details dazu finden sich hier. Dabei geht es um den Link, mit dem die entsprechenden App-Details per Web-Browser aufgerufen werden können; das „Target“ hängt daher davon ab, was zur Anzeige auf dem eigenen Webserver zum Einsatz kommt (was evtl. Teil eines separaten Artikels hier werden könnte).
Die Software aktuell halten
Um die via apt
installierten Pakete wird sich unser Linux-System kümmern. Wer die adb
Binaries manuell installiert hat, muss sich auch händisch um deren Updates kümmern (ein bis zwei Mal pro Jahr genügt in der Regel). Womit lediglich die via Git installierte fdroidserver
Software übrig bleibt. Von Zeit zu Zeit sollte man also in deren Verzeichnis wechseln (in unserem Beispiel mit cd /opt/fdroidserver
) und ein beherztes git pull
ausführen.
Feinschliff
Weiter geht es im Folge-Artikel: Erweitern des „simple binary Repos“: Screenshots & mehr.
Referenzen
- F-Droid Server Manual
- Setting up your own app store with F-Droid
- F-Droid Dokumentation
- ein Docker Container, der obiges Rezept umsetzt
- Skripte zur automatischen Installation & Konfiguration eines Apache basierten Webservers auf Debian zur Verwendung mit einem F-Droid Repository, z. B. auf einer „blanken Maschine“ bei einem Webhoster (getestet bei Hetzner)