YaJa – Yet another Jitsi article

Diesen Beitrag schrieb ich 1 Jahr und 7 Monate zuvor; die nachfolgenden Ausführungen müssen heute nicht unbedingt noch genau so funktionieren. Behalte das beim Lesen (und vor allem: beim Nachmachen!) bitte stets im Hinterkopf.

Geschätzte Lesezeit: 5 Minuten

Artikel zu Jitsi gibt es aus aktuellem Anlass viele. Und naja, jetzt gibt es halt einen mehr ;)

Hattet ihr Jitsi vorher schon auf dem Radar, wobei vorher sowas wie ante Coronam meint? Ich nicht. Bislang spielten Videokonferenzen in meinem Alltag eine sehr untergeordnete Rolle, sowohl beruflich als auch privat. Mit Beginn der Corona-Zeitrechnung sieht das natürlich anders aus, und schon vor mehreren Wochen habe ich auf meinem Netcup-Root-Server meinen eigenen Jitsi-Server aufgezogen. Da mir dazu immer mal wieder Fragen gestellt werden: hier ein paar Details dazu.

Der Artikel erhebt keinen Anspruch auf Vollständigkeit, und er setzt sicher einiges an Vorwissen voraus.

Server und Auslastung

Der Host hat 16 32GB RAM und vier sechs Cores. Damit fackele ich mehr ab als mir gut tut: alle Webseiten nebst nginx als Reverse Proxy, SMTP und IMAP, Puppetserver, Icinga 2 und Prometheus nebst diverser Exporter, MariaDB, Redis und Rspamd, InfluxDB und Mosquitto und Grafana und diverse Backups… gelangweilt hat sich das Ding noch nie, und jetzt kam eben noch Jitsi dazu. Der durchschnittliche Freitags-Stammtisch dauert gute zwei Stunden mit acht bis vierzehn Teilnehmern, und das funktioniert erfreulich gut. Der RAM-Verbrauch liegt recht konstant bei ~1GB; CPU ist definitiv die kritische Größe bei der Nutzung von Jitsi. Die aktuelle Situation war eine super Ausrede für das Upgrade auf den RS 4000 – war ich schon lange scharf drauf.

Einrichtung und Betrieb von Jitsi

Jitsi per docker-compose an den Start zu bringen hat sich als recht stressfrei erwiesen. Ich bin kein wirklicher Fan von Docker, aber es gibt so eine Handvoll Einsatzzwecke, da finde ich es sehr nützlich: Jitsi ist so einer (graphite ist ein weiterer; anderes Thema.) Wie also komme ich von Null an zu einem leidlich laufenden Videokonferenzsystem?

Als erstes habe ich mir die Subdomain meetup.unixe.eu eingerichtet; das Zertifikat dazu ist ein Wildcard-Zertifikat von Let’s Encrypt (DNS-01 Challenge) und war sowieso schon vorhanden. Im Zweifel müsst ihr euch halt ein hübsches neues Zertifikat bauen; ist ja zum Glück keine Raketenwissenschaft.

Jitsi itself

Jetzt kommt der spaßigere Teil, nämlich Jitsi selbst: ich hab mich da an Repository des Projekts orientiert; hier ist die Release-Nummer 4416 hardcoded, und ich hab das mal so belassen weil auf diese (bzw. auch auf der im Abschnitt „Upgrade” genannten 4548) auch .env und docker-compose.yml zugeschnitten sind. Ihr solltet euch natürlich immer am aktuellsten Release orientieren, vor allem je älter dieser Artikel hier wird 😎

$ cd /etc/docker
$ wget https://github.com/jitsi/docker-jitsi-meet/archive/stable-4416.tar.gz
$ tar xvfz stable-4416.tar.gz && cd docker-jitsi-meet-stable-4416
$ cp env.example .env
$ bash -x gen-passwords.sh

