ajoute le relais TURN sur 443 pour la visio (ADR 0006), avec coturn et le routage Nginx par nom

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Adam Belkacemi 2026-10-13 11:45:53 +02:00
parent ee079ddffb
commit 45f8a69e26
19 changed files with 457 additions and 14 deletions

View file

@ -0,0 +1,10 @@
---
# Bloc A (ADR 0006) : relais TURN sur 443 pour la visio, réservé aux réseaux
# scolaires qui bloquent l'UDP. coturn en paquet système (pas Docker : un
# seul process à durcir, pas de souci de réseau Docker comme avec Jitsi/Kuma).
turn_secret_fichier: /etc/turnserver-secret
turn_port_tls: 5349
turn_realm: syllabuslab.fr
# Nom du certificat Let's Encrypt (rôle portail, portail_domaine) : dupliqué
# ici plutôt que de dépendre de ce rôle, pour que `turn` reste autonome.
turn_domaine_certificat: syllabuslab.fr

View file

@ -0,0 +1,5 @@
---
- name: redémarrer coturn
ansible.builtin.systemd:
name: coturn
state: restarted

View file

@ -0,0 +1,79 @@
---
# Bloc A (ADR 0006) : relais TURN sur 443 pour la visio. coturn n'écoute
# qu'en TLS, sur 127.0.0.1 : jamais directement sur l'IP publique — c'est le
# routeur Nginx par nom (rôle portail) qui lui amène le trafic du port 443.
- name: installer coturn
ansible.builtin.apt:
name: coturn
state: present
- name: vérifier si le secret existe déjà
ansible.builtin.stat:
path: "{{ turn_secret_fichier }}"
register: turn_secret_stat
- name: générer le secret partagé une seule fois
ansible.builtin.command: openssl rand -hex 32
register: turn_secret_genere
changed_when: false
when: not turn_secret_stat.stat.exists
- name: déposer le secret (une seule fois)
ansible.builtin.copy:
content: "{{ turn_secret_genere.stdout }}\n"
dest: "{{ turn_secret_fichier }}"
owner: root
group: root
mode: "0600"
when: not turn_secret_stat.stat.exists
- name: lire le secret
ansible.builtin.slurp:
src: "{{ turn_secret_fichier }}"
register: turn_secret_lu
no_log: true
- name: créer le dossier de la copie lisible du certificat
ansible.builtin.file:
path: /etc/turnserver/cert
state: directory
owner: root
group: turnserver
mode: "0750"
- name: déployer le script de copie du certificat (Ansible + renouvellement certbot)
ansible.builtin.template:
src: turn-copier-certificat.sh.j2
dest: /usr/local/sbin/syllabus-turn-copier-certificat
owner: root
group: root
mode: "0750"
- name: brancher ce script sur le renouvellement automatique du certificat
ansible.builtin.file:
src: /usr/local/sbin/syllabus-turn-copier-certificat
dest: /etc/letsencrypt/renewal-hooks/deploy/90-turn-coturn.sh
state: link
- name: déployer la configuration de coturn
ansible.builtin.template:
src: turnserver.conf.j2
dest: /etc/turnserver.conf
owner: root
group: turnserver
mode: "0640"
vars:
turn_secret: "{{ turn_secret_lu.content | b64decode | trim }}"
notify: redémarrer coturn
- name: activer coturn
ansible.builtin.systemd:
name: coturn
enabled: true
- name: appliquer la configuration et la copie du certificat
ansible.builtin.meta: flush_handlers
- name: copier le certificat pour coturn et le démarrer avec la vraie configuration
ansible.builtin.command: /usr/local/sbin/syllabus-turn-copier-certificat
changed_when: true

View file

@ -0,0 +1,10 @@
#!/bin/bash
# Géré par Ansible (rôle turn) — ne pas modifier à la main.
# Copie le certificat Let's Encrypt dans un endroit lisible par coturn (sa
# clé privée originale reste 600 root:root, hors de portée de turnserver) et
# redémarre coturn. Lancé par Ansible (premier déploiement) et par certbot à
# chaque renouvellement (/etc/letsencrypt/renewal-hooks/deploy/).
set -euo pipefail
install -o root -g turnserver -m 0640 /etc/letsencrypt/live/{{ turn_domaine_certificat }}/fullchain.pem /etc/turnserver/cert/fullchain.pem
install -o root -g turnserver -m 0640 /etc/letsencrypt/live/{{ turn_domaine_certificat }}/privkey.pem /etc/turnserver/cert/privkey.pem
systemctl restart coturn

View file

@ -0,0 +1,29 @@
# Géré par Ansible (rôle turn) — ne pas modifier à la main.
# TURNS seulement (TLS), sur 127.0.0.1 : jamais exposé directement à
# Internet. Le port public 443 y arrive par le routeur Nginx (SNI, rôle
# portail), qui transmet les octets tels quels — coturn gère son propre TLS.
listening-ip=127.0.0.1
tls-listening-port={{ turn_port_tls }}
no-udp
no-tcp
no-tls-v1
no-tls-v1_1
# Relais vers JVB (rôle visio, réseau de l'hôte) : jamais vers l'extérieur,
# toujours en boucle locale.
relay-ip=127.0.0.1
cert=/etc/turnserver/cert/fullchain.pem
pkey=/etc/turnserver/cert/privkey.pem
# Authentification par secret partagé (TURN REST API), le même que
# TURN_CREDENTIALS côté Prosody (rôle visio) : Prosody calcule un couple
# nom d'utilisateur/mot de passe valable 24 h pour chaque participant, sans
# jamais donner ce secret au navigateur.
use-auth-secret
static-auth-secret={{ turn_secret }}
realm={{ turn_realm }}
fingerprint
no-cli
no-multicast-peers