- docker-compose.coolify(.prebuilt).yml: Service craftvia-worker (Target worker, Chromium, shm_size 1gb, gleiche Härtung), Craftvia-Variablen für app und worker. - Dockerfile: worker-Stage mit HOME=/home/app (Chromium-Profil für non-root); lokaler docker build der Targets runner und worker erfolgreich, PDF-Erzeugung im Image geprüft. - .env.example/.env.prod.example/.env.coolify.example: alle Craftvia-Variablen inkl. RLS, KI-Provider, PDF_CHROMIUM_PATH, OFFLINE_MAX_DAYS, API_RATE_LIMIT_*, AI_GENERATION_RETENTION_DAYS, AI_MONTHLY_TOKEN_LIMIT. - CI (.github, .gitea): Job gate mit Postgres (pgvector) und Redis als Service: migrate deploy, seed, Passwort für craftvia_app, tsc, lint, build, npm run test. - docs/craftvia/DEPLOY.md (aus den Certvia-Deploy-Docs abgeleitet): Architektur, Domains, Secrets, Worker, Migrationen, RLS-Aktivierung, Backup/Restore, KI, Rate Limits, Aufbewahrung, Smoke, Update/Rollback. build-and-push-images.sh baut craftvia-worker. - Certvia-/ISMS-Dokumente aus docs/ nach docs/_certvia-archiv/ (mit README); Verweise in README.md und Skript-Kommentaren angepasst. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
83 lines
4.3 KiB
Markdown
83 lines
4.3 KiB
Markdown
# Prod-Deploy via vorgebaute Images (Plan B) — Runbook
|
||
|
||
> **Warum:** Der direkte Build auf dem Prod-Coolify läuft in den Deployment-Timeout
|
||
> (~1 h; Ursache ist Coolifys Build-Pfad — u. a. die ~265-ARG-Injektion, die den
|
||
> Layer-Cache bei jedem Deploy bricht → Kaltbau). Lösung: Images **einmal auf einem
|
||
> leistungsfähigen Host bauen**, in die Registry pushen, und der Prod-Host **zieht nur**.
|
||
> Ergebnis: Prod-Deploy = Pull + Migrate = Minuten statt Stunde.
|
||
|
||
## Topologie (Stand 2026-09-10)
|
||
|
||
| Rolle | Host |
|
||
|---|---|
|
||
| **Build-Host** (baut + pusht) | `192.168.1.155` — lokales Coolify (= local-gitea-Host), amd64, Docker |
|
||
| **Registry** | **git.certvia.de** (Gitea Container Registry), Namespace `msolarczek` |
|
||
| **Prod** (`certvia_prod`, GEFIM live) | **coolify.certvia.de** (eigener Server, ≠ 192.168) |
|
||
| Quelle | git.certvia.de/msolarczek/certvia, Branch `main` |
|
||
|
||
Beteiligte Dateien im Repo:
|
||
- `docker-compose.coolify.prebuilt.yml` — wie `docker-compose.coolify.yml`, aber die App-Services ziehen `${REGISTRY:-git.certvia.de/msolarczek}/certvia-*:${IMAGE_TAG:-main}` statt zu bauen (`postgres`/`redis` unverändert).
|
||
- `scripts/build-and-push-images.sh` — baut + pusht die drei Images.
|
||
|
||
Service → Image (Dockerfile-Target):
|
||
- `app` → **certvia-app** (`runner`)
|
||
- `migrate`, `worker`, `backup-worker`, `incident-inbound-worker`, `garage-provision` → **certvia-migrate** (`migrate`)
|
||
- `garage` → **certvia-garage** (`garage`)
|
||
|
||
## Voraussetzung: Gitea-Token
|
||
Token in git.certvia.de → Settings → Applications mit Scopes:
|
||
`read:repository` (Klonen) + `read:package` + `write:package` (Image Push/Pull).
|
||
|
||
## Ablauf je Release
|
||
|
||
### 1. Auf dem Build-Host (192.168.1.155)
|
||
```bash
|
||
docker login git.certvia.de -u msolarczek # Passwort = Token
|
||
git clone https://msolarczek:<TOKEN>@git.certvia.de/msolarczek/certvia.git cv-build # oder: cd cv-build && git fetch && git pull
|
||
cd cv-build && git checkout main && git pull
|
||
ALSO_MAIN=true ./scripts/build-and-push-images.sh # baut+pusht Tag <SHA> UND :main
|
||
```
|
||
> **Wichtig:** `ALSO_MAIN=true` setzen → es wird zusätzlich das bewegliche Tag `:main`
|
||
> gepusht. Coolify zieht per Default `:main` (siehe Gotcha IMAGE_TAG unten).
|
||
|
||
### 2. Prod-Host (coolify.certvia.de) einmalig am Registry anmelden
|
||
```bash
|
||
docker login git.certvia.de -u msolarczek # Passwort = Token
|
||
```
|
||
(oder in der Coolify-UI unter Settings → Docker Registries hinterlegen). Nur beim
|
||
ersten Mal / nach Token-Wechsel nötig.
|
||
|
||
### 3. Coolify (certvia_prod, coolify.certvia.de)
|
||
- **Configuration → „Docker Compose Location"** = `docker-compose.coolify.prebuilt.yml` (einmalig).
|
||
- Env unverändert: `RUN_DEMO_SEED=false`, `BOOTSTRAP_ADMIN=false`.
|
||
- **Redeploy.** Log zeigt Pull der `certvia-*:main` → `migrate` (achte auf neue Migration) → `garage`/`garage-provision` → `app` healthy.
|
||
|
||
### 4. Nach dem Deploy — Bestandsmandanten-Migrationen der Fachdaten
|
||
Nur nötig, wenn eine Änderung Bestandsmandanten betrifft (z. B. der 5×5-Backfill). In
|
||
Coolify → certvia_prod → Service `backup-worker`/`worker` → Terminal (oder per SSH
|
||
`docker exec`):
|
||
```bash
|
||
npx tsx scripts/backfill-risk-5x5.ts # idempotent, alle Mandanten
|
||
```
|
||
|
||
### 5. Smoke-Test
|
||
Login → betroffene Modulseiten prüfen (z. B. `/processes`, `/dependencies`).
|
||
|
||
## Gotchas (aus dem ersten Live-Lauf gelernt)
|
||
|
||
- **`IMAGE_TAG` wird von Coolify NICHT in die Compose-Interpolation gereicht** → die
|
||
Datei fällt auf `:main` zurück. Deshalb `:main` immer mitpushen (`ALSO_MAIN=true`).
|
||
SHA-genaues Pinning müsste erst geklärt werden (dann `IMAGE_TAG=<sha>` in Coolify-Env).
|
||
- **Coolify entfernt die alten Container VOR dem Pull.** Fehlt der Ziel-Tag in der
|
||
Registry, schlägt der Pull fehl und **prod ist unten**. Also *immer erst* Images
|
||
(inkl. `:main`) pushen, *dann* Redeploy.
|
||
- **Klon-403:** Ein reiner Package-Token darf nicht klonen — `read:repository` fehlt.
|
||
- **Migration-Drift ungefährlich:** `prisma migrate deploy` läuft auch dann sauber (Exit 0),
|
||
wenn die DB eine angewandte Migration hat, die lokal nicht mehr existiert (empirisch geprüft).
|
||
- Nach Nutzung Token, der im Klartext (URL/History) auftauchte, **widerrufen**.
|
||
|
||
## Rollback
|
||
Alten Stand deployen: früheres Image-Tag als `:main` retaggen+pushen (auf dem Build-Host)
|
||
und Redeploy — oder Compose-Location zurück auf `docker-compose.coolify.yml` (Host-Build,
|
||
langsam) als Notnagel.
|