[Infra] F-Droid-Repo-Server aufbauen + automatisches APK-Deployment #133

Open
opened 2026-04-27 12:07:04 +02:00 by admin-mrrm · 1 comment
Owner

Ziel

Die Mobile-App soll über einen eigenen F-Droid-kompatiblen Repository-Server verteilt werden. Nightly Cron prüft, ob seit dem letzten erfolgreichen Deploy neue Commits auf main liegen — falls ja: signiertes APK bauen + im F-Droid-Repo veröffentlichen.

Trigger-Strategie

  • Schedule: Nightly Cron (z.B. 03:00 Europe/Berlin)
  • Diff-Check: aktuelles HEAD mit letztem deployten SHA vergleichen (Tag fdroid-last-deploy im Repo oder Datei im fdroid-Server)
  • Skip-Logik: kein neuer Commit → Pipeline beendet ohne Build (kein leerer Index-Push)
  • Warum nicht pro-Merge: spart Build-Minuten, reduziert F-Droid-Index-Churn, vorhersagbares Release-Fenster für User

Komponenten

1. APK-Build in Woodpecker CI

  • Voraussetzung: admin-mrrm/server-stack#17 (Migration Drone → Woodpecker)
  • Neue Pipeline-Datei .woodpecker/fdroid-nightly.yml
  • Expo/React Native: eas build (Cloud) oder lokaler Build via @expo/eas-build-job in einem Android-Docker-Image
  • Zu klären: EAS Cloud (kostenpflichtig ab bestimmtem Volumen) vs. selbst-gehosteter Build (komplexer, braucht JDK + Android SDK im CI-Image)
  • Empfehlung: zunächst EAS Build (Free Tier: 30 Builds/Monat), dann bei Bedarf auf Self-Hosted umstellen

2. APK-Signierung

  • Android Keystore als Woodpecker-Secret hinterlegen
  • Keystore bei EAS: in eas.json konfigurieren oder als EXPO_PUBLIC_*-Secret
  • Alternativ: Post-Build-Signing mit apksigner im CI

3. fdroidserver einrichten

  • fdroidserver als Docker-Container auf dem Server (/opt/server-stack/fdroid/)
  • Verzeichnisstruktur:
    /opt/server-stack/fdroid/
      repo/          ← APKs + Metadaten (öffentlich)
      metadata/      ← App-Beschreibungen (YAML)
      config.yml     ← fdroid-Konfiguration
      keystore.p12   ← Repo-Signing-Key
    
  • fdroid update generiert index-v2.json + index.jar aus den APKs im repo/-Ordner

4. Repo-Hosting

  • Statischer Webserver (nginx) serviert /opt/server-stack/fdroid/repo/ unter z.B. https://fdroid.mrrm.de/repo
  • Nutzer fügen in F-Droid hinzu: https://fdroid.mrrm.de/repo

5. Woodpecker-Pipeline (nightly)

# .woodpecker/fdroid-nightly.yml
when:
  - event: cron
    cron: fdroid-nightly

steps:
  diff-check:
    image: alpine/git
    commands:
      - LAST=$(git tag -l 'fdroid-last-deploy' | head -1 && git rev-list -n 1 fdroid-last-deploy)
      - HEAD=$(git rev-parse HEAD)
      - test "$LAST" != "$HEAD" || (echo 'no new commits — skip'; exit 78)

  build-apk:
    depends_on: [diff-check]
    # eas build oder lokaler Android-Build

  publish-fdroid:
    depends_on: [build-apk]
    # SCP: APK auf Server kopieren
    # SSH: fdroid update && fdroid deploy
    # fdroid-last-deploy Tag auf HEAD setzen + pushen

Offene Entscheidungen

  • EAS Cloud Build vs. Self-Hosted Android Build-Image?
  • APK oder AAB? (F-Droid benötigt APK)
  • Subdomain: fdroid.mrrm.de?
  • Repo-Signing-Key separat vom APK-Signing-Key?
  • State-Tracking für letzten Deploy: Git-Tag im Repo vs. Datei im fdroid-Server?

Abgrenzung

  • Kein Upload in den öffentlichen F-Droid-Hauptkatalog (eigenes Repo reicht)
  • Kein OTA-Update-Mechanismus über Expo (nur nativer APK-Update-Fluss via F-Droid)
  • Kein per-Merge-Build — bewusste Entscheidung für nightly + Diff (siehe Trigger-Strategie)