Die Ausführung von gen-passwords.sh schreibt zufällig generierte Passwörter in die .env (vgl. $secretpasswordstring$), und das ist wichtig – vor nicht allzu langer Zeit noch wurde überall mit dem Default-Passwort passw0rd hantiert, und das ist nun nicht gerade das, was man will. Wichtig ist folgendes: gen-passwords.sh schreibt die Passwörter wie gesagt in die .env; von dort aus werden sie dann jedoch verwurstet, um die jeweiligen Konfigurationen für die einzelnen Dienste zu erzeugen. Sprich: ändert ihr die Passwörter durch neuerliches Aufrufen des Scripts (und ich habe irgendwo gelesen, dass man das aus Sicherheitsgründen regelmäßig tun sollte), so müsst ihr die alten Konfigurationsdateien wegschmeißen, durch Restart der Container neue erzeugen lassen und eure lokalen Änderungen gegebenenfalls wieder einpflegen. Unter „Upgrade“ weiter unten habe ich kurz aufnotiert, wie das in meinem Setup vonstatten geht – das ist sicher keine Blaupause, aber bringt euch vielleicht auf die richtige Idee wenn’s irgendwo klemmen sollte.

Definition von Umgebungsvariablen – .env

Nun müsst ihr den Rest der .env unter die Lupe nehmen. Meine (selbstredend um die Passwörter zensierte) Version von .env ist die folgende. Durch Kommentare habe ich versucht zu verdeutlichen, worum es geht. jigasi sowie jibri bleiben in meinem Setup komplett außen vor und werden auch gar nicht erst gestartet – das mag bei euch anders aussehen.

## STABLE_RELEASE ist leider nicht Bestandteil des offiziellen Repos
## Dort sind die Versionsnummern aus Gründen hardcoded
## Ich bin halt zu faul zum Tippen
STABLE_RELEASE=4416

JICOFO_COMPONENT_SECRET=$secretpasswordstring$
JICOFO_AUTH_PASSWORD=$secretpasswordstring$
JVB_AUTH_PASSWORD=$secretpasswordstring$
JIGASI_XMPP_PASSWORD=$secretpasswordstring$
JIBRI_RECORDER_PASSWORD=$secretpasswordstring$
JIBRI_XMPP_PASSWORD=$secretpasswordstring$

## Konfiguration wird sich im $HOME des ausführenden Users finden
CONFIG=~/.jitsi-meet-cfg

## nginx als Reverse Proxy wird die Anfragen annehmen und weiterleiten
## Deshalb kommentiere ich auch HTTPS_PORT=8443 aus
HTTP_PORT=80
## HTTPS_PORT=8443
DISABLE_HTTPS=1

## Zeitzone anpassen
TZ=Europe/Berlin

## Hier muss natürlich meine Adresse rein
PUBLIC_URL="https://meetup.unixe.eu"

## Zertifikat steckt schon im nginx, also brauche ich hier nicht noch eines
ENABLE_LETSENCRYPT=0

## Nur zugelassene Personen sollen Räume eröffnen dürfen
ENABLE_AUTH=1

## Anbindung an LDAP brauche ich nicht, die User lege ich von Hand in Prosody an
AUTH_TYPE=internal

## Aber in den einmal angelegten Raum dürfen sich andere ohne Passwort einwählen
ENABLE_GUESTS=1

## Aufzeichnungen sind explizit nicht erwünscht
ENABLE_RECORDING=0

## Die Container sollen immer wieder hochkommen
RESTART_POLICY=always

## Jetzt folgen Einträge, die den Defaults entsprechen,
## aber trotzdem explizit gesetzt werden müssen
## Hier geht das System noch über die STUN-Server von Google;
## vorgesehen ist hier inzwischen ein einzelner Eintrag:
## JVB_STUN_SERVERS=meet-jit-si-turnrelay.jitsi.net:443
## Kann man sich überlegen, was man hier lieber sieht...
##
XMPP_DOMAIN=meet.jitsi
XMPP_SERVER=xmpp.meet.jitsi
XMPP_BOSH_URL_BASE=http://xmpp.meet.jitsi:5280
XMPP_AUTH_DOMAIN=auth.meet.jitsi
XMPP_MUC_DOMAIN=muc.meet.jitsi
XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
XMPP_GUEST_DOMAIN=guest.meet.jitsi
XMPP_MODULES=
XMPP_MUC_MODULES=
XMPP_INTERNAL_MUC_MODULES=

JVB_BREWERY_MUC=jvbbrewery
JVB_AUTH_USER=jvb
JVB_STUN_SERVERS=stun.l.google.com:19302,stun1.l.google.com:19302,stun2.l.google.com:19302
JVB_PORT=10000
JVB_TCP_HARVESTER_DISABLED=true
JVB_TCP_PORT=4443
JVB_TCP_MAPPED_PORT=4443

