Files
certvia/docs/HANDOVER-DEVOPS.md
T
msolarczekandClaude Opus 4.8 71361df588 Übergabe-Dokument: DevOps (Deployment Test → Produktiv)
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 <noreply@anthropic.com>
2026-07-20 10:58:46 +02:00

7.5 KiB

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 (depsbuilder 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

# 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).