From 56ef4610a6e99b7765f15e47e4c558f2be817027 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 13 Jul 2026 23:42:18 +0200 Subject: [PATCH] Add F-Droid publishing guide and self-hosted repo helper script docs/FDROID.md covers both a self-hosted F-Droid repo and the official f-droid.org route (incl. the prebuilt-OpenCV caveat). scripts/update-fdroid-repo.sh pulls the release APKs from Gitea and rebuilds the signed index. Co-Authored-By: Claude Opus 4.8 --- docs/FDROID.md | 106 ++++++++++++++++++++++++++++++++++ scripts/update-fdroid-repo.sh | 45 +++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 docs/FDROID.md create mode 100755 scripts/update-fdroid-repo.sh diff --git a/docs/FDROID.md b/docs/FDROID.md new file mode 100644 index 0000000..dee489d --- /dev/null +++ b/docs/FDROID.md @@ -0,0 +1,106 @@ +# Publishing PaperScan on F-Droid + +Two routes, from easiest to most reach: + +1. **Your own F-Droid repository** — you host your signed APKs; users add your repo URL. +2. **The official f-droid.org repository** — huge reach, but they build from source and vet + dependencies. + +Both use the store metadata in [`fastlane/metadata/android/`](../fastlane/metadata/android). + +--- + +## 1. Your own F-Droid repository (recommended first) + +You serve a small static site containing your signed APKs plus a signed index. Users add the +URL once in the F-Droid app and then get updates automatically. No review, no rebuild, and the +prebuilt OpenCV libraries are a non-issue because *you* provide the APK. + +### One-time setup + +Install `fdroidserver` (needs a JDK + the Android SDK build-tools on `PATH`): + +```bash +pipx install fdroidserver # or: sudo apt install fdroidserver +``` + +Create the repo workspace and its **repo signing key** (separate from the app signing key — +it signs the index, not the app): + +```bash +export FDROID_HOME="$HOME/paperscan-fdroid" +mkdir -p "$FDROID_HOME" && cd "$FDROID_HOME" +fdroid init # generates config.yml + keystore.p12 +``` + +Edit `config.yml`: + +```yaml +repo_url: "https://fdroid.geyskens.eu/repo" # where you'll host it +repo_name: "PaperScan" +repo_description: "Self-hosted F-Droid repository for PaperScan." +archive_older: 3 # keep last 3 versions in the main repo +``` + +⚠️ Back up `keystore.p12` and its passwords (in `config.yml` / `~/.config/fdroidserver`). +Lose it and you must publish a **new** repo URL — clients can't verify updates otherwise. + +Let F-Droid pick up the localized store text: point it at this repo's fastlane metadata: + +```bash +mkdir -p "$FDROID_HOME/metadata" +ln -s /path/to/paperscan/fastlane/metadata/android "$FDROID_HOME/metadata/eu.geyskens.pdfscan" +``` + +### Publishing a version + +Use the helper script (pulls every release APK from Gitea and rebuilds the index): + +```bash +FDROID_HOME="$HOME/paperscan-fdroid" /path/to/paperscan/scripts/update-fdroid-repo.sh +``` + +Then publish the generated `repo/` directory to your web host, e.g.: + +```bash +rsync -a --delete "$FDROID_HOME/repo/" web:/var/www/fdroid/repo/ +``` + +Serve it as plain static files (any web server). Users then: +**F-Droid app → Settings → Repositories → + → `https://fdroid.geyskens.eu/repo`**, and enable it. +Tip: `https://fdroid.geyskens.eu/repo?fingerprint=` (from `fdroid update` output) +lets them add it with the fingerprint pre-filled. + +### Automating it in CI (optional) + +The existing Gitea Actions build already produces a signed APK per tag. To also refresh the +F-Droid repo, add a job that: installs `fdroidserver`, restores the **repo** keystore from a +secret, runs `scripts/update-fdroid-repo.sh`, and `rsync`es `repo/` to the web host (host key + +key as secrets). Keep the repo keystore in a secret just like the app signing key. + +--- + +## 2. The official f-droid.org repository + +Bigger audience (it's in the default F-Droid app), but stricter: + +- **License** — must be a recognized free license. PaperScan is GPL-3.0 ✔ (`LICENSE`). +- **Build from source** — F-Droid builds the APK on their servers; no prebuilt binaries in the + APK's own code. ⚠️ Our `org.opencv:opencv` Maven dependency ships **prebuilt native `.so` + libraries**. F-Droid flags prebuilt binaries; you may need to build OpenCV from source or get + the artifact allow-listed. This is the main hurdle — resolve it before submitting. +- **Reproducible-ish, no trackers** — PaperScan already has no analytics/trackers and only the + Camera + Internet permissions, which helps. + +Process: + +1. Open a **Request For Packaging (RFP)** issue at + `https://gitlab.com/fdroid/rfp` (or go straight to a merge request). +2. Add a build recipe `metadata/eu.geyskens.pdfscan.yml` to the `fdroiddata` repo describing the + source (`git.geyskens.eu`), the tag, and the Gradle build. The fastlane metadata is picked up + automatically for the listing. +3. Iterate with the F-Droid maintainers (mostly around the OpenCV native libs). + +Because F-Droid builds from source, they also **re-sign** the APK with F-Droid's key — so an app +installed from f-droid.org can't be updated from your own repo and vice-versa (different +signatures). That's expected; pick one channel per user. diff --git a/scripts/update-fdroid-repo.sh b/scripts/update-fdroid-repo.sh new file mode 100755 index 0000000..12800f7 --- /dev/null +++ b/scripts/update-fdroid-repo.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# +# Rebuilds a self-hosted F-Droid repo for PaperScan: downloads every release APK +# from the Gitea repository and regenerates the (signed) index. +# +# Prerequisites: +# * fdroidserver installed (`pipx install fdroidserver`) +# * `fdroid init` run once in $FDROID_HOME (creates config.yml + keystore) +# * JDK + Android SDK build-tools on PATH +# +# Usage: +# FDROID_HOME=~/paperscan-fdroid ./scripts/update-fdroid-repo.sh +# +set -euo pipefail + +FDROID_HOME="${FDROID_HOME:-$HOME/paperscan-fdroid}" +GITEA_API="${GITEA_API:-https://git.geyskens.eu/api/v1/repos/sam/paperscan}" + +if [ ! -f "$FDROID_HOME/config.yml" ]; then + echo "No F-Droid repo at $FDROID_HOME. Run 'fdroid init' there first (see docs/FDROID.md)." >&2 + exit 1 +fi + +mkdir -p "$FDROID_HOME/repo" +cd "$FDROID_HOME" + +echo "Fetching release APK list from Gitea…" +curl -fsSL "$GITEA_API/releases?limit=50" \ + | python3 -c "import sys,json;[print(a['browser_download_url']) for r in json.load(sys.stdin) for a in r.get('assets',[]) if a['name'].endswith('.apk')]" \ + | while read -r url; do + dest="repo/$(basename "$url")" + if [ -f "$dest" ]; then + echo " have $(basename "$url")" + else + echo " get $(basename "$url")" + curl -fsSL "$url" -o "$dest" + fi + done + +echo "Rebuilding index…" +fdroid update --create-metadata --pretty + +echo +echo "Done. Publish the repo, e.g.:" +echo " rsync -a --delete \"$FDROID_HOME/repo/\" web:/var/www/fdroid/repo/"