# Renovate Bot - Self-hosted gegen Gitea Status: **live seit 2026-05-29**; PAT, State-Verzeichnis und Cron sind auf dem Host aktiv. Audit-Bezug: `docs/AUDIT_2026-05-25.md` Finding **F-12**. ## Zweck Wir pinnen Image-Versionen und Digests konsequent (siehe `HOMELAB_ARCHITECTURE_MASTER_V2.md` Sektion 13, "Reproduzierbare Deployments"). Das macht das Setup stabil, aber jede Image-Aktualisierung musste bisher manuell laufen. Renovate uebernimmt das in Zukunft: scant das Repo periodisch, oeffnet Pull-Requests in Gitea fuer Image-/Digest-Updates, gruppiert sinnvoll, laesst Operator entscheiden. Bewusst kein Auto-Merge: jede PR braucht eine Operator-Sichtpruefung und einen Merge-Click. Komodo deployt danach automatisch ueber den Standard-Webhook-Pfad. ## Architektur - **Image:** `renovate/renovate:41` (versioniert, kein latest) - **Lauf:** ein-shot pro Cron-Tick, danach beendet sich der Container; persistente State liegt in `/mnt/user/services/renovate/state/` - **Schedule:** alle 6 Stunden per Unraid User-Script `renovate-six-hourly` (`20 */6 * * *`) - **Plattform:** Gitea via `https://git.kaleschke.info/api/v1` - **Authentifizierung:** Gitea-PAT als Host-Secret-Datei - **Konfiguration:** `renovate.json` im Repo-Root ## Operator-Setup (historisch, einmalig) ### Schritt 1 - Service-Account in Gitea 1. Als Admin in Gitea einloggen. 2. Neuen User anlegen: - Username: `renovate` - E-Mail: ein gueltiges Postfach (Renovate sendet keine Mails, aber Gitea braucht eine Adresse) - Passwort: zufaellig, in Vaultwarden speichern 3. Diesem User Schreibrechte fuer das Repo geben, das Renovate scannen soll: Repo `homelab-infra` -> Einstellungen -> Mitarbeiter -> `renovate` mit Permission `Schreibrechte` hinzufuegen. **Wichtig:** Den Collaborator immer ueber die Gitea-UI/API hinzufuegen, nicht ueber direkten SQL-Insert. Die UI/API loest einen Permissions-Cache-Refresh aus; ein DB-Insert tut das nicht und fuehrt dazu, dass Renovate spaeter "Repository does not permit pull or push" meldet, obwohl die DB den Write-Mode kennt (Befund am 2026-05-29). ### Schritt 2 - Access-Token erzeugen 1. Als `renovate`-User in Gitea einloggen. 2. Profile -> Settings -> Applications -> Generate New Token. 3. Token-Name: `renovate-bot`. 4. Scopes: - `read:user` - `write:repository` - `write:issue` (Renovate setzt Labels und kann den Dependency Dashboard erstellen) 5. Token kopieren (wird nur einmal angezeigt). ### Schritt 3 - Token als Host-Secret ablegen Am Unraid-Host: ```bash TOKEN='hier-das-token-einfuegen' echo -n "$TOKEN" > /mnt/user/appdata/secrets/renovate_token.txt chmod 600 /mnt/user/appdata/secrets/renovate_token.txt chown root:root /mnt/user/appdata/secrets/renovate_token.txt ``` Token-Wert nicht in dieses Repo, nicht in Logs, nicht in Issues. ### Schritt 4 - Erstlauf manuell ```bash bash /mnt/user/services/homelab-infra/ops/renovate/run-renovate.sh ``` Erwartete Ausgabe: Renovate verbindet sich mit Gitea, scant Repos unter `Micha/*` und entweder - erstellt Pull-Requests, falls Updates verfuegbar sind, **oder** - erstellt nur die "Renovate Dependency Dashboard"-Issue im Repo (Onboarding-PR ist via `onboarding: false` deaktiviert) Log liegt unter `/mnt/user/services/renovate/logs/renovate-.log` und symlinkt auf `latest.log`. ### Schritt 5 - User-Script aktivieren Unraid User Scripts: ``` Name: renovate-six-hourly Description: Run Renovate against Gitea every 6 hours. Schedule: 20 */6 * * * Script: bash /mnt/user/services/homelab-infra/ops/renovate/run-renovate.sh ``` 20 Minuten nach jeder vollen Stunde, damit es nicht mit `gitea-bundle-mirror-6h` (Minute 10) kollidiert. ## Was Renovate macht und was nicht | Verhalten | Renovate-Konfig | Wirkung | |---|---|---| | Major-Updates | `groupName: major-updates`, `automerge: false` | Eine gesammelte PR pro Lauf mit allen Major-Updates, manueller Merge | | Minor + Patch + Digest fuer Docker-Compose | `groupName: minor-and-patch-updates`, `automerge: false` | Eine gesammelte PR; Operator merged manuell | | Tier-1-Datenhalter (Postgres, Mongo, Redis, Immich-Postgres) | `groupName: null`, eigener Label | Einzelne PRs ohne Group, hoehere Sichtbarkeit | | Komodo-Major-Updates | `enabled: false` fuer matchPackageNames + matchUpdateTypes major | Komodo bleibt auf `:2`, wird nicht versehentlich auf `:3` migriert | | Lock-File-Maintenance | `lockFileMaintenance.enabled: false` | Renovate macht keine reinen Lock-File-Refreshs | | Schedule | `extends ["schedule:weekly"]` | Renovate-Engine prueft, aber PRs/Updates folgen Wochen-Profilen wo sinnvoll | | Dependency Dashboard | aktiv | Gitea-Issue, die alle ausstehenden Updates auflistet | | Onboarding-PR | `onboarding: false` | Keine `Configure Renovate`-Onboarding-PR; wir nutzen die Repo-`renovate.json` direkt | | Ignore-Pfade | `_archive`, `ops/grafana-influxdb`, `ops/loki` | Renovate scant alte/abgeloeste Stacks nicht | ## Aktueller Betriebsstand Erstlauf 2026-05-29 erfolgreich: Renovate erzeugte das Dependency Dashboard und die ersten fuenf PRs. Diese wurden am 2026-05-31 manuell gemerged, deployed und danach in Gitea geschlossen. Die erledigten Branches wurden anschliessend remote geloescht: - `renovate/mongo-7.0.32` - `renovate/postgres-17.9` - `renovate/minor-patch-updates` - `renovate/mongo-7.x` - `renovate/postgres-17.x` Stand nach den 2026-05-31-Migrationen: PostgreSQL 18, Redis 8 und Immich-Postgres mit VectorChord sind produktiv ausgerollt und in `renovate.json` per `allowedVersions` auf die jeweiligen Major-/Image-Schienen begrenzt. Die Renovate-PRs #9 `renovate/postgres-18.x` und #10 `renovate/redis-8.x` wurden deshalb am 2026-05-31 geschlossen statt gemerged. Offen bleibt als bewusste separate Entscheidung: - #7 `renovate/major-major-updates`: Grafana 13 Dieser Major-PR ist eine reine Entscheidungsvorlage und wird nicht automatisch gemerged. Komodo-Mongo laeuft bereits auf der erlaubten MongoDB-8.0-Schiene; ein offener Mongo-8-Renovate-PR ist aktuell nicht vorhanden. ## Erwartete erste PRs (historisch) Beim Erstlauf wird Renovate vermutlich PRs fuer einige der digest-gepinnten Images oeffnen, weil diese Digests seit Wochen nicht erneuert wurden. Reihenfolge der Sichtpruefung: 1. **Stateful Tier-1 zuerst, einzeln**: Postgres, Redis, Mongo, Immich-Postgres - jeder eigener PR, einzeln pruefen und mergen. Smoke-Test nach Merge ueber Komodo-Webhook-Deploy beobachten. 2. **Gruppe minor-and-patch-updates**: Alle anderen Docker-Compose-Images zusammen. Wenn der Diff vernuenftig aussieht, mergen. 3. **Gruppe major-updates**: Erst nach Operator-Sichtpruefung pro Image, ggf. zurueckstellen oder manuell entscheiden. ## Notfall-Stop Wenn Renovate aus irgendeinem Grund zu aggressiv wird oder ungewollte PRs oeffnet: ```bash # 1. User-Script disablen # Unraid UI: User Scripts -> renovate-six-hourly -> Schedule -> Disabled # 2. Im Worst Case: Token sofort widerrufen # Gitea -> Login als renovate -> Settings -> Applications -> Token loeschen # 3. Offene PRs schliessen ohne mergen ``` ## Was bewusst NICHT enthalten ist - **Auto-Merge**: keine PR wird ohne Operator-Click ausgerollt. Auto-Merge waere bei einem GitOps-Setup mit live-Webhooks ein zu grosses Risiko. - **Renovate-UI**: kein Mend.io-Cloud-Account, kein zusaetzlicher Service; lokal genutzte CLI im Docker-Container. - **Slack/E-Mail-Benachrichtigungen**: Renovate signalisiert ueber Gitea-PRs und das Dependency Dashboard. - **Self-hosted Renovate-Runner-Cluster**: ein einzelner User-Script-Lauf reicht fuer den Homelab-Scope. ## Verwandte Doku - `HOMELAB_ARCHITECTURE_MASTER_V2.md` Sektion 13 ("Reproduzierbare Deployments", Digest-Pinning) - `docs/WORKFLOW.md` Image-Versionierungs-Regel - `docs/SECRETS_MAP.md` (Renovate-Token wird dort nach Aktivierung ergaenzt)