diff --git a/charts/jitsi/Chart.yaml b/charts/jitsi/Chart.yaml new file mode 100644 index 0000000..e7bc500 --- /dev/null +++ b/charts/jitsi/Chart.yaml @@ -0,0 +1,26 @@ +apiVersion: v2 +name: jitsi-meet +description: Jitsi Meet packaged for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 1.4.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: stable-9457-2 + +dependencies: + - name: prosody + condition: prosody.enabled + version: 1.4.0 diff --git a/charts/jitsi/charts/prosody/.helmignore b/charts/jitsi/charts/prosody/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/jitsi/charts/prosody/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/jitsi/charts/prosody/Chart.yaml b/charts/jitsi/charts/prosody/Chart.yaml new file mode 100644 index 0000000..7710742 --- /dev/null +++ b/charts/jitsi/charts/prosody/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: prosody +description: Prosody XMPP server for Jitsi Meet on Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +version: 1.4.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. +appVersion: stable-9111 diff --git a/charts/jitsi/charts/prosody/files/jitsi-meet.cfg.lua b/charts/jitsi/charts/prosody/files/jitsi-meet.cfg.lua new file mode 100644 index 0000000..fb61546 --- /dev/null +++ b/charts/jitsi/charts/prosody/files/jitsi-meet.cfg.lua @@ -0,0 +1,453 @@ +{{ $ENABLE_AUTH := .Env.ENABLE_AUTH | default "0" | toBool -}} +{{ $ENABLE_VISITORS := .Env.ENABLE_VISITORS | default "0" | toBool -}} +{{ $AUTH_TYPE := .Env.AUTH_TYPE | default "internal" -}} +{{ $PROSODY_AUTH_TYPE := .Env.PROSODY_AUTH_TYPE | default $AUTH_TYPE -}} +{{ $ENABLE_GUEST_DOMAIN := and $ENABLE_AUTH (.Env.ENABLE_GUESTS | default "0" | toBool) -}} +{{ $ENABLE_RECORDING := .Env.ENABLE_RECORDING | default "0" | toBool -}} +{{ $JIBRI_XMPP_USER := .Env.JIBRI_XMPP_USER | default "jibri" -}} +{{ $JIGASI_XMPP_USER := .Env.JIGASI_XMPP_USER | default "jigasi" -}} +{{ $JVB_AUTH_USER := .Env.JVB_AUTH_USER | default "jvb" -}} +{{ $JWT_ASAP_KEYSERVER := .Env.JWT_ASAP_KEYSERVER | default "" -}} +{{ $JWT_ALLOW_EMPTY := .Env.JWT_ALLOW_EMPTY | default "0" | toBool -}} +{{ $JWT_AUTH_TYPE := .Env.JWT_AUTH_TYPE | default "token" -}} +{{ $JWT_ENABLE_DOMAIN_VERIFICATION := .Env.JWT_ENABLE_DOMAIN_VERIFICATION | default "false" | toBool -}} +{{ $MATRIX_UVS_ISSUER := .Env.MATRIX_UVS_ISSUER | default "issuer" -}} +{{ $MATRIX_UVS_SYNC_POWER_LEVELS := .Env.MATRIX_UVS_SYNC_POWER_LEVELS | default "0" | toBool -}} +{{ $JWT_TOKEN_AUTH_MODULE := .Env.JWT_TOKEN_AUTH_MODULE | default "token_verification" -}} +{{ $ENABLE_LOBBY := .Env.ENABLE_LOBBY | default "true" | toBool -}} +{{ $ENABLE_AV_MODERATION := .Env.ENABLE_AV_MODERATION | default "true" | toBool -}} +{{ $ENABLE_BREAKOUT_ROOMS := .Env.ENABLE_BREAKOUT_ROOMS | default "true" | toBool -}} +{{ $ENABLE_END_CONFERENCE := .Env.ENABLE_END_CONFERENCE | default "true" | toBool -}} +{{ $ENABLE_XMPP_WEBSOCKET := .Env.ENABLE_XMPP_WEBSOCKET | default "1" | toBool -}} +{{ $ENABLE_JAAS_COMPONENTS := .Env.ENABLE_JAAS_COMPONENTS | default "0" | toBool -}} +{{ $ENABLE_RATE_LIMITS := .Env.PROSODY_ENABLE_RATE_LIMITS | default "0" | toBool -}} +{{ $GUEST_AUTH_TYPE := .Env.PROSODY_GUEST_AUTH_TYPE | default "jitsi-anonymous" -}} +{{ $PUBLIC_URL := .Env.PUBLIC_URL | default "https://localhost:8443" -}} +{{ $PUBLIC_URL_DOMAIN := $PUBLIC_URL | trimPrefix "https://" | trimSuffix "/" -}} +{{ $STUN_HOST := .Env.STUN_HOST | default "" -}} +{{ $STUN_PORT := .Env.STUN_PORT | default "443" -}} +{{ $TURN_HOST := .Env.TURN_HOST | default "" -}} +{{ $TURN_HOSTS := splitList "," $TURN_HOST -}} +{{ $TURN_PORT := .Env.TURN_PORT | default "443" -}} +{{ $TURN_TRANSPORT := .Env.TURN_TRANSPORT | default "tcp" -}} +{{ $TURN_TRANSPORTS := splitList "," $TURN_TRANSPORT -}} +{{ $TURNS_HOST := .Env.TURNS_HOST | default "" -}} +{{ $TURNS_HOSTS := splitList "," $TURNS_HOST -}} +{{ $TURNS_PORT := .Env.TURNS_PORT | default "443" -}} +{{ $XMPP_AUTH_DOMAIN := .Env.XMPP_AUTH_DOMAIN | default "auth.meet.jitsi" -}} +{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}} +{{ $XMPP_GUEST_DOMAIN := .Env.XMPP_GUEST_DOMAIN | default "guest.meet.jitsi" -}} +{{ $XMPP_INTERNAL_MUC_DOMAIN := .Env.XMPP_INTERNAL_MUC_DOMAIN | default "internal-muc.meet.jitsi" -}} +{{ $XMPP_MUC_DOMAIN := .Env.XMPP_MUC_DOMAIN | default "muc.meet.jitsi" -}} +{{ $XMPP_MUC_DOMAIN_PREFIX := (split "." $XMPP_MUC_DOMAIN)._0 -}} +{{ $XMPP_RECORDER_DOMAIN := .Env.XMPP_RECORDER_DOMAIN | default "recorder.meet.jitsi" -}} +{{ $JIBRI_RECORDER_USER := .Env.JIBRI_RECORDER_USER | default "recorder" -}} +{{ $JIGASI_TRANSCRIBER_USER := .Env.JIGASI_TRANSCRIBER_USER | default "transcriber" -}} +{{ $DISABLE_POLLS := .Env.DISABLE_POLLS | default "false" | toBool -}} +{{ $ENABLE_SUBDOMAINS := .Env.ENABLE_SUBDOMAINS | default "true" | toBool -}} +{{ $PROSODY_RESERVATION_ENABLED := .Env.PROSODY_RESERVATION_ENABLED | default "false" | toBool -}} +{{ $PROSODY_RESERVATION_REST_BASE_URL := .Env.PROSODY_RESERVATION_REST_BASE_URL | default "" -}} +{{ $RATE_LIMIT_LOGIN_RATE := .Env.PROSODY_RATE_LIMIT_LOGIN_RATE | default "3" -}} +{{ $RATE_LIMIT_SESSION_RATE := .Env.PROSODY_RATE_LIMIT_SESSION_RATE | default "200" -}} +{{ $RATE_LIMIT_TIMEOUT := .Env.PROSODY_RATE_LIMIT_TIMEOUT | default "60" -}} +{{ $RATE_LIMIT_ALLOW_RANGES := .Env.PROSODY_RATE_LIMIT_ALLOW_RANGES | default "10.0.0.0/8" -}} +{{ $RATE_LIMIT_CACHE_SIZE := .Env.PROSODY_RATE_LIMIT_CACHE_SIZE | default "10000" -}} +{{ $ENV := .Env -}} + +admins = { + {{ if .Env.JIGASI_XMPP_PASSWORD }} + "{{ $JIGASI_XMPP_USER }}@{{ $XMPP_AUTH_DOMAIN }}", + {{ end }} + + {{ if .Env.JIBRI_XMPP_PASSWORD }} + "{{ $JIBRI_XMPP_USER }}@{{ $XMPP_AUTH_DOMAIN }}", + {{ end }} + + "focus@{{ $XMPP_AUTH_DOMAIN }}", + "{{ $JVB_AUTH_USER }}@{{ $XMPP_AUTH_DOMAIN }}" +} + +unlimited_jids = { + "focus@{{ $XMPP_AUTH_DOMAIN }}", + "{{ $JVB_AUTH_USER }}@{{ $XMPP_AUTH_DOMAIN }}" +} + +plugin_paths = { "/prosody-plugins/", "/prosody-plugins-custom" } + +muc_mapper_domain_base = "{{ $XMPP_DOMAIN }}"; +muc_mapper_domain_prefix = "{{ $XMPP_MUC_DOMAIN_PREFIX }}"; + +http_default_host = "{{ $XMPP_DOMAIN }}" + +{{ if .Env.TURN_CREDENTIALS -}} +external_service_secret = "{{.Env.TURN_CREDENTIALS}}"; +{{- end }} + +{{ if or .Env.STUN_HOST .Env.TURN_HOST .Env.TURNS_HOST -}} +external_services = { + {{- if $STUN_HOST }} + { type = "stun", host = "{{ $STUN_HOST }}", port = {{ $STUN_PORT }}, transport = "udp" } + {{- end }} + {{- if $TURN_HOST -}} + {{- range $idx1, $host := $TURN_HOSTS -}} + {{- range $idx2, $transport := $TURN_TRANSPORTS -}} + {{- if or $STUN_HOST $idx1 $idx2 -}},{{- end }} + { type = "turn", host = "{{ $host }}", port = {{ $TURN_PORT }}, transport = "{{ $transport }}", secret = true, ttl = 86400, algorithm = "turn" } + {{- end -}} + {{- end -}} + {{- end -}} + + {{- if $TURNS_HOST -}} + {{- range $idx, $host := $TURNS_HOSTS -}} + {{- if or $STUN_HOST $TURN_HOST $idx -}},{{- end }} + { type = "turns", host = "{{ $host }}", port = {{ $TURNS_PORT }}, transport = "tcp", secret = true, ttl = 86400, algorithm = "turn" } + {{- end }} + {{- end }} +}; +{{- end }} + +{{ if and $ENABLE_AUTH (or (eq $PROSODY_AUTH_TYPE "jwt") (eq $PROSODY_AUTH_TYPE "hybrid_matrix_token")) .Env.JWT_ACCEPTED_ISSUERS }} +asap_accepted_issuers = { "{{ join "\",\"" (splitList "," .Env.JWT_ACCEPTED_ISSUERS) }}" } +{{ end }} + +{{ if and $ENABLE_AUTH (or (eq $PROSODY_AUTH_TYPE "jwt") (eq $PROSODY_AUTH_TYPE "hybrid_matrix_token")) .Env.JWT_ACCEPTED_AUDIENCES }} +asap_accepted_audiences = { "{{ join "\",\"" (splitList "," .Env.JWT_ACCEPTED_AUDIENCES) }}" } +{{ end }} + +consider_bosh_secure = true; +consider_websocket_secure = true; + +{{ if $ENABLE_JAAS_COMPONENTS }} +VirtualHost "jigasi.meet.jitsi" + modules_enabled = { + "ping"; + "bosh"; + "muc_password_check"; + } + authentication = "token" + app_id = "jitsi"; + asap_key_server = "https://jaas-public-keys.jitsi.net/jitsi-components/prod-8x8" + asap_accepted_issuers = { "jaas-components" } + asap_accepted_audiences = { "jigasi.{{ $PUBLIC_URL_DOMAIN }}" } +{{ end }} + +VirtualHost "{{ $XMPP_DOMAIN }}" +{{ if $ENABLE_AUTH }} + {{ if eq $PROSODY_AUTH_TYPE "jwt" }} + authentication = "{{ $JWT_AUTH_TYPE }}" + app_id = "{{ .Env.JWT_APP_ID }}" + app_secret = "{{ .Env.JWT_APP_SECRET }}" + allow_empty_token = {{ $JWT_ALLOW_EMPTY }} + {{ if $JWT_ASAP_KEYSERVER }} + asap_key_server = "{{ .Env.JWT_ASAP_KEYSERVER }}" + {{ end }} + enable_domain_verification = {{ $JWT_ENABLE_DOMAIN_VERIFICATION }} + {{ else if eq $PROSODY_AUTH_TYPE "ldap" }} + authentication = "cyrus" + cyrus_application_name = "xmpp" + allow_unencrypted_plain_auth = true + {{ else if eq $PROSODY_AUTH_TYPE "matrix" }} + authentication = "matrix_user_verification" + app_id = "{{ $MATRIX_UVS_ISSUER }}" + uvs_base_url = "{{ .Env.MATRIX_UVS_URL }}" + {{ if .Env.MATRIX_UVS_AUTH_TOKEN }} + uvs_auth_token = "{{ .Env.MATRIX_UVS_AUTH_TOKEN }}" + {{ end }} + {{ if $MATRIX_UVS_SYNC_POWER_LEVELS }} + uvs_sync_power_levels = true + {{ end }} + {{ else if eq $PROSODY_AUTH_TYPE "hybrid_matrix_token" }} + authentication = "hybrid_matrix_token" + app_id = "{{ .Env.JWT_APP_ID }}" + app_secret = "{{ .Env.JWT_APP_SECRET }}" + allow_empty_token = {{ $JWT_ALLOW_EMPTY }} + enable_domain_verification = {{ $JWT_ENABLE_DOMAIN_VERIFICATION }} + + uvs_base_url = "{{ .Env.MATRIX_UVS_URL }}" + {{ if .Env.MATRIX_UVS_ISSUER }} + uvs_issuer = "{{ .Env.MATRIX_UVS_ISSUER }}" + {{ end }} + {{ if .Env.MATRIX_UVS_AUTH_TOKEN }} + uvs_auth_token = "{{ .Env.MATRIX_UVS_AUTH_TOKEN }}" + {{ end }} + {{ else if eq $PROSODY_AUTH_TYPE "internal" }} + authentication = "internal_hashed" + {{ end }} +{{ else }} + authentication = "jitsi-anonymous" +{{ end }} + ssl = { + key = "/config/certs/{{ $XMPP_DOMAIN }}.key"; + certificate = "/config/certs/{{ $XMPP_DOMAIN }}.crt"; + } + modules_enabled = { + "bosh"; + {{ if $ENABLE_XMPP_WEBSOCKET }} + "websocket"; + "smacks"; -- XEP-0198: Stream Management + {{ end }} + "pubsub"; + "ping"; + "speakerstats"; + "conference_duration"; + "room_metadata"; + {{ if $ENABLE_END_CONFERENCE }} + "end_conference"; + {{ end }} + {{ if or .Env.TURN_HOST .Env.TURNS_HOST }} + "external_services"; + {{ end }} + {{ if $ENABLE_LOBBY }} + "muc_lobby_rooms"; + {{ end }} + {{ if $ENABLE_BREAKOUT_ROOMS }} + "muc_breakout_rooms"; + {{ end }} + {{ if $ENABLE_AV_MODERATION }} + "av_moderation"; + {{ end }} + {{ if .Env.XMPP_MODULES }} + "{{ join "\";\n \"" (splitList "," .Env.XMPP_MODULES) }}"; + {{ end }} + {{ if and $ENABLE_AUTH (eq $PROSODY_AUTH_TYPE "ldap") }} + "auth_cyrus"; + {{end}} + {{ if $PROSODY_RESERVATION_ENABLED }} + "reservations"; + {{ end }} + {{ if $ENABLE_VISITORS }} + "visitors"; + {{ end }} + } + + main_muc = "{{ $XMPP_MUC_DOMAIN }}" + room_metadata_component = "metadata.{{ $XMPP_DOMAIN }}" + {{ if $ENABLE_LOBBY }} + lobby_muc = "lobby.{{ $XMPP_DOMAIN }}" + {{ if $ENABLE_RECORDING }} + muc_lobby_whitelist = { "{{ $XMPP_RECORDER_DOMAIN }}" } + {{ end }} + {{ end }} + + {{ if $PROSODY_RESERVATION_ENABLED }} + reservations_api_prefix = "{{ $PROSODY_RESERVATION_REST_BASE_URL }}" + {{ end }} + + {{ if $ENABLE_BREAKOUT_ROOMS }} + breakout_rooms_muc = "breakout.{{ $XMPP_DOMAIN }}" + {{ end }} + + speakerstats_component = "speakerstats.{{ $XMPP_DOMAIN }}" + conference_duration_component = "conferenceduration.{{ $XMPP_DOMAIN }}" + + {{ if $ENABLE_END_CONFERENCE }} + end_conference_component = "endconference.{{ $XMPP_DOMAIN }}" + {{ end }} + + {{ if $ENABLE_AV_MODERATION }} + av_moderation_component = "avmoderation.{{ $XMPP_DOMAIN }}" + {{ end }} + + c2s_require_encryption = false + + {{ if $ENABLE_VISITORS -}} + visitors_ignore_list = { "{{ $XMPP_RECORDER_DOMAIN }}" } + {{ end }} + + {{ if .Env.XMPP_CONFIGURATION -}} + {{ join "\n " (splitList "," .Env.XMPP_CONFIGURATION) }} + {{ end -}} + +{{ if $ENABLE_GUEST_DOMAIN }} +VirtualHost "{{ $XMPP_GUEST_DOMAIN }}" + authentication = "{{ $GUEST_AUTH_TYPE }}" + modules_enabled = { + "ping"; + } + + c2s_require_encryption = false + {{ if $ENABLE_VISITORS }} + allow_anonymous_s2s = true + {{ end }} + +{{ end }} + +VirtualHost "{{ $XMPP_AUTH_DOMAIN }}" + ssl = { + key = "/config/certs/{{ $XMPP_AUTH_DOMAIN }}.key"; + certificate = "/config/certs/{{ $XMPP_AUTH_DOMAIN }}.crt"; + } + modules_enabled = { + "limits_exception"; + "ping"; + } + authentication = "internal_hashed" + +{{ if $ENABLE_RECORDING }} +VirtualHost "{{ $XMPP_RECORDER_DOMAIN }}" + modules_enabled = { + "ping"; + "smacks"; + } + authentication = "internal_hashed" +{{ end }} + +Component "{{ $XMPP_INTERNAL_MUC_DOMAIN }}" "muc" + storage = "memory" + modules_enabled = { + "ping"; + {{ if .Env.XMPP_INTERNAL_MUC_MODULES -}} + "{{ join "\";\n\"" (splitList "," .Env.XMPP_INTERNAL_MUC_MODULES) }}"; + {{ end -}} + } + restrict_room_creation = true + muc_room_locking = false + muc_room_default_public_jids = true + +Component "{{ $XMPP_MUC_DOMAIN }}" "muc" + restrict_room_creation = true + storage = "memory" + modules_enabled = { + "muc_meeting_id"; + {{ if .Env.XMPP_MUC_MODULES -}} + "{{ join "\";\n \"" (splitList "," .Env.XMPP_MUC_MODULES) }}"; + {{ end -}} + {{ if and $ENABLE_AUTH (or (eq $PROSODY_AUTH_TYPE "jwt") (eq $PROSODY_AUTH_TYPE "hybrid_matrix_token")) -}} + "{{ $JWT_TOKEN_AUTH_MODULE }}"; + {{ end }} + {{ if and $ENABLE_AUTH (eq $PROSODY_AUTH_TYPE "matrix") $MATRIX_UVS_SYNC_POWER_LEVELS -}} + "matrix_power_sync"; + {{ end -}} + {{ if and $ENABLE_AUTH (eq $PROSODY_AUTH_TYPE "hybrid_matrix_token") $MATRIX_UVS_SYNC_POWER_LEVELS -}} + "matrix_affiliation"; + {{ end -}} + {{ if not $DISABLE_POLLS -}} + "polls"; + {{ end -}} + {{ if $ENABLE_SUBDOMAINS -}} + "muc_domain_mapper"; + {{ end -}} + {{ if $ENABLE_RATE_LIMITS -}} + "muc_rate_limit"; + "rate_limit"; + {{ end -}} + {{ if .Env.MAX_PARTICIPANTS }} + "muc_max_occupants"; + {{ end }} + "muc_password_whitelist"; + "token_affiliation"; + } + + {{ if $ENABLE_RATE_LIMITS -}} + -- Max allowed join/login rate in events per second. + rate_limit_login_rate = {{ $RATE_LIMIT_LOGIN_RATE }}; + -- The rate to which sessions from IPs exceeding the join rate will be limited, in bytes per second. + rate_limit_session_rate = {{ $RATE_LIMIT_SESSION_RATE }}; + -- The time in seconds, after which the limit for an IP address is lifted. + rate_limit_timeout = {{ $RATE_LIMIT_TIMEOUT }}; + -- List of regular expressions for IP addresses that are not limited by this module. + rate_limit_whitelist = { + "127.0.0.1"; +{{ range $index, $cidr := (splitList "," $RATE_LIMIT_ALLOW_RANGES) }} + "{{ $cidr }}"; +{{ end }} + }; + + rate_limit_whitelist_jids = { + "{{ $JIBRI_RECORDER_USER }}@{{ $XMPP_RECORDER_DOMAIN }}", + "{{ $JIGASI_TRANSCRIBER_USER }}@{{ $XMPP_RECORDER_DOMAIN }}" + } + {{ end -}} + + -- The size of the cache that saves state for IP addresses + rate_limit_cache_size = {{ $RATE_LIMIT_CACHE_SIZE }}; + + muc_room_cache_size = 10000 + muc_room_locking = false + muc_room_default_public_jids = true + {{ if .Env.XMPP_MUC_CONFIGURATION -}} + {{ join "\n " (splitList "," .Env.XMPP_MUC_CONFIGURATION) }} + {{ end -}} + {{ if .Env.MAX_PARTICIPANTS }} + muc_access_whitelist = { "focus@{{ .Env.XMPP_AUTH_DOMAIN }}" } + muc_max_occupants = "{{ .Env.MAX_PARTICIPANTS }}" + {{ end }} + muc_password_whitelist = { + "focus@{{ .Env.XMPP_AUTH_DOMAIN }}" + } + + +Component "focus.{{ $XMPP_DOMAIN }}" "client_proxy" + target_address = "focus@{{ $XMPP_AUTH_DOMAIN }}" + +Component "speakerstats.{{ $XMPP_DOMAIN }}" "speakerstats_component" + muc_component = "{{ $XMPP_MUC_DOMAIN }}" + +Component "conferenceduration.{{ $XMPP_DOMAIN }}" "conference_duration_component" + muc_component = "{{ $XMPP_MUC_DOMAIN }}" + +{{ if $ENABLE_END_CONFERENCE }} +Component "endconference.{{ $XMPP_DOMAIN }}" "end_conference" + muc_component = "{{ $XMPP_MUC_DOMAIN }}" +{{ end }} + +{{ if $ENABLE_AV_MODERATION }} +Component "avmoderation.{{ $XMPP_DOMAIN }}" "av_moderation_component" + muc_component = "{{ $XMPP_MUC_DOMAIN }}" +{{ end }} + +{{ if $ENABLE_LOBBY }} +Component "lobby.{{ $XMPP_DOMAIN }}" "muc" + storage = "memory" + restrict_room_creation = true + muc_room_allow_persistent = false + muc_room_cache_size = 10000 + muc_room_locking = false + muc_room_default_public_jids = true + modules_enabled = { + {{ if $ENABLE_RATE_LIMITS -}} + "muc_rate_limit"; + {{ end -}} + {{ if .Env.XMPP_LOBBY_MUC_MODULES -}} + "{{ join "\";\n \"" (splitList "," .Env.XMPP_LOBBY_MUC_MODULES) }}"; + {{ end -}} + } + + {{ end }} + +{{ if $ENABLE_BREAKOUT_ROOMS }} +Component "breakout.{{ $XMPP_DOMAIN }}" "muc" + storage = "memory" + restrict_room_creation = true + muc_room_cache_size = 10000 + muc_room_locking = false + muc_room_default_public_jids = true + muc_room_allow_persistent = false + modules_enabled = { + "muc_meeting_id"; + {{ if $ENABLE_SUBDOMAINS -}} + "muc_domain_mapper"; + {{ end -}} + {{ if not $DISABLE_POLLS -}} + "polls"; + {{ end -}} + {{ if $ENABLE_RATE_LIMITS -}} + "muc_rate_limit"; + {{ end -}} + {{ if .Env.XMPP_BREAKOUT_MUC_MODULES -}} + "{{ join "\";\n \"" (splitList "," .Env.XMPP_BREAKOUT_MUC_MODULES) }}"; + {{ end -}} + } +{{ end }} + +Component "metadata.{{ $XMPP_DOMAIN }}" "room_metadata_component" + muc_component = "{{ $XMPP_MUC_DOMAIN }}" + breakout_rooms_component = "breakout.{{ $XMPP_DOMAIN }}" + + +{{ if $ENABLE_VISITORS }} +Component "visitors.{{ $XMPP_DOMAIN }}" "visitors_component" + auto_allow_visitor_promotion = true +{{ end }} + +-- From the helm chart diff --git a/charts/jitsi/charts/prosody/templates/NOTES.txt b/charts/jitsi/charts/prosody/templates/NOTES.txt new file mode 100644 index 0000000..8df9491 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/NOTES.txt @@ -0,0 +1,21 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "prosody.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "prosody.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "prosody.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "prosody.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/jitsi/charts/prosody/templates/_helpers.tpl b/charts/jitsi/charts/prosody/templates/_helpers.tpl new file mode 100644 index 0000000..3370472 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "prosody.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "prosody.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "prosody.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "prosody.labels" -}} +helm.sh/chart: {{ include "prosody.chart" . }} +{{ include "prosody.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "prosody.selectorLabels" -}} +app.kubernetes.io/name: {{ include "prosody.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "prosody.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "prosody.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/jitsi/charts/prosody/templates/configmap-custom-plugins.yaml b/charts/jitsi/charts/prosody/templates/configmap-custom-plugins.yaml new file mode 100644 index 0000000..623eed4 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/configmap-custom-plugins.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "prosody.fullname" . }}-custom-plugins +data: + plugins.txt: | + {{- range .Values.customPluginUrls }} + {{ . }} + {{- end }} + diff --git a/charts/jitsi/charts/prosody/templates/configmaps-cont-init.yaml b/charts/jitsi/charts/prosody/templates/configmaps-cont-init.yaml new file mode 100644 index 0000000..cf3c38b --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/configmaps-cont-init.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "prosody.fullname" . }}-cont-inits + labels: + {{- include "prosody.labels" . | nindent 4 }} +data: + 10-config: | + {{- if .Values.custom.contInit._10_config }} + {{- .Values.custom.contInit._10_config | nindent 4 }} + {{- else }} + # Using prosody /etc/cont-init.d/10-config from container image + {{ end }} diff --git a/charts/jitsi/charts/prosody/templates/configmaps-defaults.yaml b/charts/jitsi/charts/prosody/templates/configmaps-defaults.yaml new file mode 100644 index 0000000..4fd6268 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/configmaps-defaults.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "prosody.fullname" . }}-defaults + labels: + {{- include "prosody.labels" . | nindent 4 }} +data: + prosody.cfg.lua: | + {{- if .Values.custom.defaults._prosody_cfg_lua }} + {{- .Values.custom.defaults._prosody_cfg_lua | nindent 4 }} + {{- else }} + # Using prosody /default/prosody.cfg.lua from container image + {{ end }} + saslauthd.conf: | + {{- if .Values.custom.defaults._saslauthd_conf }} + {{- .Values.custom.defaults._saslauthd_conf | nindent 4 }} + {{- else }} + # Using prosody /default/saslauthd.conf from container image + {{ end }} +{{ (.Files.Glob "files/jitsi-meet.cfg.lua").AsConfig | indent 2}} diff --git a/charts/jitsi/charts/prosody/templates/envs-configmap.yaml b/charts/jitsi/charts/prosody/templates/envs-configmap.yaml new file mode 100644 index 0000000..fc3cd0a --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/envs-configmap.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "prosody.fullname" . }} + labels: + {{- include "prosody.labels" . | nindent 4 }} +data: + {{- range $key, $value := .Values.env }} + {{- if not (kindIs "invalid" $value) }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} diff --git a/charts/jitsi/charts/prosody/templates/envs-secret.yaml b/charts/jitsi/charts/prosody/templates/envs-secret.yaml new file mode 100644 index 0000000..6c9d059 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/envs-secret.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "prosody.fullname" . }} + labels: + {{- include "prosody.labels" . | nindent 4 }} +type: Opaque +data: + {{- range $key, $value := .Values.secretEnvs }} + {{- if not (kindIs "invalid" $value) }} + {{ $key }}: {{ tpl $value $ | b64enc }} + {{- end }} + {{- end }} diff --git a/charts/jitsi/charts/prosody/templates/ingress.yaml b/charts/jitsi/charts/prosody/templates/ingress.yaml new file mode 100644 index 0000000..3dcbfa7 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/ingress.yaml @@ -0,0 +1,64 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "prosody.fullname" . -}} +{{- $svcPort := index .Values.service.ports "bosh-insecure" -}} +{{- $kubeVersion := .Capabilities.KubeVersion.GitVersion -}} +{{- if semverCompare ">=1.19-0" $kubeVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" $kubeVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "prosody.labels" . | nindent 4 }} + {{- if or .Values.ingress.annotations (and .Values.ingress.ingressClassName (semverCompare "<1.19-0" $kubeVersion)) }} + annotations: + {{- if and .Values.ingress.ingressClassName (semverCompare "<1.19-0" $kubeVersion) }} + kubernetes.io/ingress.class: {{ .Values.ingress.ingressClassName }} + {{- end }} + {{- with .Values.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: +{{- if and .Values.ingress.ingressClassName (semverCompare ">=1.19-0" $kubeVersion) }} + ingressClassName: {{ .Values.ingress.ingressClassName }} +{{- end }} +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ . }} + pathType: Prefix + backend: + {{ if semverCompare ">=1.19-0" $kubeVersion }} + service: + name: {{ $fullName }} + port: + {{ if kindIs "float64" $svcPort }} + number: {{ $svcPort }} + {{ else }} + name: {{ $svcPort }} + {{ end }} + {{ else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{ end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/jitsi/charts/prosody/templates/service.yaml b/charts/jitsi/charts/prosody/templates/service.yaml new file mode 100644 index 0000000..7441654 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/service.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "prosody.fullname" . }} + labels: + {{- include "prosody.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ index .Values.service.ports "bosh-insecure" }} + protocol: TCP + name: tcp-bosh-insecure + - port: {{ index .Values.service.ports "bosh-secure" }} + protocol: TCP + name: tcp-bosh-secure + - port: {{ index .Values.service.ports "xmpp-component" }} + protocol: TCP + name: tcp-xmpp-component + - port: {{ index .Values.service.ports "xmpp-c2s" }} + protocol: TCP + name: tcp-xmpp-c2 + {{- if .Values.service.ports.xmppc2snodePort }} + nodePort: {{ index .Values.service.ports "xmppc2snodePort" }} + {{- end }} + - port: {{ index .Values.service.ports "xmpp-s2s" }} + protocol: TCP + name: tcp-xmpp-s2 + selector: + {{- include "prosody.selectorLabels" . | nindent 4 }} diff --git a/charts/jitsi/charts/prosody/templates/serviceaccount.yaml b/charts/jitsi/charts/prosody/templates/serviceaccount.yaml new file mode 100644 index 0000000..c5706a6 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "prosody.serviceAccountName" . }} + labels: + {{- include "prosody.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end -}} diff --git a/charts/jitsi/charts/prosody/templates/statefulset.yaml b/charts/jitsi/charts/prosody/templates/statefulset.yaml new file mode 100644 index 0000000..edea746 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/statefulset.yaml @@ -0,0 +1,193 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "prosody.fullname" . }} + labels: + {{- include "prosody.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + serviceName: "{{ include "prosody.fullname" . }}" + replicas: {{ if .Values.useExternalProsody }}0{{ else }}1{{end}} + selector: + matchLabels: + {{- include "prosody.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "prosody.selectorLabels" . | nindent 8 }} + {{- range $label, $value := mergeOverwrite .Values.global.podLabels .Values.podLabels }} + {{ $label }}: {{ $value }} + {{- end }} + annotations: + si.jit.meet/hash-secret: "{{ toYaml .Values.secretEnvs | sha256sum | trunc 32 }}" + si.jit.meet/hash-configmap: "{{ toYaml .Values.env | sha256sum | trunc 32 }}" + {{- range $annotation, $value := mergeOverwrite .Values.global.podAnnotations .Values.podAnnotations }} + {{ $annotation }}: {{ $value }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "prosody.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + - name: download-plugins + image: alpine + command: ['sh', '-c', 'apk add wget && wget -i /urls/plugins.txt -P /prosody-plugins-custom'] + volumeMounts: + - name: custom-plugins + mountPath: /prosody-plugins-custom + - name: plugin-urls + mountPath: /urls + + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ tpl (default .Chart.AppVersion .Values.image.tag ) . }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + envFrom: + - configMapRef: + name: {{ include "prosody.fullname" . }} + - secretRef: + name: {{ include "prosody.fullname" . }} + {{- range .Values.extraEnvFrom }} + - {{ tpl (toYaml . ) $ | indent 12 | trim }} + {{- end }} + {{- if .Values.global.releaseSecretsOverride.enabled }} + {{- range .Values.global.releaseSecretsOverride.extraEnvFrom }} + - {{ tpl (toYaml . ) $ | indent 12 | trim }} + {{- end }} + {{- end }} + {{- if .Values.extraEnvs }} + env: + {{- range .Values.extraEnvs }} + - {{ tpl (toYaml . ) $ | indent 12 | trim }} + {{- end }} + {{- end }} + ports: + - name: xmpp-c2s + containerPort: {{ index .Values.service.ports "xmpp-c2s" }} + protocol: TCP + - name: xmpp-s2s + containerPort: {{ index .Values.service.ports "xmpp-s2s" }} + protocol: TCP + - name: xmpp-component + containerPort: {{ index .Values.service.ports "xmpp-component" }} + protocol: TCP + - name: bosh-insecure + containerPort: {{ index .Values.service.ports "bosh-insecure" }} + protocol: TCP + - name: bosh-secure + containerPort: {{ index .Values.service.ports "bosh-secure" }} + protocol: TCP + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: config + mountPath: /config + - name: custom-plugins + mountPath: /prosody-plugins-custom + - name: prosody-data + mountPath: {{ .Values.dataDir }} + {{- if .Values.custom.contInit._10_config }} + - name: custom-cont-inits + mountPath: /etc/cont-init.d/10-config + subPath: 10-config + {{- end }} + {{- if .Values.custom.defaults._prosody_cfg_lua }} + - name: custom-defaults + mountPath: /defaults/prosody.cfg.lua + subPath: prosody.cfg.lua + {{- end }} + {{- if .Values.custom.defaults._saslauthd_conf }} + - name: custom-defaults + mountPath: /defaults/saslauthd.conf + subPath: saslauthd.conf + {{- end }} + {{- if .Values.custom.defaults._jitsi_meet_cfg_lua }} + - name: custom-defaults + mountPath: /defaults/conf.d/jitsi-meet.cfg.lua + subPath: jitsi-meet.cfg.lua + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + volumes: + - name: config + emptyDir: {} + - name: custom-plugins + emptyDir: {} + - name: plugin-urls + configMap: + name: {{ include "prosody.fullname" . }}-custom-plugins + - name: custom-cont-inits + configMap: + defaultMode: 493 + name: {{ include "prosody.fullname" . }}-cont-inits + items: + - key: 10-config + path: 10-config + - name: custom-defaults + configMap: + name: {{ include "prosody.fullname" . }}-defaults + items: + - key: prosody.cfg.lua + path: prosody.cfg.lua + - key: saslauthd.conf + path: saslauthd.conf + - key: jitsi-meet.cfg.lua + path: jitsi-meet.cfg.lua + - name: prosody-data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: prosody-data + {{- else }} + emptyDir: {} + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.persistence.enabled .Values.extraVolumeClaimTemplates }} + volumeClaimTemplates: + - metadata: + name: prosody-data + spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- with .Values.persistence.storageClassName }} + storageClassName: {{ . | quote }} + {{- end }} + {{- with .Values.extraVolumeClaimTemplates }} + {{- toYaml . | nindent 2 }} + {{- end }} + {{- end }} diff --git a/charts/jitsi/charts/prosody/templates/tests/test-connection.yaml b/charts/jitsi/charts/prosody/templates/tests/test-connection.yaml new file mode 100644 index 0000000..0da4bb4 --- /dev/null +++ b/charts/jitsi/charts/prosody/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "prosody.fullname" . }}-test-connection" + labels: + {{- include "prosody.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test-success +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "prosody.fullname" . }}:{{ index .Values.service.ports "bosh-insecure" }}/http-bind'] + restartPolicy: Never diff --git a/charts/jitsi/charts/prosody/values.yaml b/charts/jitsi/charts/prosody/values.yaml new file mode 100644 index 0000000..7e59102 --- /dev/null +++ b/charts/jitsi/charts/prosody/values.yaml @@ -0,0 +1,96 @@ +# Default values for prosody. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +image: + repository: nginx + pullPolicy: IfNotPresent + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +domain: + +customPluginUrls: [] + +dataDir: /config/data +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + +podLabels: {} +podAnnotations: {} +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + ports: + bosh-insecure: 5280 + bosh-secure: 5281 + xmpp-c2s: 5222 + xmpp-s2s: 5269 + xmpp-component: 5347 + +ingress: + enabled: false + # ingressClassName: "nginx-ingress-0" + annotations: {} + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: [] + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: + httpGet: + path: /http-bind + port: bosh-insecure +readinessProbe: + httpGet: + path: /http-bind + port: bosh-insecure + +persistence: + enabled: true + size: 3G + storageClassName: + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +extraEnvs: [] +extraEnvFrom: [] +secretEnvs: {} diff --git a/charts/jitsi/files/body.html b/charts/jitsi/files/body.html new file mode 100644 index 0000000..d46b460 --- /dev/null +++ b/charts/jitsi/files/body.html @@ -0,0 +1,46 @@ + diff --git a/charts/jitsi/files/eth_space.jpg b/charts/jitsi/files/eth_space.jpg new file mode 100644 index 0000000..3e33ed4 Binary files /dev/null and b/charts/jitsi/files/eth_space.jpg differ diff --git a/charts/jitsi/files/grafana_dashboards/README.md b/charts/jitsi/files/grafana_dashboards/README.md new file mode 100644 index 0000000..d1361f5 --- /dev/null +++ b/charts/jitsi/files/grafana_dashboards/README.md @@ -0,0 +1,4 @@ +# Dashboards + +For version tracking, we put here the link to the origin place, where the dashboard is from: +- https://github.com/systemli/prometheus-jitsi-meet-exporter/tree/54fbedad4e4c605f72ad88fecf4c6d9df88eed1d/dashboards diff --git a/charts/jitsi/files/grafana_dashboards/jitsi-meet-system.json b/charts/jitsi/files/grafana_dashboards/jitsi-meet-system.json new file mode 100644 index 0000000..cc90d99 --- /dev/null +++ b/charts/jitsi/files/grafana_dashboards/jitsi-meet-system.json @@ -0,0 +1,2514 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.3.7" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Dashboard for Jitsi Meet Exporter", + "editable": true, + "gnetId": 12282, + "graphTooltip": 1, + "id": null, + "iteration": 1613598823724, + "links": [], + "panels": [ + { + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 40, + "title": "Key Metrics", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "Busy state of all CPU cores together", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "nullValueMode": "null", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 85 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 95 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 44, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "(((count(count(node_cpu_seconds_total{instance=~\"$instance.*\"}) by (cpu))) - avg(sum by (mode)(irate(node_cpu_seconds_total{mode='idle',instance=~\"$instance.*\"}[5m])))) * 100) / count(count(node_cpu_seconds_total{instance=~\"$instance.*\"}) by (cpu))", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 900 + } + ], + "title": "CPU Busy", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "Non available RAM memory", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "nullValueMode": "null", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 80 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 1 + }, + "hideTimeOverride": false, + "id": 46, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "((node_memory_MemTotal_bytes{instance=~\"$instance.*\"} - node_memory_MemFree_bytes{instance=~\"$instance.*\"}) / (node_memory_MemTotal_bytes{instance=~\"$instance.*\"} )) * 100", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A", + "step": 900 + }, + { + "expr": "100 - ((node_memory_MemAvailable_bytes{instance=~\"$instance.*\"} * 100) / node_memory_MemTotal_bytes{instance=~\"$instance.*\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "B", + "step": 900 + } + ], + "title": "Used RAM Memory", + "type": "gauge" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-green", + "value": null + } + ] + }, + "unit": "decgbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 48, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "vertical", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "sum(node_network_receive_bytes_total{instance=~\"$instance.*\"})*(9.31*10^-10)", + "format": "time_series", + "instant": false, + "interval": "", + "legendFormat": "Incoming ", + "refId": "A" + }, + { + "expr": "sum(node_network_transmit_bytes_total{instance=~\"$instance.*\"})*(9.31*10^-10)", + "interval": "", + "legendFormat": "Outgoing", + "refId": "B" + }, + { + "expr": "(sum(node_network_receive_bytes_total{instance=~\"$instance.*\"})+sum(node_network_transmit_bytes_total{instance=~\"$instance.*\"}))*(9.31*10^-10)", + "interval": "", + "legendFormat": "Total", + "refId": "C" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Transfered data volume", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The total incoming bitrate for the video bridge in kilobits per second.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "Kbits" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 6 + }, + "id": 18, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_bit_rate_download{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Bitrate Download", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The total outgoing bitrate for the video bridge in kilobits per second.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "Kbits" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 6 + }, + "id": 19, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_bit_rate_upload{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Bitrate Upload", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The number of Java threads that the video bridge is using.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 6 + }, + "id": 9, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_threads{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Threads", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "An estimation of the number of current video streams forwarded by the bridge.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 6 + }, + "id": 20, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_videostreams{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Videostreams", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "An average value (in milliseconds) of the RTT across all streams.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 6 + }, + "id": 22, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_rtt_aggregate{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "RTT", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The sum of the lengths of all completed conferences, in seconds.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 15, + "y": 6 + }, + "id": 21, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_total_conference_seconds{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Completed Conferences", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The number of participants in the largest conference currently hosted on the bridge.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 18, + "y": 6 + }, + "id": 10, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "max" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "max" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "max(jitsi_largest_conference{instance=~\"$instance.*\"})", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Biggest Conference", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The total number of conferences created on the bridge.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 21, + "y": 6 + }, + "id": 8, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_total_conferences_created{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Conferences", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "decimals": null, + "description": "The current number of conferences.", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 10, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 10 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.3.7", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_conferences{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "conferences", + "refId": "A" + }, + { + "expr": "jitsi_p2p_conferences{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "p2p conferences", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Conferences", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "decimals": null, + "description": "The current number of participants.", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 10, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 10 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.3.7", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_participants{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "participants", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Participants", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 42, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The total incoming/outgoing bitrate for the video bridge in kilobits per second.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "upload", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_bit_rate_download{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "download", + "refId": "A" + }, + { + "expr": "jitsi_bit_rate_upload{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "upload", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bitrate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Kbits", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": " The total incoming/outgoing packet rate for the video bridge in packets per second.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "hiddenSeries": false, + "id": 25, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "upload", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_packet_rate_download{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "download", + "refId": "A" + }, + { + "expr": "jitsi_packet_rate_upload{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "upload", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Package Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The fraction of lost incoming RTP packets. This is based on RTP sequence numbers and is relatively accurate.\nThe fraction of lost outgoing RTP packets. This is based on incoming RTCP Receiver Reports, and an attempt to subtract the fraction of packets that were not sent (i.e. were lost before they reached the bridge). Further, this is averaged over all streams of all users as opposed to all packets, so it is not correctly weighted. This is not accurate, but may be a useful metric nonetheless.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "upload", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_loss_rate_download{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "download", + "refId": "A" + }, + { + "expr": "jitsi_loss_rate_upload{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "upload", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Lost RTP packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "Experimental. An average value (in milliseconds) of the jitter calculated for incoming and outgoing streams. This hasn't been tested and it is currently not known whether the values are correct or not.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_jitter_aggregate{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "jitter", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Jitter Aggregate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "An average value (in milliseconds) of the RTT across all streams.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 35 + }, + "hiddenSeries": false, + "id": 29, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_rtt_aggregate{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "rtt", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "RTT", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The current number of audio/video channels.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "hiddenSeries": false, + "id": 31, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_audiochannels{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "audiochannels", + "refId": "A" + }, + { + "expr": "jitsi_videochannels{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "videochannels", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Audio/Videochannels", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of participant-seconds that are loss-controlled.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 43 + }, + "hiddenSeries": false, + "id": 32, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_loss_controlled_participant_seconds{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "participant-seconds", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Loss-controlled participant-seconds", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of participant-seconds that are loss-limited.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 43 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_loss_limited_participant_seconds{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "participant-seconds", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Loss-limited participant-seconds", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of participant-seconds that are loss-degraded.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 51 + }, + "hiddenSeries": false, + "id": 34, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_loss_degraded_participant_seconds{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "participant-seconds", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Loss-degraded participant-seconds", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of failed conferences on the bridge. A conference is marked as failed when all of its channels have failed. A channel is marked as failed if it had no payload activity.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 51 + }, + "hiddenSeries": false, + "id": 35, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_failed_conferences{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "failed conferences", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Failed Conferences", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of partially failed conferences on the bridge. A conference is marked as partially failed when some of its channels has failed. A channel is marked as failed if it had no payload activity.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 59 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_partially_failed_conferences{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "partially failed conferences", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Partially Failed Conferences", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The total number messages sent/received through data channels.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 59 + }, + "hiddenSeries": false, + "id": 37, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "sent", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_data_channel_messages_received{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "received", + "refId": "A" + }, + { + "expr": "rate(jitsi_total_data_channel_messages_sent{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "sent", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sent/Received Messages", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The total number messages sent/received through COLIBRI web sockets.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 67 + }, + "hiddenSeries": false, + "id": 38, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "sent", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_colibri_web_socket_messages_received{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "received", + "refId": "A" + }, + { + "expr": "rate(jitsi_total_colibri_web_socket_messages_sent{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "sent", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sent/Received Websockets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "Stress Level reported to Jicofo by the videobridge.", + "fieldConfig": { + "defaults": { + "color": {}, + "custom": {}, + "thresholds": { + "mode": "absolute", + "steps": [] + }, + "unit": "short" + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 67 + }, + "hiddenSeries": false, + "id": 51, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_stress_level{instance=~\"$instance.*\"}", + "instant": false, + "interval": "", + "legendFormat": "stress level", + "queryType": "randomWalk", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Videobridge Stress Level", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Additional Metrics", + "type": "row" + } + ], + "refresh": "1m", + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(jitsi_conferences, instance)", + "error": null, + "hide": 0, + "includeAll": false, + "label": "instance", + "multi": false, + "name": "instance", + "options": [], + "query": "label_values(jitsi_conferences, instance)", + "refresh": 1, + "regex": "/(.*):.*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Jitsi Meet & System", + "uid": "IJXK9Q6Wz", + "version": 5 +} diff --git a/charts/jitsi/files/grafana_dashboards/jitsi-meet.json b/charts/jitsi/files/grafana_dashboards/jitsi-meet.json new file mode 100644 index 0000000..6834254 --- /dev/null +++ b/charts/jitsi/files/grafana_dashboards/jitsi-meet.json @@ -0,0 +1,2166 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.3.7" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Dashboard for Jitsi Meet Exporter", + "editable": true, + "gnetId": 12098, + "graphTooltip": 1, + "id": null, + "iteration": 1612608944252, + "links": [], + "panels": [ + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 40, + "panels": [], + "title": "Key Metrics", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The total incoming bitrate for the video bridge in kilobits per second.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "Kbits" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 18, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_bit_rate_download{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Bitrate Download", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The total outgoing bitrate for the video bridge in kilobits per second.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "Kbits" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 19, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_bit_rate_upload{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Bitrate Upload", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The number of Java threads that the video bridge is using.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 9, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_threads{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Threads", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "An estimation of the number of current video streams forwarded by the bridge.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 1 + }, + "id": 20, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_videostreams{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Videostreams", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "An average value (in milliseconds) of the RTT across all streams.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 22, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_rtt_aggregate{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "RTT", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The sum of the lengths of all completed conferences, in seconds.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 21, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_total_conference_seconds{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Completed Conferences", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The number of participants in the largest conference currently hosted on the bridge.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 18, + "y": 1 + }, + "id": 10, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "max" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "max" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "max(jitsi_largest_conference{instance=~\"$instance.*\"})", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Biggest Conference", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_PROMETHEUS}", + "description": "The total number of conferences created on the bridge.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 21, + "y": 1 + }, + "id": 8, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.3.7", + "targets": [ + { + "expr": "jitsi_total_conferences_created{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Conferences", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "decimals": null, + "description": "The current number of conferences.", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 10, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 5 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.3.7", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_conferences{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "conferences", + "refId": "A" + }, + { + "expr": "jitsi_p2p_conferences{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "p2p conferences", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Conferences", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "decimals": null, + "description": "The current number of participants.", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 10, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 5 + }, + "hiddenSeries": false, + "id": 3, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.3.7", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_participants{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "participants", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Participants", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 42, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The total incoming/outgoing bitrate for the video bridge in kilobits per second.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 19 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "upload", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_bit_rate_download{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "download", + "refId": "A" + }, + { + "expr": "jitsi_bit_rate_upload{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "upload", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bitrate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Kbits", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": " The total incoming/outgoing packet rate for the video bridge in packets per second.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 19 + }, + "hiddenSeries": false, + "id": 25, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "upload", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_packet_rate_download{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "download", + "refId": "A" + }, + { + "expr": "jitsi_packet_rate_upload{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "upload", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Package Rate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The fraction of lost incoming RTP packets. This is based on RTP sequence numbers and is relatively accurate.\nThe fraction of lost outgoing RTP packets. This is based on incoming RTCP Receiver Reports, and an attempt to subtract the fraction of packets that were not sent (i.e. were lost before they reached the bridge). Further, this is averaged over all streams of all users as opposed to all packets, so it is not correctly weighted. This is not accurate, but may be a useful metric nonetheless.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "upload", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_loss_rate_download{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "download", + "refId": "A" + }, + { + "expr": "jitsi_loss_rate_upload{instance=~\"$instance.*\"}", + "hide": false, + "interval": "", + "legendFormat": "upload", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Lost RTP packets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "Experimental. An average value (in milliseconds) of the jitter calculated for incoming and outgoing streams. This hasn't been tested and it is currently not known whether the values are correct or not.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_jitter_aggregate{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "jitter", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Jitter Aggregate", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "An average value (in milliseconds) of the RTT across all streams.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 35 + }, + "hiddenSeries": false, + "id": 29, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_rtt_aggregate{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "rtt", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "RTT", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The current number of audio/video channels.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 35 + }, + "hiddenSeries": false, + "id": 31, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "jitsi_audiochannels{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "audiochannels", + "refId": "A" + }, + { + "expr": "jitsi_videochannels{instance=~\"$instance.*\"}", + "interval": "", + "legendFormat": "videochannels", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Audio/Videochannels", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of participant-seconds that are loss-controlled.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 43 + }, + "hiddenSeries": false, + "id": 32, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_loss_controlled_participant_seconds{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "participant-seconds", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Loss-controlled participant-seconds", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of participant-seconds that are loss-limited.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 43 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_loss_limited_participant_seconds{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "participant-seconds", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Loss-limited participant-seconds", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of participant-seconds that are loss-degraded.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 51 + }, + "hiddenSeries": false, + "id": 34, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_loss_degraded_participant_seconds{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "participant-seconds", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Loss-degraded participant-seconds", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of failed conferences on the bridge. A conference is marked as failed when all of its channels have failed. A channel is marked as failed if it had no payload activity.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 51 + }, + "hiddenSeries": false, + "id": 35, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_failed_conferences{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "failed conferences", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Failed Conferences", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The rate of partially failed conferences on the bridge. A conference is marked as partially failed when some of its channels has failed. A channel is marked as failed if it had no payload activity.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 59 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_partially_failed_conferences{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "partially failed conferences", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Partially Failed Conferences", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The total number messages sent/received through data channels.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 59 + }, + "hiddenSeries": false, + "id": 37, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "sent", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_data_channel_messages_received{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "received", + "refId": "A" + }, + { + "expr": "rate(jitsi_total_data_channel_messages_sent{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "sent", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sent/Received Messages", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "The total number messages sent/received through COLIBRI web sockets.", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 67 + }, + "hiddenSeries": false, + "id": 38, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "sent", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(jitsi_total_colibri_web_socket_messages_received{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "received", + "refId": "A" + }, + { + "expr": "rate(jitsi_total_colibri_web_socket_messages_sent{instance=~\"$instance.*\"}[1m])", + "interval": "", + "legendFormat": "sent", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Sent/Received Websockets", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Additional Metrics", + "type": "row" + } + ], + "refresh": "1m", + "schemaVersion": 26, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(jitsi_conferences, instance)", + "error": null, + "hide": 0, + "includeAll": false, + "label": "instance", + "multi": false, + "name": "instance", + "options": [], + "query": "label_values(jitsi_conferences, instance)", + "refresh": 1, + "regex": "/(.*):.*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Jitsi Meet", + "uid": "wX13E8RGz", + "version": 3 +} diff --git a/charts/jitsi/files/meet.conf b/charts/jitsi/files/meet.conf new file mode 100644 index 0000000..e361893 --- /dev/null +++ b/charts/jitsi/files/meet.conf @@ -0,0 +1,239 @@ +{{ $ENABLE_COLIBRI_WEBSOCKET := .Env.ENABLE_COLIBRI_WEBSOCKET | default "1" | toBool }} +{{ $COLIBRI_WEBSOCKET_PORT := .Env.COLIBRI_WEBSOCKET_PORT | default "9090" }} +{{ $ENABLE_JAAS_COMPONENTS := .Env.ENABLE_JAAS_COMPONENTS | default "0" | toBool }} +{{ $ENABLE_OCTO := .Env.ENABLE_OCTO | default "0" | toBool -}} +{{ $ENABLE_XMPP_WEBSOCKET := .Env.ENABLE_XMPP_WEBSOCKET | default "1" | toBool }} +{{ $ENABLE_SUBDOMAINS := .Env.ENABLE_SUBDOMAINS | default "true" | toBool -}} +{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}} +{{ $XMPP_BOSH_URL_BASE := .Env.XMPP_BOSH_URL_BASE | default "http://xmpp.meet.jitsi:5280" -}} + +server_name _; + +charset utf8; + +client_max_body_size 0; + +root /usr/share/jitsi-meet; + +# ssi on with javascript for multidomain variables in config.js +ssi on; +ssi_types application/x-javascript application/javascript; + +index index.html index.htm; +error_page 404 /static/404.html; + +# Security headers +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; + +set $prefix ""; + +{{ if .Env.DEPLOYMENTINFO_SHARD }} +add_header X-Jitsi-Shard {{ .Env.DEPLOYMENTINFO_SHARD }}; +{{ end }} + +# Opt out of FLoC (deprecated) +add_header Permissions-Policy "interest-cohort=()"; + +# /oidc/redirect +location = /oidc/redirect { + proxy_pass {{ .Env.ADAPTER_INTERNAL_URL }}; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $http_host; +} + +# /oidc/tokenize +location = /oidc/tokenize { + proxy_pass {{ .Env.ADAPTER_INTERNAL_URL }}; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $http_host; +} + +# /oidc/auth +location = /oidc/auth { + proxy_pass {{ .Env.ADAPTER_INTERNAL_URL }}; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $http_host; +} + +set $region 'eu'; + +if ($host = "eu.meet.ethquokkaops.io") { + set $region 'eu'; +} + +if ($host = "us.meet.ethquokkaops.io") { + set $region 'us'; +} + +if ($host = "au.meet.ethquokkaops.io") { + set $region 'au'; +} + +location = /config.js { + ssi on; + alias /config/config.js; +} + +location = /interface_config.js { + alias /config/interface_config.js; +} + +location = /external_api.js { + alias /usr/share/jitsi-meet/libs/external_api.min.js; +} + +{{ if $ENABLE_JAAS_COMPONENTS }} +location = /_api/room-info { + proxy_pass {{ $XMPP_BOSH_URL_BASE }}/room-info?prefix=$prefix&$args; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $http_host; +} +{{ end }} + +# ensure all static content can always be found first +location ~ ^/(libs|css|static|images|fonts|lang|sounds|connection_optimization|.well-known)/(.*)$ { + add_header 'Access-Control-Allow-Origin' '*'; + alias /usr/share/jitsi-meet/$1/$2; + + # cache all versioned files + if ($arg_v) { + expires 1y; + } +} + +{{ if $ENABLE_COLIBRI_WEBSOCKET }} +# colibri (JVB) websockets +location ~ ^/colibri-ws/([a-zA-Z0-9-\._]+)/(.*) { + tcp_nodelay on; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + proxy_pass http://$1:{{ $COLIBRI_WEBSOCKET_PORT }}/colibri-ws/$1/$2$is_args$args; +} + +{{ if $ENABLE_OCTO }} +# colibri (JVB) Relay to Relay websockets +location ~ ^/colibri-relay-ws/([a-zA-Z0-9-\._]+)/(.*) { + tcp_nodelay on; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + proxy_pass http://$1:{{ $COLIBRI_WEBSOCKET_PORT }}/colibri-relay-ws/$1/$2$is_args$args; +} +{{ end }} +{{ end }} + +# BOSH +location = /http-bind { + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host {{ $XMPP_DOMAIN }}; + + proxy_pass {{ $XMPP_BOSH_URL_BASE }}/http-bind?prefix=$prefix&$args; +} + +{{ if $ENABLE_XMPP_WEBSOCKET }} +# xmpp websockets +location = /xmpp-websocket { + tcp_nodelay on; + + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host {{ $XMPP_DOMAIN }}; + proxy_set_header X-Forwarded-For $remote_addr; + + proxy_pass {{ $XMPP_BOSH_URL_BASE }}/xmpp-websocket?prefix=$prefix&$args; +} +{{ end }} + +{{ if .Env.ETHERPAD_URL_BASE }} +# Etherpad-lite +location ^~ /etherpad/ { + proxy_buffering off; + proxy_cache_bypass $http_upgrade; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Forwarded-For $remote_addr; + + proxy_pass {{ .Env.ETHERPAD_URL_BASE }}/; +} +{{ end }} + +location ~ ^/([^/?&:'"]+)$ { + try_files $uri @root_path; +} + +location @root_path { + if ($arg_oidc) { + rewrite ^/(.*)$ / break; + } + if ($arg_jwt) { + rewrite ^/(.*)$ / break; + } + + rewrite ^/(.*)$ /static/oidc-redirect.html; +} + +{{ if $ENABLE_SUBDOMAINS }} + # Matches /(TENANT)/pwa-worker.js or /(TENANT)/manifest.json to rewrite to / and look for file + location ~ ^/([^/?&:'"]+)/(pwa-worker.js|manifest.json)$ { + set $subdomain "$1."; + set $subdir "$1/"; + rewrite ^/([^/?&:'"]+)/(pwa-worker.js|manifest.json)$ /$2; + } + + location ~ ^/([^/?&:'"]+)/config.js$ { + set $subdomain "$1."; + set $subdir "$1/"; + + alias /config/config.js; + } + + # BOSH for subdomains + location ~ ^/([^/?&:'"]+)/http-bind { + set $subdomain "$1."; + set $subdir "$1/"; + set $prefix "$1"; + + rewrite ^/(.*)$ /http-bind; + } + + {{ if $ENABLE_XMPP_WEBSOCKET }} + # websockets for subdomains + location ~ ^/([^/?&:'"]+)/xmpp-websocket { + set $subdomain "$1."; + set $subdir "$1/"; + set $prefix "$1"; + + rewrite ^/(.*)$ /xmpp-websocket; + } + {{ end }} + + {{ if $ENABLE_JAAS_COMPONENTS }} + location ~ ^/([^/?&:'"]+)/_api/room-info { + set $subdomain "$1."; + set $subdir "$1/"; + set $prefix "$1"; + + rewrite ^/(.*)$ /_api/room-info; + } + {{ end }} + + # Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to / + location ~ ^/([^/?&:'"]+)/(.*)$ { + set $subdomain "$1."; + set $subdir "$1/"; + rewrite ^/([^/?&:'"]+)/(.*)$ /$2; + } +{{ end }} diff --git a/charts/jitsi/files/oidc-adapter.html b/charts/jitsi/files/oidc-adapter.html new file mode 100644 index 0000000..c6f83c5 --- /dev/null +++ b/charts/jitsi/files/oidc-adapter.html @@ -0,0 +1,73 @@ + + + + + + + + adapting... + + diff --git a/charts/jitsi/files/oidc-redirect.html b/charts/jitsi/files/oidc-redirect.html new file mode 100644 index 0000000..ceaad68 --- /dev/null +++ b/charts/jitsi/files/oidc-redirect.html @@ -0,0 +1,83 @@ + + + + + Ethereum Foundation Jitsi - Authentication + + + +
+

