Some checks failed
Momentrum CI / Version (aus PR-ID / SHA) (push) Successful in 2s
Momentrum CI / Test (compile + pytest) (push) Failing after 12s
Momentrum CI / Build & Push image (push) Has been skipped
Momentrum CI / Helm lint + template (push) Successful in 8s
Momentrum CI / Deploy PROD (Image-Tag -> CD-Repo) (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
176 lines
8.1 KiB
Markdown
176 lines
8.1 KiB
Markdown
# Runbook — ibo (Immo-Bot): CI/CD, PR-Preview-dev + prod, Zitadel-SSO
|
|
|
|
Immo-Bot = Flask-Web-App + Selenium-Chrome-Sidecar (noVNC-Live-Ansicht).
|
|
Umgebungs-Modell **wie momentrum-kanban**: ephemere PR-Previews als „dev" + eine
|
|
stehende prod. Beide hinter Zitadel-SSO (die App selbst hat KEINE eigene Auth).
|
|
|
|
| Umgebung | Host | SSO-Proxy | Deploy |
|
|
|----------|----------------------------------|-------------------|-------------------------------------------------|
|
|
| dev | `ibo-pr-<nr>.dev.momentrum.de` | generisches `dev-sso` | ephemer pro PR mit Label `preview` (ApplicationSet) |
|
|
| prod | `ibo.momentrum.de` | per-App `ibo-sso` | **automatisch** bei jedem main-Merge (CI → CD-Repo) |
|
|
|
|
Die Muster spiegeln kanban/luxly (CI/Chart/CD/ApplicationSet) und dev-sso/ibo-sso
|
|
(oauth2-proxy). Cluster-, Zitadel- und DNS-Schritte sind **manuell** — dieses
|
|
Runbook ist die Anleitung. Reihenfolge unten einhalten.
|
|
|
|
---
|
|
|
|
## 0. Repo nach Gitea bringen
|
|
|
|
```sh
|
|
cd projekte/ibo
|
|
git add -A && git commit -m "ibo: PR-Preview-dev + prod, Zitadel-SSO"
|
|
git remote add origin momentrum-gitea:momentrum/ibo.git # SSH-Alias wie andere Repos
|
|
git push -u origin main
|
|
```
|
|
|
|
**Gitea-Actions-Secrets** am Repo `momentrum/ibo` (Settings → Actions → Secrets):
|
|
- `REGISTRY_USER`, `REGISTRY_TOKEN` — Push in die Gitea-Registry.
|
|
- `DEPLOY_TOKEN` — Gitea-Token mit **Write auf `momentrum/momentrum-deploy`**
|
|
(Write-back des prod-Image-Tags bei main-Merge).
|
|
|
|
---
|
|
|
|
## 1. Zitadel-Clients + Sealed-Secret
|
|
|
|
- **prod (`ibo-sso`)** nutzt einen **eigenen** Zitadel-Web-Client. Dessen
|
|
ClientId/ClientSecret liegen im (nicht committeten) `.env` des ibo-Repos und
|
|
werden als SealedSecret **`oauth2-proxy-ibo`** (ns `iam`) in den Cluster gelegt:
|
|
|
|
```sh
|
|
# dort ausfuehren, wo Cluster-Zugriff besteht (Tunnel localhost:16443 / Bastion):
|
|
cd contabo-infra/platform/manifests/ibo-sso
|
|
IBO_ENV=../../../../projekte/ibo/.env ./seal-oauth2-proxy-ibo.sh
|
|
# -> erzeugt sealed-oauth2-proxy-ibo.yaml (committen & pushen -> ArgoCD entsiegelt)
|
|
# offline-Variante (ohne Cluster) mit Public-Cert:
|
|
# kubeseal --controller-namespace sealed-secrets --fetch-cert > pub.pem # einmal, mit Cluster
|
|
# SEALED_CERT=pub.pem IBO_ENV=.../.env ./seal-oauth2-proxy-ibo.sh
|
|
```
|
|
|
|
Am ibo-Client in Zitadel (`https://auth.momentrum.de`) die Redirect-URI
|
|
registrieren: `https://sso.ibo.momentrum.de/oauth2/callback`
|
|
(Post-Logout optional: `https://sso.ibo.momentrum.de`).
|
|
|
|
- **dev (Previews)** laufen weiter hinter dem **geteilten** `dev-sso`
|
|
(Client-Secret `oauth2-proxy-dev`). Dessen Redirect
|
|
`https://sso.dev.momentrum.de/oauth2/callback` existiert i. d. R. schon
|
|
(kanban/luxly nutzen es) — nichts zu tun.
|
|
|
|
---
|
|
|
|
## 2. Cluster-Voraussetzungen (contabo-infra) — muessen laufen
|
|
|
|
Fuer **prod** (`platform/manifests/ibo-sso/`, ArgoCD-App `platform/apps/ibo-sso.yaml`):
|
|
- oauth2-proxy `ibo-sso` (Deployment/Service, ns `iam`).
|
|
- Middlewares `iam-oauth2-ibo-auth@kubernetescrd` / `iam-oauth2-ibo-errors@kubernetescrd`.
|
|
- Ingress `sso.ibo.momentrum.de` (Login-Host, ohne Auth davor).
|
|
- **Geteilte** stripPrefix-Middleware `iam-strip-novnc@kubernetescrd` (`strip-novnc.yaml`)
|
|
— die Previews referenzieren sie cross-namespace (s. §4).
|
|
|
|
Fuer **dev/Previews** (bereits vorhanden, von kanban/luxly geteilt):
|
|
- `dev-sso` (generischer oauth2-proxy `*.dev.momentrum.de`, Middlewares
|
|
`iam-oauth2-auth`/`iam-oauth2-errors`, Login `sso.dev.momentrum.de`).
|
|
- SealedSecret `gitea-appset-token` (ns `argocd`) — Gitea-Read fuer den PR-Generator.
|
|
- AppProject `previews` — erlaubt Source `momentrum/*` (deckt ibo ab) und
|
|
begrenzt Previews auf `preview-*`-Namespaces. **Blockt bewusst
|
|
traefik.io/Middleware im Preview-ns** → deshalb die geteilte `strip-novnc` in §2.
|
|
|
|
App-of-Apps nimmt `ibo-sso.yaml` automatisch auf — committen & pushen genuegt;
|
|
alternativ einmalig `kubectl apply -f platform/manifests/ibo-sso/`. Das ibo-Repo
|
|
ist in `platform/manifests/argocd-projects/internal.yaml` (sourceRepos) bereits
|
|
erlaubt (sonst lehnt ArgoCD die prod-App-Source ab).
|
|
|
|
---
|
|
|
|
## 3. DNS
|
|
|
|
A/AAAA-Records auf die Cluster-Ingress-IP:
|
|
- `ibo.momentrum.de` (prod)
|
|
- `sso.ibo.momentrum.de` (prod-Login)
|
|
|
|
Previews brauchen **keinen eigenen Record** — sie laufen unter dem bestehenden
|
|
Wildcard `*.dev.momentrum.de` (wie kanban/luxly). cert-manager
|
|
(`letsencrypt-prod`, HTTP-01) stellt `ibo-tls`, `ibo-sso-tls` und die per-Preview-
|
|
Certs (`ibo-pr-<nr>-tls`) automatisch aus, sobald DNS/Ingress stehen.
|
|
|
|
---
|
|
|
|
## 4. CD-Apps im `momentrum-deploy` (bereits angelegt)
|
|
|
|
- `apps/internal/ibo/app.yaml` — prod-Application (`ibo.momentrum.de`,
|
|
ns `apps-internal`, SSO `iam-oauth2-ibo-*`). Auto-Sync; `image.tag` bumpt die CI.
|
|
- `apps/internal/ibo/preview.yaml` — PR-Preview-ApplicationSet (Gitea-PR-Generator,
|
|
Label-Gate `preview`). Rendert ibos Chart aus dem **PR-Branch** und setzt pro PR:
|
|
Host `ibo-pr-<nr>.dev.momentrum.de`, `priorityClassName: preview`, gedeckelte
|
|
Resources (preview-ns-Quota: ≤2 CPU / 1536Mi Limits gesamt),
|
|
`ssoMiddlewares: iam-oauth2-errors,iam-oauth2-auth` (dev-sso) und
|
|
`novncStripPrefixRef: iam-strip-novnc@kubernetescrd` (statt eigener Middleware).
|
|
|
|
committen & pushen → ArgoCD legt die prod-App + das ApplicationSet an.
|
|
|
|
---
|
|
|
|
## 5. Deploy-Flows
|
|
|
|
**dev / Preview (pro PR):**
|
|
1. PR gegen `main` oeffnen → CI baut `pr-<nr>-<sha7>` (Job build-push).
|
|
2. Am PR das Gitea-Label **`preview`** setzen (Opt-in-Gate = Concurrency-Deckel).
|
|
3. ArgoCD-ApplicationSet (Polling 120 s) legt `ibo-pr-<nr>` + ns
|
|
`preview-ibo-pr-<nr>` an → `https://ibo-pr-<nr>.dev.momentrum.de`.
|
|
4. PR schliessen/mergen oder Label entfernen → Application + Namespace kaskadieren
|
|
weg (finalizer + gemanagter Namespace, KEIN CreateNamespace).
|
|
|
|
**prod (bei main-Merge):**
|
|
- CI-Job `deploy` schreibt den neuen `image.tag` in `apps/internal/ibo/app.yaml`
|
|
zurueck → ArgoCD synct prod automatisch. Kein manueller Schritt.
|
|
- **Rollback:** `git revert` des CI-Commits im `momentrum-deploy` (ArgoCD synct
|
|
zurueck). Alternativ `image.tag` in `app.yaml` auf einen aelteren Tag setzen.
|
|
|
|
> Wer prod bewusst manuell freigeben will statt Auto-Deploy: den `deploy`-Job in
|
|
> `.gitea/workflows/momentrum-ci.yml` entfernen und den Tag per Hand nach
|
|
> `app.yaml` committen. Aktuell ist Auto-Deploy aktiv (wie kanban).
|
|
|
|
---
|
|
|
|
## 6. Browser-Live-Ansicht (noVNC)
|
|
|
|
Der Automations-Chrome laeuft im `selenium`-Sidecar; sein Bild wird per noVNC
|
|
gestreamt und in der Web-App eingebettet (Button „👁️ Browser live ansehen").
|
|
Routing:
|
|
|
|
- App-Container → Chrome via `SELENIUM_REMOTE_URL=http://localhost:4444`.
|
|
- Client-Browser → `https://<host>/novnc/…` → Ingress-Pfad `/novnc`
|
|
→ stripPrefix-Middleware → Sidecar-Port 7900 (noVNC/websockify).
|
|
- prod: chart-eigene Middleware `<ns>-ibo-novnc` (App-ns).
|
|
- Preview: geteilte `iam-strip-novnc` (weil das `previews`-Project eigene
|
|
Middlewares im Preview-ns blockt).
|
|
- Zugriff durch die SSO-Cookie (gleicher Host, gleiche Middleware-Kette).
|
|
|
|
Der Browser laeuft **serverseitig** im Container — es wird NICHT der lokale
|
|
Browser des Nutzers ferngesteuert.
|
|
|
|
---
|
|
|
|
## 7. Break-glass (Notzugang)
|
|
|
|
Faellt Zitadel aus: die SSO-Middlewares temporaer aus `ingress.ssoMiddlewares`
|
|
in `apps/internal/ibo/app.yaml` (prod) entfernen (die App selbst hat keine eigene
|
|
Auth → sie ist dann OFFEN). Nur kurz, danach sofort zuruecksetzen. Nie
|
|
ungeschuetzt lassen.
|
|
|
|
---
|
|
|
|
## 8. Verifikationscheckliste
|
|
|
|
- [ ] `docker compose up -d` lokal → `http://localhost:5000` UI, „Browser live
|
|
ansehen" zeigt den Chrome im iframe (localhost:7900).
|
|
- [ ] `curl -s localhost:5000/healthz` → `{"ok":true}`.
|
|
- [ ] PR + Label `preview` → CI gruen (version→test→build-push→helm-validate),
|
|
ArgoCD legt `ibo-pr-<nr>` an, `https://ibo-pr-<nr>.dev.momentrum.de`
|
|
redirected zu `auth.momentrum.de`, nach Login landet man in der App.
|
|
- [ ] Im Preview eingebettetes `/novnc/` zeigt den Live-Browser.
|
|
- [ ] PR schliessen → Preview + Namespace verschwinden (ArgoCD prune).
|
|
- [ ] main-Merge → CI-Job `deploy` bumpt `app.yaml`, ArgoCD rollt prod,
|
|
`https://ibo.momentrum.de` hinter Zitadel erreichbar.
|
|
- [ ] Ohne SSO-Session → Login-Redirect (kein rohes 401).
|