# GerbilManager — Betriebsanleitung (TrueNAS) > Zielgruppe: Julian (Systemadministration) und Ehefrau (tägliche Nutzung). > Bookmark für die Ehefrau: **http://\/** (z. B. http://truenas/) --- ## Inhaltsverzeichnis 1. [Übersicht & Architektur](#1-übersicht--architektur) 2. [Voraussetzungen](#2-voraussetzungen) 3. [Erstinstallation auf TrueNAS](#3-erstinstallation-auf-truenas) 4. [App starten / stoppen / aktualisieren](#4-app-starten--stoppen--aktualisieren) 5. [Backup & Wiederherstellung](#5-backup--wiederherstellung) 6. [ZFS-Snapshot-Schichtung](#6-zfs-snapshot-schichtung) 7. [CI/CD via Gitea Actions](#7-cicd-via-gitea-actions) 8. [Offene Fragen (bitte beantworten)](#8-offene-fragen) 9. [Fehlerbehebung](#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 → **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 ```bash # SSH in TrueNAS oder lokale Shell git clone http://truenas:13000/Gulum/GerbilManager.git /opt/gerbilmanager cd /opt/gerbilmanager ``` ### 3.3 Konfiguration anlegen ```bash 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 ```bash 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 ```bash # Alle Container laufen? docker compose -f deploy/truenas/compose.yaml ps # API-Healthcheck curl http://localhost/api/health # Webapp im Browser http:/// ``` --- ## 4. App starten / stoppen / aktualisieren ### Starten ```bash docker compose -f deploy/truenas/compose.yaml up -d ``` ### Stoppen ```bash docker compose -f deploy/truenas/compose.yaml down ``` ### Aktualisieren (nach `git push` auf main) ```bash 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: ```bash 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 ```bash docker compose -f deploy/truenas/compose.yaml exec backup /bin/sh /scripts/backup.sh ``` ### Backup-Log prüfen ```bash tail -50 /mnt/SSD/gerbil/backups/backup.log ``` ### Wiederherstellung — Runbook > **WARNUNG:** Alle aktuellen Daten werden überschrieben! **Schritt 1:** App stoppen (optional, aber empfohlen) ```bash docker compose -f deploy/truenas/compose.yaml stop api frontend ``` **Schritt 2:** Restore ausführen ```bash # 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 ```bash docker compose -f deploy/truenas/compose.yaml start api frontend ``` **Schritt 4:** Prüfen ```bash 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:** `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) ```bash # 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) ```bash # Snapshot auflisten zfs list -t snapshot SSD/gerbil/photos # Datei aus Snapshot kopieren cp /mnt/SSD/gerbil/photos/.zfs/snapshot//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): ```bash # 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= \ 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 ```bash # 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 ```bash # 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 ```bash # 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: ```bash docker compose -f deploy/truenas/compose.yaml exec api ls /data/photos ``` ### Container-Status zurücksetzen (Neustart) ```bash docker compose -f deploy/truenas/compose.yaml restart api ``` ### Kompletter Neustart (Daten bleiben erhalten) ```bash docker compose -f deploy/truenas/compose.yaml down docker compose -f deploy/truenas/compose.yaml up -d ```