Files
craftvia/docs/DEPLOY-PROD-PREBUILT.md
msolarczekandClaude Opus 5 c8e6f30a27
CI / build-and-check (push) Canceled after 0s
CI / audit (push) Canceled after 0s
CI / sbom (push) Canceled after 0s
Basis: Certvia dev@a48c5fb als Fundament für Craftvia
Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation
und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 11:05:39 +02:00

83 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.