Basis: Certvia dev@a48c5fb als Fundament für Craftvia
CI / build-and-check (push) Canceled after 0s
CI / audit (push) Canceled after 0s
CI / sbom (push) Canceled after 0s

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>
This commit is contained in:
2026-09-14 11:05:39 +02:00
co-authored by Claude Opus 5
commit c8e6f30a27
720 changed files with 140143 additions and 0 deletions
+82
View File
@@ -0,0 +1,82 @@
# 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.