Hadoly à mis en place en Mars 2020 un service de vidéoconférence basé sur le logiciel Jitsi Meet. Ce déploiement a été fait dans le contexte de la crise sanitaire du COVID-19 ayant entraîné le confinement de la population française
Ce service est considéré comme temporaire et sera potentiellement éteint à l'issue de la crise.
Ce document présente les détails techniques du déploiement de la solution. Il n'a pas vocation à être un tutoriel pas-à-pas d'installation, mais plutôt à mettre en avant les spécificités et les optimisations effectuées.
Le service utilise 3 machines virtuelles :
Avec le recul, le dimensionnement des machines n'est pas forcément complètement adapté aux besoins.
Pour référence, l'équipe qui développe le logiciel, et qui maintient https://meet.jit.si/, a indiqué utiliser pour ses videobridge des machines Ubuntu 18.04, 6Go de RAM, 8vCPU.
Les machines jvb2 et jvb3 ont été ajoutées après coup, afin de soulager jitsi2 lors des périodes de forte affluence. Elles hébergent uniquement des videobridge supplémentaires, et peuvent être éteintes à tout moment sans besoin de reconfiguration sur jitsi2.
L'installation principale, sur la machine jitsi2 a été faite en suivant la documentation officielle . Cette documentation permet d'arriver relativement facilement à un déploiement fonctionnel.
Officiellement, Jitsi ne fonctionne qu'avec Java 8… qui n'est pas disponible dans les dépôts Debian 10. Sous Ubuntu 18.04, openjdk-8-jre-headless est directement installé. Cette étape est donc inutile.
Sous Debian 10, on peut utiliser adoptopenjdk-8:
wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add - sudo add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/ sudo apt update sudo apt install adoptopenjdk-8-hotspot sudo update-alternatives --config java # Quick fix broken cacerts sudo ln -s /etc/ssl/certs/java/cacerts /usr/lib/jvm/adoptopenjdk-8-hotspot-amd64/jre/lib/security/cacerts
Avec l'installation par défaut, un serveur STUN/TURN est installé.
Cependant, afin de pouvoir utiliser le port TCP 443, il est configuré pour être derrière le serveur web nginx (conf dans /etc/nginx/modules-enabled/60-jitsi-meet.conf
).
Malheureusement cette configuration n'est pas compatible avec les web-sockets.
Nous avons donc fait le choix d'utiliser un FQDN séparé (turn.hadoly.fr) ainsi que de nouvelles IP publiques. Le serveur coturn, est exposé en direct sans passer par nginx. D'autres choix sont possibles. Comme installer un serveur TURN sur une machine dédiée. Ou changer le port d'écoute pour utiliser le port standard (5349) au lieu du 443… au risque de ne pas passer certains pare-feu.
Notre conf coturn:
use-auth-secret static-auth-secret=SuperSecret69 realm=turn.hadoly.fr cert=/etc/coturn/certs/turn.hadoly.fr.fullchain.pem pkey=/etc/coturn/certs/turn.hadoly.fr.privkey.pem dh-file=/etc/nginx/dh2048.pem listening-ip=80.67.185.26 listening-ip=2001:912:30aa:300::26 listening-port=443 external-ip=80.67.185.26 external-ip=2001:912:30aa:300::26 verbose syslog no-multicast-peers no-cli no-loopback-peers no-tcp-relay denied-peer-ip=0.0.0.0-0.255.255.255 denied-peer-ip=10.0.0.0-10.255.255.255 denied-peer-ip=100.64.0.0-100.127.255.255 denied-peer-ip=127.0.0.0-127.255.255.255 denied-peer-ip=169.254.0.0-169.254.255.255 denied-peer-ip=127.0.0.0-127.255.255.255 denied-peer-ip=172.16.0.0-172.31.255.255 denied-peer-ip=192.0.0.0-192.0.0.255 denied-peer-ip=192.0.2.0-192.0.2.255 denied-peer-ip=192.88.99.0-192.88.99.255 denied-peer-ip=192.168.0.0-192.168.255.255 denied-peer-ip=198.18.0.0-198.19.255.255 denied-peer-ip=198.51.100.0-198.51.100.255 denied-peer-ip=203.0.113.0-203.0.113.255 denied-peer-ip=240.0.0.0-255.255.255.255
Il faut ensuite adapter la conf prosody (/etc/prosody/conf.d/jitsi.hadoly.fr.cfg.lua
) afin d'indiquer les bons FQDN/port à utiliser
turncredentials_secret = "SuperSecret69"; turncredentials_port = 443; turncredentials_ttl = 43200; turncredentials = { { type = "stun", host = "turn.hadoly.fr", port = 443 }, { type = "turn", host = "turn.hadoly.fr", port = 443 , transport = "udp" }, { type = "turns", host = "turn.hadoly.fr", port = 443, transport = "tcp" } }
Docs intéressantes sur le sujet, notamment sur la manière de tester un serveur STUN et TURN:
Une fois le serveur TURN fonctionnel, il est possible de désactiver TCP sur le videobridge, pour ne le laisser fonctionner qu'en UDP, ce qui semble recommandé.
Le serveur TURN s'occupe alors de faire l'interface avec les clients qui sont derrière un pare-feu bloquant l'UDP, et donc obligés de passer en TCP.
Dans le fichier /etc/jitsi/videobridge/sip-communicator.properties
, on ajoute le paramètre suivant:
org.jitsi.videobridge.DISABLE_TCP_HARVESTER=true
Par défaut, les paquets actuels ne configurent pas le videobridge pour utiliser les web-sockets pour communiquer avec les clients. C'est pourtant la conf recommandée.
Chez Hadoly, la configuration par défaut avec bosh faisait apparaître beaucoup d'erreurs dans les logs (Sctp send error: : Resource temporarily unavailabl
). La solution de contournement est d'utiliser les web-sockets.
https://github.com/jitsi/jitsi-videobridge/blob/master/doc/web-sockets.md
La configuration est a faire dans /etc/jitsi/videobridge/jvb.conf
videobridge { http-servers { public { port = 9090 } } websockets { enabled = true tls = true domain = "jitsi.hadoly.fr:443" server-id = jvb1 } }
Côté serveur web, on adapte la conf du reverse proxy (dans /etc/nginx/sites-available/jitsi.hadoly.fr.conf
)
# colibri (JVB) websockets for jvb1 location ~ ^/colibri-ws/jvb1/(.*) { proxy_pass http://127.0.0.1:9090/colibri-ws/jvb1/$1$is_args$args; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; tcp_nodelay on; }
Et pour terminer on active les web-sockets côté client en modifiant /etc/jitsi/meet/jitsi.hadoly.fr-config.js
openBridgeChannel: 'websocket',
Afin d'avoir des métriques comme le nombre de personnes connectés ou le nombre de conférences, il est utile d'activer l'API.
Dans /etc/jitsi/videobridge/config
on adapte le paramètre suivant:
JVB_OPTS="--apis=rest"
Et dans /etc/jitsi/videobridge/sip-communicator.properties
:
org.jitsi.videobridge.ENABLE_STATISTICS=true org.jitsi.videobridge.rest.private.jetty.host=127.0.0.1
curl http://127.0.0.1:8080/colibri/stats | jq
doit retourner un beau json avec les métriques.
La documentation officielle sur le sujet:
La configuration par défaut des paquets a un niveau de log inadapté pour un serveur de production, créant plusieurs 10ène de milliers de messages de logs par seconde (en charge).
La création de ces logs consomme beaucoup de ressource CPU, inutilement.
La configuration par défaut a été changé récemment, et devrait arriver prochainement dans les paquets deb.
En attendant, il suffit de désactiver ces logs manuellement, dans /etc/jitsi/videobridge/logging.properties
:
java.util.logging.FileHandler.level = OFF
Le videobridge/java a tendance a utiliser la swap. Si la machine a largement suffisamment de RAM, le plus simple est de désactiver le swap. Sinon il est peut être utile de limiter le swap en baissant le paramètre swappiness.
Le videobridge est LE composant qui consomme de la ressource (principalement CPU et réseau). C'est lui qui est au centre de chaque conférence et gère le routage des flux video/audio vers l'ensemble des participants.
Ajouter des videobridge supplémentaire permet d'héberger d'avantage de conférences simultanément.
Lorsque qu'une conférence atteint 2 participants, le composant jicofo détermine le videobridge à utiliser, en se basant sur la charge de chaque bridge à cet instant t.
Les conférences se retrouvent réparti entre les différents videobridge. Dans la pratique le load balancing n'est pas parfait mais on obtient tout de même une bonne répartition de la charge.
Sur les videobridge supplémentaire, la procédure d'installation est simple, et consiste à:
jitsi-videobridge2
/etc/jitsi/videobridge/sip-communicator.properties
depuis le serveur principal.MUC_NICKNAME
par un id uniqueComme on utilise des web-sockets, il faut penser a mettre à jour la conf du reverse proxy nginx en ajoutant le nécessaire pour chaque videobridge supplémentaire:
# colibri (JVB) websockets for jvb2 location ~ ^/colibri-ws/jvb2/(.*) { proxy_pass http://X.X.X.X:9090/colibri-ws/jvb2/$1$is_args$args; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; tcp_nodelay on; }
Changements à effectuer dans /etc/jitsi/meet/jitsi.hadoly.fr-config.js
et visent à réduire la charge (principalement CPU) sur les machines clients.
startAudioOnly: true
startAudioOnly: true
resolution: 480
disableAudioLevels: true
Changements à effectuer dans /usr/share/jitsi-meet/interface_config.js
(probablement écrasé lors de mises à jour…)
Parce que j'ai commencé à faire des trucs chelous pour remettre le logo. La doc kivabien (comme la vérité) est ailleurs