Files
GerbilManager/docs/ops.md
Gulum 69a0279bb7 OPS-1: TrueNAS compose, backup sidecar, Gitea CI draft, ops docs
deploy/truenas/compose.yaml:
  - 4 services: db (postgres:17), api (.NET), frontend (nginx), backup sidecar
  - Named volumes as NAS bind-mounts (paths configured in .env)
  - Healthchecks: db pg_isready, api /health, frontend waits on api
  - ANTHROPIC_API_KEY placeholder for FEAT-12a AI stub

deploy/truenas/.env.example: POSTGRES_PASSWORD, PORT, REGISTRY, dataset paths

deploy/truenas/scripts/:
  - entrypoint.sh: installs daily 03:00 cron, starts crond in foreground
  - backup.sh: pg_dump -> .sql + tar czf photos -> .tar.gz + rotation
  - restore.sh: psql < dump + tar xzf photos; confirmation prompt (-f to skip)
  Predecessor logic (commit 6a37f9e) translated from PowerShell to POSIX sh
  for Alpine containers. Same pg_dump/restore semantics, same KEEP_DAYS rotation.

.gitea/workflows/ci.yml (DRAFT -- inactive until Julian confirms Actions):
  dotnet test + npm test/build on push/PR to main;
  docker build+push to Gitea registry on main push only

docs/ops.md:
  German ops guide -- architecture diagram, first-install checklist,
  start/stop/update commands, backup runbook (manual + auto), ZFS-snapshot
  layering strategy, CI activation steps, open questions, troubleshooting table

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 07:31:19 +02:00

11 KiB
Raw Permalink Blame History

GerbilManager — Betriebsanleitung (TrueNAS)

Zielgruppe: Julian (Systemadministration) und Ehefrau (tägliche Nutzung). Bookmark für die Ehefrau: http://<NAS-IP>/ (z. B. http://truenas/)


Inhaltsverzeichnis

  1. Übersicht & Architektur
  2. Voraussetzungen
  3. Erstinstallation auf TrueNAS
  4. App starten / stoppen / aktualisieren
  5. Backup & Wiederherstellung
  6. ZFS-Snapshot-Schichtung
  7. CI/CD via Gitea Actions
  8. Offene Fragen (bitte beantworten)
  9. Fehlerbehebung

1. Übersicht & Architektur