JICOFO_AUTH_USER=focus

JIGASI_XMPP_USER=jigasi
JIGASI_BREWERY_MUC=jigasibrewery
JIGASI_PORT_MIN=20000
JIGASI_PORT_MAX=20050

Container-Setup – docker-compose.yml

Die docker-compose.yml habe ich in erster Instanz so übernommen, wie das Projekt sie vorgibt. Meine Version der Datei weist inzwischen jedoch einige Abweichungen auf:

  1. Ich habe für alle feste Host- und Container-Namen vergeben, schlicht weil ich das immer tue und ich so einfacher debuggen kann. Das ist Geschmackssache, haltet das wie ihr möchtet.
  2. Statt fester Release-Nummern wird hier mit ${STABLE_RELEASE} gearbeitet, die ich in .env etabliert habe.
  3. jitsi-web läuft auf Port 8050 unverschlüsselt; nginx als reverse proxy leitet die Requests dort hin (Konfiguration des nginx folgt etwas weiter unten).
  4. Ich habe noch ein Volume für css erzeugt und mittels docker cp die Dateien aus dem Container herauskopiert, da ich sie lokal modifizieren wollte.

Ich hoffe, ich habe nichts Wichtiges vergessen – im Zweifel müsst ihr halt mal ein diff drauf loslassen 🙃

version: '3'

