DevOps: Coolify-Testserver-Deployment (Compose, Migrations-Job, Runbook)

- docker-compose.coolify.yml: Coolify-taugliche Variante (kein host-port,
  Env via Coolify-Variablen, migrate-Init-Job vor app, app-Healthcheck)
- .env.coolify.example: Referenz der Coolify-Env-Variablen (nur Platzhalter)
- docs/DEPLOY-COOLIFY.md: Runbook (Gitea-Deploy-Key, Ressource, Env, Domain, Seed)
- .gitignore: .env.coolify.example whitelisten

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 11:41:24 +02:00
co-authored by Claude Opus 4.8
parent 71361df588
commit 81722f0cb4
4 changed files with 213 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
# Deployment: Testserver via Coolify (intern)
> Zielumgebung: interner Coolify-Host (`192.168.1.207`), Docker-Compose-Stack,
> HTTP über eine `*.sslip.io`-Domain (kein öffentliches TLS).
> Ergänzt `docs/HANDOVER-DEVOPS.md`. Deploy-Datei: `docker-compose.coolify.yml`.
## Architekturüberblick (Coolify)
- Coolify deployt den **Compose-Stack** aus diesem Repo und übernimmt **Reverse-Proxy + Routing** — die App wird **nicht** per Host-Port exponiert.
- Services: `migrate` (Init-Job) → `app` (Next.js standalone) + `postgres` (pgvector), `redis`, `minio`.
- **Migrationen** laufen als eigener Init-Job `migrate` (`prisma migrate deploy`, builder-Image) **vor** `app` — der App-Container migriert selbst nicht.
- **Secrets/Config** kommen aus den **Coolify-Env-Variablen** (Referenz: `.env.coolify.example`), nicht aus einer committeten `.env`.
## 1. Gitea mit Coolify verbinden (Deploy Key)
SSH ist erreichbar (`git@…sslip.io:22`), daher Deploy-Key:
1. **Coolify → Keys & Tokens → Private Keys**: SSH-Key generieren (oder beim Anlegen der Ressource „Private Repository (deploy key)“ automatisch). Öffentlichen Key kopieren.
2. **Gitea → Repo `msolarczek/ISMS-Tool` → Settings → Deploy Keys → Add Deploy Key**: Key einfügen, nur Lesezugriff.
3. Repo-URL in Coolify (SSH):
`git@gitea-vkbhbn2qdkz5ppk9q4qgb0tn.192.168.1.207.sslip.io:msolarczek/ISMS-Tool.git`
## 2. Ressource anlegen
1. Projekt/Environment wählen → ** New → Private Repository (deploy key)**.
2. Repo `ISMS-Tool`, **Branch `devops/coolify-testserver`** (nach erfolgreichem Test → `main`).
3. **Build Pack: Docker Compose**, **Compose Location: `docker-compose.coolify.yml`**.
## 3. Environment-Variablen
Werte aus `.env.coolify.example` in Coolify eintragen. Kritisch:
- Hostnamen = Compose-Service-Namen: `postgres`, `redis`, `minio` (nicht `localhost`).
- `AUTH_SECRET` frisch: `openssl rand -base64 32`.
- `AUTH_URL` = exakt die in Schritt 4 vergebene App-Domain (`http://…`).
- `MINIO_ROOT_USER/PASSWORD` müssen `S3_ACCESS_KEY/S3_SECRET_KEY` entsprechen.
## 4. Domain & HTTP
- Beim Service `app` unter **Domains** die `*.sslip.io`-Domain übernehmen, Schema **`http://`**.
- Dieselbe Domain als `AUTH_URL` setzen (sonst schlägt der NextAuth-Login fehl).
## 5. Persistenz
Named Volumes müssen als Persistent Storage erkannt sein — v. a. **`pgdata`** (sonst Datenverlust bei Redeploy). Ebenso `miniodata`, `redisdata`.
## 6. Deploy
**Deploy** starten. Reihenfolge: `postgres` (healthy) → `migrate` (läuft einmalig durch) → `app` (startet erst nach erfolgreichem Migrate). Logs von `migrate`/`app` bei Fehlern prüfen.
## 7. Demo-Admin anlegen (einmalig, Testserver)
Der Demo-Seed läuft nicht automatisch. Im Coolify-**Terminal** des `migrate`-Containers (builder-Image, hat `tsx`):
```
npx tsx prisma/seed.ts
```
Login danach: `admin@demo.example` / `Demo1234!`.
> Produktiv: **kein** Demo-Seed. Stattdessen einmaliger Bootstrap des Plattform-Admins
> (`provisionTenant({ admin.isPlatformAdmin: true })`) — Skript noch zu erstellen
> (siehe `docs/HANDOVER-DEVOPS.md` §4).
## 8. Smoke-Test
Über die App-Domain: Login, Admin-Konsole, eine Modul-Seite.
## Redeploy / Migrationen-Nachziehen
Jeder Coolify-Redeploy baut neu und lässt `migrate` erneut laufen (`migrate deploy` ist idempotent — nur neue Migrationen werden angewandt). App startet erst nach erfolgreichem Migrate.
## Von Test zu Produktiv (Delta)
- `AUTH_SECRET` und DB-/MinIO-Passwörter neu/aus Secret-Store; eigene Domain + gültiges TLS.
- **Kein** Demo-Seed; Erst-Superadmin per Bootstrap-Skript.
- Backups (`pg_dump`/Volume-Snapshots) + Restore-Test, Monitoring/Alerting.
- Ggf. ≥ 2 `app`-Replicas hinter dem Coolify-Proxy.