# 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. ```bash 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: ```bash # on your server: install act_runner (Gitea) or forgejo-runner (Forgejo), then: ./act_runner register --instance https://git.mowden.top --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.top` is **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) ```bash # 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: 1. CI (or a hook) copies the APK to a web dir, e.g. `/var/www/bbp/BigBrainParking-.apk`. 2. nginx with autoindex on that dir: ```nginx location /bbp/ { root /var/www; autoindex on; } ``` 3. In Obtainium, add an **HTML** app pointing at `https:///bbp/` with an APK link filter like `BigBrainParking-.*\.apk` and 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 `fdroidserver` on 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 `versionCode` from `app.json`. Bump `expo.version` (and optionally set `expo.android.versionCode`) each release so Obtainium sees an increase.