services:
  # Frontend
  web:
    image: jitsi/web:stable-${STABLE_RELEASE}
    hostname: jitsi-web
    container_name: jitsi-web
    restart: ${RESTART_POLICY}
    ports:
      - '8050:${HTTP_PORT}'
    volumes:
      - ${CONFIG}/web:/config
      - ${CONFIG}/web/letsencrypt:/etc/letsencrypt
      - ${CONFIG}/transcripts:/usr/share/jitsi-meet/transcripts
      - ${CONFIG}/css:/usr/share/jitsi-meet/css
    environment:
      - ENABLE_AUTH
      - ENABLE_GUESTS
      - ENABLE_LETSENCRYPT
      - ENABLE_HTTP_REDIRECT
      - ENABLE_TRANSCRIPTIONS
      - DISABLE_HTTPS=1
      - JICOFO_AUTH_USER
      - LETSENCRYPT_DOMAIN
      - LETSENCRYPT_EMAIL
      - PUBLIC_URL
      - XMPP_DOMAIN
      - XMPP_AUTH_DOMAIN
      - XMPP_BOSH_URL_BASE
      - XMPP_GUEST_DOMAIN
      - XMPP_MUC_DOMAIN
      - XMPP_RECORDER_DOMAIN
      - ETHERPAD_URL_BASE
      - TZ
      - JIBRI_BREWERY_MUC
      - JIBRI_PENDING_TIMEOUT
      - JIBRI_XMPP_USER
      - JIBRI_XMPP_PASSWORD
      - JIBRI_RECORDER_USER
      - JIBRI_RECORDER_PASSWORD
      - ENABLE_RECORDING
    networks:
      meet.jitsi:
        aliases:
          - ${XMPP_DOMAIN}

  # XMPP server
  prosody:
    image: jitsi/prosody:stable-${STABLE_RELEASE}
    hostname: jitsi-prosody
    container_name: jitsi-prosody
    restart: ${RESTART_POLICY}
    expose:
      - '5222'
      - '5347'
      - '5280'
    volumes:
      - ${CONFIG}/prosody:/config
    environment:
      - AUTH_TYPE
      - ENABLE_AUTH
      - ENABLE_GUESTS
      - GLOBAL_MODULES
      - GLOBAL_CONFIG
      - LDAP_URL
      - LDAP_BASE
      - LDAP_BINDDN
      - LDAP_BINDPW
      - LDAP_FILTER
      - LDAP_AUTH_METHOD
      - LDAP_VERSION
      - LDAP_USE_TLS
      - LDAP_TLS_CIPHERS
      - LDAP_TLS_CHECK_PEER
      - LDAP_TLS_CACERT_FILE
      - LDAP_TLS_CACERT_DIR
      - LDAP_START_TLS
      - XMPP_DOMAIN
      - XMPP_AUTH_DOMAIN
      - XMPP_GUEST_DOMAIN
      - XMPP_MUC_DOMAIN
      - XMPP_INTERNAL_MUC_DOMAIN
      - XMPP_MODULES
      - XMPP_MUC_MODULES
      - XMPP_INTERNAL_MUC_MODULES
      - XMPP_RECORDER_DOMAIN
      - JICOFO_COMPONENT_SECRET
      - JICOFO_AUTH_USER
      - JICOFO_AUTH_PASSWORD
      - JVB_AUTH_USER
      - JVB_AUTH_PASSWORD
      - JIGASI_XMPP_USER
      - JIGASI_XMPP_PASSWORD
      - JIBRI_XMPP_USER
      - JIBRI_XMPP_PASSWORD
      - JIBRI_RECORDER_USER
      - JIBRI_RECORDER_PASSWORD
      - JWT_APP_ID
      - JWT_APP_SECRET
      - JWT_ACCEPTED_ISSUERS
      - JWT_ACCEPTED_AUDIENCES
      - JWT_ASAP_KEYSERVER
      - JWT_ALLOW_EMPTY
      - JWT_AUTH_TYPE
      - JWT_TOKEN_AUTH_MODULE
      - LOG_LEVEL
      - TZ
    networks:
      meet.jitsi:
        aliases:
          - ${XMPP_SERVER}

  # Focus component
  jicofo:
    image: jitsi/jicofo:stable-${STABLE_RELEASE}
    hostname: jitsi-jicofo
    container_name: jitsi-jicofo
    restart: ${RESTART_POLICY}
    volumes:
      - ${CONFIG}/jicofo:/config
    environment:
      - ENABLE_AUTH
      - XMPP_DOMAIN
      - XMPP_AUTH_DOMAIN
      - XMPP_INTERNAL_MUC_DOMAIN
      - XMPP_SERVER
      - JICOFO_COMPONENT_SECRET
      - JICOFO_AUTH_USER
      - JICOFO_AUTH_PASSWORD
      - JICOFO_RESERVATION_REST_BASE_URL
      - JVB_BREWERY_MUC
      - JIGASI_BREWERY_MUC
      - JIBRI_BREWERY_MUC
      - JIBRI_PENDING_TIMEOUT
      - TZ
    depends_on:
      - prosody
    networks:
      meet.jitsi:

  # Video bridge
  jvb:
    image: jitsi/jvb:stable-${STABLE_RELEASE}
    hostname: jitsi-jvb
    container_name: jitsi-jvb
    restart: ${RESTART_POLICY}
    ports:
      - '${JVB_PORT}:${JVB_PORT}/udp'
      - '${JVB_TCP_PORT}:${JVB_TCP_PORT}'
    volumes:
      - ${CONFIG}/jvb:/config
    environment:
      - DOCKER_HOST_ADDRESS
      - XMPP_AUTH_DOMAIN
      - XMPP_INTERNAL_MUC_DOMAIN
      - XMPP_SERVER
      - JVB_AUTH_USER
      - JVB_AUTH_PASSWORD
      - JVB_BREWERY_MUC
      - JVB_PORT
      - JVB_TCP_HARVESTER_DISABLED
      - JVB_TCP_PORT
      - JVB_STUN_SERVERS
      - JVB_ENABLE_APIS
      - TZ
    depends_on:
      - prosody
    networks:
      meet.jitsi:

# Custom network so all services can communicate using a FQDN
networks:
  meet.jitsi:

nginx als Reverse Proxy

Auf Port 443 nimmt mein nginx alle eingehenden Anfragen an und leitet sie weiter – in meiner Welt sieht das folgendermaßen aus.

server {
  server_name meetup.unixe.eu;
  listen [::]:443 ssl;

  access_log /var/log/nginx/unixe.eu/meetup/access.log combined_vhost;
  error_log  /var/log/nginx/unixe.eu/meetup/error.log error;

  ssl_certificate     /etc/letsencrypt/live/unixe.eu/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/unixe.eu/privkey.pem;

  client_max_body_size 512M;

  location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
    proxy_pass http://127.0.0.1:8050;
  }
}

Der erste Start

Ist nginx bereit und die docker-compose.yml erst bereit, könnt ihr die Container hochfeuern und auch gleich mal ausprobieren.

$ docker-compose up -d
...

