# Backup & Seeding — Betriebsnotiz Lageplan > Stand: 2026-05-20 > Autor: Automatisch generiert nach Produktionsvorfall ## Inhalt 1. [Wichtige Regeln](#wichtige-regeln) 2. [Backup-Strategie](#backup-strategie) 3. [Seed-Skripte](#seed-skripte) 4. [Post-Deploy Prüfung](#post-deploy-prüfung) 5. [Notfall-Recovery](#notfall-recovery) 6. [Docker-Build Hinweise](#docker-build-hinweise) --- ## Wichtige Regeln ### Nie löschen - **Keine** `deleteMany()`, `DELETE FROM`, `TRUNCATE` oder Cascade-Resets in Production - **Nie** direkt in `icon_assets`, `icon_categories`, `tenant_symbols`, `features`, `projects` löschen - Alle Seed-Skripte müssen **idempotent** sein (`upsert` statt `delete` + `create`) - Vor jedem Seed/Repair in Production: **Databasus-Backup erstellen** ### Databasus Backup - Databasus ist als GUI-Backup eingerichtet - Backups werden gespeichert unter: `/volume1/docker/backups/databasus` - **Nie** das Docker-Volume unter `/volume1/@docker` als einzige Backup-Strategie verwenden ### Container-Informationen | Service | Container-Name | |---------|---------------| | PostgreSQL DB | `lageplan-db-1` | | Web App | `lageplan-web-1` | | DB-Name | `lageplan` | | DB-User | `lageplan` | --- ## Backup-Strategie ### Automatisch (Databasus) 1. Databasus GUI öffnen 2. Datenbank `lageplan` auswählen 3. "Backup Now" klicken 4. Backup wird unter `/volume1/docker/backups/databasus` abgelegt ### Manuell (pg_dump) ```bash # In der NAS-Shell (oder im DB-Container) docker exec lageplan-db-1 pg_dump -U lageplan -d lageplan \ --no-owner --no-privileges \ > /volume1/docker/backups/databasus/lageplan-manual-$(date +%Y%m%d-%H%M%S).sql ``` ### Wiederherstellen ```bash # 1. Backup-Datei prüfen ls -la /volume1/docker/backups/databasus/ # 2. App stoppen docker stop lageplan-web-1 # 3. DB zurückspielen (ACHTUNG: überschreibt aktuelle Daten!) docker exec -i lageplan-db-1 psql -U lageplan -d lageplan \ < /volume1/docker/backups/databasus/lageplan-backup-YYYYmmdd-HHMMSS.sql # 4. App starten docker start lageplan-web-1 ``` --- ## Seed-Skripte ### Übersicht | Skript | Zweck | Sicherheit | Aufruf | |--------|-------|-----------|--------| | `prisma/seed.js` | Vollständiger Seed (Tenant, Users, Icons, HoseTypes, Demo-Projekt) | ✅ Idempotent, nur `upsert` | `npm run db:seed` oder `node prisma/seed.js` | | `prisma/seed-icons-only.js` | Nur Icons aus `public/signaturen/*.svg` | ✅ Idempotent, nur `upsert` | `npm run db:seed:icons` oder `node prisma/seed-icons-only.js` | | `prisma/seed.ts` | Legacy-TypeScript-Seed (korrigiert, aber nicht der Primary) | ✅ Korrigiert | Nicht direkt aufrufen | | `prisma/seed-symbol-templates.ts` | Erstellt `SymbolTemplate`-Einträge | ✅ Nur `findFirst` + `create` (skip if exists) | `npx tsx prisma/seed-symbol-templates.ts` | | `prisma/migrate-tenant-symbols.ts` | Migriert bestehende `TenantSymbol` zu neuem Schema | ✅ Nur `findFirst`, `create`, `update` | `npx tsx prisma/migrate-tenant-symbols.ts` | | `prisma/recover-symbols.js` | Recovery: Icons + TenantSymbols wiederherstellen | ✅ Dry-Run/Apply Modus | `npm run recover:symbols:dry-run` / `npm run recover:symbols:apply` | | `prisma/repair-features.js` | Repariert kaputte `iconId`-Referenzen in Features | ✅ Dry-Run/Apply Modus + Backup | `npm run repair:features:dry-run` / `npm run repair:features:apply` | | `prisma/migrate.js` | DB-Migrationen (Raw SQL, idempotent) | ✅ Keine Deletes auf User-Daten | Wird automatisch beim Container-Start ausgeführt | ### Empfohlene Seed-Strategie 1. **Neue Umgebung** (erstmalig): ```bash node prisma/seed.js ``` 2. **Nur Icons aktualisieren** (z.B. nach SVG-Update): ```bash node prisma/seed-icons-only.js ``` 3. **Recovery nach Icon-Verlust**: ```bash # 1. Erst Databasus-Backup erstellen! # 2. Dann: node prisma/recover-symbols.js --dry-run # Analyse node prisma/recover-symbols.js --apply # Anwenden ``` --- ## Post-Deploy Prüfung ### 1. SVG-Dateien im Container ```bash docker exec -it lageplan-web-1 sh -c 'find /app/public/signaturen -type f -name "*.svg" | wc -l' ``` **Erwartung:** ca. 117 ### 2. Icons seeden ```bash docker exec -it lageplan-web-1 node prisma/seed-icons-only.js ``` **Erwartung:** ``` ✅ 10 icon categories upserted ✅ FKS Signaturen: X created, Y updated (117 total SVGs) ``` ### 3. Datenbank-Prüfung ```bash docker exec -it lageplan-db-1 psql -U lageplan -d lageplan -c " SELECT 'icon_categories' AS table_name, COUNT(*) AS count FROM icon_categories UNION ALL SELECT 'icon_assets' AS table_name, COUNT(*) AS count FROM icon_assets UNION ALL SELECT 'tenant_symbols' AS table_name, COUNT(*) AS count FROM tenant_symbols UNION ALL SELECT 'features' AS table_name, COUNT(*) AS count FROM features UNION ALL SELECT 'projects' AS table_name, COUNT(*) AS count FROM projects; " ``` ### 4. Logs prüfen ```bash docker logs --tail=100 lageplan-web-1 ``` **Keine** der folgenden Fehler sollen auftreten: - `404` für `/signaturen/*.svg` - `Prisma error` wegen `tenant_symbols.categoryId` - `Seed failed` --- ## Notfall-Recovery ### Szenario: Symbole sind verschwunden (404) **Ursache:** `IconAsset`-Einträge wurden gelöscht (z.B. durch altes Seed-Skript mit `deleteMany`) **Lösung:** ```bash # 1. Backup erstellen (Databasus GUI oder pg_dump) # 2. Container-Status prüfen docker exec -it lageplan-web-1 sh -c 'ls -la /app/public/signaturen/ | head -5' # → Sollte SVG-Dateien anzeigen # 3. Icons neu seeden (idempotent, sicher) docker exec -it lageplan-web-1 node prisma/seed-icons-only.js # 4. Tenant-Symbols wiederherstellen (falls auch gelöscht) docker exec -it lageplan-web-1 node prisma/recover-symbols.js --dry-run docker exec -it lageplan-web-1 node prisma/recover-symbols.js --apply # 5. Prüfen docker exec -it lageplan-web-1 node -e " const {PrismaClient} = require('@prisma/client'); const p = new PrismaClient(); p.iconAsset.count({where:{isSystem:true}}).then(c=>console.log('System-Icons:',c)); p.tenantSymbol.count().then(c=>console.log('TenantSymbols:',c)); " ``` ### Szenario: Features haben kaputte iconId-Referenzen **Ursache:** Alte `iconId`-UUIDs in `Feature.properties` zeigen auf gelöschte `IconAsset`s **Lösung:** ```bash # 1. Dry-Run: Analyse docker exec -it lageplan-web-1 node prisma/repair-features.js --dry-run # 2. Apply: Reparatur (erstellt automatisch JSON-Backup) docker exec -it lageplan-web-1 node prisma/repair-features.js --apply ``` --- ## Docker-Build Hinweise ### public/signaturen muss im Image sein - `public/signaturen/*.svg` muss im Git-Index sein (`.gitignore` erlaubt es explizit) - `.dockerignore` darf `public/signaturen/` **nicht** ausschliessen - `Dockerfile` kopiert `public/` in die Runtime-Stage: ```dockerfile COPY --from=builder /app/public ./public ``` ### Next.js standalone - `next.config.js` hat `output: 'standalone'` - Der Build erzeugt `.next/standalone/` (minimaler Server) - `public/` wird explizit in die Runtime-Stage kopiert ### Multi-Stage Build 1. **deps**: `npm ci` (nur Dependencies) 2. **builder**: `npm run build` (inkl. Prisma Generate) 3. **runner**: Runtime-Image mit `public/`, `.next/standalone/`, Prisma-Client --- ## Änderungshistorie | Datum | Änderung | |-------|----------| | 2026-05-20 | `.gitignore` korrigiert: `Signaturen/` → `/Signaturen/` (Root-only), `public/signaturen/*.svg` erlaubt | | 2026-05-20 | 117 SVG-Dateien force-added zum Git-Index | | 2026-05-20 | `.dockerignore` korrigiert: `Signaturen` → `/Signaturen/` | | 2026-05-20 | `package.json`: `db:seed` zeigt jetzt auf `prisma/seed.js` statt broken `seed.ts` | | 2026-05-20 | `seed.ts` korrigiert: Role-Enums + stabile IDs für `iconCategory.upsert` | | 2026-05-20 | Alle Seed-Skripte auf `deleteMany`-Freiheit geprüft | | 2026-05-20 | Dokumentation `docs/backup-und-seeding.md` erstellt |