From 71361df58865fe17695d152366e60d4f6238b550 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 20 Jul 2026 10:58:46 +0200 Subject: [PATCH] =?UTF-8?q?=C3=9Cbergabe-Dokument:=20DevOps=20(Deployment?= =?UTF-8?q?=20Test=20=E2=86=92=20Produktiv)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs/HANDOVER-DEVOPS.md: Runtime-Architektur (Next standalone + Postgres/pgvector/ Redis/MinIO/Mailhog), Umgebungsvariablen, Build/Start, kritische Migrations-/ Bootstrap-Strategie (Migrationen laufen nicht beim Container-Start; erster Superadmin fehlt), Persistenz/Backup, bekannte Lücken (worker-Script fehlt, MinIO- Env, Reverse-Proxy/TLS, Healthcheck), Test-vs-Prod-Unterschiede, Deploy-Checkliste. Co-Authored-By: Claude Opus 4.8 --- docs/HANDOVER-DEVOPS.md | 122 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 docs/HANDOVER-DEVOPS.md diff --git a/docs/HANDOVER-DEVOPS.md b/docs/HANDOVER-DEVOPS.md new file mode 100644 index 0000000..084ded2 --- /dev/null +++ b/docs/HANDOVER-DEVOPS.md @@ -0,0 +1,122 @@ +# DevOps-Übergabe — ISMS-Tool (Deployment Test → Produktiv) + +> Stand: 2026-07-20 · Branch `main` · Commit `081c000` +> Zweck: Betrieb/Deployment. Gemeinsame Arbeit an Dockerfile, Einrichtung Testserver (remote), danach Produktivserver. +> Ergänzt: `docs/HANDOVER-DEV.md` (App-Architektur/Setup) und `docs/HANDOVER-PM.md` (fachlicher Status). + +--- + +## 1. Überblick der Runtime + +Die App ist eine **Next.js-16-Anwendung im Standalone-Modus** (`output: "standalone"` in `next.config`, Start via `node server.js`), zustandslos horizontal skalierbar. Zustand liegt ausschließlich in den Backing-Services. + +| Service | Image / Herkunft | Port | Zweck | Persistenz | +|--------|------------------|------|-------|-----------| +| **app** | Multi-Stage-Build (`Dockerfile`) | 3000 | Web-App (Next.js standalone) | zustandslos | +| **postgres** | `pgvector/pgvector:pg16` | 5432 | Primärdatenbank (inkl. `vector`-Extension) | Volume `pgdata` | +| **redis** | `redis:7-alpine` | 6379 | Cache/Queue (für späteren BullMQ-Worker) | Volume `redisdata` | +| **minio** | `minio/minio:latest` | 9000/9001 | Objektspeicher (noch **ungenutzt**; für kommenden Logo-/Datei-Upload) | Volume `miniodata` | +| **mailhog** | `mailhog/mailhog` (Profil `dev`) | 1025/8025 | SMTP-Fang für Entwicklung | — | +| **worker** | s. Dockerfile (Profil `worker`) | — | **noch nicht lauffähig** (kein `worker`-npm-Script vorhanden) | — | + +Alles bereits als **`docker-compose.yml`** im Repo-Root beschrieben; **`Dockerfile`** ist ein sauberer 3-Stage-Build (`deps` → `builder` mit `prisma generate` + `next build` → schlanker `runner` als non-root `app`-User). + +--- + +## 2. Umgebungsvariablen (`.env`) + +Vorlage: **`.env.example`**. Vollständige Liste: + +| Variable | Zweck | Prod-Hinweis | +|----------|-------|-------------| +| `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB` | Compose-Init von Postgres | **Secret** (Passwort) | +| `DATABASE_URL` | Prisma-Verbindungsstring | **Secret**; muss auf denselben DB-Nutzer/-Namen zeigen | +| `REDIS_URL` | Redis-Verbindung | — | +| `AUTH_SECRET` | NextAuth-Signaturschlüssel (JWT) | **Secret**, zwingend gesetzt & stark | +| `AUTH_URL` | Öffentliche Basis-URL der App | pro Umgebung (Test/Prod) unterschiedlich, inkl. `https://` | +| `AI_PROVIDER` / `AI_API_KEY` | KI-Chat / KI-Formulierungshilfe (noch ungenutzt) | Secret, optional | +| `SMTP_HOST/PORT/USER/PASSWORD/FROM` | E-Mail (noch ungenutzt; Einladungs-/Benachrichtigungsflow offen) | Secret, optional | +| `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD` | Objektspeicher | **fehlen in `.env.example`** → für Prod ergänzen (sonst Compose-Defaults `isms`/`isms-secret`) | + +> **Secrets** gehören nicht ins Git. Für Prod: Secret-Management (Docker Secrets / Env aus Vault / CI-Variablen). `.env.example` enthält nur Namen/Defaults. + +--- + +## 3. Build & Start + +```bash +# Image bauen +docker compose build app + +# Test/lokal hochfahren (ohne dev-only mailhog) +docker compose up -d postgres redis minio app + +# mit Mailhog (Dev): docker compose --profile dev up -d +# Worker (aktuell NICHT lauffähig, s. §6): docker compose --profile worker up -d worker +``` + +App danach unter `AUTH_URL` (Port 3000) erreichbar. + +--- + +## 4. ⚠️ Datenbank-Migrationen & Bootstrap (kritisch) + +**Der App-Container führt KEINE Migrationen beim Start aus** (CMD ist `node server.js`). Migrationen und das erste Provisioning sind ein **separater Deploy-Schritt**: + +1. **Migrationen anwenden:** `npx prisma migrate deploy` gegen die Ziel-DB. + - Die `runner`-Stage enthält Prisma-CLI/`tsx` **nicht** (nur Runtime-Trace). Migrationen daher aus der **`builder`-Stage** (voller `node_modules`) oder aus einem eigenen **Migrations-Job/CI-Step** fahren. → **Designentscheidung mit DevOps** (z. B. Init-Container `command: npx prisma migrate deploy` mit builder-Image, `restart: "no"`). + - Die Init-Migration legt `CREATE EXTENSION IF NOT EXISTS "vector"` an (pgvector) — das Postgres-Image bringt die Extension mit. +2. **Erster Mandant / Superadmin (Prod):** Der Demo-Seed (`prisma/seed.ts`) ist **nur für Entwicklung** (Demo-Mandant + Testnutzer) — **nicht in Produktion ausführen**. In Prod erfolgt das Anlegen von Kunden über die **Admin-Konsole** (`provisionTenant`). **Offen:** Es gibt aktuell **kein Bootstrap-Skript** für den allerersten Plattform-Admin — dieser muss initial angelegt werden (Skript/One-Off gegen `provisionTenant` mit `isPlatformAdmin: true`, oder manuell). → **Mit App-Entwickler abstimmen** (kleiner Task). + +--- + +## 5. Persistenz, Backup & Restore + +- **Volumes:** `pgdata` (kritisch), `miniodata` (künftig Uploads), `redisdata` (unkritisch, Cache). +- **Backups Prod:** regelmäßiger `pg_dump` (logisch) oder Volume-/Snapshot-Backup; MinIO-Bucket-Backup, sobald Uploads aktiv. Aufbewahrung + Restore-Test einplanen (DSGVO-Löschkonzept ist app-seitig noch offen). +- Mandantentrennung ist **logisch** (eine DB, `tenant_id` + Postgres-RLS + App-Guard) — Backups umfassen alle Mandanten gemeinsam. + +--- + +## 6. Bekannte Lücken / To-dos für DevOps + +1. **`worker`-Service nicht lauffähig:** Es existiert **kein `npm run worker`**-Script (BullMQ-Scheduler ist app-seitig noch nicht implementiert). Profil `worker` bis dahin **nicht** starten. +2. **Migrations-/Bootstrap-Strategie** festlegen (§4) — Migrations-Job + Erst-Superadmin. +3. **MinIO-Env** in `.env` für Prod ergänzen; MinIO wird erst mit dem kommenden Logo-/Datei-Upload wirklich genutzt (Bucket-Präfix je Mandant vorgesehen). +4. **Reverse-Proxy + TLS** vor der App (Port 3000 nicht direkt exponieren): Traefik/Caddy/nginx mit HTTPS; `AUTH_URL` auf die öffentliche `https://`-Adresse setzen. Rate-Limiting/IP-Härtung für Login/Admin einplanen. +5. **Ressourcen/Skalierung:** `app` ist zustandslos → mehrere Replicas möglich; Sticky-Sessions nicht nötig (JWT). Postgres/Redis als Singleton bzw. Managed-Service. +6. **Health/Observability:** Postgres-Healthcheck vorhanden; für `app` einen HTTP-Healthcheck/Readiness ergänzen (derzeit keiner definiert). Log-Aggregation + Alerting einrichten. +7. **`AUTH_SECRET`** je Umgebung eindeutig & stark; bei Rotation invalidieren alle Sessions. + +--- + +## 7. Test- vs. Produktivumgebung — Unterschiede + +| Aspekt | Test (Remote) | Produktiv | +|--------|---------------|-----------| +| Daten | ggf. Demo-Seed erlaubt | **kein Demo-Seed**; nur echtes Provisioning | +| Secrets | Test-Werte | echte Secrets aus Secret-Store | +| Mail | Mailhog (Profil `dev`) | echtes SMTP-Relay | +| TLS | optional/self-signed | verpflichtend, gültiges Zertifikat | +| Backups | optional | verpflichtend + Restore-Test | +| Skalierung | 1 Replica | ≥ 2 App-Replicas hinter Proxy | + +--- + +## 8. Deploy-Checkliste (Kurz) + +**Testserver:** +1. Repo klonen/pullen (Gitea, Branch `main`). +2. `.env` aus `.env.example` mit Test-Werten (inkl. `MINIO_*`). +3. `docker compose build app`. +4. `docker compose up -d postgres redis minio`. +5. **Migrationen:** `prisma migrate deploy` (builder-Image/Job). +6. **Erst-Superadmin** anlegen (One-Off, s. §4) — für Test ggf. Demo-Seed ok. +7. `docker compose up -d app`; Reverse-Proxy/TLS davor; Smoke-Test (Login, Admin-Konsole, Modul-Seite). + +**Produktivserver:** wie oben, aber Secret-Store, **kein** Demo-Seed, TLS verpflichtend, Backups + Monitoring aktiv, ≥ 2 App-Replicas, Migrations-/Bootstrap-Schritt in die Deploy-Pipeline integriert. + +--- + +## 9. Referenzen im Repo +`Dockerfile`, `docker-compose.yml`, `.env.example`, `next.config.*` (`output: standalone`), `prisma/schema.prisma` + `prisma/migrations/**` (inkl. RLS-Policies & pgvector), `prisma/seed.ts` (nur Dev), `src/server/provision.ts` (Provisioning-Logik für Prod-Onboarding).