Eine zweite JVB zu Jitsi Meet hinzufügen (Docker)
In der vorherhigen Anleitung habe ich gezeigt wie teamjoin.de angepasst wurde.
Tutorial: Jitsi Meet Docker Instanz anpassen
Tutorial: Eigene Jitsi Meet Instanz installieren (Docker / Ubuntu / Nginx)
Was ist Jitsi Meet?: Videokonferenzen mit Jitsi Meet
Meeting starten: https://teamjoin.de
Nun möchte ich euch zeigen wie eine zweite Jitsi-Videobridge (JVB) eurer bestehenden Jitsi Meet Instanz hinzugefügt werden kann. Dies ermöglicht euch mehr gleichzeitige Teilnehmer auf eurer Jitsi Meet Instanz zu haben.
Vorteile:
- automatische Lastverteilung der Videostreams auf die einzelnen Videobridges (Round Robin)
- in die Breite skalierbare Jitsi Meet Instanz
- ein Zutrittspunkt für die Teilnehmer wie bsp. teamjoin.de
- Erweiterung durch weitere JVB’s möglich
Was wird benötigt?
- Eine laufenden Docker Jitsi Meet Instanz (siehe Anleitung)
- 2 Server mit gleicher Ausstattung an CPU Kernen und Bandbreite
- Optional: Die beiden Server sind über ein internes Netzwerk verbunden
Offene Ports in der Firewall (extern):
- 4443/tcp
- 10000/udp
Offene Ports in der Firewall (host zu host):
- 2377/tcp
- 7946/tcp+udp
- 4789/udp
Punkt 1: Docker Swarm einrichten
Docker liefert ein Orchestrierungswerkzeug namens Swarm mit. Wir benutzen Swarm nur um ein Overlay Netzwerk zwischen Server A und B herzustellen. Die Docker Container starten wir weiterhin über docker-compose
. Das hält uns weiterhin nahe am originalen Jitsi Meet Docker.
Im Testsetup habe ich 2 Debian Linux Server mit einem internen Netzwerk 10.10.0.0/16. Es funktioniert aber auch über das öffentliche Internet.
Unseren Server A richten wir als Swarm Manager ein.
1 2 3 4 5 6 7 8 | test:/opt/docker/jitsi-meet# docker swarm init Swarm initialized: current node (zfmm8ze98lgdlc5qgo9jojqfn) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-5ixzd9lfw7o9f0xp4gx27yuxggb9anse6savqs7cous55oqpdd-ce4yj3e5zybrwhl6o60am9a3s 10.10.60.20:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. |
Auf unserem zweiten Server (Server B) installieren wir docker
und docker-compose
nach Anleitung: Eigene Jitsi Meet Instanz installieren (Docker / Ubuntu / Nginx)
Es reicht der Anleitung bis Punkt 2 zu folgen.
Server B wird dann als Worker Node hinzugefügt.
1 2 | test2:/opt/docker/jitsi-meet# docker swarm join --token SWMTKN-1-5ixzd9lfw7o9f0xp4gx27yuxggb9anse6savqs7cous55oqpdd-ce4yj3e5zybrwhl6o60am9a3s 10.10.60.20:2377 This node joined a swarm as a worker. |
Nun überprüfen wir ob Server A beide Nodes korrekt sieht.
1 2 3 4 | test:/opt/docker/jitsi-meet# docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION o2xn4ksllc5o3b1zii0lemylh test2 Ready Active 19.03.8 zfmm8ze98lgdlc5qgo9jojqfn * test Ready Active Leader 19.03.8 |
Punkt 2: Overlay Netzwerk anlegen
Auf der Manager Node (Server A) erstellen wir unser Jitsi Meet Overlay Netzwerk.
1 2 | test:/opt/docker/jitsi-meet# docker network create --driver=overlay --attachable jitsi-meet prjmyedevt8yumtfwyepza9te |
Punkt 3: restart.sh auf Server A anpassen
Wir fügen die markierten Zeilen unserem restart.sh
Script hinzu.
- Es wird geprüft ob das Overlay Netzwerk existiert, falls nein wird es erstellt
- Es wird der Netzwerkname ausgetauscht. Docker Swarm erlaubt keine Punkte („.“) im Overlay Netzwerknamen
- Das Netzwerk muss auf „external“ gestellt werden, ansonsten kann
docker-compose
nicht das Overlay Netzwerk von Swarm nutzen
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #!/bin/bash DOCKERPATH=/opt/docker # Create overlay network if not exist if [ $(docker network ls | grep jitsi-meet | wc -l) = 0 ]; then docker network create --driver=overlay --attachable jitsi-meet fi # Configure overlay network in docker-compose.yml cd $DOCKERPATH/jitsi-meet sed -i 's/meet.jitsi/jitsi-meet/g' docker-compose.yml if [ $(grep "hostname: jvb" docker-compose.yml | wc -l) = 0 ]; then sed -i '/image: jitsi\/jvb:latest/a \ hostname: jvb' docker-compose.yml fi grep -qxF ' external: true' docker-compose.yml || echo ' external: true' >> docker-compose.yml # Shutdown jitsi meet containers and remove images cd $DOCKERPATH/jitsi-meet docker-compose down --rmi all # Delete configs and recreate folders rm -rf .jitsi-meet-cfg/ mkdir -p .jitsi-meet-cfg/{web/letsencrypt,transcripts,prosody,jicofo,jvb} # Start Jitsi Meet docker-compose up -d sleep 10 # Customize ./customize.sh # Set JVB Logging from INFO to WARNING sed -i 's/.level=.*/.level=WARNING/' .jitsi-meet-cfg/jvb/logging.properties docker restart jitsi-meet-jvb-1 |
Wir starten Jitsi Meet auf Server A mit dem angepassten Script neu.
1 | ./restart.sh |
Punkt 4: Zweite JVB auf Server B einrichten
Wichtig ist ein identisches JVB_AUTH_PASSWORD
auf allen JVB Instanzen zu verwenden. Wir nutzen das Passwort von Server A und spielen es auf Server B ein.
Server A:
1 2 | test:/opt/docker/jitsi-meet# grep JVB_AUTH_PASSWORD .env JVB_AUTH_PASSWORD=8d3a55aab4fced07e5304f624d86b1ce |
Server B:
1 | test2:/opt/docker/jitsi-meet# sed -i 's/JVB_AUTH_PASSWORD=.*/JVB_AUTH_PASSWORD=8d3a55aab4fced07e5304f624d86b1ce/' .env |
Websockets: Damit die Websockets korrekt funktionieren, muss in die .env
noch JVB_WS_SERVER_ID=jvb2
eingefügt werden. Als ID muss die Service-Bezeichnung aus der docker-compose.yml Datei genutzt werden (jvb2).
Wir erstellen docker-compose-jvb2.yml
um nur die Jitsi Videobridge (JVB) auf Server B zu starten.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | version: '3' services: # Video bridge jvb2: hostname: jvb2 image: jitsi/jvb:${JITSI_IMAGE_VERSION:-stable} restart: ${RESTART_POLICY:-unless-stopped} ports: - '${JVB_PORT:-10000}:${JVB_PORT:-10000}/udp' volumes: - ${CONFIG}/jvb:/config:Z environment: - AUTH_TYPE - DISABLE_POLLS - ENABLE_AUTH - ENABLE_AV_MODERATION - ENABLE_BREAKOUT_ROOMS - ENABLE_END_CONFERENCE - ENABLE_GUESTS - ENABLE_IPV6 - ENABLE_LOBBY - ENABLE_RECORDING - ENABLE_XMPP_WEBSOCKET - ENABLE_JAAS_COMPONENTS - GC_TYPE - GC_INC_TH - GC_INC_SPEED - GC_INC_STEP_SIZE - GC_GEN_MIN_TH - GC_GEN_MAX_TH - GLOBAL_CONFIG - GLOBAL_MODULES - JIBRI_RECORDER_USER - JIBRI_RECORDER_PASSWORD - JIBRI_XMPP_USER - JIBRI_XMPP_PASSWORD - JICOFO_AUTH_PASSWORD - JICOFO_COMPONENT_SECRET - JIGASI_XMPP_USER - JIGASI_XMPP_PASSWORD - JVB_AUTH_USER - JVB_AUTH_PASSWORD - JWT_APP_ID - JWT_APP_SECRET - JWT_ACCEPTED_ISSUERS - JWT_ACCEPTED_AUDIENCES - JWT_ASAP_KEYSERVER - JWT_ALLOW_EMPTY - JWT_AUTH_TYPE - JWT_ENABLE_DOMAIN_VERIFICATION - JWT_TOKEN_AUTH_MODULE - MATRIX_UVS_URL - MATRIX_UVS_ISSUER - MATRIX_UVS_AUTH_TOKEN - MATRIX_UVS_SYNC_POWER_LEVELS - LOG_LEVEL - LDAP_AUTH_METHOD - LDAP_BASE - LDAP_BINDDN - LDAP_BINDPW - LDAP_FILTER - LDAP_VERSION - LDAP_TLS_CIPHERS - LDAP_TLS_CHECK_PEER - LDAP_TLS_CACERT_FILE - LDAP_TLS_CACERT_DIR - LDAP_START_TLS - LDAP_URL - LDAP_USE_TLS - MAX_PARTICIPANTS - PROSODY_RESERVATION_ENABLED - PROSODY_RESERVATION_REST_BASE_URL - PUBLIC_URL - TURN_CREDENTIALS - TURN_HOST - TURNS_HOST - TURN_PORT - TURNS_PORT - TURN_TRANSPORT - TZ - XMPP_DOMAIN - XMPP_AUTH_DOMAIN - XMPP_GUEST_DOMAIN - XMPP_MUC_DOMAIN - XMPP_INTERNAL_MUC_DOMAIN - XMPP_MODULES - XMPP_MUC_MODULES - XMPP_MUC_CONFIGURATION - XMPP_INTERNAL_MUC_MODULES - XMPP_RECORDER_DOMAIN - XMPP_PORT networks: jitsi-meet: aliases: - ${XMPP_SERVER:-xmpp.meet.jitsi} # Custom network so all services can communicate using a FQDN networks: jitsi-meet: external: true |
Dazu legen wir ein passendes restart.sh
Script an.
- Als erstes wird ein Dummy Container gestartet, da
docker-compose
aktuell kein Overlay Netzwerk auf den Worker Nodes anlegen kann - Danach wird der JVB Container gestartet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/bin/bash DOCKERPATH=/opt/docker # Start dummy container (for overlay network) if [ $(docker network ls | grep jitsi-meet | wc -l) = 0 ]; then docker rm dummy docker run -itd --name dummy --net jitsi-meet alpine sleep 5 fi # Shutdown jitsi meet containers and remove images cd $DOCKERPATH/jitsi-meet docker-compose -f docker-compose-jvb2.yml down --rmi all # Delete Configs and recreate folders rm -rf .jitsi-meet-cfg/ mkdir -p .jitsi-meet-cfg/jvb # Start Stack docker-compose -f docker-compose-jvb2.yml up -d sleep 10 # JVB Logging from INFO to WARNING sed -i 's/.level=.*/.level=WARNING/' .jitsi-meet-cfg/jvb/logging.properties docker restart jitsi-meet-jvb2-1 |
Punkt 5: Zweite JVB starten
Zuerst überwachen wir das Logfile auf Server A.
1 | docker logs -f jitsi-meet-jicofo-1 |
Dann starten wir auf Server B den JVB Container.
WICHTIG: Es muss immer zuerst die Jitsi Meet Master Instanz (auf Server A) gestartet werden bevor eine JVB Instanz joinen kann!
1 | ./restart.sh |
Im Log sollte nun diese Zeile zu sehen sein.
1 2 3 | ... Jicofo 2020-04-29 13:44:34.207 INFO: [38] org.jitsi.jicofo.bridge.BridgeSelector.log() Added new videobridge: Bridge[jid=jvbbrewery@internal-muc.meet.jitsi/1a542adbca3a, relayId=null, region=null, stress=0.00] ... |
Fertig! Eine zweite JVB steht eurer Jitsi Meet Instanz nun zur Verfügung.
Als nächstes: Jitsi Meet Grafana Statistiken (Docker)
oder: Jitsi Meet Docker: WelcomePage anpassen
Euer adminForge Team
Das Betreiben der Dienste, Webseite und Server machen wir gerne, kostet aber leider auch Geld. Unterstütze unsere Arbeit mit einer Spende. |
Vielen Dank für die Anleitung. Ich habe noch eine Verständnisfrage. Müsste Pkt. 4 nicht vor Pkt. 1 erfolgen? Da auf Server 2 noch kein Docker bzw. Docker-compose läuft, dürfte der Worker noch nicht aktiviert werden können oder habe ich einen Denkfehler?
Die Punkte 1-3 spielen sich doch alle auf Server A ab, dort sollte ja bereits Jitsi Meet Docker laufen. Erst in Punkt 4 wird begonnen auf Server B Docker zu installieren und dann die zweite JVB.
Hallo Dominion,
Unter Punkt 1 soll doch der Worker (Test2 – Server B) dem Swarm hinzugefügt werden?
Ach sorry, natürlich …. jetzt sehe ich es auch. Ich passe die Anleitung an!
Hi Dominion,
wann habt ihr geplant:
Als nächstes: Tutorial über die Grafana Statistiken stats.adminforge.de
Euer adminForge Team
Danke für eure super Hilfe – Jitsi Server läuft wunderbar im Docker nach eurer Anleitung
Danke Tobias,
mal schauen, vielleicht diese Woche noch.
Super Sache 🙂
Weiterhin habe ich bei meiner jitsi Installation immer das Thema, das auch wenn nur 2 User eingeloggt ein 3. Fellow Jister mit Moderatorrechte bereist „eingeloggt“ ist – hast du oder ihr mir da ein Tipp ?
Hallo Tobias,
das klingt stark nach einem Problem mit der Videobridge. Schau mal bitte ins log des JVB Containers, was der so meldet bei 3 Leuten.
Gruß
Hallo Dominion,
Danke für die Anleitung.
Vllt. sollte in die Anleitung etwas zu öffnenden Ports, falls man einen Paketfilter verwendet.
Fürn ufw:
ufw allow 2377/tcp
ufw allow 4789/udp
ufw allow 7946/tcp
ufw allow 7946/udp
VG
Dirk
Sehr gut Danke dir.
In dieser Anleitung bin ich selbst von einem „internen Netz“ ausgegangen, da hat man eher selten eine Firewall aktiv.
Wenn mein Server A mit ./restart.sh neu gestartet wird, bekomme ich einen nginx 502 Bad Gateway-Fehler und nichts geht mehr.
Meine beiden Server A und Server B sind nicht in einem internen Netzwerk verbunden, sondern sind also 2 VPS mit 2 verschiedenen IP-Adressen vorhanden.
Vermute, dass der Netzwerknamenstausch von meet.jitsi in jitsi-meet alles durcheinder bringt, oder nicht weitreichend genug ist.
Hi Dominion, danke für deine Anleitungen. Das hat mir alles sehr geholfen. Ich habe nun nur das Problem, dass meine Nodes das Netzwerk nicht finden. Das join hat zwar geklappt aber wenn ich das restart-Skript ausführe, schlägt es bereits bei dem Dummy Container fehl. Ich bekomme folgende Fehlermeldung:
docker: Error response from daemon: attaching to network failed, make sure your network options are correct and check manager logs: context deadline exceeded.
An der Portfreigabe kann es nicht liegen, da es schon mal funktioniert hatte ohne dass ich seitdem etwas an der Portfreigabe geändert habe. Als Nodes habe ich zum einen meinen Docker Daemon auf meinem Mac Rechner sowie eine VM in der Google Cloud probiert. Gestern hatte es funktioniert nachdem ich die Container und das Swarm Netzwerk auf Server A gelöscht habe und dann das restart-Skript ausgeführt habe, doch heute hat das leider nicht geklappt. Hast du eine Idee woran das liegen könnte?
Vielen Dank im Voraus,
Jonas
Hi Jonas,
schwer zu sagen aus der Ferne.
Du hast geschrieben, dass du das Netzwerk auf Server A gelöscht hast, deinem Swarm Master?
Prüf mal bitte ob die Netzwerke da sind und ob die Container sich untereinander sehen können.
Gruß
Dominion
Gude 👋🏻 Dominion,
ich habe alles soweit hin bekommen, auch werden die Nutzer auf die zwei jvb verteilt. Nur meldet sich nach ner Zeit der nginx (als Reverse Proxy vor JitsiMeet) mit error Meldungen (der DockerGW würde Probleme machen), trennt dann Upstream Server und schmeißt irgendwann alle Benutzer raus. Mein Reverse Proxy lasse ich als Docker laufen.
Hast du ggf nen Tipp für mich?
Grüße und danke für deine super Artikel 👍🏻
hast du genaue Fehler ?
Am besten im Chat besprechen
hey laeuft soweit, nur noch ein mini prob zwecks websocket 🙂
( BridgeChannel.js:86 WebSocket connection to ‚wss://domain.dm/colibri-ws/jvb2/62dgdfccc746dfde32/6adfdsf9cf?pwd=2fnpdfsdfsdfgi9l11caese45v‘ failed:
_initWebSocket @ BridgeChannel.js:86
t @ BridgeChannel.js:105
Logger.js:154 2021-03-14T18:00:57.514Z [modules/RTC/BridgeChannel.js] : Channel closed by server
)
dein rat die bridge noch einzufuegen hab ich auch so umgesetzt ( .env – JVB_WS_SERVER_ID=jvb2 ) – jvb.conf ( websockets {
enabled = true
domain = „domain.dm“
tls = true
server-id = „jvb2“
)
sonst wuerde hier nur die docker ip stehen statt jvb2
bridges laufen auch soweit (teilnehmer werden auch sauber verteilt )
nur ist die qualy auf 320 gedroppt 🙁
hab die bridges wieder ausgehangen und swarm entfernt, da laeuft es mit SD & HD!
war hier auch schon das thema ( Poor Videoquality with JVB2 on dedicated host: https://community.jitsi.org/t/poor-videoquality-with-jvb2-on-dedicated-host/86560/5 )
event hat noch wer ein rat, sonst geniale anleitung.. thx !
greetz
Hi,
sobald ich Server B mit dem mit dem restart.sh Skript starte, bekomm ich in dem Log jvb2 Log folgende Error-Meldung:
„The following addresses failed: ‚xmpp.meet.jitsi:522‘ failed because: java.net.UnknownHostException: xmpp.meet.jitsi: Name or service not known“
Sprich er kann den Dienst von Server A nicht finden. Allerdings habe ich nochmal in der .env nachgechaut und die interne xmpp Addresse, lautet xmpp.meet.jitsi. Hat jemand evtl. eine Idee was ich falsch/anders machen muss?
Habe das Problem gelöst^^. Allerdings stell ich mir noch die Frage, wie das Load-Balancing mit der hier beschriebenen Konfiguration funktioniert?
Wie genau hast du das Problem gelöst?
Die Lastverteilung funktioniert pro Raum und JVB. Anders als beim OCTO Setup wird die Last pro Raum verteilt, bei OCTO wird jeder User per Round Robin auf den einzelnen JVB verteilt.
Sollten Sehr große Räume so 40+ angestrebt werden, wäre eine OCTO Lastverteilung besser.
Ich hatte das gleiche Problem bei Version 8319 und musste im docker-compose file unter prosody das folgende anpassen, weil es sich im upstream repo offenbar geändert hat:
networks:
jitsi-meet:
aliases:
– ${XMPP_SERVER}
Generell gibt es viele moving/breaking parts mit jeder dritten neuen jitsi docker version, man muss echt immer direkt die alten und neuen files vergleichen, sonst bricht schnell mal was