# 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-.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: Redirect-URIs (KEIN neuer Client) `ibo-sso` und `dev-sso` nutzen — wie `luxly-sso` — den **bestehenden geteilten** Zitadel-Client (K8s-Secret `oauth2-proxy-dev` in ns `iam`). **Kein neuer Client, kein neues Secret.** Nur am vorhandenen Client (`https://auth.momentrum.de`) die Redirect-URI ergaenzen: - prod: `https://sso.ibo.momentrum.de/oauth2/callback` ← nur diese ist ibo-spezifisch - dev (Previews): `https://sso.dev.momentrum.de/oauth2/callback` ← existiert i. d. R. schon (kanban/luxly-Previews nutzen dasselbe dev-sso). Nichts zu tun, falls vorhanden. --- ## 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--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-.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--` (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-` + ns `preview-ibo-pr-` an → `https://ibo-pr-.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:///novnc/…` → Ingress-Pfad `/novnc` → stripPrefix-Middleware → Sidecar-Port 7900 (noVNC/websockify). - prod: chart-eigene Middleware `-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-` an, `https://ibo-pr-.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).