Browser / Handy
      |  HTTP :80
      v
 ┌──────────────────┐
 │  frontend (nginx) │  statisches React-SPA + Reverse-Proxy
 └──────┬───────────┘
        │ /api/*  →  http://api:8080/*
        │ /scalar →  http://api:8080/scalar
        v
 ┌──────────────────┐
 │   api (.NET 10)  │  GerbilManagerWebAPI, Minimal API
 └──────┬───────────┘
        │ ConnectionStrings__gerbilmanager
        v
 ┌──────────────────┐      ┌──────────────────────┐
 │  db (Postgres 17)│      │  backup (Sidecar)     │
 └──────────────────┘      │  pg_dump + tar + cron │
        │                  └──────────────────────┘
        └─ pgdata-Volume (NAS-Dataset)
           photos-Volume  (NAS-Dataset)
           backups-Volume (NAS-Dataset)

Einziger veröffentlichter Port: 80 (konfigurierbar via PORT in .env). Alles andere läuft intern im Docker-Netz.


2. Voraussetzungen

Was Details
TrueNAS SCALE Electric Eel 24.10+ (native Docker Custom Apps)
Gitea http://truenas:13000 — Repository Gulum/GerbilManager
Docker bereits auf TrueNAS vorhanden (Custom Apps nutzen es)
Datasets Drei ZFS-Datasets anlegen (siehe Schritt 3)

3. Erstinstallation auf TrueNAS

3.1 ZFS-Datasets anlegen

In TrueNAS → DatasetsDataset hinzufügen (je einmal wiederholen):

Dataset-Name Empfohlener Pfad Verwendung
gerbil/pgdata /mnt/SSD/gerbil/pgdata Postgres-Datenbankdateien
gerbil/photos /mnt/SSD/gerbil/photos Hochgeladene Tierfotos
gerbil/backups /mnt/SSD/gerbil/backups Tägliche Backups

Tipp: Passe die Pool-Bezeichnung (SSD) an deinen tatsächlichen Pool an.

3.2 Repository klonen

# SSH in TrueNAS oder lokale Shell
git clone http://truenas:13000/Gulum/GerbilManager.git /opt/gerbilmanager
cd /opt/gerbilmanager

3.3 Konfiguration anlegen

cp deploy/truenas/.env.example deploy/truenas/.env
# Jetzt .env bearbeiten:
nano deploy/truenas/.env

Mindestens setzen:

  • POSTGRES_PASSWORD — sicheres Passwort (mind. 20 Zeichen)
  • PGDATA_PATH, PHOTOS_PATH, BACKUPS_PATH — tatsächliche Dataset-Pfade

3.4 Images bauen und App starten

cd /opt/gerbilmanager
docker compose -f deploy/truenas/compose.yaml build
docker compose -f deploy/truenas/compose.yaml up -d

Erster Start dauert ca. 23 Minuten (Postgres-Init + EF-Migrationen).

3.5 Prüfen

# Alle Container laufen?
docker compose -f deploy/truenas/compose.yaml ps

# API-Healthcheck
curl http://localhost/api/health

# Webapp im Browser
http://<NAS-IP>/

4. App starten / stoppen / aktualisieren

Starten

docker compose -f deploy/truenas/compose.yaml up -d

Stoppen

docker compose -f deploy/truenas/compose.yaml down

Aktualisieren (nach git push auf main)

cd /opt/gerbilmanager
git pull
docker compose -f deploy/truenas/compose.yaml build
docker compose -f deploy/truenas/compose.yaml up -d

EF-Migrationen laufen automatisch beim API-Start — kein manueller Schritt nötig.

Mit Gitea CI (wenn Actions aktiviert)

Push auf main triggert automatisch Build → Test → Image-Push. Danach auf der NAS:

docker compose -f deploy/truenas/compose.yaml pull
docker compose -f deploy/truenas/compose.yaml up -d

5. Backup & Wiederherstellung

Automatisches Backup

Der backup-Sidecar-Container läuft dauerhaft und sichert täglich um 03:00 Uhr:

  • Kompletter pg_dump der Datenbank als .sql
  • Komprimiertes Foto-Archiv als .tar.gz
  • Rotation: Backups älter als BACKUP_KEEP_DAYS (Standard: 7) werden gelöscht

Backups liegen unter: ${BACKUPS_PATH}/YYYY-MM-DD_HH-MM/

/mnt/SSD/gerbil/backups/
  2026-06-06_03-00/
    gerbilmanager_2026-06-06_03-00.sql   (Datenbank)
    photos_2026-06-06_03-00.tar.gz       (Fotos)
  backup.log                              (Protokoll)

Manuelles Backup auslösen

docker compose -f deploy/truenas/compose.yaml exec backup /bin/sh /scripts/backup.sh

Backup-Log prüfen

tail -50 /mnt/SSD/gerbil/backups/backup.log

Wiederherstellung — Runbook

WARNUNG: Alle aktuellen Daten werden überschrieben!

Schritt 1: App stoppen (optional, aber empfohlen)

docker compose -f deploy/truenas/compose.yaml stop api frontend

Schritt 2: Restore ausführen

# Neuestes Backup wiederherstellen:
docker compose -f deploy/truenas/compose.yaml exec backup \
    /bin/sh /scripts/restore.sh

# Bestimmtes Backup wiederherstellen:
docker compose -f deploy/truenas/compose.yaml exec backup \
    /bin/sh /scripts/restore.sh 2026-06-05_03-00

Schritt 3: API neu starten

docker compose -f deploy/truenas/compose.yaml start api frontend

Schritt 4: Prüfen

curl http://localhost/api/color-varieties | grep -c '"id"'
# Erwarteter Wert: 73

Restore-Nachweis (Round-Trip-Test)

Protokoll vom Test auf lokalem Aspire-Postgres (Vorgänger-Instanz, 2026-06-06 07:09):

73 ColorVarieties vorhanden
→ DELETE 12 Zeilen → 61 verbleibend
→ pg_restore eingespielt
→ 73 ColorVarieties bestätigt
Exit-Code: 0

Die Container-Restore-Skripte nutzen dieselbe psql < dump.sql Logik. Erster echter Test auf TrueNAS: nach Erstinstallation bitte ausführen und das Ergebnis notieren.


6. ZFS-Snapshot-Schichtung

ZFS-Snapshots ergänzen die pg_dump-Backups als zweite Sicherungsebene. Sie schützen vor versehentlichem Datenverlust auf Dataset-Ebene.

Empfohlene Snapshot-Konfiguration

In TrueNAS → Datasets → Dataset auswählen → SnapshotsRegelmäßige Snapshots:

Dataset Häufigkeit Aufbewahrung
gerbil/photos Stündlich 24 Stunden
gerbil/photos Täglich 30 Tage
gerbil/pgdata Stündlich 24 Stunden
gerbil/pgdata Täglich 30 Tage
gerbil/backups Täglich 90 Tage

Hinweis: pgdata enthält Live-Postgres-Dateien. ZFS-Snapshots davon sind crash-konsistent, aber nicht application-konsistent — für einen sauberen DB-Restore immer den pg_dump verwenden, nicht den ZFS-Snapshot von pgdata.

Snapshot manuell erstellen (z. B. vor Update)

# TrueNAS CLI
zfs snapshot SSD/gerbil/photos@vor-update-$(date +%Y%m%d)
zfs snapshot SSD/gerbil/backups@vor-update-$(date +%Y%m%d)

Aus ZFS-Snapshot wiederherstellen (Fotos)

# Snapshot auflisten
zfs list -t snapshot SSD/gerbil/photos

# Datei aus Snapshot kopieren
cp /mnt/SSD/gerbil/photos/.zfs/snapshot/<NAME>/datei.jpg /mnt/SSD/gerbil/photos/

7. CI/CD via Gitea Actions

Der Workflow .gitea/workflows/ci.yml ist als Entwurf vorhanden, aber inaktiv.

Aktivierung

  1. Gitea Actions aktivieren: Gitea → Repository GerbilManager → Einstellungen → Actions → "Actions aktivieren"

  2. Gitea Actions Runner installieren (auf TrueNAS oder einem separaten Gerät):

    # Gitea Runner Container (einfachste Variante für TrueNAS)
    docker run -d --name gitea-runner \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v /opt/gitea-runner:/data \
      -e GITEA_INSTANCE_URL=http://truenas:13000 \
      -e GITEA_RUNNER_REGISTRATION_TOKEN=<TOKEN> \
      gitea/act_runner:latest
    

    Token: Gitea → Admin → Actions → Runner → "Runner hinzufügen"

  3. Registry-Secrets konfigurieren: Gitea → Repository → Einstellungen → Secrets:

    • REGISTRY_USER — dein Gitea-Benutzername
    • REGISTRY_TOKEN — Gitea Access Token mit package:write-Berechtigung

Workflow nach Aktivierung

git push origin main
  → Gitea Actions: dotnet test + npm test + npm run build
  → Bei Erfolg: docker build + push zu truenas:13000/gulum/
  → Auf NAS: docker compose pull + up -d

8. Offene Fragen

Bitte beantworte diese Fragen, damit das Setup fertiggestellt werden kann:

# Frage Auswirkung
1 TrueNAS SCALE Version? Electric Eel 24.10 hat native Docker Custom Apps. Ältere Versionen nutzen Kubernetes. Bestimmt ob docker compose direkt läuft
2 Gitea Actions verfügbar/aktivierbar? CI/CD-Workflow aktiv oder nur manuell deployen
3 Eigener Postgres-Container (empfohlen) oder vorhandene NAS-Postgres-App? Isolation vs. geteilte Instanz
4 Genaue Dataset-Pfade? Poolname und Pfad-Präfix .env-Konfiguration
5 Port-Wahl? Standard 80 — frei auf der NAS? PORT-Wert in .env

9. Fehlerbehebung

App startet nicht

# Logs aller Container
docker compose -f deploy/truenas/compose.yaml logs

# Logs eines bestimmten Containers
docker compose -f deploy/truenas/compose.yaml logs api
docker compose -f deploy/truenas/compose.yaml logs db

Datenbank nicht erreichbar

# DB-Container läuft?
docker compose -f deploy/truenas/compose.yaml ps db

# Verbindung testen
docker compose -f deploy/truenas/compose.yaml exec db \
    psql -U postgres -d gerbilmanager -c "\dt"

Backup-Fehler

# Backup-Log prüfen
cat /mnt/SSD/gerbil/backups/backup.log | tail -30

# Backup manuell starten (mit Fehlerausgabe)
docker compose -f deploy/truenas/compose.yaml exec backup \
    /bin/sh /scripts/backup.sh

Fotos werden nicht angezeigt

Prüfe ob das photos-Volume korrekt gemounted ist:

docker compose -f deploy/truenas/compose.yaml exec api ls /data/photos

Container-Status zurücksetzen (Neustart)

docker compose -f deploy/truenas/compose.yaml restart api

Kompletter Neustart (Daten bleiben erhalten)

docker compose -f deploy/truenas/compose.yaml down
docker compose -f deploy/truenas/compose.yaml up -d