Table des matières

Vidéoconférence Jitsi Meet

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.

Architecture globale

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.

Installation principale

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.

Optimisations côté serveur

Java 8

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

STUN/TURN

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:

Désactiver TCP

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

Utiliser les web-sockets à la place de bosh

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',

Activer l'API pour avoir des statistiques

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:

Limiter logs

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

Limiter le swap

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.

Ajouter de videobridge supplémentaires

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 à:

https://github.com/jitsi/jitsi-meet/wiki/jitsi-meet-load-balancing-installation-Ubuntu-18.04-with-MUC-and-JID

Comme 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;
    }

Optimisations côté client

Changements à effectuer dans /etc/jitsi/meet/jitsi.hadoly.fr-config.js et visent à réduire la charge (principalement CPU) sur les machines clients.

Changements à effectuer dans /usr/share/jitsi-meet/interface_config.js (probablement écrasé lors de mises à jour…)

Personnalisation

Parce que j'ai commencé à faire des trucs chelous pour remettre le logo. La doc kivabien (comme la vérité) est ailleurs