Ethereum Foundation Jitsi - Authentication

+ +

+ Authenticate to start a meeting or become a moderator.
+ To simply join a call you can continue as guest + +

+ + + + + +

+ Note: Some rooms might only allow moderator rights to certain individuals.
+ Contact EF DevOps for setting up moderator allow-lists for your room. +

+ + +
+ + + + + diff --git a/charts/jitsi/files/settings-config.js b/charts/jitsi/files/settings-config.js new file mode 100644 index 0000000..9e109f4 --- /dev/null +++ b/charts/jitsi/files/settings-config.js @@ -0,0 +1,494 @@ +{{ $DEPLOYMENTINFO_USERREGION := .Env.DEPLOYMENTINFO_USERREGION | default "" -}} +{{ $ENABLE_AUDIO_PROCESSING := .Env.ENABLE_AUDIO_PROCESSING | default "true" | toBool -}} +{{ $ENABLE_BREAKOUT_ROOMS := .Env.ENABLE_BREAKOUT_ROOMS | default "true" | toBool -}} +{{ $ENABLE_CALENDAR := .Env.ENABLE_CALENDAR | default "false" | toBool -}} +{{ $ENABLE_FILE_RECORDING_SHARING := .Env.ENABLE_FILE_RECORDING_SHARING | default "false" | toBool -}} +{{ $ENABLE_IPV6 := .Env.ENABLE_IPV6 | default "true" | toBool -}} +{{ $ENABLE_LIPSYNC := .Env.ENABLE_LIPSYNC | default "false" | toBool -}} +{{ $ENABLE_NO_AUDIO_DETECTION := .Env.ENABLE_NO_AUDIO_DETECTION | default "true" | toBool -}} +{{ $ENABLE_P2P := .Env.ENABLE_P2P | default "true" | toBool -}} +{{ $ENABLE_PREJOIN_PAGE := .Env.ENABLE_PREJOIN_PAGE | default "true" | toBool -}} +{{ $ENABLE_WELCOME_PAGE := .Env.ENABLE_WELCOME_PAGE | default "true" | toBool -}} +{{ $ENABLE_CLOSE_PAGE := .Env.ENABLE_CLOSE_PAGE | default "false" | toBool -}} +{{ $ENABLE_RECORDING := .Env.ENABLE_RECORDING | default "false" | toBool -}} +{{ $ENABLE_SERVICE_RECORDING := .Env.ENABLE_SERVICE_RECORDING | default ($ENABLE_RECORDING | printf "%t") | toBool -}} +{{ $ENABLE_LIVESTREAMING := .Env.ENABLE_LIVESTREAMING | default "false" | toBool -}} +{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK := .Env.ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK | default "https://policies.google.com/privacy" -}} +{{ $ENABLE_LIVESTREAMING_HELP_LINK := .Env.ENABLE_LIVESTREAMING_HELP_LINK | default "https://jitsi.org/live" -}} +{{ $ENABLE_LIVESTREAMING_TERMS_LINK := .Env.ENABLE_LIVESTREAMING_TERMS_LINK | default "https://www.youtube.com/t/terms" -}} +{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING := .Env.ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING | default "^(?:[a-zA-Z0-9]{4}(?:-(?!$)|$)){4}" -}} +{{ $ENABLE_REMB := .Env.ENABLE_REMB | default "true" | toBool -}} +{{ $ENABLE_REQUIRE_DISPLAY_NAME := .Env.ENABLE_REQUIRE_DISPLAY_NAME | default "false" | toBool -}} +{{ $ENABLE_SIMULCAST := .Env.ENABLE_SIMULCAST | default "true" | toBool -}} +{{ $ENABLE_STATS_ID := .Env.ENABLE_STATS_ID | default "false" | toBool -}} +{{ $ENABLE_STEREO := .Env.ENABLE_STEREO | default "false" | toBool -}} +{{ $ENABLE_OPUS_RED := .Env.ENABLE_OPUS_RED | default "false" | toBool -}} +{{ $ENABLE_TALK_WHILE_MUTED := .Env.ENABLE_TALK_WHILE_MUTED | default "false" | toBool -}} +{{ $ENABLE_TCC := .Env.ENABLE_TCC | default "true" | toBool -}} +{{ $ENABLE_TRANSCRIPTIONS := .Env.ENABLE_TRANSCRIPTIONS | default "false" | toBool -}} +{{ $TRANSLATION_LANGUAGES := .Env.TRANSLATION_LANGUAGES | default "[]" -}} +{{ $TRANSLATION_LANGUAGES_HEAD := .Env.TRANSLATION_LANGUAGES_HEAD | default "['en']" -}} +{{ $USE_APP_LANGUAGE := .Env.USE_APP_LANGUAGE | default "true" | toBool -}} +{{ $PREFERRED_LANGUAGE := .Env.PREFERRED_LANGUAGE | default "en-US" -}} +{{ $DISABLE_START_FOR_ALL := .Env.DISABLE_START_FOR_ALL | default "false" | toBool -}} +{{ $AUTO_CAPTION_ON_RECORD := .Env.AUTO_CAPTION_ON_RECORD | default "false" | toBool -}} +{{ $ENABLE_JAAS_COMPONENTS := .Env.ENABLE_JAAS_COMPONENTS | default "0" | toBool }} +{{ $HIDE_PREJOIN_DISPLAY_NAME := .Env.HIDE_PREJOIN_DISPLAY_NAME | default "false" | toBool -}} +{{ $PUBLIC_URL := .Env.PUBLIC_URL | default "https://localhost:8443" -}} +{{ $RESOLUTION := .Env.RESOLUTION | default "720" -}} +{{ $RESOLUTION_MIN := .Env.RESOLUTION_MIN | default "180" -}} +{{ $RESOLUTION_WIDTH := .Env.RESOLUTION_WIDTH | default "1280" -}} +{{ $RESOLUTION_WIDTH_MIN := .Env.RESOLUTION_WIDTH_MIN | default "320" -}} +{{ $START_AUDIO_ONLY := .Env.START_AUDIO_ONLY | default "false" | toBool -}} +{{ $START_AUDIO_MUTED := .Env.START_AUDIO_MUTED | default 10 -}} +{{ $START_WITH_AUDIO_MUTED := .Env.START_WITH_AUDIO_MUTED | default "false" | toBool -}} +{{ $START_SILENT := .Env.START_SILENT | default "false" | toBool -}} +{{ $DISABLE_AUDIO_LEVELS := .Env.DISABLE_AUDIO_LEVELS | default "false" | toBool -}} +{{ $ENABLE_NOISY_MIC_DETECTION := .Env.ENABLE_NOISY_MIC_DETECTION | default "true" | toBool -}} +{{ $START_VIDEO_MUTED := .Env.START_VIDEO_MUTED | default 10 -}} +{{ $START_WITH_VIDEO_MUTED := .Env.START_WITH_VIDEO_MUTED | default "false" | toBool -}} +{{ $DESKTOP_SHARING_FRAMERATE_MIN := .Env.DESKTOP_SHARING_FRAMERATE_MIN | default 5 -}} +{{ $DESKTOP_SHARING_FRAMERATE_MAX := .Env.DESKTOP_SHARING_FRAMERATE_MAX | default 5 -}} +{{ $TESTING_OCTO_PROBABILITY := .Env.TESTING_OCTO_PROBABILITY | default "0" -}} +{{ $TESTING_CAP_SCREENSHARE_BITRATE := .Env.TESTING_CAP_SCREENSHARE_BITRATE | default "1" -}} +{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}} +{{ $XMPP_RECORDER_DOMAIN := .Env.XMPP_RECORDER_DOMAIN | default "recorder.meet.jitsi" -}} +{{ $DISABLE_DEEP_LINKING := .Env.DISABLE_DEEP_LINKING | default "false" | toBool -}} +{{ $VIDEOQUALITY_ENFORCE_PREFERRED_CODEC := .Env.VIDEOQUALITY_ENFORCE_PREFERRED_CODEC | default "false" | toBool -}} +{{ $DISABLE_POLLS := .Env.DISABLE_POLLS | default "false" | toBool -}} +{{ $DISABLE_REACTIONS := .Env.DISABLE_REACTIONS | default "false" | toBool -}} +{{ $DISABLE_REMOTE_VIDEO_MENU := .Env.DISABLE_REMOTE_VIDEO_MENU | default "false" | toBool -}} +{{ $DISABLE_PRIVATE_CHAT:= .Env.DISABLE_PRIVATE_CHAT | default "false" | toBool -}} +{{ $DISABLE_KICKOUT := .Env.DISABLE_KICKOUT | default "false" | toBool -}} +{{ $DISABLE_GRANT_MODERATOR := .Env.DISABLE_GRANT_MODERATOR | default "false" | toBool -}} +{{ $ENABLE_E2EPING := .Env.ENABLE_E2EPING | default "false" | toBool -}} +{{ $DISABLE_LOCAL_RECORDING := .Env.DISABLE_LOCAL_RECORDING | default "false" | toBool -}} +{{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT := .Env.ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT | default "false" | toBool -}} +{{ $ENABLE_LOCAL_RECORDING_SELF_START := .Env.ENABLE_LOCAL_RECORDING_SELF_START | default "false" | toBool -}} +{{ $DISABLE_PROFILE := .Env.DISABLE_PROFILE | default "false" | toBool -}} +{{ $ROOM_PASSWORD_DIGITS := .Env.ROOM_PASSWORD_DIGITS | default "false" -}} +{{ $WHITEBOARD_COLLAB_SERVER_PUBLIC_URL := .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL | default "" -}} +{{ $WHITEBOARD_ENABLED := .Env.WHITEBOARD_ENABLED | default "false" | toBool -}} + +// Giphy +config.giphy = { enabled: true, sdkKey: 'xL9gUISOB9vvb9UV3giMl4cV68mI0Gas', displayMode: 'all', tileTime: 5000 }; + +// Video configuration. +// + +if (!config.hasOwnProperty('constraints')) config.constraints = {}; +if (!config.constraints.hasOwnProperty('video')) config.constraints.video = {}; + +config.resolution = {{ $RESOLUTION }}; +config.constraints.video.height = { ideal: {{ $RESOLUTION }}, max: {{ $RESOLUTION }}, min: {{ $RESOLUTION_MIN }} }; +config.constraints.video.width = { ideal: {{ $RESOLUTION_WIDTH }}, max: {{ $RESOLUTION_WIDTH }}, min: {{ $RESOLUTION_WIDTH_MIN }}}; +config.disableSimulcast = {{ not $ENABLE_SIMULCAST }}; +config.startVideoMuted = {{ $START_VIDEO_MUTED }}; +config.startWithVideoMuted = {{ $START_WITH_VIDEO_MUTED }}; + +{{ if .Env.START_BITRATE -}} +config.startBitrate = '{{ .Env.START_BITRATE }}'; +{{ end -}} + +if (!config.hasOwnProperty('flags')) config.flags = {}; +config.flags.sourceNameSignaling = true; +config.flags.sendMultipleVideoStreams = true; +config.flags.receiveMultipleVideoStreams = true; + + +// ScreenShare Configuration. +// + +config.desktopSharingFrameRate = { min: {{ $DESKTOP_SHARING_FRAMERATE_MIN }}, max: {{ $DESKTOP_SHARING_FRAMERATE_MAX }} }; + +// Audio configuration. +// + +config.enableNoAudioDetection = {{ $ENABLE_NO_AUDIO_DETECTION }}; +config.enableTalkWhileMuted = {{ $ENABLE_TALK_WHILE_MUTED }}; +config.disableAP = {{ not $ENABLE_AUDIO_PROCESSING }}; + +if (!config.hasOwnProperty('audioQuality')) config.audioQuality = {}; +config.audioQuality.stereo = {{ $ENABLE_STEREO }}; + +{{ if .Env.AUDIO_QUALITY_OPUS_BITRATE -}} +config.audioQuality.opusMaxAverageBitrate = '{{ .Env.AUDIO_QUALITY_OPUS_BITRATE }}'; +{{ end -}} + +config.startAudioOnly = {{ $START_AUDIO_ONLY }}; +config.startAudioMuted = {{ $START_AUDIO_MUTED }}; +config.startWithAudioMuted = {{ $START_WITH_AUDIO_MUTED }}; +config.startSilent = {{ $START_SILENT }}; +config.enableOpusRed = {{ $ENABLE_OPUS_RED }}; +config.disableAudioLevels = {{ $DISABLE_AUDIO_LEVELS }}; +config.enableNoisyMicDetection = {{ $ENABLE_NOISY_MIC_DETECTION }}; + + +// Peer-to-Peer options. +// + +if (!config.hasOwnProperty('p2p')) config.p2p = {}; + +config.p2p.enabled = {{ $ENABLE_P2P }}; + + +// Breakout Rooms +// + +config.hideAddRoomButton = {{ $ENABLE_BREAKOUT_ROOMS | not }}; + + +// Etherpad +// + +{{ if .Env.ETHERPAD_PUBLIC_URL -}} +config.etherpad_base = '{{ .Env.ETHERPAD_PUBLIC_URL }}'; +{{ else if .Env.ETHERPAD_URL_BASE -}} +config.etherpad_base = '{{ $PUBLIC_URL }}/etherpad/p/'; +{{ end -}} + + +// Recording. +// + +{{ if $ENABLE_RECORDING -}} + +config.hiddenDomain = '{{ $XMPP_RECORDER_DOMAIN }}'; + +if (!config.hasOwnProperty('recordingService')) config.recordingService = {}; + +// Whether to enable file recording or not using the "service" defined by the finalizer in Jibri +config.recordingService.enabled = {{ $ENABLE_SERVICE_RECORDING }}; + +// Whether to show the possibility to share file recording with other people +// (e.g. meeting participants), based on the actual implementation +// on the backend. +config.recordingService.sharingEnabled = {{ $ENABLE_FILE_RECORDING_SHARING }}; + +// Live streaming configuration. +if (!config.hasOwnProperty('liveStreaming')) config.liveStreaming = {}; +config.liveStreaming.enabled = {{ $ENABLE_LIVESTREAMING }}; +config.liveStreaming.dataPrivacyLink= '{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK }}'; +config.liveStreaming.helpLink= '{{ $ENABLE_LIVESTREAMING_HELP_LINK }}'; +config.liveStreaming.termsLink= '{{ $ENABLE_LIVESTREAMING_TERMS_LINK }}'; +config.liveStreaming.validatorRegExpString= '{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING }}'; + +{{ if .Env.DROPBOX_APPKEY -}} +// Enable the dropbox integration. +if (!config.hasOwnProperty('dropbox')) config.dropbox = {}; +config.dropbox.appKey = '{{ .Env.DROPBOX_APPKEY }}'; +{{ if .Env.DROPBOX_REDIRECT_URI -}} +// A URL to redirect the user to, after authenticating +// by default uses: +// 'https://jitsi-meet.example.com/static/oauth.html' +config.dropbox.redirectURI = '{{ .Env.DROPBOX_REDIRECT_URI }}'; +{{ end -}} +{{ end -}} +{{ end -}} + + +// Local recording configuration. +if (!config.hasOwnProperty('localRecording')) config.localRecording = {}; +config.localRecording.disable = {{ $DISABLE_LOCAL_RECORDING }}; +config.localRecording.notifyAllParticipants = {{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT }}; +config.localRecording.disableSelfRecording = {{ $ENABLE_LOCAL_RECORDING_SELF_START }}; + + +// Analytics. +// + +if (!config.hasOwnProperty('analytics')) config.analytics = {}; + +{{ if .Env.AMPLITUDE_ID -}} +// The Amplitude APP Key: +config.analytics.amplitudeAPPKey = '{{ .Env.AMPLITUDE_ID }}'; +{{ end -}} + +{{ if .Env.GOOGLE_ANALYTICS_ID -}} +// The Google Analytics Tracking ID: +config.analytics.googleAnalyticsTrackingId = '{{ .Env.GOOGLE_ANALYTICS_ID }}'; +{{ end -}} + +{{ if .Env.MATOMO_ENDPOINT -}} +// Matomo endpoint: +config.analytics.matomoEndpoint = '{{ .Env.MATOMO_ENDPOINT }}'; +{{ end -}} + +{{ if .Env.MATOMO_SITE_ID -}} +// Matomo site ID: +config.analytics.matomoSiteID = '{{ .Env.MATOMO_SITE_ID }}'; +{{ end -}} + +{{ if .Env.ANALYTICS_SCRIPT_URLS -}} +// Array of script URLs to load as lib-jitsi-meet "analytics handlers". +config.analytics.scriptURLs = [ '{{ join "','" (splitList "," .Env.ANALYTICS_SCRIPT_URLS) }}' ]; +{{ end -}} + +{{ if .Env.ANALYTICS_WHITELISTED_EVENTS -}} +config.analytics.whiteListedEvents = [ '{{ join "','" (splitList "," .Env.ANALYTICS_WHITELISTED_EVENTS) }}' ]; +{{ end -}} + +{{ if .Env.CALLSTATS_CUSTOM_SCRIPT_URL -}} +config.callStatsCustomScriptUrl = '{{ .Env.CALLSTATS_CUSTOM_SCRIPT_URL }}'; +{{ end -}} + +{{ if .Env.CALLSTATS_ID -}} +// To enable sending statistics to callstats.io you must provide the +// Application ID and Secret. +config.callStatsID = '{{ .Env.CALLSTATS_ID }}'; +{{ end -}} + +{{ if .Env.CALLSTATS_ID -}} +config.callStatsSecret = '{{ .Env.CALLSTATS_SECRET }}'; +{{ end -}} + +// Enables callstatsUsername to be reported as statsId and used +// by callstats as repoted remote id. +config.enableStatsID = {{ $ENABLE_STATS_ID }}; + + +// Dial in/out services. +// + +{{ if $ENABLE_JAAS_COMPONENTS }} +config.dialInConfCodeUrl = 'https://conference-mapper.jitsi.net/v1/access'; +config.dialInNumbersUrl = 'https://conference-mapper.jitsi.net/v1/access/dids'; +{{ else }} +{{ if .Env.CONFCODE_URL -}} +config.dialInConfCodeUrl = '{{ .Env.CONFCODE_URL }}'; +{{ end -}} +{{ if .Env.DIALIN_NUMBERS_URL -}} +config.dialInNumbersUrl = '{{ .Env.DIALIN_NUMBERS_URL }}'; +{{ end -}} +{{ end -}} + +{{ if .Env.DIALOUT_AUTH_URL -}} +config.dialOutAuthUrl = '{{ .Env.DIALOUT_AUTH_URL }}'; +{{ end -}} + +{{ if .Env.DIALOUT_CODES_URL -}} +config.dialOutCodesUrl = '{{ .Env.DIALOUT_CODES_URL }}'; +{{ end -}} + + +// Calendar service integration. +// + +config.enableCalendarIntegration = {{ $ENABLE_CALENDAR }}; + +{{ if .Env.GOOGLE_API_APP_CLIENT_ID -}} +config.googleApiApplicationClientID = '{{ .Env.GOOGLE_API_APP_CLIENT_ID }}'; +{{ end -}} + +{{ if .Env.MICROSOFT_API_APP_CLIENT_ID -}} +config.microsoftApiApplicationClientID = '{{ .Env.MICROSOFT_API_APP_CLIENT_ID }}'; +{{ end -}} + + +// Invitation service. +// + +{{ if .Env.INVITE_SERVICE_URL -}} +config.inviteServiceUrl = '{{ .Env.INVITE_SERVICE_URL }}'; +{{ end -}} + +{{ if .Env.PEOPLE_SEARCH_URL -}} +config.peopleSearchUrl = '{{ .Env.PEOPLE_SEARCH_URL }}'; +config.peopleSearchQueryTypes = ['user','conferenceRooms']; +{{ end -}} + + +// Miscellaneous. +// + +// Prejoin page. +if (!config.hasOwnProperty('prejoinConfig')) config.prejoinConfig = {}; +config.prejoinConfig.enabled = {{ $ENABLE_PREJOIN_PAGE }}; + +// Hides the participant name editing field in the prejoin screen. +config.prejoinConfig.hideDisplayName = {{ $HIDE_PREJOIN_DISPLAY_NAME }}; + +// List of buttons to hide from the extra join options dropdown on prejoin screen. +{{ if .Env.HIDE_PREJOIN_EXTRA_BUTTONS -}} +config.prejoinConfig.hideExtraJoinButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREJOIN_EXTRA_BUTTONS) }}' ]; +{{ end -}} + +// Welcome page. +config.enableWelcomePage = {{ $ENABLE_WELCOME_PAGE }}; + +// Close page. +config.enableClosePage = {{ $ENABLE_CLOSE_PAGE }}; + +// Default language. +{{ if .Env.DEFAULT_LANGUAGE -}} +config.defaultLanguage = '{{ .Env.DEFAULT_LANGUAGE }}'; +{{ end -}} + +// Require users to always specify a display name. +config.requireDisplayName = {{ $ENABLE_REQUIRE_DISPLAY_NAME }}; + +// Chrome extension banner. +{{ if .Env.CHROME_EXTENSION_BANNER_JSON -}} +config.chromeExtensionBanner = {{ .Env.CHROME_EXTENSION_BANNER_JSON }}; +{{ end -}} + +// Disables profile and the edit of all fields from the profile settings (display name and email) +config.disableProfile = {{ $DISABLE_PROFILE }}; + +// Room password (false for anything, number for max digits) +{{ if $ENABLE_JAAS_COMPONENTS -}} +config.roomPasswordNumberOfDigits = 10; +{{ else -}} +config.roomPasswordNumberOfDigits = {{ $ROOM_PASSWORD_DIGITS }}; +{{ end -}} + +// Advanced. +// + +// Lipsync hack in jicofo, may not be safe. +config.enableLipSync = {{ $ENABLE_LIPSYNC }}; + +config.enableRemb = {{ $ENABLE_REMB }}; +config.enableTcc = {{ $ENABLE_TCC }}; + +// Enable IPv6 support. +config.useIPv6 = {{ $ENABLE_IPV6 }}; + +// Transcriptions (subtitles and buttons can be configured in interface_config) +config.transcription = { enabled: {{ $ENABLE_TRANSCRIPTIONS }} }; +config.transcription.translationLanguages = {{ $TRANSLATION_LANGUAGES }}; +config.transcription.translationLanguagesHead = {{ $TRANSLATION_LANGUAGES_HEAD }}; +config.transcription.useAppLanguage = {{ $USE_APP_LANGUAGE }}; +config.transcription.preferredLanguage = '{{ $PREFERRED_LANGUAGE }}'; +config.transcription.disableStartForAll = {{ $DISABLE_START_FOR_ALL }}; +config.transcription.autoCaptionOnRecord = {{ $AUTO_CAPTION_ON_RECORD }}; + +{{ if .Env.DYNAMIC_BRANDING_URL -}} +// External API url used to receive branding specific information. +config.dynamicBrandingUrl = '{{ .Env.DYNAMIC_BRANDING_URL }}'; +{{ else if .Env.BRANDING_DATA_URL -}} +config.brandingDataUrl = '{{ .Env.BRANDING_DATA_URL }}'; +{{ end -}} + +{{ if .Env.TOKEN_AUTH_URL -}} +// Authenticate using external service or just focus external auth window if there is one already. +config.tokenAuthUrl = '{{ .Env.TOKEN_AUTH_URL }}'; +{{ end -}} + + +// Deployment information. +// + +if (!config.hasOwnProperty('deploymentInfo')) config.deploymentInfo = {}; + +{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT -}} +config.deploymentInfo.environment = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT }}'; +{{ end -}} + +{{ if .Env.DEPLOYMENTINFO_SHARD -}} +config.deploymentInfo.shard = '{{ .Env.DEPLOYMENTINFO_SHARD }}'; +{{ end -}} + +{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE -}} +config.deploymentInfo.envType = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE }}'; +{{ end -}} + +{{ if .Env.DEPLOYMENTINFO_REGION -}} +config.deploymentInfo.region = '{{ .Env.DEPLOYMENTINFO_REGION }}'; +{{ end -}} + +{{ if $DEPLOYMENTINFO_USERREGION -}} +config.deploymentInfo.userRegion = '{{ $DEPLOYMENTINFO_USERREGION }}'; +{{ end -}} + + +// SSI +config.deploymentInfo.userRegion =''; // SSI Instruction +config.deploymentInfo.region =''; // SSI Instruction + + + +// Testing +// + +if (!config.hasOwnProperty('testing')) config.testing = {}; +if (!config.testing.hasOwnProperty('octo')) config.testing.octo = {}; + +config.testing.capScreenshareBitrate = {{ $TESTING_CAP_SCREENSHARE_BITRATE }}; +config.testing.octo.probability = {{ $TESTING_OCTO_PROBABILITY }}; + +// Deep Linking +config.disableDeepLinking = {{ $DISABLE_DEEP_LINKING }}; + +// P2P preferred codec +{{ if .Env.P2P_PREFERRED_CODEC -}} +config.p2p.preferredCodec = '{{ .Env.P2P_PREFERRED_CODEC }}'; +{{ end -}} + +// Enable preferred video Codec +if (!config.hasOwnProperty('videoQuality')) config.videoQuality = {}; +{{ if .Env.VIDEOQUALITY_PREFERRED_CODEC -}} +config.videoQuality.preferredCodec = '{{ .Env.VIDEOQUALITY_PREFERRED_CODEC }}'; +{{ end -}} + +config.videoQuality.enforcePreferredCodec = {{ $VIDEOQUALITY_ENFORCE_PREFERRED_CODEC }}; + +if (!config.videoQuality.hasOwnProperty('maxBitratesVideo')) config.videoQuality.maxBitratesVideo = null; +{{ if and .Env.VIDEOQUALITY_BITRATE_H264_LOW .Env.VIDEOQUALITY_BITRATE_H264_STANDARD .Env.VIDEOQUALITY_BITRATE_H264_HIGH -}} +config.videoQuality.maxBitratesVideo = config.videoQuality.maxBitratesVideo || {} +config.videoQuality.maxBitratesVideo.H264 = { low: {{ .Env.VIDEOQUALITY_BITRATE_H264_LOW }}, standard: {{ .Env.VIDEOQUALITY_BITRATE_H264_STANDARD }}, high: {{ .Env.VIDEOQUALITY_BITRATE_H264_HIGH }} }; +{{ end -}} +{{ if and .Env.VIDEOQUALITY_BITRATE_VP8_LOW .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD .Env.VIDEOQUALITY_BITRATE_VP8_HIGH -}} +config.videoQuality.maxBitratesVideo = config.videoQuality.maxBitratesVideo || {} +config.videoQuality.maxBitratesVideo.VP8 = { low: {{ .Env.VIDEOQUALITY_BITRATE_VP8_LOW }}, standard: {{ .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD }}, high: {{ .Env.VIDEOQUALITY_BITRATE_VP8_HIGH }} }; +{{ end -}} +{{ if and .Env.VIDEOQUALITY_BITRATE_VP9_LOW .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD .Env.VIDEOQUALITY_BITRATE_VP9_HIGH -}} +config.videoQuality.maxBitratesVideo = config.videoQuality.maxBitratesVideo || {} +config.videoQuality.maxBitratesVideo.VP9 = { low: {{ .Env.VIDEOQUALITY_BITRATE_VP9_LOW }}, standard: {{ .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD }}, high: {{ .Env.VIDEOQUALITY_BITRATE_VP9_HIGH }} }; +{{ end -}} +{{ if and .Env.VIDEOQUALITY_BITRATE_AV1_LOW .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD .Env.VIDEOQUALITY_BITRATE_AV1_HIGH -}} +config.videoQuality.maxBitratesVideo = config.videoQuality.maxBitratesVideo || {} +config.videoQuality.maxBitratesVideo.AV1 = { low: {{ .Env.VIDEOQUALITY_BITRATE_AV1_LOW }}, standard: {{ .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD }}, high: {{ .Env.VIDEOQUALITY_BITRATE_AV1_HIGH }} }; +{{ end -}} + + // Reactions +config.disableReactions = {{ $DISABLE_REACTIONS }}; + +// Polls +config.disablePolls = {{ $DISABLE_POLLS }}; + +// Configure toolbar buttons +{{ if .Env.TOOLBAR_BUTTONS -}} +config.toolbarButtons = [ '{{ join "','" (splitList "," .Env.TOOLBAR_BUTTONS) }}' ]; +{{ end -}} + +// Hides the buttons at pre-join screen +{{ if .Env.HIDE_PREMEETING_BUTTONS -}} +config.hiddenPremeetingButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREMEETING_BUTTONS) }}' ]; +{{ end -}} + +// Configure remote participant video menu +if (!config.hasOwnProperty('remoteVideoMenu')) config.remoteVideoMenu = {}; +config.remoteVideoMenu.disabled = {{ $DISABLE_REMOTE_VIDEO_MENU }}; +config.remoteVideoMenu.disableKick = {{ $DISABLE_KICKOUT }}; +config.remoteVideoMenu.disableGrantModerator = {{ $DISABLE_GRANT_MODERATOR }}; +config.remoteVideoMenu.disablePrivateChat = {{ $DISABLE_PRIVATE_CHAT }}; + +// Configure e2eping +if (!config.hasOwnProperty('e2eping')) config.e2eping = {}; +config.e2eping.enabled = {{ $ENABLE_E2EPING }}; +{{ if .Env.E2EPING_NUM_REQUESTS -}} +config.e2eping.numRequests = {{ .Env.E2EPING_NUM_REQUESTS }}; +{{ end -}} +{{ if .Env.E2EPING_MAX_CONFERENCE_SIZE -}} +config.e2eping.maxConferenceSize = {{ .Env.E2EPING_MAX_CONFERENCE_SIZE }}; +{{ end -}} +{{ if .Env.E2EPING_MAX_MESSAGE_PER_SECOND -}} +config.e2eping.maxMessagePerSecond = {{ .Env.E2EPING_MAX_MESSAGE_PER_SECOND }}; +{{ end }} + +// Settings for the Excalidraw whiteboard integration. +if (!config.hasOwnProperty('whiteboard')) config.whiteboard = {}; +config.whiteboard.enabled = {{ $WHITEBOARD_ENABLED }}; +config.whiteboard.collabServerBaseUrl = '{{ $WHITEBOARD_COLLAB_SERVER_PUBLIC_URL }}'; + diff --git a/charts/jitsi/files/sip-communicator.properties b/charts/jitsi/files/sip-communicator.properties new file mode 100644 index 0000000..16d9fe6 --- /dev/null +++ b/charts/jitsi/files/sip-communicator.properties @@ -0,0 +1,181 @@ +{{ $JIGASI_BREWERY_MUC := .Env.JIGASI_BREWERY_MUC | default "jigasibrewery" -}} +{{ $JIGASI_XMPP_USER := .Env.JIGASI_XMPP_USER | default "jigasi" -}} +{{ $XMPP_AUTH_DOMAIN := .Env.XMPP_AUTH_DOMAIN | default "auth.meet.jitsi" -}} +{{ $XMPP_MUC_DOMAIN := .Env.XMPP_MUC_DOMAIN | default "muc.meet.jitsi" -}} +{{ $XMPP_GUEST_DOMAIN := .Env.XMPP_GUEST_DOMAIN | default "guest.meet.jitsi" -}} +{{ $XMPP_INTERNAL_MUC_DOMAIN := .Env.XMPP_INTERNAL_MUC_DOMAIN | default "internal-muc.meet.jitsi" -}} +{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}} +{{ $XMPP_PORT := .Env.XMPP_PORT | default "5222" -}} +{{ $XMPP_SERVER := .Env.XMPP_SERVER | default "xmpp.meet.jitsi" -}} +{{ $XMPP_SERVERS := splitList "," $XMPP_SERVER -}} +{{ $SHUTDOWN_REST_ENABLED := .Env.SHUTDOWN_REST_ENABLED | default "false" | toBool -}} +{{ $DISABLE_SIP := .Env.JIGASI_DISABLE_SIP | default "false" | toBool -}} +{{/* assign env from context, preserve during range when . is re-assigned */}} +{{ $ENV := .Env -}} + +net.java.sip.communicator.impl.protocol.SingleCallInProgressPolicy.enabled=false + +# Adjust opus encoder complexity +net.java.sip.communicator.impl.neomedia.codec.audio.opus.encoder.COMPLEXITY=10 + +# Disables packet logging +net.java.sip.communicator.packetlogging.PACKET_LOGGING_ENABLED=false + +# Control REST Shutdown +org.jitsi.jigasi.ENABLE_REST_SHUTDOWN={{ $SHUTDOWN_REST_ENABLED }} + +# SIP account +net.java.sip.communicator.impl.protocol.sip.acc1=acc1 +{{ if .Env.JIGASI_SIP_SERVER }} +net.java.sip.communicator.impl.protocol.sip.acc1.PROXY_ADDRESS={{ .Env.JIGASI_SIP_SERVER }} +net.java.sip.communicator.impl.protocol.sip.acc1.PROXY_AUTO_CONFIG=false +net.java.sip.communicator.impl.protocol.sip.acc1.PROXY_PORT={{ .Env.JIGASI_SIP_PORT | default "5060" }} +net.java.sip.communicator.impl.protocol.sip.acc1.PREFERRED_TRANSPORT={{ .Env.JIGASI_SIP_TRANSPORT | default "UDP" }} +{{ end }} +{{ if .Env.JIGASI_ENABLE_SDES_SRTP | default "0" | toBool }} +net.java.sip.communicator.impl.protocol.sip.acc1.SAVP_OPTION=1 +net.java.sip.communicator.impl.protocol.sip.acc1.DEFAULT_ENCRYPTION=true +net.java.sip.communicator.impl.protocol.sip.acc1.DEFAULT_SIPZRTP_ATTRIBUTE=false +net.java.sip.communicator.impl.protocol.sip.acc1.ENCRYPTION_PROTOCOL.ZRTP=0 +net.java.sip.communicator.impl.protocol.sip.acc1.ENCRYPTION_PROTOCOL.SDES=1 +net.java.sip.communicator.impl.protocol.sip.acc1.ENCRYPTION_PROTOCOL.DTLS-SRTP=0 +net.java.sip.communicator.impl.protocol.sip.acc1.ENCRYPTION_PROTOCOL_STATUS.ZRTP=false +net.java.sip.communicator.impl.protocol.sip.acc1.ENCRYPTION_PROTOCOL_STATUS.SDES=true +net.java.sip.communicator.impl.protocol.sip.acc1.ENCRYPTION_PROTOCOL_STATUS.DTLS-SRTP=false +net.java.sip.communicator.impl.protocol.sip.acc1.SDES_CIPHER_SUITES=AES_CM_128_HMAC_SHA1_80,AES_CM_128_HMAC_SHA1_32 +{{ end }} +net.java.sip.communicator.impl.protocol.sip.acc1.ACCOUNT_UID=SIP\:{{ .Env.JIGASI_SIP_URI }} +net.java.sip.communicator.impl.protocol.sip.acc1.PASSWORD={{ .Env.JIGASI_SIP_PASSWORD | b64enc }} +net.java.sip.communicator.impl.protocol.sip.acc1.PROTOCOL_NAME=SIP +net.java.sip.communicator.impl.protocol.sip.acc1.SERVER_ADDRESS={{ .Env.JIGASI_SIP_SERVER }} +net.java.sip.communicator.impl.protocol.sip.acc1.USER_ID={{ .Env.JIGASI_SIP_URI }} +net.java.sip.communicator.impl.protocol.sip.acc1.KEEP_ALIVE_INTERVAL=25 +net.java.sip.communicator.impl.protocol.sip.acc1.KEEP_ALIVE_METHOD={{ .Env.JIGASI_SIP_KEEP_ALIVE_METHOD | default "OPTIONS" }} +net.java.sip.communicator.impl.protocol.sip.acc1.VOICEMAIL_ENABLED=false +net.java.sip.communicator.impl.protocol.sip.acc1.JITSI_MEET_ROOM_HEADER_NAME=X-Room-Name +net.java.sip.communicator.impl.protocol.sip.acc1.JITSI_MEET_DOMAIN_BASE_HEADER_NAME=X-Domain-Base +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.AMR-WB/16000=750 +# Temporarily disable G722, see: https://github.com/jitsi/docker-jitsi-meet/issues/1357 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.G722/8000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.GSM/8000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.H263-1998/90000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.H264/90000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.PCMA/8000=600 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.PCMU/8000=650 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.SILK/12000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.SILK/16000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.SILK/24000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.SILK/8000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.VP8/90000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.iLBC/8000=10 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.opus/48000=1000 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.red/90000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.speex/16000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.speex/32000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.speex/8000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.telephone-event/8000=1 +net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.ulpfec/90000=0 +net.java.sip.communicator.impl.protocol.sip.acc1.OVERRIDE_ENCODINGS=true +net.java.sip.communicator.impl.protocol.sip.acc1.DOMAIN_BASE={{ $XMPP_DOMAIN }} + +# XMPP account used for control + +{{ range $index, $element := $XMPP_SERVERS -}} +{{ $SERVER := splitn ":" 2 $element }} +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}=acc{{ $index }} +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.ACCOUNT_UID=Jabber:{{ $JIGASI_XMPP_USER }}@{{ $XMPP_AUTH_DOMAIN }} +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.USER_ID={{ $JIGASI_XMPP_USER }}@{{ $XMPP_AUTH_DOMAIN }} +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.IS_SERVER_OVERRIDDEN=true +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.SERVER_ADDRESS={{ $SERVER._0 }} +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.SERVER_PORT={{ $SERVER._1 | default $XMPP_PORT }} +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.PASSWORD={{ $ENV.JIGASI_XMPP_PASSWORD | b64enc }} +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.AUTO_GENERATE_RESOURCE=true +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.RESOURCE_PRIORITY=30 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.IS_CARBON_DISABLED=true +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.DEFAULT_ENCRYPTION=true +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.IS_USE_ICE=true +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.IS_ACCOUNT_DISABLED=false +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.IS_PREFERRED_PROTOCOL=false +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.AUTO_DISCOVER_JINGLE_NODES=false +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.PROTOCOL=Jabber +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.IS_USE_UPNP=false +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.USE_DEFAULT_STUN_SERVER=true +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.ENCRYPTION_PROTOCOL.DTLS-SRTP=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.ENCRYPTION_PROTOCOL_STATUS.DTLS-SRTP=true +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.VIDEO_CALLING_DISABLED=true +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.OVERRIDE_ENCODINGS=true +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.G722/8000=705 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.GSM/8000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.H263-1998/90000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.H264/90000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.PCMA/8000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.PCMU/8000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.SILK/12000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.SILK/16000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.SILK/24000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.SILK/8000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.VP8/90000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.iLBC/8000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.opus/48000=750 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.speex/16000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.speex/32000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.speex/8000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.Encodings.telephone-event/8000=0 +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.BREWERY={{ $JIGASI_BREWERY_MUC }}@{{ $XMPP_INTERNAL_MUC_DOMAIN }} +net.java.sip.communicator.impl.protocol.jabber.acc{{ $index }}.DOMAIN_BASE={{ $XMPP_DOMAIN }} +{{ end -}} +org.jitsi.jigasi.BREWERY_ENABLED=true +org.jitsi.jigasi.ENABLE_SIP={{ not $DISABLE_SIP }} + +org.jitsi.jigasi.HEALTH_CHECK_SIP_URI={{ .Env.JIGASI_HEALTH_CHECK_SIP_URI | default "" }} +org.jitsi.jigasi.HEALTH_CHECK_INTERVAL={{ .Env.JIGASI_HEALTH_CHECK_INTERVAL | default "300000" }} +org.jitsi.jigasi.HEALTH_CHECK_TIMEOUT=600000 + +org.jitsi.jigasi.xmpp.acc.IS_SERVER_OVERRIDDEN=true +org.jitsi.jigasi.xmpp.acc.SERVER_ADDRESS={{ $XMPP_SERVER }} +org.jitsi.jigasi.xmpp.acc.VIDEO_CALLING_DISABLED=true +org.jitsi.jigasi.xmpp.acc.JINGLE_NODES_ENABLED=false +org.jitsi.jigasi.xmpp.acc.AUTO_DISCOVER_STUN=false +org.jitsi.jigasi.xmpp.acc.IM_DISABLED=true +org.jitsi.jigasi.xmpp.acc.SERVER_STORED_INFO_DISABLED=true +org.jitsi.jigasi.xmpp.acc.IS_FILE_TRANSFER_DISABLED=true +{{ if .Env.ENABLE_AUTH | default "0" | toBool }} +{{ if .Env.ENABLE_GUESTS | default "0" | toBool }} +org.jitsi.jigasi.xmpp.acc.USER_ID={{ $JIGASI_XMPP_USER }}@{{ $XMPP_GUEST_DOMAIN }} +org.jitsi.jigasi.xmpp.acc.ANONYMOUS_AUTH=true +{{ else }} +org.jitsi.jigasi.xmpp.acc.USER_ID={{ $JIGASI_XMPP_USER }}@{{ $XMPP_AUTH_DOMAIN }} +org.jitsi.jigasi.xmpp.acc.ANONYMOUS_AUTH=false +{{ end }} +org.jitsi.jigasi.xmpp.acc.PASS={{ .Env.JIGASI_XMPP_PASSWORD }} +org.jitsi.jigasi.xmpp.acc.ALLOW_NON_SECURE=true +{{ end }} + +# Activate this property if you are using self-signed certificates or other +# type of non-trusted certicates. In this mode your service trust in the +# remote certificates always. +net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED=true + +{{ if .Env.ENABLE_TRANSCRIPTIONS | default "0" | toBool }} +# Transcription config +org.jitsi.jigasi.ENABLE_TRANSCRIPTION=true +org.jitsi.jigasi.transcription.ENABLE_TRANSLATION=true +org.jitsi.jigasi.transcription.DIRECTORY=/tmp/transcripts +org.jitsi.jigasi.transcription.BASE_URL={{ .Env.PUBLIC_URL }}/transcripts +org.jitsi.jigasi.transcription.jetty.port=-1 +org.jitsi.jigasi.transcription.ADVERTISE_URL={{ .Env.JIGASI_TRANSCRIBER_ADVERTISE_URL | default "false"}} +org.jitsi.jigasi.transcription.SAVE_JSON=false +org.jitsi.jigasi.transcription.SEND_JSON=true +org.jitsi.jigasi.transcription.SAVE_TXT=true +org.jitsi.jigasi.transcription.SEND_TXT={{ .Env.JIGASI_TRANSCRIBER_SEND_TXT | default "false"}} +org.jitsi.jigasi.transcription.RECORD_AUDIO={{ .Env.JIGASI_TRANSCRIBER_RECORD_AUDIO | default "false"}} +org.jitsi.jigasi.transcription.RECORD_AUDIO_FORMAT=wav +org.jitsi.jigasi.transcription.customService=org.jitsi.jigasi.transcription.VoskTranscriptionService +org.jitsi.jigasi.transcription.vosk.websocket_url=ws://{{ .Env.VOSK_SVC }}:2700 +{{end}} + +{{ if .Env.JIGASI_SIP_DEFAULT_ROOM }} +org.jitsi.jigasi.DEFAULT_JVB_ROOM_NAME={{ .Env.JIGASI_SIP_DEFAULT_ROOM }} +{{ end }} + +org.jitsi.jigasi.MUC_SERVICE_ADDRESS={{ $XMPP_MUC_DOMAIN }} diff --git a/charts/jitsi/templates/NOTES.txt b/charts/jitsi/templates/NOTES.txt new file mode 100644 index 0000000..c1e2bcc --- /dev/null +++ b/charts/jitsi/templates/NOTES.txt @@ -0,0 +1,21 @@ +1. Get the application URL by running these commands: +{{- if .Values.web.ingress.enabled }} +{{- range $host := .Values.web.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.web.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.web.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "jitsi-meet.web.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.web.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "jitsi-meet.web.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "jitsi-meet.web.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.web.service.port }} +{{- else if contains "ClusterIP" .Values.web.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "jitsi-meet.name" . }},app.kubernetes.io/component=web,app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/charts/jitsi/templates/_helpers.tpl b/charts/jitsi/templates/_helpers.tpl new file mode 100644 index 0000000..8f607bf --- /dev/null +++ b/charts/jitsi/templates/_helpers.tpl @@ -0,0 +1,112 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "jitsi-meet.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "jitsi-meet.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "jitsi-meet.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "jitsi-meet.labels" -}} +helm.sh/chart: {{ include "jitsi-meet.chart" . }} +{{ include "jitsi-meet.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "jitsi-meet.selectorLabels" -}} +app.kubernetes.io/name: {{ include "jitsi-meet.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "jitsi-meet.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "jitsi-meet.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* + https://github.com/helm/helm/issues/4535 +*/}} +{{- define "call-nested" }} +{{- $dot := index . 0 }} +{{- $subchart := index . 1 }} +{{- $template := index . 2 }} +{{- include $template (dict "Chart" (dict "Name" $subchart) "Values" (index $dot.Values $subchart) "Release" $dot.Release "Capabilities" $dot.Capabilities) }} +{{- end }} + +{{- define "jitsi-meet.xmpp.domain" -}} +{{- if .Values.xmpp.domain -}} + {{ .Values.xmpp.domain }} +{{- else -}} +{{- if .Values.global.clusterDomain -}} + {{ .Release.Namespace }}.svc.{{ .Values.global.clusterDomain }} +{{- else -}} + {{ .Release.Namespace }}.svc +{{- end -}} +{{- end -}} +{{- end -}} + +{{- define "jitsi-meet.xmpp.server" -}} +{{- if .Values.prosody.server -}} + {{ .Values.prosody.server }} +{{- else -}} +{{- if .Values.global.clusterDomain -}} + {{ include "call-nested" (list . "prosody" "prosody.fullname") }}.{{ .Release.Namespace }}.svc.{{ .Values.global.clusterDomain }} +{{- else -}} + {{ include "call-nested" (list . "prosody" "prosody.fullname") }}.{{ .Release.Namespace }}.svc +{{- end -}} +{{- end -}} +{{- end -}} + + +{{- define "jitsi-meet.publicURL" -}} +{{- if .Values.publicURL }} +{{- .Values.publicURL -}} +{{- else -}} +{{- if .Values.web.ingress.tls -}}https://{{- else -}}http://{{- end -}} +{{- if .Values.web.ingress.tls -}} +{{- (.Values.web.ingress.tls|first).hosts|first -}} +{{- else if .Values.web.ingress.hosts -}} +{{- (.Values.web.ingress.hosts|first).host -}} +{{ required "You need to define a publicURL or some value for ingress" .Values.publicURL }} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/jitsi/templates/common-configmap.yaml b/charts/jitsi/templates/common-configmap.yaml new file mode 100644 index 0000000..acf24fd --- /dev/null +++ b/charts/jitsi/templates/common-configmap.yaml @@ -0,0 +1,60 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-common + labels: + {{- include "jitsi-meet.labels" . | nindent 4 }} +data: + ENABLE_AUTH: {{ ternary "1" "0" .Values.enableAuth | quote }} + {{- if .Values.enableAuth }} + AUTH_TYPE: {{ .Values.auth.type }} + JWT_APP_ID: {{ .Values.auth.jwtAppId }} + JWT_APP_SECRET: {{ .Values.auth.jwtAppSecret }} + ADAPTER_INTERNAL_URL: http://{{ .Release.Name }}-keycloak-adapter-svc:9000 + JWT_ALLOW_EMPTY: "1" + JICOFO_AUTH_TYPE: "internal" + JICOFO_AUTH_LIFETIME: "100 milliseconds" + PROSODY_AUTH_TYPE: "jwt" + ENABLE_AUTO_LOGIN: "0" + {{- end }} + ENABLE_GUESTS: {{ ternary "1" "0" .Values.enableGuests | quote }} + PUBLIC_URL: {{ include "jitsi-meet.publicURL" . }} + XMPP_DOMAIN: {{ include "jitsi-meet.xmpp.domain" . }} + XMPP_MUC_DOMAIN: {{ .Values.xmpp.mucDomain | default (printf "muc.%s" (include "jitsi-meet.xmpp.domain" .)) }} + XMPP_AUTH_DOMAIN: {{ .Values.xmpp.authDomain | default (printf "auth.%s" (include "jitsi-meet.xmpp.domain" .)) }} + XMPP_GUEST_DOMAIN: {{ .Values.xmpp.guestDomain | default (printf "guest.%s" (include "jitsi-meet.xmpp.domain" .)) }} + XMPP_RECORDER_DOMAIN: {{ .Values.xmpp.recorderDomain | default (printf "recorder.%s" (include "jitsi-meet.xmpp.domain" .)) }} + XMPP_INTERNAL_MUC_DOMAIN: {{ .Values.xmpp.internalMucDomain | default (printf "internal-muc.%s" (include "jitsi-meet.xmpp.domain" .)) }} + {{- if .Values.websockets.colibri.enabled }} + ENABLE_COLIBRI_WEBSOCKET: 'true' + # TODO: rework into a proper regex or dynamic name list + ENABLE_COLIBRI_WEBSOCKET_UNSAFE_REGEX: '1' + {{- else }} + ENABLE_COLIBRI_WEBSOCKET: 'false' + {{- end }} + {{- if .Values.websockets.xmpp.enabled }} + ENABLE_XMPP_WEBSOCKET: 'true' + {{- else }} + ENABLE_XMPP_WEBSOCKET: 'false' + {{- end }} + {{- if .Values.jibri.enabled }} + {{- if .Values.jibri.recording }} + ENABLE_RECORDING: "true" + ENABLE_FILE_RECORDING_SERVICE_SHARING: "true" + {{- end }} + {{- if .Values.jibri.livestreaming }} + ENABLE_LIVESTREAMING: "true" + {{- end }} + {{- end }} + TZ: '{{ .Values.tz }}' + {{- range $key, $value := .Values.extraCommonEnvs }} + {{- if not (kindIs "invalid" $value) }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} + {{- if .Values.octo.enabled }} + ENABLE_OCTO: "1" + TESTING_OCTO_PROBABILITY: "1" + DEPLOYMENTINFO_REGION: "all" + DEPLOYMENTINFO_USERREGION: "all" + {{- end }} diff --git a/charts/jitsi/templates/geo-selector/deploy.yaml b/charts/jitsi/templates/geo-selector/deploy.yaml new file mode 100644 index 0000000..aac666a --- /dev/null +++ b/charts/jitsi/templates/geo-selector/deploy.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-geoselector +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Release.Name }}-geoselector + template: + metadata: + labels: + app: {{ .Release.Name }}-geoselector + spec: + containers: + - name: {{ .Release.Name }}-geoselector + image: ghcr.io/ethdevops/jitsi-geo-selector:{{ .Values.geoselector.imageTag }} + ports: + - containerPort: 3000 + resources: + {{- toYaml .Values.geoselector.resources | nindent 12 }} diff --git a/charts/jitsi/templates/geo-selector/svc.yaml b/charts/jitsi/templates/geo-selector/svc.yaml new file mode 100644 index 0000000..c50cf8c --- /dev/null +++ b/charts/jitsi/templates/geo-selector/svc.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-geoselector-svc +spec: + selector: + app: {{ .Release.Name }}-geoselector + ports: + - protocol: TCP + port: 3000 + targetPort: 3000 + type: ClusterIP diff --git a/charts/jitsi/templates/ingress.yaml b/charts/jitsi/templates/ingress.yaml new file mode 100644 index 0000000..36a6f7d --- /dev/null +++ b/charts/jitsi/templates/ingress.yaml @@ -0,0 +1,120 @@ +{{- if .Values.web.ingress.enabled -}} +{{- $fullName := include "jitsi-meet.web.fullname" . -}} +{{- $svcPort := .Values.web.service.port -}} +{{- $release := .Release.Name -}} +{{- $kubeVersion := .Capabilities.KubeVersion.GitVersion -}} +{{- if semverCompare ">=1.19-0" $kubeVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" $kubeVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "jitsi-meet.web.labels" . | nindent 4 }} + {{- if or .Values.web.ingress.annotations (and .Values.web.ingress.ingressClassName (semverCompare "<1.19-0" $kubeVersion)) }} + annotations: + {{- if and .Values.web.ingress.ingressClassName (semverCompare "<1.19-0" $kubeVersion) }} + kubernetes.io/ingress.class: {{ .Values.web.ingress.ingressClassName }} + {{- end }} + {{- with .Values.web.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +spec: +{{- if and .Values.web.ingress.ingressClassName (semverCompare ">=1.19-0" $kubeVersion) }} + ingressClassName: {{ .Values.web.ingress.ingressClassName }} +{{- end }} +{{- if .Values.web.ingress.tls }} + tls: + {{- range .Values.web.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + - host: {{ .Values.web.mainHost }} + http: + paths: + - path: '/colibri-relay-ws' + pathType: Prefix + backend: + service: + name: {{ $fullName }} + port: + {{ if kindIs "float64" $svcPort }} + number: {{ $svcPort }} + {{ else }} + name: {{ $svcPort }} + {{ end }} + - path: '/colibri-ws' + pathType: Prefix + backend: + service: + name: {{ $fullName }} + port: + {{ if kindIs "float64" $svcPort }} + number: {{ $svcPort }} + {{ else }} + name: {{ $svcPort }} + {{ end }} + - path: '/xmpp-websocket' + pathType: Prefix + backend: + service: + name: {{ $fullName }} + port: + {{ if kindIs "float64" $svcPort }} + number: {{ $svcPort }} + {{ else }} + name: {{ $svcPort }} + {{ end }} + - path: '/http-bind' + pathType: Prefix + backend: + service: + name: {{ $fullName }} + port: + {{ if kindIs "float64" $svcPort }} + number: {{ $svcPort }} + {{ else }} + name: {{ $svcPort }} + {{ end }} + - path: '/' + pathType: Prefix + backend: + service: + name: {{ $release }}-geoselector-svc + port: + number: 3000 + + {{- range .Values.web.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ . }} + pathType: Prefix + backend: + {{ if semverCompare ">=1.19-0" $kubeVersion }} + service: + name: {{ $fullName }} + port: + {{ if kindIs "float64" $svcPort }} + number: {{ $svcPort }} + {{ else }} + name: {{ $svcPort }} + {{ end }} + {{ else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{ end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/jitsi/templates/jibri/_helper.tpl b/charts/jitsi/templates/jibri/_helper.tpl new file mode 100644 index 0000000..30d1bc4 --- /dev/null +++ b/charts/jitsi/templates/jibri/_helper.tpl @@ -0,0 +1,18 @@ + +{{- define "jitsi-meet.jibri.fullname" -}} +{{ include "jitsi-meet.fullname" . }}-jibri +{{- end -}} + +{{- define "jitsi-meet.jibri.labels" -}} +{{ include "jitsi-meet.labels" . }} +app.kubernetes.io/component: jibri +{{- end -}} + +{{- define "jitsi-meet.jibri.selectorLabels" -}} +{{ include "jitsi-meet.selectorLabels" . }} +app.kubernetes.io/component: jibri +{{- end -}} + +{{- define "jitsi-meet.jibri.secret" -}} +{{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jibri +{{- end -}} diff --git a/charts/jitsi/templates/jibri/configmap.yaml b/charts/jitsi/templates/jibri/configmap.yaml new file mode 100644 index 0000000..9d768de --- /dev/null +++ b/charts/jitsi/templates/jibri/configmap.yaml @@ -0,0 +1,21 @@ +{{- if .Values.jibri.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.jibri.fullname" . }} + labels: + {{- include "jitsi-meet.jibri.labels" . | nindent 4 }} +data: + XMPP_SERVER: '{{ include "jitsi-meet.xmpp.server" . }}' + JIBRI_BREWERY_MUC: '{{ .Values.jibri.breweryMuc }}' + JIBRI_RECORDING_DIR: '{{ .Values.jibri.recordingDir | default "/data/recordings" }}' + JIBRI_FINALIZE_RECORDING_SCRIPT_PATH: "/config/finalize.sh" + JIBRI_STRIP_DOMAIN_JID: muc + DISPLAY: ":0" + JIBRI_SINGLE_USE_MODE: {{ .Values.jibri.singleUseMode | default false | quote }} + {{- range $key, $value := .Values.jibri.extraEnvs }} + {{- if not (kindIs "invalid" $value) }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/jitsi/templates/jibri/configmaps-cont-init.yaml b/charts/jitsi/templates/jibri/configmaps-cont-init.yaml new file mode 100644 index 0000000..b09aa78 --- /dev/null +++ b/charts/jitsi/templates/jibri/configmaps-cont-init.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.jibri.fullname" . }}-cont-inits + labels: + {{- include "jitsi-meet.jibri.labels" . | nindent 4 }} +data: + 10-config: | + {{- if .Values.jibri.custom.contInit._10_config }} + {{- .Values.jibri.custom.contInit._10_config | nindent 4 }} + {{- else }} + # Using jibri /etc/cont-init.d/10-config from container image + {{ end }} + diff --git a/charts/jitsi/templates/jibri/configmaps-defaults.yaml b/charts/jitsi/templates/jibri/configmaps-defaults.yaml new file mode 100644 index 0000000..f53c13d --- /dev/null +++ b/charts/jitsi/templates/jibri/configmaps-defaults.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.jibri.fullname" . }}-defaults + labels: + {{- include "jitsi-meet.jibri.labels" . | nindent 4 }} +data: + jibri.conf: | + {{- if .Values.jibri.custom.defaults._jibri_conf }} + {{- .Values.jibri.custom.defaults._jibri_conf | nindent 4 }} + {{- else }} + # Using jibri /default/jibri.conf from container image + {{ end }} + logging.properties: | + {{- if .Values.jibri.custom.defaults._logging_properties }} + {{- .Values.jibri.custom.defaults._logging_properties | nindent 4 }} + {{- else }} + # Using jibri /default/logging.properties from container image + {{ end }} + autoscaler-sidecar.config: | + {{- if .Values.jibri.custom.defaults._jibri_autoscaler_sidecar_config }} + {{- .Values.jibri.custom.defaults._jibri_autoscaler_sidecar_config | nindent 4 }} + {{- else }} + # Using jibri /default/autoscaler-sidecar.config from container image + {{ end }} + xorg-video-dummy.conf: | + {{- if .Values.jibri.custom.defaults._xorg_video_dummy_conf }} + {{- .Values.jibri.custom.defaults._xorg_video_dummy_conf | nindent 4 }} + {{- else }} + # Using jibri /default/xorg-video-dummy.conf from container image + {{ end }} + diff --git a/charts/jitsi/templates/jibri/deployment.yaml b/charts/jitsi/templates/jibri/deployment.yaml new file mode 100644 index 0000000..8b08b68 --- /dev/null +++ b/charts/jitsi/templates/jibri/deployment.yaml @@ -0,0 +1,155 @@ +{{- if and .Values.jibri.enabled (not .Values.jibri.useExternalJibri) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "jitsi-meet.jibri.fullname" . }} + labels: + {{- include "jitsi-meet.jibri.labels" . | nindent 4 }} + {{- with .Values.jibri.annotations }} + annotations: + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.jibri.replicaCount | default 1 }} + {{- if .Values.jibri.strategy }} + strategy: {{- toYaml .Values.jibri.strategy | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "jitsi-meet.jibri.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "jitsi-meet.jibri.selectorLabels" . | nindent 8 }} + {{- range $label, $value := mergeOverwrite .Values.global.podLabels .Values.jibri.podLabels }} + {{ $label }}: {{ $value }} + {{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/jibri/configmap.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/jibri/xmpp-secret.yaml") . | sha256sum }} + {{- range $annotation, $value := mergeOverwrite .Values.global.podAnnotations .Values.jibri.podAnnotations }} + {{ $annotation }}: {{ $value|quote }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "jitsi-meet.serviceAccountName" . }} + containers: + - name: {{ .Chart.Name }} + securityContext: + capabilities: + add: ["SYS_ADMIN"] + image: "{{ .Values.jibri.image.repository }}:{{ default .Chart.AppVersion .Values.jibri.image.tag }}" + imagePullPolicy: {{ pluck "pullPolicy" .Values.jibri.image .Values.image | first }} + ports: + - name: http-internal + containerPort: 3333 + - name: http-api + containerPort: 2222 + {{- with default .Values.jibri.livenessProbe .Values.jibri.livenessProbeOverride }} + livenessProbe: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with default .Values.jibri.readinessProbe .Values.jibri.readinessProbeOverride }} + readinessProbe: + {{- toYaml . | nindent 10 }} + {{- end }} + + envFrom: + - secretRef: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jibri + - configMapRef: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-common + - configMapRef: + name: {{ include "jitsi-meet.jibri.fullname" . }} + + {{- if (gt (int .Values.jibri.replicaCount) 1) }} + # Set Jibri Instance ID based on pod name: + env: + - name: JIBRI_INSTANCE_ID + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- end }} + + resources: + {{- toYaml .Values.jibri.resources | nindent 12 }} + + volumeMounts: + - name: config + mountPath: /config + {{- if .Values.jibri.custom.contInit._10_config }} + - name: custom-cont-inits + mountPath: /etc/cont-init.d/10-config + subPath: 10-config + {{- end }} + {{- if .Values.jibri.custom.defaults._jibri_conf }} + - name: custom-defaults + mountPath: /defaults/jibri.conf + subPath: jibri.conf + {{- end }} + {{- if .Values.jibri.custom.defaults._logging_properties }} + - name: custom-defaults + mountPath: /defaults/logging.properties + subPath: logging.properties + {{- end }} + {{- if .Values.jibri.custom.defaults._autoscaler_sidecar_config }} + - name: custom-defaults + mountPath: /defaults/autoscaler-sidecar.config + subPath: autoscaler-sidecar.config + {{- end }} + {{- if .Values.jibri.custom.defaults._xorg_video_dummy_conf }} + - name: custom-defaults + mountPath: /defaults/xorg-video-dummy.conf + subPath: xorg-video-dummy.conf + {{- end }} + - name: jibri-data + mountPath: /data + {{- if .Values.jibri.shm.enabled }} + - name: dev-shm + mountPath: /dev/shm + {{- end }} + + volumes: + - name: config + emptyDir: {} + - name: custom-cont-inits + configMap: + defaultMode: 493 + name: {{ include "jitsi-meet.jibri.fullname" . }}-cont-inits + items: + - key: 10-config + path: 10-config + - name: custom-defaults + configMap: + name: {{ include "jitsi-meet.jibri.fullname" . }}-defaults + items: + - key: jibri.conf + path: jibri.conf + - key: logging.properties + path: logging.properties + - key: autoscaler-sidecar.config + path: autoscaler-sidecar.config + - key: xorg-video-dummy.conf + path: xorg-video-dummy.conf + - name: jibri-data + {{- if .Values.jibri.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ .Values.jibri.persistence.existingClaim | default (include "jitsi-meet.jibri.fullname" .) }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.jibri.shm.enabled }} + - name: dev-shm + {{- if .Values.jibri.shm.useHost }} + hostPath: + path: /dev/shm + {{- else }} + emptyDir: + medium: Memory + sizeLimit: {{ .Values.jibri.shm.size | default "2Gi" | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/jitsi/templates/jibri/persistentvolumeclaim.yaml b/charts/jitsi/templates/jibri/persistentvolumeclaim.yaml new file mode 100644 index 0000000..7ac1d29 --- /dev/null +++ b/charts/jitsi/templates/jibri/persistentvolumeclaim.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.jibri.enabled .Values.jibri.persistence.enabled (not .Values.jibri.persistence.existingClaim) (not .Values.jibri.useExternalJibri) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "jitsi-meet.jibri.fullname" . }} + labels: + {{- include "jitsi-meet.jibri.labels" . | nindent 4 }} + namespace: {{ .Release.Namespace }} +spec: + accessModes: + - ReadWriteOnce + - ReadWriteMany + resources: + requests: + storage: {{ .Values.jibri.persistence.size | quote }} + {{- with .Values.jibri.persistence.storageClassName }} + storageClassName: {{ . | quote }} + {{- end }} +{{- end -}} diff --git a/charts/jitsi/templates/jibri/service.yaml b/charts/jitsi/templates/jibri/service.yaml new file mode 100644 index 0000000..5a03d7c --- /dev/null +++ b/charts/jitsi/templates/jibri/service.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.jibri.enabled (not .Values.jibri.useExternalJibri) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "jitsi-meet.jibri.fullname" . }} + labels: + {{- include "jitsi-meet.jibri.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - name: http-internal + port: 3333 + targetPort: 3333 + protocol: TCP + - name: http-api + port: 2222 + targetPort: 2222 + protocol: TCP + selector: + {{- include "jitsi-meet.jibri.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/jitsi/templates/jibri/xmpp-secret.yaml b/charts/jitsi/templates/jibri/xmpp-secret.yaml new file mode 100644 index 0000000..3b0f4ea --- /dev/null +++ b/charts/jitsi/templates/jibri/xmpp-secret.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jibri + labels: + {{- include "jitsi-meet.jibri.labels" . | nindent 4 }} +type: Opaque +data: +{{- if .Values.jibri.enabled }} + JIBRI_XMPP_USER: '{{ .Values.jibri.xmpp.user | b64enc }}' + JIBRI_XMPP_PASSWORD: '{{ default (randAlphaNum 10) .Values.jibri.xmpp.password | b64enc }}' + JIBRI_RECORDER_USER: '{{ .Values.jibri.recorder.user | b64enc }}' + JIBRI_RECORDER_PASSWORD: '{{ default (randAlphaNum 10) .Values.jibri.recorder.password | b64enc }}' +{{- end }} diff --git a/charts/jitsi/templates/jicofo/_helper.tpl b/charts/jitsi/templates/jicofo/_helper.tpl new file mode 100644 index 0000000..3a55245 --- /dev/null +++ b/charts/jitsi/templates/jicofo/_helper.tpl @@ -0,0 +1,18 @@ + +{{- define "jitsi-meet.jicofo.fullname" -}} +{{ include "jitsi-meet.fullname" . }}-jicofo +{{- end -}} + +{{- define "jitsi-meet.jicofo.labels" -}} +{{ include "jitsi-meet.labels" . }} +app.kubernetes.io/component: jicofo +{{- end -}} + +{{- define "jitsi-meet.jicofo.selectorLabels" -}} +{{ include "jitsi-meet.selectorLabels" . }} +app.kubernetes.io/component: jicofo +{{- end -}} + +{{- define "jitsi-meet.jicofo.secret" -}} +{{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jicofo +{{- end -}} diff --git a/charts/jitsi/templates/jicofo/configmap.yaml b/charts/jitsi/templates/jicofo/configmap.yaml new file mode 100644 index 0000000..5b8d32a --- /dev/null +++ b/charts/jitsi/templates/jicofo/configmap.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.jicofo.fullname" . }} + labels: + {{- include "jitsi-meet.jicofo.labels" . | nindent 4 }} +data: + JVB_BREWERY_MUC: '{{ .Values.jvb.breweryMuc }}' + XMPP_SERVER: '{{ include "jitsi-meet.xmpp.server" . }}' + {{- if .Values.jibri.enabled }} + JIBRI_BREWERY_MUC: '{{ .Values.jibri.breweryMuc }}' + JIBRI_PENDING_TIMEOUT: '{{ .Values.jibri.timeout }}' + {{- end }} + {{- if .Values.jigasi.enabled }} + JIGASI_BREWERY_MUC: '{{ .Values.jigasi.breweryMuc }}' + JIGASI_SIP_URI: "available" + {{- end }} + {{- range $key, $value := .Values.jicofo.extraEnvs }} + {{- if not (kindIs "invalid" $value) }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} + {{- if .Values.octo.enabled }} + ENABLE_OCTO: "1" + OCTO_BRIDGE_SELECTION_STRATEGY: "{{ .Values.octo.strategy }}" + {{- end }} diff --git a/charts/jitsi/templates/jicofo/configmaps-cont-init.yaml b/charts/jitsi/templates/jicofo/configmaps-cont-init.yaml new file mode 100644 index 0000000..4511bb6 --- /dev/null +++ b/charts/jitsi/templates/jicofo/configmaps-cont-init.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.jicofo.fullname" . }}-cont-inits + labels: + {{- include "jitsi-meet.jicofo.labels" . | nindent 4 }} +data: + 10-config: | + {{- if .Values.jicofo.custom.contInit._10_config }} + {{- .Values.jicofo.custom.contInit._10_config | nindent 4 }} + {{- else }} + # Using jicofo /etc/cont-init.d/10-config from container image + {{ end }} + diff --git a/charts/jitsi/templates/jicofo/configmaps-defaults.yaml b/charts/jitsi/templates/jicofo/configmaps-defaults.yaml new file mode 100644 index 0000000..ca07634 --- /dev/null +++ b/charts/jitsi/templates/jicofo/configmaps-defaults.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.jicofo.fullname" . }}-defaults + labels: + {{- include "jitsi-meet.jicofo.labels" . | nindent 4 }} +data: + jicofo.conf: | + {{- if .Values.jicofo.custom.defaults._jicofo_conf }} + {{- .Values.jicofo.custom.defaults._jicofo_conf | nindent 4 }} + {{- else }} + # Using jicofo /default/jicofo.conf from container image + {{ end }} + logging.properties: | + {{- if .Values.jicofo.custom.defaults._logging_properties }} + {{- .Values.jicofo.custom.defaults._logging_properties | nindent 4 }} + {{- else }} + # Using jicofo /default/logging.properties from container image + {{ end }} diff --git a/charts/jitsi/templates/jicofo/deployment.yaml b/charts/jitsi/templates/jicofo/deployment.yaml new file mode 100644 index 0000000..47d9180 --- /dev/null +++ b/charts/jitsi/templates/jicofo/deployment.yaml @@ -0,0 +1,117 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "jitsi-meet.jicofo.fullname" . }} + labels: + {{- include "jitsi-meet.jicofo.labels" . | nindent 4 }} + {{- with .Values.jicofo.annotations }} + annotations: + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.jicofo.replicaCount }} + selector: + matchLabels: + {{- include "jitsi-meet.jicofo.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "jitsi-meet.jicofo.selectorLabels" . | nindent 8 }} + {{- range $label, $value := mergeOverwrite .Values.global.podLabels .Values.jicofo.podLabels }} + {{ $label }}: {{ $value }} + {{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/jicofo/configmap.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/jicofo/xmpp-secret.yaml") . | sha256sum }} + {{- range $annotation, $value := mergeOverwrite .Values.global.podAnnotations .Values.jicofo.podAnnotations }} + {{ $annotation }}: {{ $value|quote }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "jitsi-meet.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.jicofo.podSecurityContext | nindent 8 }} + volumes: + - name: config + emptyDir: {} + - name: custom-cont-inits + configMap: + defaultMode: 493 + name: {{ include "jitsi-meet.jicofo.fullname" . }}-cont-inits + items: + - key: 10-config + path: 10-config + - name: custom-defaults + configMap: + name: {{ include "jitsi-meet.jicofo.fullname" . }}-defaults + items: + - key: jicofo.conf + path: jicofo.conf + - key: logging.properties + path: logging.properties + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.jicofo.securityContext | nindent 12 }} + image: "{{ .Values.jicofo.image.repository }}:{{ default .Chart.AppVersion .Values.jicofo.image.tag }}" + imagePullPolicy: {{ pluck "pullPolicy" .Values.jicofo.image .Values.image | first }} + envFrom: + - secretRef: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jicofo + - configMapRef: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-common + - configMapRef: + name: {{ include "jitsi-meet.jicofo.fullname" . }} + {{- if .Values.global.releaseSecretsOverride.enabled }} + {{- range .Values.global.releaseSecretsOverride.extraEnvFrom }} + - {{ tpl (toYaml . ) $ | indent 12 | trim }} + {{- end }} + {{- end }} + ports: + - name: http + containerPort: 80 + protocol: TCP + {{- with .Values.jicofo.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.jicofo.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.jicofo.resources | nindent 12 }} + volumeMounts: + # to support readOnlyRootFilesystem + - name: config + mountPath: /config + {{- if .Values.jicofo.custom.contInit._10_config }} + - name: custom-cont-inits + mountPath: /etc/cont-init.d/10-config + subPath: 10-config + {{- end }} + {{- if .Values.jicofo.custom.defaults._jicofo_conf }} + - name: custom-defaults + mountPath: /defaults/jicofo.conf + subPath: jicofo.conf + {{- end }} + {{- if .Values.jicofo.custom.defaults._logging_properties }} + - name: custom-defaults + mountPath: /defaults/logging.properties + subPath: logging.properties + {{- end }} + {{- with .Values.jicofo.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.jicofo.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.jicofo.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/jitsi/templates/jicofo/xmpp-secret.yaml b/charts/jitsi/templates/jicofo/xmpp-secret.yaml new file mode 100644 index 0000000..fbfa41a --- /dev/null +++ b/charts/jitsi/templates/jicofo/xmpp-secret.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jicofo + labels: + {{- include "jitsi-meet.jicofo.labels" . | nindent 4 }} +type: Opaque +data: + JICOFO_AUTH_USER: '{{ b64enc "focus" }}' + JICOFO_AUTH_PASSWORD: '{{ default (randAlphaNum 10) .Values.jicofo.xmpp.password | b64enc }}' + JICOFO_COMPONENT_SECRET: '{{ default (randAlphaNum 10) .Values.jicofo.xmpp.componentSecret | b64enc }}' diff --git a/charts/jitsi/templates/jigasi/_helper.tpl b/charts/jitsi/templates/jigasi/_helper.tpl new file mode 100644 index 0000000..debe33f --- /dev/null +++ b/charts/jitsi/templates/jigasi/_helper.tpl @@ -0,0 +1,18 @@ + +{{- define "jitsi-meet.jigasi.fullname" -}} +{{ include "jitsi-meet.fullname" . }}-jigasi +{{- end -}} + +{{- define "jitsi-meet.jigasi.labels" -}} +{{ include "jitsi-meet.labels" . }} +app.kubernetes.io/component: jigasi +{{- end -}} + +{{- define "jitsi-meet.jigasi.selectorLabels" -}} +{{ include "jitsi-meet.selectorLabels" . }} +app.kubernetes.io/component: jigasi +{{- end -}} + +{{- define "jitsi-meet.jigasi.secret" -}} +{{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jigasi +{{- end -}} diff --git a/charts/jitsi/templates/jigasi/configmap-sip.yaml b/charts/jitsi/templates/jigasi/configmap-sip.yaml new file mode 100644 index 0000000..5b88a23 --- /dev/null +++ b/charts/jitsi/templates/jigasi/configmap-sip.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-custom-sipconfig +data: +{{ (.Files.Glob "files/sip-communicator.properties").AsConfig | indent 2}} diff --git a/charts/jitsi/templates/jigasi/configmap.yaml b/charts/jitsi/templates/jigasi/configmap.yaml new file mode 100644 index 0000000..d137ae7 --- /dev/null +++ b/charts/jitsi/templates/jigasi/configmap.yaml @@ -0,0 +1,16 @@ +{{- if .Values.jigasi.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.jigasi.fullname" . }} + labels: + {{- include "jitsi-meet.jigasi.labels" . | nindent 4 }} +data: + JIGASI_BREWERY_MUC: '{{ .Values.jigasi.breweryMuc }}' + XMPP_SERVER: '{{ include "jitsi-meet.xmpp.server" . }}' + {{- range $key, $value := .Values.jigasi.extraEnvs }} + {{- if not (kindIs "invalid" $value) }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/jitsi/templates/jigasi/deployment.yaml b/charts/jitsi/templates/jigasi/deployment.yaml new file mode 100644 index 0000000..bc0c59a --- /dev/null +++ b/charts/jitsi/templates/jigasi/deployment.yaml @@ -0,0 +1,87 @@ +{{- if and .Values.jigasi.enabled (not .Values.jigasi.useExternalJigasi) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "jitsi-meet.jigasi.fullname" . }} + labels: + {{- include "jitsi-meet.jigasi.labels" . | nindent 4 }} + {{- with .Values.jigasi.annotations }} + annotations: + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.jigasi.replicaCount | default 1 }} + selector: + matchLabels: + {{- include "jitsi-meet.jigasi.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "jitsi-meet.jigasi.selectorLabels" . | nindent 8 }} + {{- range $label, $value := mergeOverwrite .Values.global.podLabels .Values.jigasi.podLabels }} + {{ $label }}: {{ $value }} + {{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/jigasi/configmap.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/jigasi/xmpp-secret.yaml") . | sha256sum }} + {{- range $annotation, $value := mergeOverwrite .Values.global.podAnnotations .Values.jigasi.podAnnotations }} + {{ $annotation }}: {{ $value|quote }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "jitsi-meet.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.jigasi.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.jigasi.securityContext | nindent 12 }} + image: "{{ .Values.jigasi.image.repository }}:{{ default .Chart.AppVersion .Values.jigasi.image.tag }}" + imagePullPolicy: {{ pluck "pullPolicy" .Values.jigasi.image .Values.image | first }} + env: + - name: VOSK_SVC + value: {{ .Release.Name }}-vosk-server-svc + envFrom: + - secretRef: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jigasi + - configMapRef: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-common + - configMapRef: + name: {{ include "jitsi-meet.jigasi.fullname" . }} + {{- if .Values.transcription.enabled }} + volumeMounts: + - name: sipconfig + mountPath: /defaults/sip-communicator.properties + subPath: sip-communicator.properties + {{- end }} + {{- with .Values.jigasi.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.jigasi.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.jigasi.resources | nindent 12 }} + + {{- with .Values.jigasi.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.jigasi.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.jigasi.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: sipconfig + configMap: + name: {{ .Release.Name }}-custom-sipconfig +{{- end }} diff --git a/charts/jitsi/templates/jigasi/xmpp-secret.yaml b/charts/jitsi/templates/jigasi/xmpp-secret.yaml new file mode 100644 index 0000000..c926d0c --- /dev/null +++ b/charts/jitsi/templates/jigasi/xmpp-secret.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jigasi + labels: + {{- include "jitsi-meet.jigasi.labels" . | nindent 4 }} +type: Opaque +data: + {{- if .Values.jigasi.enabled }} + JIGASI_XMPP_USER: '{{ .Values.jigasi.xmpp.user | b64enc }}' + JIGASI_XMPP_PASSWORD: '{{ default (randAlphaNum 10) .Values.jigasi.xmpp.password | b64enc }}' + {{- end }} diff --git a/charts/jitsi/templates/jvb/_helper.tpl b/charts/jitsi/templates/jvb/_helper.tpl new file mode 100644 index 0000000..5aa1d9b --- /dev/null +++ b/charts/jitsi/templates/jvb/_helper.tpl @@ -0,0 +1,18 @@ + +{{- define "jitsi-meet.jvb.fullname" -}} +{{ include "jitsi-meet.fullname" . }}-jvb +{{- end -}} + +{{- define "jitsi-meet.jvb.labels" -}} +{{ include "jitsi-meet.labels" . }} +app.kubernetes.io/component: jvb +{{- end -}} + +{{- define "jitsi-meet.jvb.selectorLabels" -}} +{{ include "jitsi-meet.selectorLabels" . }} +app.kubernetes.io/component: jvb +{{- end -}} + +{{- define "jitsi-meet.jvb.secret" -}} +{{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jvb +{{- end -}} diff --git a/charts/jitsi/templates/jvb/configmap.yaml b/charts/jitsi/templates/jvb/configmap.yaml new file mode 100644 index 0000000..7799684 --- /dev/null +++ b/charts/jitsi/templates/jvb/configmap.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.jvb.fullname" . }} + labels: + {{- include "jitsi-meet.jvb.labels" . | nindent 4 }} +data: + JVB_BREWERY_MUC: '{{ .Values.jvb.breweryMuc }}' + JVB_PORT: '{{ .Values.jvb.UDPPort }}' + JVB_STUN_SERVERS: '{{.Values.jvb.stunServers }}' + JVB_TCP_HARVESTER_DISABLED: '1' + XMPP_SERVER: '{{ include "jitsi-meet.xmpp.server" . }}' + {{- range $key, $value := .Values.jvb.extraEnvs }} + {{- if not (kindIs "invalid" $value) }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} + COLIBRI_REST_ENABLED: 'true' + {{- if .Values.octo.enabled }} + ENABLE_OCTO: "1" + JVB_OCTO_BIND_PORT: "4096" + JVB_OCTO_REGION: "{{ .Values.octo.region }}" + JVB_OCTO_RELAY_ID: "{{ .Values.octo.relayId }}" + {{- end }} diff --git a/charts/jitsi/templates/jvb/configmap_grafana_dashboards.yaml b/charts/jitsi/templates/jvb/configmap_grafana_dashboards.yaml new file mode 100644 index 0000000..bfcc153 --- /dev/null +++ b/charts/jitsi/templates/jvb/configmap_grafana_dashboards.yaml @@ -0,0 +1,16 @@ +{{- if and (.Values.jvb.metrics.enabled) .Values.jvb.metrics.grafanaDashboards.enabled }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.fullname" . }}-grafana-dashboards + labels: + {{- include "jitsi-meet.labels" . | nindent 4 }} + {{- with .Values.jvb.metrics.grafanaDashboards.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- toYaml .Values.jvb.metrics.grafanaDashboards.annotations | nindent 4 }} +data: + {{- (.Files.Glob "files/grafana_dashboards/*.json").AsConfig | nindent 2 }} +{{- end }} diff --git a/charts/jitsi/templates/jvb/deployment.yaml b/charts/jitsi/templates/jvb/deployment.yaml new file mode 100644 index 0000000..beebcee --- /dev/null +++ b/charts/jitsi/templates/jvb/deployment.yaml @@ -0,0 +1,182 @@ +{{- if .Values.jvb.enableDeploy }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "jitsi-meet.jvb.fullname" . }} + labels: + {{- include "jitsi-meet.jvb.labels" . | nindent 4 }} + {{- with .Values.jvb.annotations }} + annotations: + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.jvb.replicaCount }} + selector: + matchLabels: + {{- include "jitsi-meet.jvb.selectorLabels" . | nindent 6 }} + {{- if .Values.jvb.useHostPort }} + strategy: + type: Recreate + {{- end }} + template: + metadata: + labels: + {{- include "jitsi-meet.jvb.selectorLabels" . | nindent 8 }} + {{- range $label, $value := mergeOverwrite .Values.global.podLabels .Values.jvb.podLabels }} + {{ $label }}: {{ $value }} + {{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/jvb/configmap.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/jvb/xmpp-secret.yaml") . | sha256sum }} + {{- if and .Values.jvb.metrics.enabled .Values.jvb.metrics.prometheusAnnotations }} + prometheus.io/port: "9888" + prometheus.io/scrape: "true" + {{- end }} + {{- range $annotation, $value := mergeOverwrite .Values.global.podAnnotations .Values.jvb.podAnnotations }} + {{ $annotation }}: {{ $value|quote }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "jitsi-meet.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.jvb.podSecurityContext | nindent 8 }} + {{- if .Values.jvb.useHostNetwork }} + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + {{- end }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.jvb.securityContext | nindent 12 }} + image: "{{ .Values.jvb.image.repository }}:{{ default .Chart.AppVersion .Values.jvb.image.tag }}" + imagePullPolicy: {{ pluck "pullPolicy" .Values.jvb.image .Values.image | first }} + envFrom: + - secretRef: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jvb + - configMapRef: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-common + - configMapRef: + name: {{ include "jitsi-meet.jvb.fullname" . }} + {{- if .Values.global.releaseSecretsOverride.enabled }} + {{- range .Values.global.releaseSecretsOverride.extraEnvFrom }} + - {{ tpl (toYaml . ) $ | indent 12 | trim }} + {{- end }} + {{- end }} + env: + {{- if or .Values.jvb.useNodeIP .Values.jvb.publicIPs }} + - name: DOCKER_HOST_ADDRESS + {{- if .Values.jvb.publicIPs }} + value: {{ first .Values.jvb.publicIPs }} + {{- else }} + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- end }} + - name: JVB_ADVERTISE_IPS + {{- if .Values.jvb.publicIPs }} + value: {{ .Values.jvb.publicIPs | join "," }} + {{- else }} + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- end }} + {{- end }} + {{- if .Values.websockets.colibri.enabled }} + - name: JVB_WS_SERVER_ID + valueFrom: + fieldRef: + fieldPath: status.podIP + {{- end }} + {{- if .Values.octo.enabled }} + - name: JVB_OCTO_BIND_ADDRESS + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: JVB_OCTO_PUBLIC_ADDRESS + valueFrom: + fieldRef: + fieldPath: status.podIP + {{- end }} + ports: + - name: rtp-udp + containerPort: {{ .Values.jvb.UDPPort }} + {{- if .Values.jvb.useHostPort }} + hostPort: {{ .Values.jvb.UDPPort }} + {{- end }} + protocol: UDP + {{- if .Values.websockets.colibri.enabled }} + - name: colibri-ws-tcp + containerPort: 9090 + protocol: TCP + {{- end }} + {{- with .Values.jvb.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.jvb.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.jvb.resources | nindent 12 }} + {{- with .Values.jvb.extraVolumeMounts }} + volumeMounts: + {{- toYaml . | nindent 10 }} + {{- end }} + + {{- if .Values.jvb.metrics.enabled }} + - name: metrics + image: {{ .Values.jvb.metrics.image.repository }}:{{ .Values.jvb.metrics.image.tag }} + imagePullPolicy: {{ .Values.jvb.metrics.image.pullPolicy }} + securityContext: + runAsUser: 10001 + command: + - /prometheus-jitsi-meet-exporter + - -videobridge-url + - http://localhost:8080/colibri/stats + ports: + - containerPort: 9888 + name: tcp-metrics + protocol: TCP + readinessProbe: + httpGet: + path: /health + port: 9888 + initialDelaySeconds: 3 + periodSeconds: 5 + resources: + {{- toYaml .Values.jvb.metrics.resources | nindent 12 }} + {{- end }} + + {{- with .Values.jvb.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if or .Values.jvb.useHostPort .Values.jvb.affinity }} + affinity: + {{- if .Values.jvb.affinity }} + {{- toYaml .Values.jvb.affinity | nindent 8 }} + {{- else }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app.kubernetes.io/component + operator: In + values: + - jvb + topologyKey: "kubernetes.io/hostname" + {{- end }} + {{- end }} + {{- with .Values.jvb.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.jvb.extraVolumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/jitsi/templates/jvb/metrics-prometheus.yaml b/charts/jitsi/templates/jvb/metrics-prometheus.yaml new file mode 100644 index 0000000..1618c41 --- /dev/null +++ b/charts/jitsi/templates/jvb/metrics-prometheus.yaml @@ -0,0 +1,27 @@ +{{- if and (.Values.jvb.metrics.enabled) (.Values.jvb.metrics.serviceMonitor.enabled) }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "jitsi-meet.jvb.fullname" . }} + labels: + {{- include "jitsi-meet.jvb.labels" . | nindent 4 }} + {{- with .Values.jvb.metrics.serviceMonitor.selector }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: tcp-metrics + path: /metrics + {{- with .Values.jvb.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ . }} + {{- end }} + {{- with .Values.jvb.metrics.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + selector: + matchLabels: + {{- include "jitsi-meet.jvb.labels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + {{- end -}} diff --git a/charts/jitsi/templates/jvb/metrics-service.yaml b/charts/jitsi/templates/jvb/metrics-service.yaml new file mode 100644 index 0000000..32a656d --- /dev/null +++ b/charts/jitsi/templates/jvb/metrics-service.yaml @@ -0,0 +1,16 @@ +{{- if .Values.jvb.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "jitsi-meet.jvb.fullname" . }}-metrics + labels: + {{- include "jitsi-meet.jvb.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 9888 + protocol: TCP + name: tcp-metrics + selector: + {{- include "jitsi-meet.jvb.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/jitsi/templates/jvb/service.yaml b/charts/jitsi/templates/jvb/service.yaml new file mode 100644 index 0000000..fb8b941 --- /dev/null +++ b/charts/jitsi/templates/jvb/service.yaml @@ -0,0 +1,35 @@ +{{- if or (and (kindIs "invalid" .Values.jvb.service.enabled) (not (or .Values.jvb.useHostPort .Values.jvb.useHostNetwork))) .Values.jvb.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "jitsi-meet.jvb.fullname" . }} + annotations: + {{- range $key, $value := .Values.jvb.service.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + labels: + {{- include "jitsi-meet.jvb.labels" . | nindent 4 }} +spec: + type: {{ .Values.jvb.service.type }} + {{- with .Values.jvb.service.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + ports: + - port: 9500 + protocol: TCP + targetPort: 8080 + name: http-health + - port: {{ default 10000 .Values.jvb.UDPPort }} + {{- if and .Values.jvb.nodePort (or (eq .Values.jvb.service.type "NodePort") (eq .Values.jvb.service.type "LoadBalancer")) }} + nodePort: {{ .Values.jvb.nodePort }} + {{- end }} + protocol: UDP + name: rtp-udp + {{- with .Values.jvb.service.externalIPs }} + externalIPs: + {{ toYaml . | indent 2 | trim }} + {{- end }} + externalTrafficPolicy: {{ .Values.jvb.service.externalTrafficPolicy }} + selector: + {{- include "jitsi-meet.jvb.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/jitsi/templates/jvb/xmpp-secret.yaml b/charts/jitsi/templates/jvb/xmpp-secret.yaml new file mode 100644 index 0000000..4e0a7a4 --- /dev/null +++ b/charts/jitsi/templates/jvb/xmpp-secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-jvb + labels: + {{- include "jitsi-meet.jvb.labels" . | nindent 4 }} +type: Opaque +data: + JVB_AUTH_USER: '{{ .Values.jvb.xmpp.user | b64enc }}' + JVB_AUTH_PASSWORD: '{{ default (randAlphaNum 10) .Values.jvb.xmpp.password | b64enc }}' diff --git a/charts/jitsi/templates/keycloak-adapter/cm-html.yaml b/charts/jitsi/templates/keycloak-adapter/cm-html.yaml new file mode 100644 index 0000000..6e14e82 --- /dev/null +++ b/charts/jitsi/templates/keycloak-adapter/cm-html.yaml @@ -0,0 +1,11 @@ +{{- $bgContent := .Files.Get "files/eth_space.jpg" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-keycloak-additions +data: +{{ (.Files.Glob "files/meet.conf").AsConfig | indent 2}} +{{ (.Files.Glob "files/body.html").AsConfig | indent 2}} +{{ (.Files.Glob "files/oidc-adapter.html").AsConfig | indent 2}} +{{ (.Files.Glob "files/oidc-redirect.html").AsConfig | indent 2}} + diff --git a/charts/jitsi/templates/keycloak-adapter/configmap.yaml b/charts/jitsi/templates/keycloak-adapter/configmap.yaml new file mode 100644 index 0000000..3597029 --- /dev/null +++ b/charts/jitsi/templates/keycloak-adapter/configmap.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-keycloak-adapter-config +data: + KEYCLOAK_ORIGIN: "{{ .Values.keycloak_adapter.keycloak_url }}" + KEYCLOAK_REALM: "{{ .Values.keycloak_adapter.keycloak_realm }}" + KEYCLOAK_CLIENT_ID: "{{ .Values.keycloak_adapter.keycloak_client_id }}" + JWT_APP_ID: "{{ .Values.auth.jwtAppId }}" + JWT_APP_SECRET: "{{ .Values.auth.jwtAppSecret }}" + ALLOW_UNSECURE_CERT: "true" + DEBUG: "{{ .Values.keycloak_adapter.enableDebug }}" +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-keycloak-adapter-permissions +data: + permissions.json: | + {{ .Values.keycloak_adapter.roomPermissions | toJson }} diff --git a/charts/jitsi/templates/keycloak-adapter/deployment.yaml b/charts/jitsi/templates/keycloak-adapter/deployment.yaml new file mode 100644 index 0000000..6368977 --- /dev/null +++ b/charts/jitsi/templates/keycloak-adapter/deployment.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-keycloak-adapter +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Release.Name }}-keycloak-adapter + template: + metadata: + labels: + app: {{ .Release.Name }}-keycloak-adapter + spec: + containers: + - name: {{ .Release.Name }}-keycloak-adapter + image: ghcr.io/ethdevops/jitsi-keycloak-adapter:{{ .Values.keycloak_adapter.imageTag }} + ports: + - containerPort: 9000 + envFrom: + - configMapRef: + name: {{ .Release.Name }}-keycloak-adapter-config + env: + - name: PERMISSIONS_FILE + value: "/config-permissions/permissions.json" + volumeMounts: + - name: permissions + mountPath: /config-permissions + resources: + {{- toYaml .Values.keycloak_adapter.resources | nindent 12 }} + + volumes: + - name: permissions + configMap: + name: {{ .Release.Name }}-keycloak-adapter-permissions diff --git a/charts/jitsi/templates/keycloak-adapter/service.yaml b/charts/jitsi/templates/keycloak-adapter/service.yaml new file mode 100644 index 0000000..ffbc1b7 --- /dev/null +++ b/charts/jitsi/templates/keycloak-adapter/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-keycloak-adapter-svc +spec: + selector: + app: {{ .Release.Name }}-keycloak-adapter + ports: + - protocol: TCP + port: 9000 + targetPort: 9000 + type: ClusterIP diff --git a/charts/jitsi/templates/serviceaccount.yaml b/charts/jitsi/templates/serviceaccount.yaml new file mode 100644 index 0000000..d0b57df --- /dev/null +++ b/charts/jitsi/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "jitsi-meet.serviceAccountName" . }} + labels: + {{- include "jitsi-meet.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end -}} diff --git a/charts/jitsi/templates/tests/test-connection.yaml b/charts/jitsi/templates/tests/test-connection.yaml new file mode 100644 index 0000000..9f523ba --- /dev/null +++ b/charts/jitsi/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "jitsi-meet.web.fullname" . }}-test-connection" + labels: + {{- include "jitsi-meet.web.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test-success +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "jitsi-meet.web.fullname" . }}:{{ .Values.web.service.port }}'] + restartPolicy: Never diff --git a/charts/jitsi/templates/vosk-server/deployment.yaml b/charts/jitsi/templates/vosk-server/deployment.yaml new file mode 100644 index 0000000..5407f50 --- /dev/null +++ b/charts/jitsi/templates/vosk-server/deployment.yaml @@ -0,0 +1,35 @@ +{{- if .Values.transcription.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }}-vosk-server +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Release.Name }}-vosk-server + template: + metadata: + labels: + app: {{ .Release.Name }}-vosk-server + spec: + tolerations: + - key: "ethquokkaops.io/jitsi" + operator: "Equal" + value: "transcription" + effect: "NoSchedule" + containers: + - name: {{ .Release.Name }}-vosk-server + image: alphacep/kaldi-en:latest + resources: + {{- toYaml .Values.transcription.resources | nindent 12 }} + ports: + - containerPort: 2700 + resources: + requests: + memory: "8Gi" + cpu: "250m" + limits: + memory: "12Gi" + cpu: "2" +{{- end }} diff --git a/charts/jitsi/templates/vosk-server/service.yaml b/charts/jitsi/templates/vosk-server/service.yaml new file mode 100644 index 0000000..7f87daf --- /dev/null +++ b/charts/jitsi/templates/vosk-server/service.yaml @@ -0,0 +1,14 @@ +{{- if .Values.transcription.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }}-vosk-server-svc +spec: + selector: + app: {{ .Release.Name }}-vosk-server + ports: + - protocol: TCP + port: 2700 + targetPort: 2700 + type: ClusterIP +{{- end }} diff --git a/charts/jitsi/templates/web/_helper.tpl b/charts/jitsi/templates/web/_helper.tpl new file mode 100644 index 0000000..18b1f09 --- /dev/null +++ b/charts/jitsi/templates/web/_helper.tpl @@ -0,0 +1,15 @@ + +{{- define "jitsi-meet.web.fullname" -}} +{{ include "jitsi-meet.fullname" . }}-web +{{- end -}} + +{{- define "jitsi-meet.web.labels" -}} +{{ include "jitsi-meet.labels" . }} +app.kubernetes.io/component: web +{{- end -}} + +{{- define "jitsi-meet.web.selectorLabels" -}} +{{ include "jitsi-meet.selectorLabels" . }} +app.kubernetes.io/component: web +{{- end -}} + diff --git a/charts/jitsi/templates/web/configmap.yaml b/charts/jitsi/templates/web/configmap.yaml new file mode 100644 index 0000000..ccfda6a --- /dev/null +++ b/charts/jitsi/templates/web/configmap.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.web.fullname" . }} + labels: + {{- include "jitsi-meet.web.labels" . | nindent 4 }} +data: + DISABLE_HTTPS: {{ ternary "0" "1" .Values.web.httpsEnabled | quote }} + ENABLE_HTTP_REDIRECT: {{ ternary "1" "0" .Values.web.httpRedirect | quote }} + JICOFO_AUTH_USER: focus + XMPP_BOSH_URL_BASE: 'http://{{ include "jitsi-meet.xmpp.server" . }}:{{ index .Values.prosody.service.ports "bosh-insecure" }}' + {{- if .Values.web.resolverIP }} + NGINX_RESOLVER: {{ .Values.web.resolverIP }} + {{- end }} + {{- range $key, $value := .Values.web.extraEnvs }} + {{- if not (kindIs "invalid" $value) }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} diff --git a/charts/jitsi/templates/web/configmaps-cont-init.yaml b/charts/jitsi/templates/web/configmaps-cont-init.yaml new file mode 100644 index 0000000..de8800e --- /dev/null +++ b/charts/jitsi/templates/web/configmaps-cont-init.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.web.fullname" . }}-cont-inits + labels: + {{- include "jitsi-meet.web.labels" . | nindent 4 }} +data: + 10-config: | + {{- if .Values.web.custom.contInit._10_config }} + {{- .Values.web.custom.contInit._10_config | nindent 4 }} + {{- else }} + # Using web /etc/cont-init.d/10-config from container image + {{ end }} diff --git a/charts/jitsi/templates/web/configmaps-defaults.yaml b/charts/jitsi/templates/web/configmaps-defaults.yaml new file mode 100644 index 0000000..d807b61 --- /dev/null +++ b/charts/jitsi/templates/web/configmaps-defaults.yaml @@ -0,0 +1,50 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "jitsi-meet.web.fullname" . }}-defaults + labels: + {{- include "jitsi-meet.web.labels" . | nindent 4 }} +data: + default: | + {{- if .Values.web.custom.defaults._default }} + {{- .Values.web.custom.defaults._default | nindent 4 }} + {{- else }} + # Using web /defaults/default from container image + {{ end }} + ffdhe2048.txt: | + {{- if .Values.web.custom.defaults._ffdhe2048_txt }} + {{- .Values.web.custom.defaults._ffdhe2048_txt | nindent 4 }} + {{- else }} + # Using web /defaults/ffdhe2048.txt from container image + {{ end }} + interface_config.js: | + {{- if .Values.web.custom.defaults._interface_config_js }} + {{- .Values.web.custom.defaults._interface_config_js | nindent 4 }} + {{- else }} + # Using web /defaults/interface_config.js from container image + {{ end }} + meet.conf: | + {{- if .Values.web.custom.defaults._meet_conf }} + {{- .Values.web.custom.defaults._meet_conf | nindent 4 }} + {{- else }} + # Using web /defaults/meet.conf from container image + {{ end }} + nginx.conf: | + {{- if .Values.web.custom.defaults._nginx_conf }} + {{- .Values.web.custom.defaults._nginx_conf | nindent 4 }} + {{- else }} + # Using web /defaults/nginx.conf from container image + {{ end }} +{{ (.Files.Glob "files/settings-config.js").AsConfig | indent 2}} + ssl.conf: | + {{- if .Values.web.custom.defaults._ssl_conf }} + {{- .Values.web.custom.defaults._ssl_conf | nindent 4 }} + {{- else }} + # Using web /defaults/ssl.conf from container image + {{ end }} + system-config.js: | + {{- if .Values.web.custom.defaults._system_config_js }} + {{- .Values.web.custom.defaults._system_config_js | nindent 4 }} + {{- else }} + # Using web /defaults/system-config.js from container image + {{ end }} diff --git a/charts/jitsi/templates/web/deployment.yaml b/charts/jitsi/templates/web/deployment.yaml new file mode 100644 index 0000000..f33f4ab --- /dev/null +++ b/charts/jitsi/templates/web/deployment.yaml @@ -0,0 +1,179 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "jitsi-meet.web.fullname" . }} + labels: + {{- include "jitsi-meet.web.labels" . | nindent 4 }} + {{- with .Values.web.annotations }} + annotations: + {{ toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.web.replicaCount }} + selector: + matchLabels: + {{- include "jitsi-meet.web.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "jitsi-meet.web.selectorLabels" . | nindent 8 }} + {{- range $label, $value := mergeOverwrite .Values.global.podLabels .Values.web.podLabels }} + {{ $label }}: {{ $value }} + {{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/web/configmap.yaml") . | sha256sum }} + checksum/additional-config: {{ include (print $.Template.BasePath "/keycloak-adapter/cm-html.yaml") . | sha256sum }} + {{- range $annotation, $value := mergeOverwrite .Values.global.podAnnotations .Values.web.podAnnotations }} + {{ $annotation }}: {{ $value|quote }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "jitsi-meet.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.web.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.web.securityContext | nindent 12 }} + image: "{{ .Values.web.image.repository }}:{{ default .Chart.AppVersion .Values.web.image.tag }}" + imagePullPolicy: {{ pluck "pullPolicy" .Values.web.image .Values.image | first }} + envFrom: + - configMapRef: + name: {{ include "jitsi-meet.web.fullname" . }} + - configMapRef: + name: {{ include "call-nested" (list . "prosody" "prosody.fullname") }}-common + {{- if .Values.global.releaseSecretsOverride.enabled }} + {{- range .Values.global.releaseSecretsOverride.extraEnvFrom }} + - {{ tpl (toYaml . ) $ | indent 12 | trim }} + {{- end }} + {{- end }} + ports: + - name: http + containerPort: 80 + protocol: TCP + - name: https + containerPort: 443 + protocol: TCP + {{- with .Values.web.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.web.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.web.resources | nindent 12 }} + volumeMounts: + - name: config + mountPath: /config + {{- if .Values.web.custom.contInit._10_config }} + - name: custom-cont-inits + mountPath: /etc/cont-init.d/10-config + subPath: 10-config + {{- end }} + {{- if .Values.web.custom.defaults._default }} + - name: custom-defaults + mountPath: /defaults/default + subPath: default + {{- end }} + {{- if .Values.web.custom.defaults._ffdhe2048_txt }} + - name: custom-defaults + mountPath: /defaults/ffdhe2048.txt + subPath: ffdhe2048.txt + {{- end }} + {{- if .Values.web.custom.defaults._interface_config_js }} + - name: custom-defaults + mountPath: /defaults/interface_config.js + subPath: interface_config.js + {{- end }} + {{- if .Values.web.custom.defaults._meet_conf }} + - name: custom-defaults + mountPath: /defaults/meet.conf + subPath: meet.conf + {{- end }} + {{- if .Values.web.custom.defaults._nginx_conf }} + - name: custom-defaults + mountPath: /defaults/nginx.conf + subPath: nginx.conf + {{- end }} + - name: custom-defaults + mountPath: /defaults/settings-config.js + subPath: settings-config.js + {{- if .Values.web.custom.defaults._ssl_conf }} + - name: custom-defaults + mountPath: /defaults/ssl.conf + subPath: ssl.conf + {{- end }} + {{- if .Values.web.custom.defaults._system_config_js }} + - name: custom-defaults + mountPath: /defaults/system-config.js + subPath: system-config.js + {{- end }} + - name: adapter-additions + mountPath: /defaults/meet.conf + subPath: meet.conf + - name: adapter-additions + mountPath: /usr/share/jitsi-meet/body.html + subPath: body.html + - name: adapter-additions + mountPath: /usr/share/jitsi-meet/static/oidc-adapter.html + subPath: oidc-adapter.html + - name: adapter-additions + mountPath: /usr/share/jitsi-meet/static/oidc-redirect.html + subPath: oidc-redirect.html + {{- with .Values.web.extraVolumeMounts }} + {{- toYaml . | nindent 10 }} + {{- end }} + + {{- with .Values.web.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.web.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.web.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: adapter-additions + configMap: + name: {{ .Release.Name }}-keycloak-additions + - name: config + emptyDir: {} + - name: custom-cont-inits + configMap: + defaultMode: 493 + name: {{ include "jitsi-meet.web.fullname" . }}-cont-inits + items: + - key: 10-config + path: 10-config + - name: custom-defaults + configMap: + name: {{ include "jitsi-meet.web.fullname" . }}-defaults + items: + - key: default + path: default + - key: ffdhe2048.txt + path: ffdhe2048.txt + - key: interface_config.js + path: interface_config.js + - key: meet.conf + path: meet.conf + - key: nginx.conf + path: nginx.conf + - key: settings-config.js + path: settings-config.js + - key: ssl.conf + path: ssl.conf + - key: system-config.js + path: system-config.js + {{- with .Values.web.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/jitsi/templates/web/service.yaml b/charts/jitsi/templates/web/service.yaml new file mode 100644 index 0000000..cfb70a9 --- /dev/null +++ b/charts/jitsi/templates/web/service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "jitsi-meet.web.fullname" . }} + labels: + {{- include "jitsi-meet.web.labels" . | nindent 4 }} +spec: + type: {{ .Values.web.service.type }} + ports: + - port: {{ .Values.web.service.port }} + protocol: TCP + name: http + {{- if .Values.web.service.nodePort }} + nodePort: {{ index .Values.web.service.nodePort }} + {{- end }} + {{- with .Values.web.service.externalIPs }} + externalIPs: + {{ toYaml . | indent 2 | trim }} + {{- end }} + selector: + {{- include "jitsi-meet.web.selectorLabels" . | nindent 4 }} diff --git a/charts/jitsi/values.yaml b/charts/jitsi/values.yaml new file mode 100644 index 0000000..782695e --- /dev/null +++ b/charts/jitsi/values.yaml @@ -0,0 +1,507 @@ +# Default values for jitsi-meet. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +jitsi-admin: + wsHost: admin-ws.meet.ethquokkaops.io + adminHost: admin.meet.ethquokkaops.io + jwtSecret: + keycloak: + url: https://keycloak.ethquokkaops.io + clientId: jitsiadmin + clientSecret: + realm: master + registerEmail: example@example.com + + +global: + # Set your cluster's DNS domain here. + # "cluster.local" should work for most environments. + # Set to "" to disable the use of FQDNs (default in older chart versions). + clusterDomain: cluster.local + podLabels: {} + podAnnotations: {} + releaseSecretsOverride: + enabled: false + #Support environment variables from pre-created secrets, such as 1Password operator + #extraEnvFrom: + # - secretRef: + # name: '{{ include "prosody.fullname" . }}-overrides' + # optional: true + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +enableAuth: false +enableGuests: true +# Where Jitsi Web UI is made available +# such as jitsi.example.com +publicURL: "https://meet.ethquokkaops.io" + +tz: Europe/Berlin + +image: + pullPolicy: IfNotPresent + +## WebSocket configuration: +# +# Both Colibri and XMPP WebSockets are disabled by default, +# since some LoadBalancer / Reverse Proxy setups can't pass +# WebSocket connections properly, which might result in breakage +# for some clients. +# +# Enable both Colibri and XMPP WebSockets to replicate the current +# upstream `meet.jit.si` setup. Keep both disabled to replicate +# older setups which might be more compatible in some cases. +websockets: + ## Colibri (JVB signalling): + colibri: + enabled: true + ## XMPP (Prosody signalling): + xmpp: + enabled: true + +web: + replicaCount: 1 + image: + repository: jitsi/web + + custom: + contInit: + _10_config: "" + defaults: + _default: "" + _ffdhe2048_txt: "" + _interface_config_js: "" + _meet_conf: "" + _nginx_conf: "" + _settings_config_js: "" + _ssl_conf: "" + _system_config_js: "" + + extraEnvs: {} + service: + type: ClusterIP + port: 80 + ## If you want to expose the Jitsi Web service directly + # (bypassing the Ingress Controller), use this: + # + # type: NodePort + # nodePort: 30580 + # port: 80 + externalIPs: [] + + ingress: + enabled: false + ingressClassName: nginx + annotations: {} + hosts: + - host: jitsi.local + paths: ['/'] + tls: + - secretName: jitsi-web-certificate + hosts: + - jitsi.local + + # Useful for ingresses that don't support http-to-https redirect by themself, (namely: GKE), + httpRedirect: false + + # When tls-termination by the ingress is not wanted, enable this and set web.service.type=Loadbalancer + httpsEnabled: false + + ## Resolver IP for nginx. + # + # Starting with version `stable-8044`, the web container can + # auto-detect the nameserver from /etc/resolv.conf. + # Use this option if you want to override the nameserver IP. + # + # resolverIP: 10.43.0.10 + + livenessProbe: + httpGet: + path: / + port: 80 + readinessProbe: + httpGet: + path: / + port: 80 + + podLabels: {} + podAnnotations: {} + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + + resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + + nodeSelector: {} + + tolerations: [] + + affinity: {} + +jicofo: + replicaCount: 1 + image: + repository: jitsi/jicofo + + custom: + contInit: + _10_config: "" + defaults: + _jicofo_conf: "" + _logging_properties: "" + + xmpp: + password: + componentSecret: + + livenessProbe: + tcpSocket: + port: 8888 + + readinessProbe: + tcpSocket: + port: 8888 + + podLabels: {} + podAnnotations: {} + podSecurityContext: {} + securityContext: {} + resources: {} + nodeSelector: {} + tolerations: [] + affinity: {} + extraEnvs: {} + +jvb: + replicaCount: 1 + image: + repository: jitsi/jvb + + xmpp: + user: jvb + password: + + ## Set public IP addresses to be advertised by JVB. + # You can specify your nodes' IP addresses, + # or IP addresses of proxies/LoadBalancers used for your + # Jitsi Meet installation. Or both! + # + # Note that only the first IP address will be used for legacy + # `DOCKER_HOST_ADDRESS` environment variable. + # + #publicIPs: + # - 1.1.1.1 + + ## Use a STUN server to help some users punch through some + # especially nasty NAT setups. Usually makes sense for P2P calls. + stunServers: 'meet-jit-si-turnrelay.jitsi.net:443' + ## Try to use the hostPort feature: + # (might not be supported by some clouds or CNI engines) + useHostPort: false + ## Use host's network namespace: + # (not recommended, but might help for some cases) + useHostNetwork: false + ## UDP transport port: + UDPPort: 10000 + ## Use a pre-defined external port for NodePort or LoadBalancer service, + # if needed. Will allocate a random port from allowed range if unset. + # (Default NodePort range for K8s is 30000-32767) + # nodePort: 10000 + service: + enabled: + type: ClusterIP + #externalTrafficPolicy: Cluster + externalIPs: [] + ## Annotations to be added to the service (if LoadBalancer is used) + ## + annotations: {} + + breweryMuc: jvbbrewery + + livenessProbe: + httpGet: + path: /about/health + port: 8080 + readinessProbe: + httpGet: + path: /about/health + port: 8080 + + podLabels: {} + podAnnotations: {} + podSecurityContext: {} + securityContext: {} + resources: {} + nodeSelector: {} + tolerations: [] + affinity: {} + extraEnvs: {} + + metrics: + enabled: true + image: + repository: docker.io/systemli/prometheus-jitsi-meet-exporter + tag: 1.2.3 + pullPolicy: IfNotPresent + + resources: + requests: + cpu: 10m + memory: 16Mi + limits: + cpu: 20m + memory: 32Mi + + prometheusAnnotations: false + serviceMonitor: + enabled: true + selector: + release: prometheus-operator + interval: 10s + # honorLabels: false + + grafanaDashboards: + enabled: false + labels: + grafana_dashboard: "1" + annotations: {} +octo: + enabled: false + region: all + relayId: k8s-jvb + strategy: SplitBridgeSelectionStrategy + + +jigasi: + ## Enabling Jigasi will allow regular SIP clients to join Jitsi meetings + ## or nearly real-time transcription. + enabled: false + + ## Use external Jigasi installation. + ## This setting skips the creation of Jigasi Deployment altogether, + ## instead creating just the config secret and enabling services. + ## Defaults to disabled (use bundled Jigasi). + useExternalJigasi: false + + replicaCount: 1 + image: + repository: jitsi/jigasi + + breweryMuc: jigasibrewery + + ## jigasi XMPP user credentials: + xmpp: + user: jigasi + password: + + livenessProbe: + tcpSocket: + port: 8788 + readinessProbe: + tcpSocket: + port: 8788 + + podLabels: {} + podAnnotations: {} + podSecurityContext: {} + securityContext: {} + resources: {} + nodeSelector: {} + tolerations: [] + affinity: {} + extraEnvs: {} + + +jibri: + ## Enabling Jibri will allow users to record + ## and/or stream their meetings (e.g. to YouTube). + enabled: false + + ## Use external Jibri installation. + ## This setting skips the creation of Jibri Deployment altogether, + ## instead creating just the config secret + ## and enabling recording/streaming services. + ## Defaults to disabled (use bundled Jibri). + useExternalJibri: false + + ## Enable single-use mode for Jibri. + ## With this setting enabled, every Jibri instance + ## will become "expired" after being used once (successfully or not) + ## and cleaned up (restarted) by Kubernetes. + ## + ## Note that detecting expired Jibri, restarting and registering it + ## takes some time, so you'll have to make sure you have enough + ## instances at your disposal. + ## You might also want to make LivenessProbe fail faster. + singleUseMode: false + + ## Enable recording service. + ## Set this to true/false to enable/disable local recordings. + ## Defaults to enabled (allow local recordings). + recording: true + + ## Enable livestreaming service. + ## Set this to true/false to enable/disable live streams. + ## Defaults to disabled (livestreaming is forbidden). + livestreaming: false + + ## Enable multiple Jibri instances. + ## If enabled (i.e. set to 2 or more), each Jibri instance + ## will get an ID assigned to it, based on pod name. + ## Multiple replicas are recommended for single-use mode. + replicaCount: 1 + + ## Enable persistent storage for local recordings. + ## If disabled, jibri pod will use a transient + ## emptyDir-backed storage instead. + persistence: + enabled: false + size: 4Gi + ## Set this to existing PVC name if you have one. + existingClaim: + storageClassName: + + shm: + ## Set to true to enable "/dev/shm" mount. + ## May be required by built-in Chromium. + enabled: true + ## If "true", will use host's shared memory dir, + ## and if "false" — an emptyDir mount. + useHost: false + size: 2Gi + + ## Configure the update strategy for Jibri deployment. + ## This may be useful depending on your persistence settings, + ## e.g. when you use ReadWriteOnce PVCs. + ## Default strategy is "RollingUpdate", which keeps + ## the old instances up until the new ones are ready. + # strategy: + # type: RollingUpdate + + image: + repository: jitsi/jibri + + podLabels: {} + podAnnotations: {} + resources: {} + + + breweryMuc: jibribrewery + timeout: 90 + + ## jibri XMPP user credentials: + xmpp: + user: jibri + password: + + ## recorder XMPP user credentials: + recorder: + user: recorder + password: + + livenessProbe: + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 2 + exec: + command: + - /bin/bash + - "-c" + - >- + curl -sq localhost:2222/jibri/api/v1.0/health + | jq '"\(.status.health.healthStatus) \(.status.busyStatus)"' + | grep -qP 'HEALTHY (IDLE|BUSY)' + + readinessProbe: + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 2 + exec: + command: + - /bin/bash + - "-c" + - >- + curl -sq localhost:2222/jibri/api/v1.0/health + | jq '"\(.status.health.healthStatus) \(.status.busyStatus)"' + | grep -qP 'HEALTHY (IDLE|BUSY)' + + extraEnvs: {} + custom: + contInit: + _10_config: "" + defaults: + _autoscaler_sidecar_config: "" + _jibri_conf: "" + _logging_properties: "" + _xorg_video_dummy_conf: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + +xmpp: + domain: meet.jitsi + authDomain: + mucDomain: + internalMucDomain: + guestDomain: + +extraCommonEnvs: {} + +prosody: + enabled: true + useExternalProsody: false + server: + extraEnvFrom: + - secretRef: + name: '{{ include "prosody.fullname" . }}-jibri' + - secretRef: + name: '{{ include "prosody.fullname" . }}-jicofo' + - secretRef: + name: '{{ include "prosody.fullname" . }}-jigasi' + - secretRef: + name: '{{ include "prosody.fullname" . }}-jvb' + - configMapRef: + name: '{{ include "prosody.fullname" . }}-common' + customPluginUrls: + - https://raw.githubusercontent.com/jitsi-contrib/prosody-plugins/main/token_lobby_bypass/mod_token_lobby_bypass.lua + - https://raw.githubusercontent.com/jitsi-contrib/prosody-plugins/main/token_affiliation/mod_token_affiliation.lua + + image: + repository: jitsi/prosody + # service: + # ports: + # If Prosody c2s in needed on private net outside the cluster + # xmppc2snodePort: 30522 + custom: + contInit: + _10_config: "" + defaults: + _prosody_cfg_lua: "" + _saslauthd_conf: "" + _jitsi_meet_cfg_lua: true + tag: 'stable-9111'