$ docker ps
CONTAINER ID        IMAGE                                      COMMAND                  CREATED             STATUS                   PORTS                                              NAMES
262cb6c56f19        jitsi/jvb:stable-4416                      "/init"                  18 minutes ago      Up 18 minutes            0.0.0.0:4443->4443/tcp, 0.0.0.0:10000->10000/udp   jitsi-jvb
0a1804260ce2        jitsi/jicofo:stable-4416                   "/init"                  18 minutes ago      Up 18 minutes                                                               jitsi-jicofo
7adc130febdc        jitsi/web:stable-4416                      "/init"                  18 minutes ago      Up 18 minutes            443/tcp, 0.0.0.0:8050->80/tcp                      jitsi-web
55d8cd8c3eee        jitsi/prosody:stable-4416                  "/init"                  18 minutes ago      Up 18 minutes            5222/tcp, 5269/tcp, 5280/tcp, 5347/tcp             jitsi-prosody

Sobald alles so weit gediehen ist, könnt ihr die offizielle Adresse (in meinem Beispiel https://meetup.unixe.eu) im Browser aufrufen; nun könnt ihr einen Namen für die erste Konferenz vergeben, ihr werdet gefragt ob ihr der Organisator seid und… bumm. Ihr erinnert euch? Wir hatten festgelegt, dass Gäste sich zwar jederzeit einwählen, jedoch nur registrierte User Räume eröffnen dürfen. Und einen dahingehend berechtigten User müssen wir nun erst noch einrichten. Das geschieht innerhalb des Containers jitsi-prosody.

$ docker exec -it jitsi-prosody bash
$ prosodyctl --config /config/prosody.cfg.lua register marianne meet.jitsi "M@D3yYYF$mrsvv"

Der neu erzeugte User steht sofort zur Verfügung, ihr müsst nichts durchstarten oder so; allerdings verfügt der prosody-Container in der derzeitigen Konfiguration nicht über ein persistentes Volume, und ich war bislang zu faul eins einzubauen. Kann so schwierig ja nicht sein… im Moment muss ich nach einem Upgrade meinen User neu anlegen, aber sei’s drum.

Jitsi-Exporter für Prometheus

Graphen sind immer toll!

Hübsch sind Graphen natürlich immer, und nützlich sind sie auch. Deshalb hab ich meine docker-compose.yml erweitert um jitsi-exporter – das stellt meinem lokalen Prometheus dann auf localhost Port 8062 Metriken zur Verfügung, welche sich wiederum mit Grafana darstellen lassen.

  jitsi-exporter:
    image: karrieretutor/jitsi:prom-exporter-latest
    hostname: jitsi-exporter
    <!-- container_name: jitsi-exporter -->
    ports:
      - "127.0.0.1:8062:8080"
    restart: always
    environment:
      - XMPP_USER=prometheus
      - XMPP_PW=rs$IkYB!S89T@eC71
      - XMPP_AUTH_DOMAIN=meet.jitsi
      - XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi
      - XMPP_SERVER=prosody
      - XMPP_PORT=5222
      - JVB_BREWERY_MUC=jvbbrewery
    depends_on:
      - prosody
    networks:
      meet.jitsi:

Der Exporter benötigt einen eigenen XMPP-User, und dieser muss ebenfalls in jitsi-prosody angelegt werden wie oben gezeigt. Tut man das nicht oder macht dabei etwas falsch, bleibt der Container im Status restarting, und schaut man sich die Logs an, so erkennt man den auth failure. Das war bei Ersteinrichtung sehr tricky für mich

SEND:
AHByb21ldGhldXMAcnNJa1lCUzg5VGVD

RECV:
Unable to authorize you with the authentication credentials you've sent.

xmpp connection manager returned with error: unrecoverable connect error : auth failure:
SEND:

panic: sync: negative WaitGroup counter

goroutine 1 [running]:
sync.(*WaitGroup).Add(0xc0001220b0, 0xffffffffffffffff)
  /usr/local/go/src/sync/waitgroup.go:74 +0x135
sync.(*WaitGroup).Done(...)
  /usr/local/go/src/sync/waitgroup.go:99
github.com/FluuxIO/go-xmpp.(*StreamManager).Stop(0xc000122090)
  /go/src/github.com/FluuxIO/go-xmpp/stream_manager.go:107 +0x6e
main.shutdown(...)
  /go/src/exporter/main.go:196
main.main()

Prometheus habe ich um einige wenige Konfigurationszeilen erweitert

- job_name: jitsi-exporter
  honor_timestamps: true
  scrape_interval: 30s
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
  static_configs:
  - targets:
    - 127.0.0.1:8062

Das dazgehörige Grafana-Dashboard könnt ihr dann importieren, gegebenenfalls noch ein bisschen anpassen et voilà – Dashboards. Überm Schreiben fiel mir gerade ein, dass ich die Variable instance des Dashboards modifizieren musste, da in meinem Setup der Container ja jitsi-exporter heißt – als Query habe ich für diese Variable deshalb label_values(go_info{job = "jitsi-exporter"}, instance) hinterlegt, dann funktioniert auch die Sache mit dem Dropdown.

Upgrade

Weil das alles gar nicht mal so trivial ist hab ich mich eine Weile vor den Upgrades gedrückt, inzwischen ist es aber klarer. Damit ihr euch ein wenig „Lernen durch Schmerz“ sparen könnt hier also noch ein Exklusiv-Einblick in den Upgrade-Prozess.

  • Die laufenden Container mittels docker-compose down anhalten und wegschmeißen
$ cd /etc/docker/docker-jitsi-meet-stable-$ALTE_VERSION && docker-compose down
Stopping jitsi-jvb      ... done
Stopping jitsi-jicofo   ... done
Stopping jitsi-exporter ... done
Stopping jitsi-web      ... done
Stopping jitsi-prosody  ... done
Removing jitsi-jvb      ... done
Removing jitsi-jicofo   ... done
Removing jitsi-exporter ... done
Removing jitsi-web      ... done
Removing jitsi-prosody  ... done
Removing network docker-jitsi-meet-stable-4416_meet.jitsi
  • Die alte Konfiguration wegsichern
$ mv ~/.jitsi-meet-cfg ~/.jitsi-meet-cfg-$ALTE_VERSION
  • Neue Version an den Start bringen; natürlich CHANGELOG & Co. lesen und docker-compose.yml sowie .env gegebenenfalls anpassen/ erweitern, falls nötig (die Anpassung von ${STABLE_RELEASE} ist das mindeste!).
$ cd /etc/docker
$ wget https://github.com/jitsi/docker-jitsi-meet/archive/stable-$NEUE_VERSION.tar.gz
$ tar xvfz stable-$NEUE_VERSION.tar.gz
$ cd docker-jitsi-meet-stable-$NEUE_VERSION
$ cp ../docker-jitsi-meet-stable-$ALTE_VERSION/.env .
$ ./gen-passwords.sh
$ cp ../docker-jitsi-meet-stable-$ALTE_VERSION/docker-compose.yml .
$ docker-compose up -d --force-recreate
Creating network "docker-jitsi-meet-stable-4548_meet.jitsi" with the default driver
Creating jitsi-prosody ... done
Creating jitsi-web     ... done
Creating jitsi-jvb      ... done
Creating jitsi-exporter ... done
Creating jitsi-jicofo   ... done

Das Starten der Container wirft die neue Konfiguration wiederum nach ~/.jitsi-meet-cfg; aus dem alten Verzeichnis heraus kopiere ich meine Änderungen – derzeit sind das eigentlich nur zwei.

$ mv ~/.jitsi-meet-cfg-$ALTE_VERSION/css/* ~/.jitsi-meet-cfg/css/
$ cp ~/.jitsi-meet-cfg-$ALTE_VERSION/web/*.js ~/.jitsi-meet-cfg/web/
$ docker restart jitsi-web

Zur Erinnerung: alle prosody-User müssen nun neu angelegt werden

Debugging

Nutzt ein Teilnehmer etwas anderes als einen Chrome-basierten Browser, wirkt sich das allerdings auch negativ auf den Server und die übrigen Teilnehmer aus: die Load geht bei allen gleichermaßen hoch. Ich hatte keine Zeit und Lust, das so richtig eingehend zu analysieren, es scheint aber in direktem Zusammenhang mit den Teilnehmer-Browsern zu stehen: nachdem der Teilnehmer die Konferenz verlassen hatte – er hatte ohnehin keinen Ton, und die Bildqualität war lausig – normalisierte sich der Zustand für alle wieder.

Der Web-Container macht mir noch den wenigsten Ärger; wenn etwas nicht geht, sind jitsi-jvb und jitsi-jicofo meine ersten Anlaufstellen.

$ docker logs --follow --tail 10 jitsi-jvb
$ docker logs --follow --tail 10 jitsi-jicofo