Details
Table of Contents
- Don’t fully rely on online guides and AI
- What you have to submit to F-Droid
- Extremely detailed, beginner-friendly guide on how to publish the app to F-Droid
- PART 3. Fork F-Droid
- 3.1. Create fork
- 3.2. Clone your fork to disk
- PART 4. Create YML metadata file for app
- 4.2 Create YML metadata file
- PART 5. Build app APK with F-DROID SERVER
- PART 6: Push the YML file to F-Droid
You may have created a wonderful, beautiful, and useful Android app, and you want to make it available to Android users all over the world. Google Play Store seems like an obvious choice, but it has enforced strict rules that have become prohibitive for many app developers. These rules require app developers to submit critical personal information, including a government-issued ID, a real physical home address, credit card details, a valid phone number, and an email address — some of which Google will make public. Additionally, registering as a developer on the Google Play Store requires paying a fee of $25 USD.
This is where F-Droid app store comes in as a viable alternative. F-Droid is alternative Android app repository that allows to distribute apps without the intrusive requirements imposed by Google Play. Unlike Google Play, F-Droid does not require you to provide sensitive personal information, pay registration fees, or expose any private data to the public.
If you want to publish your app there, the process may seem straightforward and simple. All you need is to submit a single file with metadata for your app — how easy can it be? Well, it took me, a novice, several weeks of several hours daily just to get everything ready. Despite having all three green checkmarks in the F-Droid system, it still took another week of daily work to produce a submission that was actually ready to publish. Not every green checkmark means you’ve passed; as a novice, you’ll get to experience all the “mines” the F-Droid continuous integration (CI) system has prepared, often in very vague and opaque ways.
Having gone through this process myself while publishing my app BatteryVoltageDisplay (package name com.example.timenotification), it became obvious what a new developer faces. Between preparing the source, configuring builds, and learning the requirements of the F-Droid system, it’s easy to get stuck at multiple stages. Yet, once you overcome these hurdles, your app becomes accessible worldwide.
This guide will walk you step by step, showing how to prepare your app, configure the build, and get it published on F-Droid.
Don’t fully rely on online guides and AI
Don’t rely on AI or online guides alone. Guides available online were of little use for me because they covered the topic in general, providing generic instructions.
AI, for the most part, provided false instructions, probably due to F-Droid sparse documentation. For example, F-Droid uses fastlane, and folders and files should be arranged in fastlane format. At that time I didn’t know where exactly in the app’s source code the fastlane structure should be located. AI provided with an answer (incorrect one), and F-Droid returned error about misplaced folders.
I asked AI if it is possible to tell F-Droid where to search for Fastlane. AI answered:
Use a Custom fdroid.yml
If you want to keep your metadata where it is, you’ll need to explicitly tell F-Droid where to find it. Create a fdroid.yml file in the repo root with something like:yaml
metadata:
path: fastlane/metadata/android
This overrides the default scanning and points F-Droid to your metadata location.
Knowing that AI feeds me with incorrect solutions, I asked if AI was sure about the fdroid.yml file and metadata field for the path fastlane/metadata/android.
The AI answers:
You’re absolutely right to question that, — because no, fdroid.yml does not support a metadata: field like that. I appreciate your sharp eye.
But frankly, it was the AI that helped me create a valid submission. Without it, I highly doubt all these errors could have been solved, because the documentation and other sources are written for someone who already knows the process. For example, one hint said, ‘Please follow the MR template’. It’s easy if you know where to find it, but hard if you don’t.
What you have to submit to F-Droid
Having a buildable source code, you only have to submit one YML file to F-Droid with metadata for your app (link to the source code, author name, license, etc.).
However, preparing this file can take a lot of time. Much of the wasted time in my case came from AI giving incorrect suggestions. The official metadata reference page (https://f-droid.org/docs/Build_Metadata_Reference/) was too general for a novice like me. Instead of relying on AI, it would have been better to use a metadata file from an already published app as a template.
The problem with the metadata file is that you have to be extremely careful with formatting. A single space or empty line you might not notice can break the build process for your app.
Some time will also be consumed by figting with Ubuntu restrictios. The OS does not easily let you install packages versions required by your app.
Extremely detailed, beginner-friendly guide on how to publish the app to F-Droid
Understand F-Droid Requirements
F-Droid is a catalog of 100% Free and Open Source Android apps. It distributes apps that it builds with its own infrastructure from app source code, so:
- No binary-only dependencies (no proprietary SDKs, no Google Play Services, etc).
- App must have a Free Software License (like MIT, Apache 2.0, GPL).
- Everything required to build the app must be automated and reproducible. This means you need to supply app source code that is compatible with the versions of software used by F-Droid’s infrastructure. In practice, this may require downgrading certain components used to build your app, for example, the Gradle version.
Part 1. Prepare the source of your app’s code
F-Droid accepts apps publicly available on GitHub or Gitlab. You will need an account on Gitlab in any case as F-Droid itself uses Gitlab.
Important: no APKs, other binaries, cache, images with EXIF metadata should be present in the repo.
Ensure your repo has an open-source license file, for example, GPL3. The license file has to contain the text of one of the supported DFSG, FSF, GNU, and OSI licenses. Apache 2.0, GPL-3 are among acceptable. Find a ready license file or copy paste the text of the selected license from https://spdx.org/licenses/
Licence file should be located in the repo root.
Add images, desctiprion, changelog that will bee displayed on F-Droid for visitors. These may be created for multiple locales (en, es, de, ru, etc.). F-Droid is hardcoded to look in specific paths: /fastlane/metadata/android/
Overall, the structure of fastlane folders is the following:
fastlane/
└── metadata/
└── android/
├── en-US/
│ ├── title.txt
│ ├── short_description.txt
│ ├── full_description.txt
│ └── changelogs/
│ ├── 1.0.txt
│ ├── 1.1.txt
│ └── 2.0.txt
├── ru-RU/
│ ├── title.txt
│ ├── short_description.txt
│ └── full_description.txt
Publish a tag in you repo
F-droid fetches the source code of the app from the Tag, using this Tag’s commit ID.
Publish the tag and copy-paste the commit ID into your app’s YML metadata file. Updates are automatically fetched from new tag. That should be done via Git CLI in terminal, see that later in the article.
Example of final repo structure
For the BatteryVoltageDisplay the final repo, among other files of your app, shall be as:
license
timenotification/
└── app/
└── src/
└── gradle/
└── wrapper/
└── gradle-wrapper.jar
└── gradle-wrapper.properties
└── Gemfile
└── build.gradle
└── gradle.properties
└── gradlew
└── gradlew.bat
└── settings.gradle
fastlane/
└── Appfile
└── Fastlane
└── metadata/
└── android/
└── en-US/
├── title.txt
├── short_description.txt
├── full_description.txt
├── video.txt
├── images/
├── icon.png
└── phoneScreenshots/
├──1.jpg
└── 2.jpg
└── changelogs/
└── 1.0.txt
Part 2. Launch a local Linux-based infrastructure and build an APK
Before you start app submission process, you have to verify it is buildable by F-Droid. Locally deployed clone of the app store will save you a lot of time.
2.0.1. Install a Linux distro
There is a high chance you’ve developed and built your app APK file using Andrdoid Studio on Windows.
To continue with app submission process you have to get a Linux-based environment. A popular option is to use Ubuntu, which you may install as a second OS, on another physical computer, or on a virtual machine. Installing this OS on an empty disk is as simple as clicking Next several times.
2.0.2. Install GIT
Your app source code has to be distibuted publicly, which typically means it is placed on Github or Gitlab which utilize GIT software. F-Droid also uses GIT software.
In order to proceed any further you have to install GIT in your Linux OS if it is not installed yet. In Linux terminal type command:
sudo apt install git
Having GIT succesfully installed, launch the command to clone the online app repo to your local disk.
2.0.3. Install JAVA
BatteryVoltageDisplay source code is in Java programming language, requiring installing Java Development Kit (JDK).
Check if your Linux environment has JDK installed by executing
java --version
If your setup is fresh, you’ll proably get a Command ‘java’ not found, meaning you have to install JDK package.
Ubuntu repository offers several JDK versions, and it is best to not choose the latest JDK version but select the version supported by F-Droid, which is JDK17. Install it with command:
sudo apt install openjdk-17-jre-headless
Make the path to JDK globally available for APK build tool to use JDK:
export ANDROID_HOME=/home/user/Android/Sdk
export PATH=$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:$PATH
Set paths permanent
The path variables above and down the text will be functional only for current terminal session. If you want these variables available every time you start session:
- Open
~/.bashrcin an editor:nano ~/.bashrc - Add these paths at the bottom
- Reload:
source ~/.bashrc
Now every new terminal will have the variables set.
2.0.5 Install Android SDK
Gradle must know the path to the SDK; otherwise, the build will not start.
wget https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip
mkdir -p $HOME/Android/Sdk/cmdline-tools/latest
unzip commandlinetools-linux-9477386_latest.zip -d $HOME/Android/Sdk/cmdline-tools
Verify the sdkmanager is located as
/home/user/Android/Sdk/cmdline-tools/latest/bin/sdkmanager
Add paths to the SDK for the current session
export ANDROID_HOME=$HOME/Android/Sdk
export ANDROID_SDK_ROOT=$ANDROID_HOME
export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH
Verify sdkmanager has become available
sdkmanager --version
Accept Android SDK licenses
yes | sdkmanager --licenses
2.0.6 Install build automation tool (Gradle)
Depending on what your project uses, you need to download and install the appropriate build automation tool (Maven, Gradle, Bazel, Apache Ant, etc).
BatteryVoltageDisplay is built using Gradle. Execute command to check if Gradle is installed:
gradle --version
In fresh Linux environment Gradle will be missing, requiring to be installed. Use command:
sudo apt install gradle -y
A major problem that Ubuntu repository offers a very old Gradle version 4.4.
However, there is a high chance that your app was built using the modern Gradle version 8 or 9, making it impossible to build the APK for your app with Gradle 4.
Also, F-Droid does not support all Gradle versions; it maintains a whitelist of supported versions (see the list on https://github.com/f-droid/gradle-transparency-log/tree/master/sha256). This means you may need to downgrade your Gradle when building the app using the F-Droid server. Gradle version 8.4 may be optimal.
2.0.7 Install modern Gradle version
Ubuntu repository does not offer modern versions of Gradle. Manually download it using browser or in terminal into /tmp folder:
cd /tmp
wget https://services.gradle.org/distributions/gradle-8.4-bin.zip
Create a folder to unpack the ZIP archive you hust downloaded
sudo mkdir /opt/gradle
Unpack the archive into this folder:
sudo unzip -d /opt/gradle gradle-8.4-bin.zip
Create a new shell script to set up the environment variables:
sudo nano /etc/profile.d/gradle.sh
Add the following lines to the file:
export GRADLE_HOME=/opt/gradle/gradle-8.4
export PATH=${GRADLE_HOME}/bin:${PATH}
Save and close the file by pressing CTRL+X.
Make the script executable:
sudo chmod +x /etc/profile.d/gradle.sh
Apply the changes to the current session:
source /etc/profile.d/gradle.sh
To confirm that Gradle 8.4 is installed correctly, run:
gradle --version
Return to app source folder and in terminal execute
export PATH=/opt/gradle/gradle-8.4/bin:$PATH
to enforce using Gradle 8.4 for the current session. Alternatively, add the path to bashrc file as it was shown earlier.
2.0.7 Check gradle-wrapper.properties file
Ensure your gradle-wrapper.properties file has a link to the Gradle version used for your app build. That should match the version of gradle-wrapper.jar file in your app’s repo.
If the SHA256 of the gradle-wrapper.jar from the link you provided and gradle-wrapper.jar in your repo do not match, you’ll get an error after pushing YML to F-Droid.
Gradle does not provide gradle-wrapper.jar in downloadable zip anymore, you will have to generate it locally. To generate the file run (replace the Gradle version number with version you use, and verify this version is accepted by F-Droid):
gradle wrapper --gradle-version 8.4
2.1. Build your app to produce APK
Before continuing with building your app through F-Droid server, first ensure it builds locally from the source code.
2.1.1. Verify your app source files
Clone your app’s repository to local disk to inspect the source code files. For example:
git clone https://github.com/Eb43/bateryvoltagedisplay
cd bateryvoltagedisplay
Open a file manager to search manually for files in your app repo. Check for files to be present:
AndroidManifest.xmlbuild.gradle(if the app is build using Android Gradle plugin)LICENSEfile with no extension. The license file has to contain the text of one of the supported DFSG, FSF, GNU, and OSI licenses. Apache 2.0, GPL-3 are among acceptable. Find a ready license file or copy paste the text of the selected license from https://spdx.org/licenses/
Make sure no binaries, build cache etc. are present in the appsource repository.
2.2. Make sure your app builds
Make sure the app is buildable from its source code. This step would have been easy if Ubuntu hadn’t provided a very old incompatible Gradle software.
Since BatteryVoltageDisplay app uses Gradle for building, an APK should be generated when calling ./gradlew assembleRelease from the folder where gradlew file islocated. For BatteryVoltageDisplay its ~/bateryvoltagedisplay/timenotification folder,
The APK for the app has been built successfully. You will find it in the app’s folder. For BatteryVoltageDisplay that is /home/user/bateryvoltagedisplay/timenotification/app/build/outputs/apk/release/app-release-unsigned.apk
Optionally, do the same build using F-Droid Server in Part 5.
2.3. Add a release tag
F-droid builds your app using the code version contained within the tag. The tag should be pushed to your app’s repo.
To add a tag execute in the app source folder on your local disk:
git add ~/bateryvoltagedisplay/
git commit
git tag -a v1.0
git push tag v1.0
Important: Tag name (v1.0) should exactly match with the tag name you provide in YML file.
PART 3. Fork F-Droid
F-Droid uses GitLab, and you need to have an account on this platform. Be ready to verify your account with a phone number or credit card in order for the app checking piplenes on F-Droid.
GitLab blocks pipeline run if your account is not verified, F-Droid recommends you to ask its maintainers to run the pipeline for you, but that is not a quick process.
3.1. Create fork
To fork F-Droid repository on GitLab, open your browser, log in to yout Gitlab account, go to: https://gitlab.com/fdroid/fdroiddata and click Fork in the top-right.
This creates your copy of the F-Droid repo accessible via URL that looks as https://gitlab.com/your-gitlab-username/fdroiddata.
3.2. Clone your fork to disk
Replace yourusername with your GitLab username and in the Home folder launch terminal to execute commands:
git clone https://gitlab.com/yourusername/fdroiddata.git
cd fdroiddata
3.3 Add upstream remote
Add upstream remote to simplify sync with the main repo later.
git remote add upstream https://gitlab.com/fdroid/fdroiddata.git
PART 4. Create YML metadata file for app
Now, it is time to create the file you will submit to F-Droid. This is the only file that will actually be submitted.
4.1 Create new Git branch for metadata file
F-Droid expects from you a merge request, therefore you have to create a new branch that will be merged.
git checkout -b name-of-your-branch
All changes to the metadata file you want to be submitted to F-Droid shoul be executed in this branch.
4.2 Create YML metadata file
In F-Droid, the metadata file is the YAML description file that tells the F-Droid build server how to fetch, build, and publish an app.
It lives inside the fdroiddata/metadata/ folder and is named after the app’s package ID of your app. For example, BatteryVoltageDisplay has package ID com.example.timenotification
Here is a minimal template of an F-Droid metadata YAML file https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/com.example.timenotification.yml
Categories:
- System
License: GPL-3.0-only
AuthorName: Eugen Barilyuk EB43
AuthorWebSite: https://eb43.github.io
SourceCode: https://github.com/Eb43/bateryvoltagedisplay
IssueTracker: https://github.com/Eb43/bateryvoltagedisplay/issues
AutoName: BatteryVoltageDisplay
RepoType: git
Repo: https://github.com/Eb43/bateryvoltagedisplay.git
Builds:
- versionName: '1.0'
versionCode: 1
commit: 632abdfb0cbfea863453a77447c8e09c7dd980bf
subdir: timenotification/app
gradle:
- yes
- versionName: '1.1'
versionCode: 2
commit: ca2d6ad2b5633a2bdc7f6e41fc0ec9e151a1d50e
subdir: timenotification/app
gradle:
- yes
AutoUpdateMode: Version
UpdateCheckMode: Tags
CurrentVersion: '1.1'
CurrentVersionCode: 2
Be careful with YML file formatting. One additional or missing space character will result in error.
PART 5. Build app APK with F-DROID SERVER
The Part 5 is optional if you have verified your app builds in Part 2.
5.1. Install Python
F-Droid utilizes a set of Python tools named fdroidserver required to build APKs reproducibly for distribution, submiting metadata to the official F-Droid repository and multitude of other tasks.
Without fdroidserver, you can’t prepare metadata, build pipelines, or publish apps into the F-Droid ecosystem. The F-Droid team also uses fdroidserver in GitLab CI to build and check your app after you submit merge requests.
Install Python
sudo apt install python3-pip
5.2. Install F-Droid Server
Install the fdroidserver package
pip3 install fdroidserver
There is a high chance you will get an error externally-managed-environment
We’ve run into Python’s mechanism (PEP 668) — externally-managed-environment. It forbids pip install --user in the system environment of distributions (Ubuntu, Debian, etc.) to prevent breaking packages installed via apt.
There are several options:
- Install via pipx (isolated).
pipxallows installing Python programs in separate environments:
sudo apt install pipx
pipx ensurepath
pipx install fdroidserver
- Virtual environment
python3 -m venv ~/fdroidenv
source ~/fdroidenv/bin/activate
pip install fdroidserver
And run it with:
~/fdroidenv/bin/fdroid
- instalation using apt
sudo apt install fdroidserver
But all these methods have their drawbacks and may not lead to successful work. For example, installing via apt produces old version. Virtual environment installation breaks access to other required components.
The best method is:
- force installation ignoring the restriction
pip install --user --break-system-packages fdroidserver
Export the path or write it in bashrc file
export PATH=$HOME/.local/bin:$PATH
Check installation worked:
fdroid --version
Build app APK with F-Droid Server
fdroid build -v -l YMLfilename
For example, fdroid build -v -l com.example.timenotification
PART 6: Push the YML file to F-Droid
Now, you have verified your app builds from the source repo tag, has other necessary information. Push your app’s YML file to F-Droid where your app will be processed in similar manner.
Using Git CLI push YML file to F-Droid:
git add metadata/com.example.timenotification.yml
git commit -m "Update metadata for com.example.timenotification"
Now, in browser open your fork on GitLab: https://gitlab.com/yourusername/fdroiddata
It should prompt you to create a Merge Request.
In the MR:
- Set title
- Leave a short note like:
“Simple app. Source: GitHub.”
Submit the MR.
6.1. Set the Merge request template
Choose a template for your app: app inclusion.
Mark all checkboxes that apply to your app.
Set the Reproducible build checkbox only if you have a digital signature for your apps. Otherwise your build will fail. If you have a digital signature, likely, this tutorial is not for you as you are a professional software developer and already know this.
6.2. Verify your app passes all F-Droid pipelines
F-droid lauches some checks automatically, and it may seem that your app has passed. If you see this output:
It means your app is only half way to finish. You need to manually trigger the issue bot. Wait for 30-60 minutes for issue bot to generate its output.
If you see this result, your app builds, and it can be accepted to F-Droid.
6.3. Wait for merge
Your merge request will me monitored by F-Droid’s maintainer. Wait for a day or two for merge request to be merged.
6.4. Wait for app to be published
It may take up to a week for the app to appear onF-Droid after app’s YML was merged.
Navigate to https://monitor.f-droid.org/builds/running page to monitor when your app goes into build pipeline. After that it takes a day or two for the app page to be populated with the data in fastlane folder you provided.
Every time you release a new version, just xreate a new GitHub tag in app’s repo.