electric-horses-infra/docs/runbooks/forgejo-admin-recovery.md
Benjamin Weinlich 09925f7eda docs(adr): add ADR-0007 on OIDC avatar data-URL gotcha
When a new user logs in via Authentik OIDC for the first time,
Forgejo tries to fetch the 'picture' claim as an avatar — but
Authentik delivers a 'data:image/svg+xml;base64,...' URL that
Forgejo can't store. Result: DB has an avatar hash but no file,
so /avatars/<hash> returns 404, the <img> is in broken state,
and the activity page's canvas renderer crashes with
'drawImage on broken state'.

Fix (per user, after first login):
  UPDATE "user" SET avatar = '', use_custom_avatar = false
  WHERE lower_name = '<name>';

Triggers Forgejo's default identicon generation, which works.

This commit:
- Adds ADR-0007 with full root cause + three rejected alternatives
- Updates docs/adr/README.md index
- Extends stacks/forgejo/Agent.md 'Known Gotchas' with the fix
- Appends the fix to docs/runbooks/forgejo-admin-recovery.md

Applied for user 'bw' already on 2026-04-12.

Refs OP#1119
2026-04-12 04:47:25 +02:00

4.9 KiB

Runbook — Admin-Recovery wenn Authentik down ist

Kontext: Forgejo nutzt Authentik OIDC als Primär-Auth. Wenn Authentik ausfällt, kommt niemand mehr per Login rein. Für diesen Fall gibt es einen lokalen Fallback-User admin-local.

Wann dieses Runbook anwenden

  • welcome.sdda.eu gibt 500er / nicht erreichbar
  • OIDC-Callback zu Forgejo bricht ab
  • Authentik-Docker-Container crasht
  • authentik-sso VM ist down

Voraussetzung

  • SSH-Zugang zu ai-apps (ssh ai-apps)
  • admin-local Passwort aus Password-Manager / Vault

Recovery-Schritte

1. PROHIBIT_LOGIN lösen

Normalerweise ist admin-local.prohibit_login = true gesetzt, damit niemand das Passwort bruteforcen kann. Wir müssen es temporär deaktivieren.

ssh ai-apps
docker exec forgejo-db psql -U forgejo -d forgejo \
  -c "UPDATE \"user\" SET prohibit_login = false WHERE lower_name = 'admin-local';"

Output:

UPDATE 1

2. Einloggen

Im Browser: https://code.sdda.eu/user/login

  • Username: admin-local
  • Passwort: aus Password-Manager

Du siehst jetzt das Forgejo Dashboard mit Admin-Rechten.

3. Was du während des Authentik-Ausfalls machen kannst

  • Repos anlegen / ändern
  • User manuell anlegen (fallback wenn jemand dringend Zugang braucht)
  • System-Settings anpassen
  • Backups prüfen

Achtung: Andere normale User können sich auch nicht einloggen während Authentik down ist. Das ist bewusst so. Wenn ein User dringend arbeiten muss, können sie:

  • Von dir ein Personal Access Token bekommen (Settings → Applications)
  • git clone via HTTPS mit diesem Token

4. Authentik wieder hochbringen

ssh authentik-sso
cd /opt/authentik
docker compose ps                   # Was läuft?
docker compose logs --tail 50      # Warum down?
docker compose restart              # Versuch 1
# Wenn restart nicht hilft: docker compose up -d --force-recreate

Bei Datenbank-Problemen:

docker compose logs authentik-db    # DB ok?
# Im Worst Case: Restore aus Authentik-Backup

5. Nach der Wiederherstellung: PROHIBIT_LOGIN zurücksetzen

WICHTIG: Sobald Authentik wieder läuft, sofort den Notfall-Fallback wieder sperren:

ssh ai-apps
docker exec forgejo-db psql -U forgejo -d forgejo \
  -c "UPDATE \"user\" SET prohibit_login = true WHERE lower_name = 'admin-local';"

Aus dem Forgejo Admin-UI deine bw-Session ausloggen, dann via Authentik neu einloggen — sicherstellen dass OIDC wieder funktioniert.

Warum dieses Pattern?

  • admin-local hat keinen Zugang über Authentik (nicht in Gruppe forgejo-users, und nicht mal ein OIDC-linked User).
  • admin-local ist per default gesperrt (prohibit_login=true).
  • Zum Aktivieren braucht man DB-Zugang → bedeutet SSH-Zugang zu ai-apps → bedeutet physischen Zugang zu deinem Rechner / SSH-Key.
  • Nach Recovery sofort zurück in den gesperrten Zustand — kein dauerhaftes Bypass.

Was du NIE machen solltest

  • admin-local Passwort aus dem Password-Manager entfernen. Das ist deine einzige Notfall-Tür.
  • admin-local Passwort in Klartext irgendwo committen. Das ist wie GH-Secret-in-Public-Repo, nur schlimmer.
  • PROHIBIT_LOGIN dauerhaft auf false lassen nach Recovery. Das bricht das Sicherheitsprinzip.

Alternative für sehr lange Authentik-Ausfälle

Wenn Authentik auf Dauer nicht mehr funktioniert (z.B. Lizenz-Issue, Migration nötig):

  1. admin-local temporär entsperren
  2. OIDC-Auth-Source in Forgejo deaktivieren: docker exec -u git forgejo sh -c 'cd / && forgejo admin auth update-oauth --id 1 --not-enabled'
  3. Lokale User bestehen bleibt (bw kann admin-local-Passwort bekommen oder eigenes lokales Passwort setzen)
  4. Neuer Auth-Provider später einrichten
  5. Doku in neue ADR schreiben

Zusatz: Neue OIDC-User Avatar-Fix

Wann anwenden: Direkt nachdem ein neuer User zum ersten Mal via Authentik eingeloggt hat (Leonard, Martin, etc.).

Grund: Forgejo speichert beim OIDC-First-Login einen Avatar-Hash in der DB, aber die eigentliche Bilddatei ist leer (weil Authentik ein data:-URL statt einer echten HTTP-URL im picture-Claim liefert). Resultat: /avatars/<hash> gibt 404, und die Activity-Seite crasht mit einem drawImage on broken state Fehler. Siehe ADR-0007.

Fix:

ssh ai-apps
docker exec forgejo-db psql -U forgejo -d forgejo -c \
  "UPDATE \"user\" SET avatar = '', use_custom_avatar = false WHERE lower_name = '<new-username>';"

Danach generiert Forgejo ein Default-Identicon on-the-fly, die Activity-Seite funktioniert wieder. Der User kann später im Web-UI ein eigenes Avatar hochladen (Einstellungen → Konto → Profilbild).