07 deployment view - smart-village-solutions/sva-studio GitHub Wiki
Dieser Abschnitt beschreibt die technische Verteilung auf Umgebungen und Laufzeitknoten auf Basis des aktuellen Repos.
- Deployment-Topologie (lokal, CI, staging, production)
- Abhängigkeiten zu externen Diensten (z. B. Redis, OTEL, Loki)
- Sicherheits- und Betriebsaspekte je Umgebung
- App:
pnpm nx run sva-studio-react:serveauflocalhost:3000 - Postgres IAM-DB:
docker-compose.yml(5432) - Redis:
docker-compose.yml(6379, optional TLS6380) - Monitoring Stack:
docker-compose.monitoring.yml- Collector:
4317,4318,13133 - Loki:
3100 - Prometheus:
9090 - Grafana:
3001 - Promtail:
3101 - Alertmanager:
9093 - Redis Exporter:
9121(für Redis-/Permission-Cache-Metriken im Zielbild)
- Collector:
- Web-App Runtime (TanStack Start / Node)
- Nx-/pnpm-basierte Build- und Test-Pipeline
- Separates IAM-Acceptance-Gate für Paket-1-/2-Abnahmen
- Externe Plattform (GitHub Actions) für CI-Ausführung
- Keycloak als zentraler OIDC Identity Provider
- Redis Session Store
- Redis Permission Snapshot Cache als primärer Shared-Read-Path für effektive IAM-Berechtigungen
- Postgres IAM Core Data Layer
- OTEL Collector als Telemetrie-Hub
- Loki/Prometheus als Storage, Grafana für Auswertung
-
redis-exporterals Prometheus-Scrape-Target für Redis-Infrastrukturmetriken
Hinweis: Der ursprüngliche, nicht-Swarm-basierte Portainer-Stack ist durch das Swarm-Referenz-Betriebsprofil ersetzt. Die folgenden Abschnitte beschreiben den aktuellen Stand.
Für den serverbasierten Betrieb ist ein Docker-Swarm-Stack mit Traefik als Ingress-Proxy definiert:
- Compose-Datei:
deploy/portainer/docker-compose.yml - Services:
app,postgres,redis,otel-collector,loki,prometheus,grafana,promtail,alertmanager - Monitoring bleibt intern auf dem Overlay-Netzwerk; nur die App hängt zusätzlich am
public-Netzwerk
Internet
│
▼
Traefik (Ingress, TLS, HostRegexp-Routing)
│ Overlay-Netzwerk „public"
▼
┌──────────────────────────────────────────────────────────────┐
│ Swarm-Stack „sva-studio" │
│ │
│ app ←──── internes Overlay ────→ redis │
│ │ │ │
│ ├──── internes Overlay ────→ postgres │ │
│ │ │ │
│ └──── internes Overlay ────→ otel-collector ──→ Loki │
│ │ │ │
│ └──────→ Prometheus │
│ │ │
│ Grafana + Alerting │
│ Promtail (Node-Logs)│
└──────────────────────────────────────────────────────────────┘
Neben dem Referenzprofil mit Docker Swarm Secrets existiert ein vereinfachtes
Demo-Profil (deploy/portainer/docker-compose.demo.yml) für Evaluierungs-
und Vorführungszwecke. Unterschiede zum Referenzprofil:
- Secrets werden als Umgebungsvariablen statt Docker Swarm Secrets übergeben
- Konfiguration über
deploy/portainer/.env.demo.example - Quantum-CLI-Unterstützung über
.quantum-Datei im Repository-Root - Traefik-v1-kompatible Labels statt der v2+-Router-Labels des Referenzprofils
- Nicht für Produktionseinsatz vorgesehen
-
Der Build-Graph des Portainer-Images baut
sva-mainserverexplizit nachauthund vorroutingsowie dem App-Build, damit die serverseitige Integrationsschicht im Deploy-Artefakt verlässlich vorhanden ist. -
Image-basiert: Vorgebaute Images aus Container-Registry; für die App ist im Acceptance-Referenzpfad
SVA_IMAGE_REFmit Digest verpflichtend, der Tag bleibt nur Metadatum. Keinbuild:-Block im Stack. -
Traefik-Labels: Host-basiertes Routing über
HostRegexpfür Instanz-Subdomains unterSVA_PARENT_DOMAIN. TLS über Traefikscertresolver. -
Profilgrenze Traefik: Das Referenzprofil verwendet Traefik v2+-Labels; das Demo-Profil bleibt bewusst bei Traefik-v1-kompatiblen Labels und ist deshalb kein 1:1-Abbild des Referenzbetriebs.
-
Swarm Secrets: Vertrauliche Werte als externe Docker-Swarm-Secrets mit Namenskonvention
sva_studio_<service>_<secret_name>. Ein Shell-Entrypoint (entrypoint.sh) liest Secret-Dateien und exportiert sie als Env-Variablen. -
Versionierte Monitoring-Konfigurationen: Prometheus-, Loki-, Grafana-, Promtail- und Alertmanager-Konfigurationen liegen versioniert im Repository und werden über ein dediziertes
monitoring-config-init-Image einmalig in die Swarm-Volumes geschrieben. -
Rolling Updates:
start-firstfür Updates,stop-firstfür Rollbacks. -
Kanonischer Studio-Releasepfad:
studionutzt den geteilten PfadFinal Runtime Artifact Verify -> Studio Image Build and Publish -> Studio Image Verify -> lokaler Operator-Deploymitruntime-artifact-verify -> environment-precheck -> image-smoke -> optional migrate-job -> optional bootstrap-job -> deploy -> internal-verify -> external-smoke -> release-decision -> Deploy-Report. -
Finales Runtime-Artefakt als Release-Wahrheit: Vor jedem Image-Build prueft der CI-Pfad den gebauten Node-Output
apps/sva-studio-react/.output/server/**direkt. Intermediate-SSR-Artefakte unter.nitro/vite/services/ssr/**sind nur Diagnosematerial und kein Freigabenachweis. -
Release-Gate-Bündel:
pnpm test:release:studioverbindet das normale PR-Gate mitverify:runtime-artifact;test:prbleibt bewusst leichter und enthält den Runtime-Verify nicht. -
Image-Verify-Evidenz:
env:precheck:studioweist fuer den Ziel-Digest aus, ob unterartifacts/runtime/image-verify/ein erfolgreiches Studio-Image-Verify-Artefakt vorhanden ist. -
Release-Klassen: Studio-Deploys unterscheiden
app-onlyundschema-and-app; nurschema-and-appdarf Migrationen auslösen. -
Gepinnter Goose-Pfad: Schema-Rollouts laufen über einen repository-lokalen
goose-Wrapper mit fixer Version innerhalb eines dedizierten Swarm-One-off-Jobs; Zielsysteme benötigen keine permanentegoose-Vorinstallation. -
Dedizierte Job-Services: Die Stack-Compose-Dateien führen zusätzlich die Services
migrateundbootstrapmitreplicas: 0. Remote-Deploys rendern daraus ein temporäres Quantum-Projekt, das genau den benoetigten One-off-Job gegen das bestehende Overlay-Netz<stack>_internalstartet. -
Gehärteter Live-Render: Der für
quantum-cli stacks updateerzeugte Deploy-Render validiert vor dem Rollout die vollständigeapp-Service-Spec. Pflicht sind mindestens die Netzwerkeinternalundpublicsowie die ingressrelevanten Traefik-Labels. -
Prod-nahe Paritaet vor Mutationen: Vor mutierenden
studio-Rollouts prueftimage-smokeRoot-Host, Tenant-Hosts und OIDC-Verhalten gegen das Zielartefakt. Wenn dasselbe Digest bereits live laeuft, ist nur eine dokumentierte Live-Paritaets-Wiederverwendung fuer genau dieses Digest zulaessig. -
Strikte Stack-Trennung: Temp-Job-Stacks für
migrateundbootstrapenthalten keinenapp-Service und dürfen keine Live-Service-Spec des eigentlichen Stacks ableiten oder überschreiben. -
Deploy-Evidenz: Jeder Studio-Deploy schreibt JSON- und Markdown-Artefakte unter
artifacts/runtime/deployments/mit Image-, Actor-, Workflow-, Stack- und Verifikationsdaten. -
Health-Modell:
livebleibt prozessnah und ohne schwere optionale Abhängigkeiten;readybildet nur minimale Traffic-Voraussetzungen ab; öffentliche Freigabe erfolgt erst über externe Smoke-Probes. -
Recovery-Patch ist Legacy:
deploy/portainer/entrypoint.shdarf Build-Artefakte nur noch unter explizitem Recovery-FlagSVA_ENABLE_RUNTIME_RECOVERY_PATCH=1umschreiben. Der Standardbetrieb nutzt den finalen Build-Output unverändert. -
App-Principal als Betriebsvertrag:
precheck,doctorund Post-Deploy-Verifikation muessen Registry-, Auth- und RLS-relevante Readiness aus Sicht des laufendenAPP_DB_USERbestaetigen. Eine rein administrative DB-Sicht reicht nicht als Freigabe. -
Persistenz: Named Volumes für Postgres, Redis, Prometheus, Loki, Grafana und Alertmanager.
-
Monitoring-Bootstrap: Der Node-Prozess lädt OpenTelemetry vor dem Nitro-Entry per
--import, statt erst beim ersten Root-Request. -
Ressourcenprofile: Das Referenzprofil setzt CPU-Limits für App, Datenbank und Monitoring-Services, damit der Stack auf kleinen Swarm-Nodes kontrolliert bleibt.
-
Redis-Keyspaces: Session-/Login-State und Permission-Snapshots teilen sich höchstens die Infrastruktur, werden aber fachlich getrennt behandelt (
session:*vs.perm:v1:*). -
Eviction-Policy: Für den Permission-Snapshot-Keyspace ist
allkeys-lruverbindlich; wenn Session- und Snapshot-Keys dieselbe Redis-Instanz nutzen, muss das Betriebsprofil Evictions getrennt überwachen oder die Keyspaces logisch/physisch separieren.
-
<instanceId>.<SVA_PARENT_DOMAIN>→ Instanz-Kontext - Root-Domain (
SVA_PARENT_DOMAIN) → Kanonischer Auth-Host - Registry-basierte Freigabe in Postgres als autoritative Quelle
- Env-basierte Allowlist (
SVA_ALLOWED_INSTANCE_IDS) nur noch als lokaler oder migrationsbezogener Kompatibilitätspfad - Startup-Validierung gegen
instanceId-Regex bleibt für Kompatibilitätsprofile aktiv
Im Swarm-Stack sind keine automatischen Initialisierungsskripte enthalten. Die DB-Einrichtung bleibt ein bewusster Betriebsschritt und wird fuer studio ueber den offiziellen env:migrate:studio-/env:release:studio:local-Pfad mit dediziertem Swarm-Migrationsjob und nachgelagertem Bootstrap-Job statt ueber ad-hoc SQL, quantum-cli exec-Streaming oder implizite Redeploys gesteuert. Details im Swarm-Deployment-Runbook.
Betriebliche Einordnung:
- App läuft als Node-/Nitro-Server aus dem TanStack-Start-Build.
- Für spätere Updates bestehender Datenbanken bleiben Migrationen ein bewusster separater Betriebsschritt.
- Der kanonische Migrationspfad nutzt ein einzelnes
goose-SQL-File pro Version mitUpundDown; ein getrennterup/down-Dateibaum ist kein Sollzustand mehr. - Ein reiner Job-Lauf für
migrateoderbootstrapdarf keinen vollständigen Stack-Reconcile aufsva-studio_appauslösen; der Live-Stack wird erst im explizitendeploy-Schritt aktualisiert.
- Der Live-Precheck vergleicht den gerenderten Sollzustand der
app-Service-Spec mit der Remote-Spec aus Portainer-/Swarm-Daten. - Read-only Runtime-Diagnostik fuer
status,doctorundprechecknutzt bevorzugt die Portainer-API mit fester Endpoint-ID statt lokalemquantum-cli-Kontext. - Drift wird nicht nur über Image-Referenz und Env-Schlüssel bewertet, sondern auch über Netzwerknamen und ingressrelevante Traefik-Labels.
- Der Fehlerzustand
app 1/1, aber externer502, gilt als eigener Ingress-/Netz-Drift-Fall und nicht als unscharfer generischer Verify-Fehler. - Die Vertragsgrenze zwischen lokalem Development und
studiobleibt hart: lokale Docker-Kandidaten koennen Private-DNS-, Swarm- und Ingress-Vertraege nur teilweise abbilden und sind deshalb kein alleiniger Freigabenachweis. - Der kanonische Recovery-Pfad lautet:
- Ziel-Digest, Render-Compose und Live-Service-Spec verifizieren.
- Kontrollierten
app-only-Reconcile gegen denselben Ziel-Digest ausführen. - Danach
status,smokeundprecheckerneut pruefen. - Direkte Portainer-API-Eingriffe bleiben Incident-Recovery und sind kein Standardweg.
Referenzen:
deploy/portainer/docker-compose.ymldeploy/portainer/entrypoint.shdocs/guides/swarm-deployment-runbook.mddocs/guides/swarm-deployment-guide.mddocs/adr/ADR-019-swarm-traefik-referenz-betriebsprofil.mddocs/adr/ADR-020-kanonischer-auth-host-multi-host-grenze.md
- Monitoring-Ports in Compose explizit auf
127.0.0.1gebunden - Redis TLS-Unterstützung vorhanden, in local Dev optional
- Postgres mit Healthcheck (
pg_isready) und separatem Volume - Healthchecks für zentrale Monitoring-Services konfiguriert
- Graceful OTEL Shutdown im SDK vorgesehen
-
/health/readybewertet den Authorization-Cache separat überchecks.authorizationCachemit den Zuständenready,degradedundfailed -
degradedgilt für den Permission-Cache bei Redis-Latenz >50 msoder Recompute-Rate >20/min;failedbei drei aufeinanderfolgenden Redis-Fehlern - Session-Ausfälle und Permission-Cache-Ausfälle werden operativ getrennt behandelt: Session-Wiederherstellung folgt dem Plattform-RTO, Snapshots sind flüchtig und werden aus Postgres rekonstruiert
- Keycloak wird aktuell als externer Dienst angebunden (nicht über Repo-Compose provisioniert)
- Das IAM-Acceptance-Gate läuft gegen eine bereits vorhandene Testumgebung und startet keine eigene Keycloak-Topologie im Workflow.
- Swarm-Stack: Secrets als externe Swarm-Secrets, nicht als Klartext-Env-Variablen
- Swarm-Stack: Entrypoint-basierte Secret-Injektion, abwärtskompatibel mit Nicht-Swarm-Betrieb
- Swarm-Stack: Host-Validierung gegen Registry-Status mit fail-closed-Policy (identische 403-Antwort)
- Swarm-Stack: Root-Host rendert die globale Instanzverwaltung, Tenant-Hosts nicht
- Swarm-Stack: Monitoring-UI und Storage bleiben intern; keine öffentliche Exponierung ohne zusätzliche Zugangskontrolle
- Swarm-Stack:
monitoring-config-initist ein One-shot-Initialisierer und soll nach erfolgreicher Volume-Befüllung beendet sein - Swarm-Stack:
postgres-schema-bootstrapist nur noch ein Legacy-Übergangspfad; der regulaere Schemarollout erfolgt ueberpnpm env:migrate:studiobzw.pnpm env:release:studio:local -- --release-mode=schema-and-appmitmigrate- undbootstrap-Job - Operative Zielwerte für das Referenzprofil:
RTO <= 2hfür App/Monitoring und Session-Store,RTO <= 15 minfür den rekonstruierbaren Permission-Cache,RPO <= 24hfür IAM-Daten in Postgres - Primäre betriebliche Eskalation via
[email protected], Sicherheits-/DSGVO-Eskalation via[email protected]
- HA-/Skalierungsdetails für produktiven Betrieb sind nur teilweise als ADR/Doku beschrieben
- Sichere externe Erreichbarkeit für Grafana oder alternative interne Zugriffswege sind noch kein Teil des Referenzprofils
- Redis-L2-Cache für Registry-Lookups ist Folgearbeit
Referenzen:
-
docker-compose.yml(lokale Entwicklung) docker-compose.monitoring.yml-
deploy/portainer/docker-compose.yml(Swarm-Referenzprofil) docs/development/postgres-setup.mddocs/guides/swarm-deployment-runbook.mddocs/guides/instance-registry-local-development.mdpackages/sdk/src/server/bootstrap.server.ts
Für den produktiven Betrieb der Account-/Admin-UI sind zusätzlich erforderlich:
- Keycloak Service-Account
sva-studio-iam-servicemit Minimalrechten (manage-users,view-users,view-realm,manage-realm). - Secret-Injektion für
KEYCLOAK_ADMIN_CLIENT_SECRETüber Secrets-Manager (nicht im Repository). - Feature-Flags auf Backend-Seite:
IAM_UI_ENABLEDIAM_ADMIN_ENABLEDIAM_BULK_ENABLED
- Scheduler-Konfiguration für Rollen-Reconciliation:
IAM_ROLE_RECONCILE_INTERVAL_MSIAM_ROLE_RECONCILE_INSTANCE_IDS
- Optional korrespondierende Frontend-Flags:
VITE_IAM_UI_ENABLEDVITE_IAM_ADMIN_ENABLEDVITE_IAM_BULK_ENABLED
Rollout-Reihenfolge:
- Datenbankmigrationen (
0004bis0007) ausrollen. - Keycloak-Service-Account inklusive
manage-realmprüfen und Secret-Injektion verifizieren. - Backend mit Keycloak-Admin-Credentials deployen.
- Feature-Flags initial auf
falseverifizieren (Kill-Switch). - Stufenweise aktivieren: UI -> Admin -> Bulk.
- Geplanten Reconcile-Lauf aktivieren und Alerting gegen Drift-Backlog prüfen.
- Separates IAM-Acceptance-Gate gegen die Zielumgebung ausführen und Bericht unter
docs/reports/archivieren.