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>
11 KiB
GerbilManager — Betriebsanleitung (TrueNAS)
Zielgruppe: Julian (Systemadministration) und Ehefrau (tägliche Nutzung). Bookmark für die Ehefrau: http://<NAS-IP>/ (z. B. http://truenas/)
Inhaltsverzeichnis
- Übersicht & Architektur
- Voraussetzungen
- Erstinstallation auf TrueNAS
- App starten / stoppen / aktualisieren
- Backup & Wiederherstellung
- ZFS-Snapshot-Schichtung
- CI/CD via Gitea Actions
- Offene Fragen (bitte beantworten)
- 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 → Datasets → Dataset 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. 2–3 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_dumpder 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 → Snapshots → Regelmäß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:
pgdataenthält Live-Postgres-Dateien. ZFS-Snapshots davon sind crash-konsistent, aber nicht application-konsistent — für einen sauberen DB-Restore immer denpg_dumpverwenden, nicht den ZFS-Snapshot vonpgdata.
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
-
Gitea Actions aktivieren: Gitea → Repository
GerbilManager→ Einstellungen → Actions → "Actions aktivieren" -
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:latestToken: Gitea → Admin → Actions → Runner → "Runner hinzufügen"
-
Registry-Secrets konfigurieren: Gitea → Repository → Einstellungen → Secrets:
REGISTRY_USER— dein Gitea-BenutzernameREGISTRY_TOKEN— Gitea Access Token mitpackage: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