====== Meet Jitsi dans un Docker et reverse-proxy avec Nginx ====== Tutoriel en cours d'écriture Le but ici est d'avoir un container Docker pour Jitsi Meet, et de créer un reverse proxy dans Nginx vers ce container tout en ayant un certificat SSL. Meet Jitsi sera accessible via l'url **visio.mondomaine.org**. ===== Install ===== ==== Install nginx ==== apt install nginx ==== Install Docker ==== [[https://docs.docker.com/engine/install/debian/#install-using-the-repository|Voir la doc]]. apt-get install ca-certificates curl gnupg install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg |gpg --dearmor -o /etc/apt/keyrings/docker.gpg chmod a+r /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" |tee /etc/apt/sources.list.d/docker.list > /dev/null apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ==== Install Certbot ==== apt install certbot python3-certbot-nginx ===== Config ===== ==== Config et démarrage du container Jitsi ==== [[https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker/|Doc officielle d'install via Docker]]. On se place par exemple dans un home dédié à Jitsi, histoire de séparer les choses : **/home/jitsi** On télécharge [[https://github.com/jitsi/docker-jitsi-meet/releases/latest|la dernière version]], par exemple en ZIP et on décompresse. Entrer dans le dossier obtenu, par exemple **docker-jitsi-meet-stable-9111**. On copie le fichier env.example en .env : cp env.example .env Dans ce fichier **.env**, modifier les valeurs des variables suivantes : TZ=Europe/Paris PUBLIC_URL=https://visio.mondomaine.org CONFIG=/home/jitsi/.jitsi-meet-cfg Le dossier **.jitsi-meet-cfg** (configuré ci-dessus), accueillera la config de Jitsi exposée par le container docker. On génère des passwords forts, qui seront ajoutés dans le fichier .env précédent : ./gen-passwords.sh Toujours depuis le dossier **docker-jitsi-meet-stable-9111**, démarrer le container : docker compose up -d ==== Création du vhost temporaire ==== D'abord, on crée un vhost sur le port 80 qui permettra d'initialiser let's encrypt et de récupérer un certificat pour le sous domaine **visio.mondomaine.org**. On veut que le certificat soit validé depuis un répertoire exterieur au Docker de Jistsi, on choisit : **/var/www/certbot** (créer le dossier). Et pour le moment, on fait pointer le root du vhost sur **/var/www/html**. Dans le dossier **/etc/nginx/sites-available**, créer un fichier **visio.mondomaine.org** qui contient donc : server { listen [::]:80; listen 80; server_name visio.mondomaine.org; # Temporaire root /var/www/html; index index.html; location ~ /.well-known/acme-challenge/ { default_type "text/plain"; root /var/www/certbot; } } Activer ce vhost : ln -s /etc/nginx/sites-available/visio.mondomaine.org /etc/nginx/sites-enabled/visio.mondomaine.org Rédemarrer nginx : systemctl restart nginx.service ==== Création du certificat SSL ==== D'abord, lancer une demande de certificat automatisée pour générer les fichiers nécessaires : en lançant certbot avec le plugin nginx, cela créera 2 fichiers qui seront à inclure dans tous les les vhosts : * /etc/letsencrypt/options-ssl-nginx.conf * /etc/letsencrypt/ssl-dhparams.pem Attention : en lançant cette commande, annuler le choix d'un vhost, on veut juste que les fichiers ci-dessus soient créés : certbot --nginx Lancer ensuite la commande créant les certificats SSL pour notre nom de domaine, en passant par nginx (`--webroot`) mais sans modifier le vhost (`certonly`). On pointe bien vers le dossier spécial configuré dans le vhost pour que certbot fasse sa vérification : certbot certonly --webroot -w /var/www/certbot -d visio.mondomaine.org Par ailleurs, il faut rédémarrer nginx lorsqu'un certificat est recréé. Pour ça, on ajoute un "post hook" qui s'éxecute après chaque recréation de certificat. Aller dans **/etc/letsencrypt/renewal-hooks/post** et créer le fichier **01-restart-nginx** (lui donner les droits 755) avec dedans : #!/bin/bash systemctl restart nginx.service ==== Modification du vhost ==== On va pouvoir finaliser le vhost pour : * accepter les requêtes sur le port 443 (SSL) * rediriger les requêtes sur le port 80 vers le 443 * ajouter les certificats et la config de let's encrypt * créer des proxies vers le docker Jitsi pour tous les services Le vhost doit ressembler à ça désormais : # Port 443 server { # IPv6 then IPv4 listen [::]:443 ssl; listen 443 ssl; server_name visio.mondomaine.org; # For Certbot renew (outside Docker) location ~ /.well-known/acme-challenge/ { allow all; root /var/www/certbot; } # All traffic goes to Docker Jitsi location / { proxy_pass https://localhost:8443; } # For websocket location /xmpp-websocket { proxy_pass https://localhost:8443; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # For websocket too location /colibri-ws { proxy_pass https://localhost:8443; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # SSL ssl_certificate /etc/letsencrypt/live/visio.mondomaine.org/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/visio.mondomaine.org/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # Logs access_log /var/log/nginx/visio.mondomaine.org.access.log; error_log /var/log/nginx/visio.mondomaine.org.error.log; } # Port 80 server { # IPv6 then IPv4 listen [::]:80; listen 80; server_name visio.mondomaine.org; # For Certbot renew (outside Docker) location ~ /.well-known/acme-challenge/ { allow all; root /var/www/certbot; } # Redirect to https if ($host = visio.mondomaine.org) { return 301 https://$host$request_uri; } # Everything else not expected return 404; # managed by Certbot } Rédemarrer nginx : systemctl restart nginx.service Normalement Jitsi est visible sur %%https://visio.mondomaine.org%%. ===== Installer un Firewall ===== On utilise ufw : apt install ufw On autorise les ports : ufw allow XXX Remplacer XXX par : * 22 (SSH ou autre c'est mieux) * 80 (http) * 443 (https) * 3478 (requêtes vers serveur STUN) * 5349 (fallback TCP si 10000 UDP est bloqué) * 10000 (audio / video network) ===== Customisation ===== Pour le moment, on a 2 dossiers dans **/home/jitsi** : * **docker-jitsi-meet-stable-9111** : contient de quoi démarrer le Docker * **.jitsi-meet-cfg** : config actuelle exposée par le Docker. Attention, les fichiers sont écrasés à chaque **docker compose up -d** ==== Modifier la config ==== La config tient principalement en 2 fichiers : * **.jitsi-meet-cfg/web/config.js** * **.jitsi-meet-cfg/web/interface_config.js** Le fichier **interface_config.js** est progressivement abandonné au profit de **config.js**. Il ne faut pas y ajouter de variables mais utiliser seulement celles présentes et voir à chaque mise à jour si certaines ont migré vers **config.js**. Puisque ces fichiers sont écrasés à chaque démarrage du Docker, il faut créer respectivement les fichiers suivants qui seront mélangés aux originaux en écrasant les valeurs (et qui ne sont **pas** écrasés) : * **custom-config.js** : ici on peut reporter les variables du fichier original. * **custom-interface_config.js** : ici il faut copier/coller tout le fichier original et modifier les valeurs souhaitées. ==== Personnaliser l'interface ==== On va avoir besoin d'un dossier sur l'hôte qui contiendra les fichiers de l'interface que l'on souhaite modifier. Par exemple le créer ici : **/home/jitsi/jisti-custom-web**. === Le Logo === Pas possible de le changer dans les fichiers de config pour le moment (v.2.0.9111 de Jitsi), il faut passer par une astuce avec nginx : on redirige simplement le path du logo actuel (**images/watermark.svg**) vers un fichier sur l'hôte. On ajoute dans le vhost nginx, après les proxy websockets : # Custom logo location = /images/watermark.svg { alias /home/jitsi/jitsi-custom-web/images/logo.png; } === Le Favicon === Comme le logo, on crée un fichier favicon.ico, par exemple avec [[https://favicon.io/|cet outil]], et on ajoute une section dans le vhost : # Custom Favicon location = /images/favicon.svg { alias /home/jitsi/jitsi-custom-web/images/favicon.ico; } De la même manière, on peut aussi remplacer : * le Touch Icon : **/images/apple-touch-icon.png** * Le logo Jitsi qui est utilisé lors de partage sur les réseaux sociaux : **/images/jitsilogo.png** === Le design (CSS) === Rien n'est prévu pour ça, il faut encore bricoler. On va remplacer le fichier CSS original par le notre, copie de cet original dans lequel on ajoute à la fin nos règles. Le fichier CSS de Jitsi web s'appelle **all.css** et se trouve dans le container Docker nommé **docker-jitsi-meet-stable-9111-web-1**, à cet endroit : **/usr/share/jitsi-meet/css/all.css** On crée un dossier CSS dans notre dossier de customisation et on y entre : mkdir /home/jitsi/jitsi-custom-web/css && cd /home/jitsi/jitsi-custom-web/css On y copie la version originale provenant du Docker : docker cp docker-jitsi-meet-stable-9111-web-1:/usr/share/jitsi-meet/css/all.css all.css A la fin de ce fichier, ajouter le CSS de vos rêves. Maintenant il faut détourner le fichier depuis le vhost nginx en y ajoutant : # Custom CSS location ~ /css/all.css { alias /home/jitsi/jitsi-custom-web/css/all.css; } Et redémarrer nginx. ===== Mise à jour ===== Dans le dossier actuel contenant les différents dossiers créés précédemment (le dossier de Jitsi, son dossier de config et le dossier de la customisation), il faut donc : * [[https://github.com/jitsi/docker-jitsi-meet/releases/latest|Télécharger la dernière version]] puis la décompresser * Arrêter l'ancien container : dans le dossier de Jitsi actuel executer ''%%docker compose down%%''. * Aller dans le dossier de la nouvelle version et démarrer le container avec ''%%docker compose up -d%%'' * Vérifier les fichiers **.jitsi-meet-cfg/web/custom-config.js** et **.jitsi-meet-cfg/web/custom-interface_config.js**, il y a peut être de nouvelles variables * Pour le CSS, il faut aller re-chercher le fichier original de la nouvelle version pour y ajouter votre code personnalisé (voir la customisation CSS plus haut). * Rédémarrer nginx pour le plaisir aussi