electric-horses-infra/docs/runbooks/forgejo-backup-restore.md
Benjamin Weinlich 6570e81850 docs(runbooks,guides): mirror runbooks and Authentik OIDC guide
Two Forgejo runbooks plus the Authentik OAuth2 provider guide,
mirrored from the iCloud folder into the versioned repo.

Runbooks:
- forgejo-admin-recovery.md — fallback login when Authentik is down
  using the local admin-local user (prohibit_login reset via SQL).
- forgejo-backup-restore.md — backup format, restore scenarios
  (full / DB-only / single file), disaster recovery on new host.

Guides:
- authentik-oauth2-provider.md — reusable template for adding native
  OIDC integrations in Authentik. First applied for Forgejo, ready
  to reuse for OpenProject, Nextcloud, Grafana. Includes the
  important launch-URL gotcha from ADR-0006.

Each category folder has a README.md with format conventions and
an index of the current documents.

Refs OP#1118
2026-04-11 22:26:24 +02:00

4.1 KiB

Runbook — Forgejo Backup und Restore

Backup-Architektur

  • Script: /opt/ai-apps/forgejo/backup.sh
  • Cron: 0 3 * * * (täglich 03:00 UTC auf ai-apps)
  • Ziel: /opt/backups/forgejo/
  • Format:
    • forgejo-db-<YYYYMMDD-HHMMSS>.sql.gz — pg_dump der Postgres DB
    • forgejo-data-<YYYYMMDD-HHMMSS>.tar.gz — tar des Forgejo /data Volumes
  • Retention: 14 Tage (ältere Dateien werden via find -mtime +14 -delete entfernt)

Manueller Backup-Run

ssh ai-apps
bash /opt/ai-apps/forgejo/backup.sh
ls -lh /opt/backups/forgejo/

Erwartete Ausgabe:

[2026-04-11T19:39:11+00:00] backup start
  db dump: 26K
  data tar: 12K
[2026-04-11T19:39:12+00:00] backup complete

Restore-Szenarien

Szenario A: Komplett-Restore aus Backup (Disaster Recovery)

Voraussetzung: Backup-Files sind vorhanden (entweder in /opt/backups/forgejo/ oder aus Offsite-Kopie).

# 1. Stack stoppen
cd /opt/ai-apps/forgejo
docker compose down

# 2. Volumes löschen (ACHTUNG: unwiderruflich!)
docker volume rm forgejo_forgejo-data forgejo_forgejo-db-data

# 3. Stack wieder starten — leere Volumes werden neu angelegt
docker compose up -d forgejo-db

# 4. Warten bis Postgres healthy
sleep 20
docker ps --filter name=forgejo-db --format '{{.Status}}'  # Up (healthy)

# 5. DB restoren
gunzip -c /opt/backups/forgejo/forgejo-db-<TIMESTAMP>.sql.gz | \
  docker exec -i forgejo-db psql -U forgejo -d forgejo

# 6. Data volume restoren
docker run --rm \
  -v forgejo_forgejo-data:/data \
  -v /opt/backups/forgejo:/backup:ro \
  alpine \
  sh -c "cd /data && tar -xzf /backup/forgejo-data-<TIMESTAMP>.tar.gz"

# 7. Forgejo starten
docker compose up -d forgejo

# 8. Verifikation
sleep 30
curl -s https://code.sdda.eu/api/healthz
curl -s https://code.sdda.eu/api/v1/version
docker exec -u git forgejo sh -c 'cd / && forgejo admin user list'

Szenario B: Nur DB zurückspielen (z.B. nach Korruption durch Update)

cd /opt/ai-apps/forgejo
docker compose stop forgejo     # nur Forgejo, nicht DB

# DB mit -c wipen und neu importieren
docker exec forgejo-db psql -U forgejo -d postgres \
  -c "DROP DATABASE forgejo;"
docker exec forgejo-db psql -U forgejo -d postgres \
  -c "CREATE DATABASE forgejo OWNER forgejo;"

gunzip -c /opt/backups/forgejo/forgejo-db-<TIMESTAMP>.sql.gz | \
  docker exec -i forgejo-db psql -U forgejo -d forgejo

docker compose start forgejo

Szenario C: Einzelne Datei / Config aus Data-Volume wiederherstellen

# Tar-Inhalt inspizieren
tar -tzf /opt/backups/forgejo/forgejo-data-<TIMESTAMP>.tar.gz | head -30

# Einzelne Datei extrahieren
mkdir -p /tmp/forgejo-restore
tar -xzf /opt/backups/forgejo/forgejo-data-<TIMESTAMP>.tar.gz \
  -C /tmp/forgejo-restore gitea/conf/app.ini

# Ins laufende Volume kopieren
docker cp /tmp/forgejo-restore/gitea/conf/app.ini forgejo:/data/gitea/conf/app.ini
docker restart forgejo

Disaster-Recovery: Kompletter Neuaufbau auf neuem Server

  1. Neuen Host aufsetzen (Docker + Compose)
  2. /opt/ai-apps/forgejo/ Stack-Verzeichnis kopieren (inkl. .env, docker-compose.yml, backup.sh)
  3. Backup-Files aus Offsite-Quelle holen (Nextcloud / Hetzner Snapshot)
  4. Szenario A durchführen
  5. DNS ggf. auf neue IP anpassen

Verification nach Restore

# Health
curl -s https://code.sdda.eu/api/healthz

# Auth-Sources
docker exec -u git forgejo sh -c 'cd / && forgejo admin auth list'
# Erwartet: 1 authentik OAuth2 true

# User
docker exec -u git forgejo sh -c 'cd / && forgejo admin user list'
# Erwartet: admin-local + bw + alle anderen

# Repo-Zähler
docker exec forgejo-db psql -U forgejo -d forgejo \
  -c "SELECT count(*) FROM repository;"

Offsite-Backup-Strategie (zukünftig, M7.5)

  • Tier 2: rclone → Nextcloud, zweiter Cron 03:30
  • Tier 3: Hetzner Cloud Snapshot, manuell wöchentlich

Beides noch nicht eingerichtet — solange lokale 14-Tage-Retention + Hetzner-VM-Stabilität unser Sicherheitsnetz.

Was NIE machen

  • Backup-Files niemals in Git einchecken (können sensible Repo-Daten enthalten)
  • Restore auf laufender Prod ohne vorheriges Backup (einfach docker compose down macht keine DB-Kopie!)
  • docker volume prune wenn Forgejo noch läuft (wird Daten verlieren)