4.2 KiB
Distribution: self-hosted CI → Obtainium
Goal: push a git tag, have your server build a signed APK, publish it as a release
on git.mowden.top, and have Obtainium on your GrapheneOS phone auto-offer updates.
Repo: ssh://git@git.mowden.top:222/hank/BigBrainParking.git
(web: https://git.mowden.top/hank/BigBrainParking)
1. One-time: create the signing key (do this locally)
The signer is permanent — Obtainium (and F-Droid) pin it, so if you ever rebuild with a different key, users must uninstall + reinstall. Keep this keystore backed up and secret.
keytool -genkeypair -v -keystore bigbrainparking.keystore \
-alias bigbrainparking -keyalg RSA -keysize 2048 -validity 10000
base64 -w0 bigbrainparking.keystore # copy this string for the CI secret
2. One-time: add CI secrets
On git.mowden.top → the repo → Settings → Actions → Secrets, add:
| Secret | Value |
|---|---|
ANDROID_KEYSTORE_B64 |
the base64 string from step 1 |
ANDROID_KEYSTORE_PASSWORD |
keystore password |
ANDROID_KEY_ALIAS |
bigbrainparking |
ANDROID_KEY_PASSWORD |
key password |
3. One-time: an Actions runner that can build Android
You need a Gitea/Forgejo Actions runner registered to this repo/instance. The provided
workflow (.gitea/workflows/build-apk.yml) runs inside a container image that already has
the Android SDK + Node, so the host runner just needs Docker:
# on your server: install act_runner (Gitea) or forgejo-runner (Forgejo), then:
./act_runner register --instance https://git.mowden.top --token <RUNNER_TOKEN>
./act_runner daemon # (or a systemd unit)
Make sure the runner labels include ubuntu-latest (or edit runs-on: in the workflow).
If
git.mowden.topis Forgejo, move the workflow to.forgejo/workflows/build-apk.yml(Forgejo also reads.gitea/workflows, so it usually works as-is).
4. Release flow (every update)
# bump version in app/app.json ("version") first, then:
git tag v0.1.0
git push origin v0.1.0
CI builds app/android/app/build/outputs/apk/release/*.apk, signs it, and attaches it to a
new release v0.1.0. Done.
5. Add the app in Obtainium (on the phone)
Obtainium reads straight from the repo site via its native Gitea/Forgejo Releases source — no separate web server needed. Add app → paste:
https://git.mowden.top/hank/BigBrainParking
Pick the Gitea (or Forgejo) source type if prompted, and Obtainium tracks releases and offers each new signed APK. The repo being public means Obtainium needs no token. Install ntfy + set it as your UnifiedPush distributor for push later.
Releases vs. Packages
Use Releases, not the Packages tab. Gitea/Forgejo Packages is a general artifact registry (npm, maven, container, generic) — Obtainium has no package-registry source, so it won't see APKs there. (You can upload an APK to the generic registry and point Obtainium at a "Direct APK link," but then Obtainium can't detect new versions automatically. Releases — where CI attaches the versioned APK — is the right mechanism.)
Fallback if your Obtainium build lacks Gitea support
Serve the APK statically and use Obtainium's "HTML" source:
- CI (or a hook) copies the APK to a web dir, e.g.
/var/www/bbp/BigBrainParking-<version>.apk. - nginx with autoindex on that dir:
location /bbp/ { root /var/www; autoindex on; } - In Obtainium, add an HTML app pointing at
https://<yourserver>/bbp/with an APK link filter likeBigBrainParking-.*\.apkand version extraction from the filename.
This path skips Gitea releases entirely — it's just a directory of signed APKs — but you lose changelogs and per-release metadata.
Notes
- Reproducibility / F-Droid later: if you ever want a real F-Droid repo (signed index,
usable by the F-Droid client too), run
fdroidserveron the server pointed at the same APK output dir. Obtainium consumes F-Droid repos as well. Overkill for one app, but an option. - Version code: Expo derives Android
versionCodefromapp.json. Bumpexpo.version(and optionally setexpo.android.versionCode) each release so Obtainium sees an increase.