Introduction
Jarvis, create a README.md file for this repository that manipulates people into contributing to the project.
Building an App
Building an app is as easy as:
nix build .#app-name
Analyzing an APK File
First build the app
nix build .#mihon
Then use apktool to decode the APK file
nix run nixpkgs#apktool -- d result
Adding a New App
Updating an App
-
Bump
version, the sourcetag/rev, and the fetchhashin the app’spackage.nix(get the new hash withnix flake prefetch github:<owner>/<repo>/<tag>). -
Update
meta.androidif upstream changed minSdk/targetSdk/versionCode — the values live in the app’sgradle.properties,gradle/libs.versions.toml, orapp/build.gradle.kts. -
Regenerate the app’s verification metadata (see Adding a New App) and merge it into the central lockfile:
python3 lib/tools/merge-verification-metadata.py <app>/gradle/verification-metadata.xml -
nix build .#<app>.tests.meta— builds the apk and verifies its manifest againstmeta.android.
After nix flake update
Rebuild every app before committing a lock bump
(nix build .#<app>.tests.meta). Per-app verification-metadata.xml files
record the artifacts of the Gradle version they were generated with —
including Gradle’s embedded Kotlin. When nixpkgs bumps gradle_9
(e.g. 9.5 → 9.7) the build asks for artifacts that are not in the metadata
(Could not resolve org.jetbrains.kotlin:kotlin-stdlib:<new version>).
The fix is to regenerate the metadata in the matching devshell; the diff is
usually a handful of lines.
Hash conflicts in the lockfile
The merge tool refuses to change a hash that is already locked:
HASH CONFLICT com.github.tibbi:reprint (reprint-2cb206415d.jar)
locked: 0c6de154...
new: 201f65fa...
A published Maven artifact must never change bytes. A conflict means the
upstream repository rebuilt or replaced the artifact — JitPack does this
routinely, Maven Central and Google should never. Inspect before accepting
(--force keeps the new hash). Treat a conflict on a Central/Google
artifact as a potential supply-chain incident, not an inconvenience.
Derivation Metadata
A derivation’s metadata gives information regarding the application and its target android environment.
An example of a proper metadata field for an android application is as follows:
meta = {
description = "An open source flashcard app for spaced repetition learning";
homepage = "https://mihon.app";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [ osbm ]; # from nixpkgs maintainers list
android = {
minSdk = 26;
targetSdk = 36;
applicationId = "app.mihon";
abis = [
"armeabi-v7a"
"arm64-v8a"
"x86"
"x86_64"
];
};
};
Description
A short description of the application.
Homepage
The homepage URL of the application. If it does not have a homepage, you can use the repository URL.
License
The license under which the application is distributed. You can use licenses from lib.licenses in nixpkgs.
Maintainers
A list of maintainers for the derivation. You can use maintainers from lib.maintainers in nixpkgs.
TODO: what happens if the maintainer is not in the nixpkgs maintainers list?
Android
Metadata specific to the Android application, including SDK versions, application ID, and supported ABIs.
minSdk
The minimum SDK version required to run the application.
targetSdk
The target SDK version for which the application is optimized.
applicationId
The unique application ID (package name) for the Android application.
abis
A list of supported ABIs (Application Binary Interfaces) for the application. Common values include:
armeabi-v7aarm64-v8ax86x86_64
No runtime dependencies
An APK is a self-contained file: it must not reference any Nix store path.
This is not a convention but a build-time guarantee. Every package under
apks/ is given allowedReferences = [ ] (in lib/default.nix; the
gradle2nix builder sets it itself), so Nix refuses to register an output
that refers to the store:
error: output '/nix/store/…-fossify-calculator-1.4.0.apk' is not allowed to refer to the following paths:
Nothing has to be added to a package for this, and there is no separate CI
step: any nix build of an app, locally or in CI, is the check. If it ever
triggers, look for a store path leaking into the apk (a hard-coded tool path
in a generated file, a copied symlink, …). Avoid buildInputs in APK
packages — evaluation warns about them — and put tools in
nativeBuildInputs.
ROADMAP
The thing is, I am a very shitty developer. And my capabilities are extremely limited. But I am ambitious so nix is perfect for me 😭.
- Add CI that builds all apps on every commit.
- Design a proper meta field for the needs of android apps.
- description
- license
- main page
- maintainers
- minSdkVersion (explain what is this)
- targetSdkVersion (explain what is this)
- abi (list of supported abis: armeabi-v7a, arm64-v8a, x86, x86_64)
- applicationID (the unique identifier of the app, e.g. com.example.app)
- Check the meta field
- Add documentation on github pages.
- Add first flutter app.
- Add first react-native app. (bluesky)
- Add first ionic app.
- Support building apps on more platforms (currently only x86_64-linux is supported)
- After adding 10 different apps (they all must be successfully built) ask to migrate this repo to the nix-community github organization.
- Have base functional coverage See functional-coverage
- Verify built apks against their declared metadata (
tests.metarunsaapt2 dump badgingand compares withmeta.android, in CI for every app) - Design an APK signing mechanism: zipalign + apksigner wrapper with a user-supplied keystore, so outputs are actually installable. Then add
apksigner verifyto the apk verifier, and after that an emulator-basedadb installsmoke test. - Check if the apk can be installed (hopefully on multiple architectures) (blocked on signing, see above)
- Check if the output derivation has any runtime dependencies (it should not) — enforced at build time with
allowedReferences = [ ], see Derivation metadata - Check if the app got an update (maybe from fdroid or github releases) and create a PR automatically.
- Add binary cache — self-hosted attic cache
nixapks, CI pushes every build closure to it and pulls from it, reached over tailscale (see.github/workflows/build.yml) - Prepare reproducibility report
- Compile an application without using any maven repository (fetch all dependencies from their respective sources and compile them into jar files and feed the resulting jars to the apk build process) (this is probably impossible but worth a try) (in progress: see the nixjars project in
java/)
BASIC FUNCTIONAL COVERAGE
The idea is that we should be able to have all the basic functionalities of a smartphone just by using Free and Open Source Software (FOSS) applications available in this repository. 1 app per functionality is enough for now.
- Phone (dialling / contacts)
- Messaging / SMS
- Mail / email
- Browser / web access
- Calendar / scheduling
- Clock / alarms & timers
- Calculator / conversions
- Fossify-Calculator
- Settings / device control & preferences
- File manager / storage browser
- Gallery / photos & media
- Camera
- Games & entertainment
- Productivity / notes / to-do
- Fossify-Notes
- Networking / VPN
- Media player / video playback
- Music player / audio playback
- Social / communication (chat, video calls)
- Off grid communication
- Navigation / maps / GPS
- Office suite / document editing
- PDF viewer / reading
- Terminal / command line access / emulator