jitsi-meet/CLAUDE.md
Dennis Paradzinski 8e76a96668
All checks were successful
deploy / deploy (push) Successful in 4s
feat: switch Prosody to JWT auth (HS256, Embertime as issuer)
Replaces the anonymous-OK setup with JWT-gated joins. Only participants
that Embertime invited get a valid token — random URL-guessers can no
longer enter rooms even if they discover the slug.

- ConfigMap: ENABLE_AUTH=1 + AUTH_TYPE=jwt + JWT_APP_ID=embertime
- 20-secrets.yaml.example: JWT_APP_SECRET placeholder with docs
- CLAUDE.md: documents the new auth model + rotation flow

Pipeline rolls config out; the secret itself stays out-of-band — admin
copies it from Embertime UI (Settings → Meeting-Server) or queries the
embertime DB directly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:19:00 +02:00

4.2 KiB

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.ymlkubectl 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:
    ./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