Setting up a simple binary F-Droid repo
In this article I want to show how to set up a simple binary repo for use with any F-Droid client. It won’t be as convenient as Repomaker (instead of a GUI we’ll have to do some command-line work), but on the pro side you’ll be always up-to-date with the tools the F-Droid project itself uses, and thus can easily get help there. My guide here is targeted at Debian-based systems; if you use something else, you’ll need to substitute (e.g. the package installer commands).
fdroidserver is what the F-Droid project itself uses. And its setup as „simple binary repo“ is what the IzzyOnDroid repo runs on.
While there’s an
fdroidserver package in the repos of our Linux distribution, that’s usually pretty outaged1. We could have gone with that (
apt install fdroidserver) and be done with the setup, but then we’d probably run on old code the F-Droid team would have a hard time supporting us with. And we’d miss much of the newer features, plus running out of sync with the official documentation.
Hence let us use the manual approach, which also gives us more flexibility – for example it’s quite easy to get fixes or new features in as soon as they are committed: no waiting for the packagers of your distribution, just switch into the
fdroidserver directory and do a
Installing required dependencies
Those might change over time (and e.g. a newer OpenJDK might be recommended). At the time of my writing this, we need to install:
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
Setting up a (fake) AndroidSDK
Note: with recent versions of
fdroidserver (at least since 12/2021) this is no longer needed and can be skipped.
We’d also need parts of the Android buildtools. Installing the entire AndroidSDK is a bit overkill if you only want to run a simple binary repo (and not compile apps yourself). Fdroidserver only looks for (and needs) very few of that to run a „simple binary repo“ (mostly
aapt), so you could either go with
android-tools-adb (or directly
android-tools-fastboot (or directly
fastboot) installed via
apt install (so your Linux system also takes care for updates) – or download the minimal ADB and Fastboot packages from IzzyOnDroid (updates may be delayed with them) and place the binaries manually – which avoids the dependencies dragged in by above packages.
With those tools available, we need to fake a real AndroidSDK to make fdroidserver believe it’s there (and to stop complaining it cannot find it). The following establishes this in the
bin/android-sdk sub-directory of your Linux home directory. My example here uses the manually downloaded files from IzzyOnDroid, which I installed into the
bin/ sub-directory of my Linux home:
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 .
Install and set up fdroidserver
We’ve already set up the dependencies manually, and will now use the latest code from the development
repository. This of course requires you to have a working Git set up. The following assumes an installation
/opt/fdroidserver (to keep it easy) – you can of course use any other location of your choice (
will require you to have write permission there).
cd /opt # Get and setup the software (only required once) git clone https://gitlab.com/fdroid/fdroidserver.git # make an alias (best integrate it with `.bashrc`) alias fdroid=/opt/fdroidserver/fdroid
Create your first repo
You’ll probably want to make your repository (publicly) accessible, which is usually done via a web server.
Again, you can pick any location of your choice. Going by „known structures“, let’s use
for our example here:
# create the directory our repo shall reside in sudo mkdir /var/www/fdroid # have it owned by us, but let the web server have its access permissions via group sudo chown <MyUser>:www-data /var/www/fdroid sudo chmod 755 # initialize the repo cd /var/www/fdroid fdroid init # this will complain about "No Android SDK found" (but initialize the repo fine). So let’s # fix up the config, especially `keydname` while we’re on it. See below for details. # then delete the `keystore.p12` file and run fdroid update --create-key # verify index and keystore jarsigner -verify -verbose repo/index-v1.jar keytool -keystore keystore.p12 -list -v # use the password from keystorepass in your config # now apply some safeguards. After this, only the owner (our user) can run F-Droid operations: sudo chmod 0600 /var/www/fdroid/config.yml /var/www/fdroid/keystore.p12
Adjustments for the
config.yaml (just look for and edit the corresponding sections):
# Only needed if a "fake AndroidSDK" was set up (or the real one was not found): # have the sdk_path point to where we faked it. This assumes you have set it up # in the home of the user running the `fdroid` commands later; to be on the safe # side, just use an absulute path: sdk_path: ~/bin/android-sdk # details for our repo_ and archive_ (in the example, they are commented out. # Adjust them to your liking. URLs here must point to your real web server where # you want to make your repo publicly available). # Basically, you’ll only need repo_ and set archive_older to 0 if you want no # archiving at all. # How many (older) APKs to keep when newer come in: archive_older: 3 # to keep things simple, you MAY wish to: make_current_version_link: false # The distinguished name used for all keys. # Make sure to set this BEFORE you make your repo public and better do NOT change # it afterwards – as this defines a.o. how your index will be signed. If you change # it later, your users will receive a signature error on update and will be confused # (which is why my repo still runs with the "example keydname" as I’ve noticed that # too late). # keydname (syntax): CN=myDomain.com, O=MyOrganisationName, OU=MyDevelopmentUnit, L=MyTown, C=MyCountry # please substitute your own values – ACME, Inc is just a place-holder here to show you how it looks like! keydname: CN=acme.com, O=ACME, OU=ACMEDev, L=Berlin, C=DE #--=[ if you don’t use a remote web server to publish to, you can skip the following ]=-- # serverwebroot points to the SSH counter-part on your public server serverwebroot: www.example.com:/var/www/fdroid # should you need a specific SSH key, you can define that as in the comment: identity_file: ~/.ssh/fdroid_id_rsa
Now, after deleting the
keystore.p12 file and re-creating it via
fdroid update --create-key, running
jarsigner -verify -verbose repo/index-v1.jar should first confirm your
keydname settings (ending with
jar verified.). Following that you’ll receive several warnings which are safe to ignore:
- entries whose certificate chain is invalid (well, we have no „chain“ because…)
- signer certificate is self-signed (yepp, we did that)
- SHA1 digest algorithm is considered a security risk (nothing we can do about that, must be fixed by fdroidserver devs)
- SHA1withRSA signature algorithm is considered a security risk (same story)
- jar contains signatures that do not include a timestamp (yupp, again)
Feeding your new repo
We have a simple binary repo here, so it should be simple with binaries. Copy some
.apk files into your new repo (make sure to place them inside
repo/ – so with our above examples, this would be
/var/www/fdroid/repo/), then have fdroidserver update it and create the corresponding metadata by running
fdroid update -c. Metadata need to created only once per package, so if you e.g. now put v1 of
com.example.app in there, you won’t need to create metadata again for v2 later. On subsequent runs when only updating descriptions or apps, you’ll only need to run
Recommended file naming:
<package_name>_<versionCode>.apk – so with our dummy example, the file should be
fdroid update -c will now have generated an initial metadata file for our new app(s), which can be found in the
metadata/ sub-directory. The name again corresponds to the package name, and in our example would be
/var/www/fdroid/repo/com.example.app.yml. A reference to all available fields can
be found in F-Droid’s Build Metadata Reference. As we’re talking about a simple binary repo here, all build-specific data can be skipped for us. Let me show a basic example from an existing app in my repo for what’s needed for starters:
Categories: - Money License: MIT AuthorName: Zap AuthorEmail: firstname.lastname@example.org 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
Author* fields are optional and can be skipped, same for
AutoName. I’ve included the use of
ArchivePolicy here as it might come in handy: it says to only ever keep 1 APK in the repo and move older ones to
archive/ where you then can simply
rm *.apk to clean up should you not serve it publicly.
Syncing to a remote
As this was most likely your development machine, and the real website resides somewhere else, you need to create the proper remote setup as well. So go to your web server for that and…
# create the directory our repo shall reside in sudo mkdir /var/www/fdroid # give the web server read+exec access, and the user you connect to via rsync read+write+exec sudo chown <MyUser>:www-data /var/www/fdroid sudo chmod 755
Now, to publish your updated local repo, simply run
fdroid deploy from within your local repository (in our example, from within
Some optional, but recommended adjustments to your webserver config
When a user wants to share an app link out of the official F-Droid client app, F-Droid cannot know about your server setup. Thus it constructs an URL similar to the structures used at f-droid.org – which you will need to let your web server know about so it redirects properly. Details on that can be found here. This is about the link pointing to app details looked up by web browser, thus the target depends on how you have set that front-end up (and which one you use – maybe part of a separate article).
Keep your software up-to-date
For those packages installed via
apt, our Linux system will take care. If you installed the
adb binaries manually, you’ll have to manually check for updates. That leaves the
fdroidserver software we’ve installed via Git. So from time to time you should
cd into that directory (in our example here,
cd /opt/fdroidserver) and run
Continued with the follow-up article: Extend the „simple binary repo“: Screenshots & more.
- F-Droid Server Manual
- Setting up your own app store with F-Droid
- F-Droid Documentation
- a Docker container implementing the above recipe
- scripts to automatically set up an Apache based web server on Debian for use with an F-Droid repository, e.g. on a „blank machine“ at a web hoster
update: for users of Ubuntu, theres also a PPA available. ↩︎