Jitsi Meet Helm Chart

repository·main·Indexed 41 days ago

https://github.com/jitsi-contrib/jitsi-helm

A Helm chart to bootstrap and manage a complete Jitsi Meet stack on Kubernetes, including components such as JVB, Jibri, and Prosody. It provides comprehensive guides for exposing JVB media via LoadBalancer, NodePort, hostPort, and hostNetwork, as well as configurations for recording, streaming, and near real-time transcription using opus-transcriber-proxy.

Tokens
12K
Snippets
39
Records
61
Agent score
50%

What's inside Jitsi Helm

  1. Enable near real-time transcription

    main

    The chart supports bridge-based near real-time transcription (subtitles).

    How it works:

    1. Jicofo instructs JVB which transcription service to use for a conference.
    2. JVB streams audio to opus-transcriber-proxy.
    3. The proxy relays audio to a speech-to-text provider (OpenAI, Deepgram, Gemini) or a custom OpenAI-compatible service.

    Setup requirements:

    • Set opusTranscriberProxy.enabled to true.
    • Manual Step: You must manually enable the force_async_transcription Prosody module; the chart does not enable this automatically.
  2. Scale JVB using portRangeSize

    main

    The JVB (Jitsi Videobridge) scaling mechanism has been updated. You can now use jvb.portRangeSize to run multiple JVBs behind a single Service. Each JVB will receive its own unique port, and the Service will publish all of them.

    Important Constraints:

    • Naming: The JVB UDP container port is now named rtp-udp-0 (previously rtp-udp). Update any NetworkPolicies that use named ports.
    • Replica Conflict: If you set jvb.replicaCount greater than 1 while the JVB Service is enabled, the Helm render will fail. To run multiple JVBs, you must use portRangeSize instead of increasing replicaCount (unless using useHostPort).
    • NodePort: If using a NodePort Service, ensure nodePort is set equal to UDPPort so advertised and reachable ports match.
  3. Handle privileged ports in non-root containers

    main

    Non-root containers cannot bind to ports below 1024. To accommodate this, the chart listens on unprivileged ports inside the container and uses a Kubernetes Service to map public ports to them (e.g., web listens on 8000, and coTURN listens on 3478 behind a Service on 443).

    If you use hostNetwork: true or hostPort, the Service translation is bypassed. In such cases, if you need to bind to a public port below 1024, you must set runAsUser: 0 for that component.

  4. Understand Jitsi Meet security hardening defaults

    main

    Since stable-11146 images, all Jitsi components run as a non-root user with a read-only root filesystem by default. The chart applies a strict securityContext to hardened components to satisfy the Kubernetes Pod Security Admission restricted profile.

    Hardened components include:

    • web, prosody, jicofo, jvb, jigasi, transcriber, jibri (and their init containers)
    • coturn (including init-coturn and acme-proxy init containers)
    • Metrics sidecars (prosody, jicofo, jvb)

    Default Security Configuration: Containers are configured with runAsUser: 1000, runAsGroup: 1000, readOnlyRootFilesystem: true, and all capabilities dropped. They can only write to specific mounted paths like /run and /tmp. The jvb metrics sidecar is an exception, using UID 10001.

    Note: Third-party images like Etherpad, Excalidraw, Skynet, and the Opus transcriber proxy do not satisfy the restricted profile by default and require manual configuration via their own securityContext values.

    podSecurityContext:
      fsGroup: 1000
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop:
          - ALL
      privileged: false
      readOnlyRootFilesystem: true
      runAsGroup: 1000
      runAsNonRoot: true
      runAsUser: 1000
      seccompProfile:
        type: RuntimeDefault
  5. Deprecated: Jigasi-based transcription

    main

    Jigasi-based transcription (used by Transcriber and Skynet) is deprecated and will be removed in a future release.

    Recommendation: New deployments should use the bridge-based path via opusTranscriberProxy. Existing setups will continue to work for now, but you should plan a migration to the new path.

  6. Scale Jitsi Meet installation

    main

    Scaling strategies differ based on the component:

    • Stateless Components: Jitsi Web, Jibri, and Coturn can be scaled freely by adjusting their replicaCount.
    • JVB (Videobridge): Scales via the OCTO relay feature, which distributes participants of a single meeting across multiple bridges. JVB can also scale based on load and supports 'draining' to ensure existing calls are not dropped when a bridge is removed.
  7. Understand Chart version vs appVersion

    main

    The Chart.yaml file contains two distinct versioning fields that affect how images are pulled:

    1. version: The version of the Helm chart itself. This is incremented whenever the chart code changes.
    2. appVersion: The default image tag used for core Jitsi components (web, prosody, jvb, jicofo, jigasi, jibri) if you have not explicitly set an image.tag in your values.yaml.

    Note: Third-party components (like coturn, etherpad, excalidraw, or Skynet) are pinned to their own specific image.tag in values.yaml and are independent of the appVersion field.

  8. Expose Jitsi Meet JVB media

    main

    The Jitsi Videobridge (JVB) must be reachable by all participants, typically via a public IP. The Helm chart supports several methods for exposing JVB:

    • LoadBalancer
    • NodePort
    • hostPort (supports auto-detected node IP and port ranges)
    • hostNetwork
    • Ingress TCP/UDP forwarding

    Refer to the detailed Exposing guide for specific configuration examples for each method.

  9. Requirements for custom AI services with opus-transcriber-proxy

    main

    When using the openai_custom provider in opus-transcriber-proxy, your service must implement the OpenAI Realtime API over WebSocket.

    Key requirements:

    • Protocol: It must support WebSocket-based Realtime API. A standard OpenAI-compatible REST API (like /v1/chat/completions) is not sufficient.
    • Authentication: The proxy does not send an Authorization: Bearer header. Instead, it passes the credential during the WebSocket handshake. Your service must be prepared to accept the key in that format.
    • Audio Format: The proxy decodes Opus audio from the JVB and sends a Realtime session to your service.
    • URL Handling: The proxy uses the openaiCustomUrl provided in the configuration verbatim, including any paths or query parameters.
    • Security: By default, the proxy requires the wss:// scheme. If your service uses plain ws:// (e.g., inside a cluster), you must set OPENAI_CUSTOM_REQUIRE_WSS: "false".
  10. Expose JVB using a NodePort service

    main

    Use this option to expose JVB via a specific port on your cluster nodes or through an external LoadBalancer pointing to the nodes.

    Configuration Rules:

    • jvb.replicaCount must remain at 1 unless using jvb.portRangeSize.
    • If using jvb.portRangeSize > 1, you must set both jvb.UDPPort and jvb.nodePort to the same base value. This ensures the advertised port and the node port match for the consecutive range.
    • Every port in the range must be within the cluster's allowed NodePort range (default 30000-32767).
    # Single JVB instance
    jvb:
      service:
        type: NodePort
      publicIPs:
        - 30.10.10.1
    
    # Multiple JVB instances using a port range
    jvb:
      UDPPort: 32000
      nodePort: 32000
      portRangeSize: 3
      service:
        type: NodePort
      publicIPs:
        - 30.10.10.1
  11. Scale JVB behind a LoadBalancer service

    main

    If you prefer to keep the JVB service enabled (e.g., using type: LoadBalancer), you cannot use replicaCount because all pods in a deployment would share the same service port. Instead, use portRangeSize. This configuration deploys one JVB per port within a specified range, and the service publishes all of them.

    Example for 3 JVBs listening on 10000/UDP, 10001/UDP, and 10002/UDP:

    jvb:
      # 3 JVBs, listening on 10000/UDP, 10001/UDP and 10002/UDP
      UDPPort: 10000
      portRangeSize: 3
    
      service:
        type: LoadBalancer
    
    octo:
      enabled: true
  12. Add custom Prosody plugins via ConfigMap mounts

    main

    To extend your Jitsi Meet installation with additional Prosody features, you can mount custom Lua modules using extraVolumes and extraVolumeMounts in your Helm chart configuration. This allows you to inject specific .lua files from a ConfigMap into the Prosody container's file system.

    Note: If you are looking for plugins from the jitsi-contrib/prosody-plugins repository, they are already included in the official ghcr.io/jitsi/prosody container and do not need to be added manually.

    prosody:
      extraVolumes:
        - name: prosody-modules
          configMap:
            name: prosody-modules
    
      extraVolumeMounts:
        - name: prosody-modules
          subPath: mod_measure_client_presence.lua
          mountPath: /prosody-plugins-custom/mod_measure_client_presence.lua