All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 17m48s
248 lines
7.7 KiB
Markdown
248 lines
7.7 KiB
Markdown
# 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 |
|