## Ziel Die Mobile-App soll über einen eigenen F-Droid-kompatiblen Repository-Server verteilt werden. **Nightly Cron** prüft, ob seit dem letzten erfolgreichen Deploy neue Commits auf `main` liegen — falls ja: signiertes APK bauen + im F-Droid-Repo veröffentlichen. ## Trigger-Strategie - **Schedule:** Nightly Cron (z.B. 03:00 Europe/Berlin) - **Diff-Check:** aktuelles `HEAD` mit letztem deployten SHA vergleichen (Tag `fdroid-last-deploy` im Repo oder Datei im fdroid-Server) - **Skip-Logik:** kein neuer Commit → Pipeline beendet ohne Build (kein leerer Index-Push) - **Warum nicht pro-Merge:** spart Build-Minuten, reduziert F-Droid-Index-Churn, vorhersagbares Release-Fenster für User ## Komponenten ### 1. APK-Build in Woodpecker CI - **Voraussetzung:** `admin-mrrm/server-stack#17` (Migration Drone → Woodpecker) - Neue Pipeline-Datei `.woodpecker/fdroid-nightly.yml` - Expo/React Native: `eas build` (Cloud) **oder** lokaler Build via `@expo/eas-build-job` in einem Android-Docker-Image - Zu klären: EAS Cloud (kostenpflichtig ab bestimmtem Volumen) vs. selbst-gehosteter Build (komplexer, braucht JDK + Android SDK im CI-Image) - Empfehlung: zunächst **EAS Build** (Free Tier: 30 Builds/Monat), dann bei Bedarf auf Self-Hosted umstellen ### 2. APK-Signierung - Android Keystore als Woodpecker-Secret hinterlegen - Keystore bei EAS: in `eas.json` konfigurieren oder als `EXPO_PUBLIC_*`-Secret - Alternativ: Post-Build-Signing mit `apksigner` im CI ### 3. fdroidserver einrichten - `fdroidserver` als Docker-Container auf dem Server (`/opt/server-stack/fdroid/`) - Verzeichnisstruktur: ``` /opt/server-stack/fdroid/ repo/ ← APKs + Metadaten (öffentlich) metadata/ ← App-Beschreibungen (YAML) config.yml ← fdroid-Konfiguration keystore.p12 ← Repo-Signing-Key ``` - `fdroid update` generiert `index-v2.json` + `index.jar` aus den APKs im `repo/`-Ordner ### 4. Repo-Hosting - Statischer Webserver (nginx) serviert `/opt/server-stack/fdroid/repo/` unter z.B. `https://fdroid.mrrm.de/repo` - Nutzer fügen in F-Droid hinzu: `https://fdroid.mrrm.de/repo` ### 5. Woodpecker-Pipeline (nightly) ```yaml # .woodpecker/fdroid-nightly.yml when: - event: cron cron: fdroid-nightly steps: diff-check: image: alpine/git commands: - LAST=$(git tag -l 'fdroid-last-deploy' | head -1 && git rev-list -n 1 fdroid-last-deploy) - HEAD=$(git rev-parse HEAD) - test "$LAST" != "$HEAD" || (echo 'no new commits — skip'; exit 78) build-apk: depends_on: [diff-check] # eas build oder lokaler Android-Build publish-fdroid: depends_on: [build-apk] # SCP: APK auf Server kopieren # SSH: fdroid update && fdroid deploy # fdroid-last-deploy Tag auf HEAD setzen + pushen ``` ## Offene Entscheidungen - [ ] EAS Cloud Build vs. Self-Hosted Android Build-Image? - [ ] APK oder AAB? (F-Droid benötigt APK) - [ ] Subdomain: `fdroid.mrrm.de`? - [ ] Repo-Signing-Key separat vom APK-Signing-Key? - [ ] State-Tracking für letzten Deploy: Git-Tag im Repo vs. Datei im fdroid-Server? ## Abgrenzung - Kein Upload in den öffentlichen F-Droid-Hauptkatalog (eigenes Repo reicht) - Kein OTA-Update-Mechanismus über Expo (nur nativer APK-Update-Fluss via F-Droid) - Kein per-Merge-Build — bewusste Entscheidung für nightly + Diff (siehe Trigger-Strategie)
Author
Owner

Strategie-Update (2026-05-19):

  • Trigger geändert: pro-Merge → nightly Cron mit Diff-Check (HEAD vs. letzter Deploy-SHA). Spart Build-Minuten, vermeidet leere F-Droid-Index-Pushes, vorhersagbares Release-Fenster.
  • CI-Tool: Drone → Woodpecker, abhängig von admin-mrrm/server-stack#17.

Body entsprechend aktualisiert.

**Strategie-Update (2026-05-19):** - **Trigger geändert:** pro-Merge → **nightly Cron mit Diff-Check** (HEAD vs. letzter Deploy-SHA). Spart Build-Minuten, vermeidet leere F-Droid-Index-Pushes, vorhersagbares Release-Fenster. - **CI-Tool:** Drone → **Woodpecker**, abhängig von `admin-mrrm/server-stack#17`. Body entsprechend aktualisiert.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
admin-mrrm/mrrmlabapp#133
No description provided.