# jitsi-meet — Projekt-Kontext für Claude-Sessions Selbst-gehostete Jitsi-Meet-Instanz auf darkemberserver via k3s. Same-Cluster-Deploy wie Embertime/Gitea/Headscale. Repo unter `~/Developer/jitsi-meet/`, Public-URL `https://meet.it.financeflow.de`. Zweck: privater Online-Meeting-Service ohne Google-/GitHub-Login-Zwang (das öffentliche meet.jit.si verlangt seit 2024/25 Moderator-Auth). Wird unter anderem von Embertime als Default-Meeting-URL referenziert. ## Architektur Vier Container nach offiziellem `jitsi/docker-jitsi-meet`-Pattern: - **web** (`jitsi/web`): Nginx + Meet-Frontend, exposed via Ingress :443 - **prosody** (`jitsi/prosody`): XMPP-Server, cluster-intern - **jicofo** (`jitsi/jicofo`): Focus/Conference-Manager, cluster-intern - **jvb** (`jitsi/jvb`): Videobridge — `hostNetwork: true` damit UDP **10001** direkt auf Node-Interface bindet. UDP 10000 ist auf darkember bereits von einer OpenDesk-Bundle-Jitsi-Instanz belegt (`opendesk/jitsi-jvb` LoadBalancer-Service), daher Shift auf 10001. Inter-Component-Auth über shared XMPP-Component-Secrets (im Kubernetes-Secret, nicht im Repo). ## Wichtigste Dateien - `infra/k3s/00-namespace.yaml` — Namespace `jitsi` - `infra/k3s/10-config.yaml` — ConfigMap mit nicht-sensiblen Env-Vars (XMPP-Domains, PUBLIC_URL, ...) - `infra/k3s/20-secrets.yaml.example` — Vorlage; **echte Secrets manuell erzeugen** via `scripts/generate-secrets.sh`, dann `kubectl apply -f infra/k3s/20-secrets.yaml` einmalig out-of-band - `infra/k3s/30-prosody.yaml`, `40-jicofo.yaml`, `50-web.yaml`, `60-jvb.yaml` — Component-Deployments + Services - `infra/k3s/70-ingress.yaml` — Ingress mit cert-manager (letsencrypt-prod ClusterIssuer) - `.gitea/workflows/deploy.yml` — `kubectl apply -f infra/k3s/...` auf Push nach main - `scripts/generate-secrets.sh` — generiert random Component-Passwords + schreibt `20-secrets.yaml` ## Setup-Schritte (einmalig) 1. **DNS**: A-Record `meet.it.financeflow.de` → öffentliche IP von darkemberserver 2. **Firewall/Router**: UDP-Port **10001** auf darkember-Node forwarden (kritisch! ohne das funktioniert nur Audio, kein Video). Hinweis: 10000 ist von OpenDesks Jitsi-Bundle belegt, daher der Versatz. 3. **Secrets generieren + applyen**: ```bash ./scripts/generate-secrets.sh > infra/k3s/20-secrets.yaml # DOCKER_HOST_ADDRESS in 60-jvb.yaml auf die Public-IP von darkember setzen kubectl apply -f infra/k3s/20-secrets.yaml ``` 4. **Gitea-Repo + Secret KUBECONFIG_B64**: Repo bei Gitea anlegen, KUBECONFIG_B64 als Repo-Secret hinterlegen (gleicher Wert wie bei Embertime), push. Danach: Pipeline rollt aus, in ~3 Min steht `https://meet.it.financeflow.de`. ## Auth-Modell (JWT, Stand 2026-05-11) Prosody ist auf **`AUTH_TYPE=jwt`** (HS256) konfiguriert — Joins ohne signiertes Token werden abgelehnt. Embertime ist der einzige Token-Issuer: - HMAC-Secret lebt in `app_settings.meeting_jwt_secret` (Embertime-DB) - Wird auch im k8s-Secret `jitsi-secrets` als `JWT_APP_SECRET` benötigt — beide müssen identisch sein - Embertime-Endpoint `GET /meetings/:id/join` mintet pro Teilnehmer + Meeting ein zeitlich begrenztes Token (gültig bis Meeting-Ende + 2h) - Token-Payload enthält `room` (= room_slug), `context.user` (Display-Name + email + moderator-Flag) Bei Secret-Rotation: neuer Wert über Embertime-Admin-UI sichtbar, dann `kubectl -n jitsi patch secret jitsi-secrets ...` + `kubectl -n jitsi rollout restart deployment` (sonst gilt noch der alte JWT_APP_SECRET in den laufenden Pods). ## Was NICHT machen - `ENABLE_AUTH=0` zurücksetzen — würde das ganze Auth-Modell unwirksam machen. Wenn du eine offene Instanz brauchst, lieber zweite Jitsi-Instanz auf anderem Subdomain. - Keinen Jibri (Recording) ohne expliziten Auftrag — braucht extra Pod mit Chrome + viel mehr Ressourcen - Kein Helm — bleibt beim raw-Manifest-Pattern wie Embertime - Nicht `replicas > 1` für prosody/jicofo — beide sind stateful Single-Instance - JVB skaliert prinzipiell horizontal, aber für ein Single-Cluster reicht 1 Replica ## Verwandt im Obsidian-Vault - `feedback_git_workflow.md` — Klone-Pfad, Gitea-SSH-Setup - Embertime-CLAUDE.md (`~/Developer/embertime/CLAUDE.md`) — gleicher Deploy-Pattern, gleiches KUBECONFIG-Secret