User Tools

Site Tools


nomades:monter_son_peertube

Déployer PeerTube derrière un serveur SME (Apache) — de A à Z

by thenoiser / apo33

Résumé : installation d'une instance PeerTube auto-hébergée (Docker) sur une machine du réseau local (ex: ThinkPad T460s), exposée publiquement via reverse proxy Apache sur le serveur SME principal (bruit), avec certificat SSL dédié et renouvellement automatique.

<note important> Ce tutoriel suppose que le serveur SME (bruit) a déjà un domaine principal fonctionnel (ici apo33.org) et qu'on ajoute un sous-domaine (peertube.apo33.org) pointant vers une machine tierce du réseau local. Pour la partie SSL automatisée en détail, voir le tuto séparé : SSL Let's Encrypt automatisé via API Gandi (DNS-01). </note>

1. Vérifier les ressources disponibles

Avant d'installer quoi que ce soit, vérifier que la machine cible a de quoi tourner :

free -h
nproc
lscpu | grep -E "Model name|Thread"
df -h
uptime
docker ps -a 2>/dev/null
ss -tulpn | grep -E ":80|:443|:9000"

<note tip> Repères officiels PeerTube : minimum 1 vCore / 1.5 Go RAM sans transcoding. Avec transcoding sur la même machine : 8 vCore / 8 Go RAM recommandés. En dessous (ex: un laptop à 2 cœurs), c'est jouable pour un usage modéré (petite structure, pas 1000 viewers simultanés), à condition de limiter les résolutions de transcodage (voir section 8). </note>

<note warning> Vérifier qu'aucun autre service lourd ne tourne déjà sur cette machine (radio Icecast/Liquidsoap, Pure Data/JACK, etc.) : ça entre directement en concurrence avec le CPU du transcoding vidéo. Idéalement, dédier la machine à PeerTube seul. </note>

2. Préparer le réseau local

2.1 IP fixe

Passer la machine en IP fixe (Ethernet de préférence, pas WiFi) via NetworkManager :

nmcli connection show
sudo nmcli connection modify "Wired connection 1" \
  ipv4.addresses 192.168.1.XX/24 \
  ipv4.gateway 192.168.1.1 \
  ipv4.dns "192.168.1.1 8.8.8.8" \
  ipv4.method manual
sudo nmcli connection down "Wired connection 1"
sudo nmcli connection up "Wired connection 1"

Désactiver le WiFi si inutile :

sudo nmcli radio wifi off
sudo nmcli connection modify <nom_connexion_wifi> connection.autoconnect no

2.2 Empêcher la mise en veille (si laptop)

sudo sed -i 's/^#HandleLidSwitch=.*/HandleLidSwitch=ignore/' /etc/systemd/logind.conf
sudo sed -i 's/^#HandleLidSwitchDocked=.*/HandleLidSwitchDocked=ignore/' /etc/systemd/logind.conf
sudo systemctl restart systemd-logind

<note> Vérifier aussi l'historique de reboot (last reboot, journalctl –list-boots) pour confirmer la stabilité de la machine avant de s'appuyer dessus en prod. </note>

3. Installer Docker Compose

docker --version
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-compose-plugin
docker compose version

4. Installer PeerTube (test local d'abord)

mkdir -p ~/peertube && cd ~/peertube
curl -s https://raw.githubusercontent.com/Chocobozzz/PeerTube/develop/support/docker/production/docker-compose.yml -o docker-compose.yml
curl -s https://raw.githubusercontent.com/Chocobozzz/PeerTube/develop/support/docker/production/.env -o .env

Générer les secrets et écrire un .env de test en HTTP local :

PT_SECRET=$(openssl rand -hex 32)
PG_PASS=$(openssl rand -hex 16)
 
cat > .env << EOF
POSTGRES_USER=peertube
POSTGRES_PASSWORD=${PG_PASS}
POSTGRES_DB=peertube
PEERTUBE_DB_USERNAME=\$POSTGRES_USER
PEERTUBE_DB_PASSWORD=\$POSTGRES_PASSWORD
PEERTUBE_DB_SSL=false
PEERTUBE_DB_HOSTNAME=postgres
 
PEERTUBE_WEBSERVER_HOSTNAME=192.168.1.XX
PEERTUBE_WEBSERVER_PORT=9000
PEERTUBE_WEBSERVER_HTTPS=false
 
PEERTUBE_TRUST_PROXY=["127.0.0.1", "loopback", "172.18.0.0/16"]
PEERTUBE_SECRET=${PT_SECRET}
 
PEERTUBE_SMTP_HOSTNAME=postfix
PEERTUBE_SMTP_PORT=25
PEERTUBE_SMTP_FROM=noreply@votredomaine.org
PEERTUBE_SMTP_TLS=false
PEERTUBE_SMTP_DISABLE_STARTTLS=false
PEERTUBE_ADMIN_EMAIL=admin@votredomaine.org
 
POSTFIX_myhostname=votredomaine.org
OPENDKIM_DOMAINS=votredomaine.org=peertube
OPENDKIM_RequireSafeKeys=no
 
PEERTUBE_OBJECT_STORAGE_UPLOAD_ACL_PUBLIC="public-read"
PEERTUBE_OBJECT_STORAGE_UPLOAD_ACL_PRIVATE="private"
EOF

<note important> Le <<'EOF' (sans backslash) laisse le shell substituer ${PT_SECRET}/${PG_PASS}. Les lignes PEERTUBE_DB_USERNAME=\$POSTGRES_USER doivent garder le \$ littéral (backslash devant) — c'est Docker Compose qui interprète ce $POSTGRES_USER, pas le shell. </note>

Décommenter le port 9000 dans docker-compose.yml (nécessaire pour test local direct) :

sed -i 's|#  - "9000:9000"|  - "9000:9000"|' docker-compose.yml

Lancer :

docker compose up -d
docker compose logs -f --tail=50

Le mot de passe admin root généré automatiquement apparaît dans les logs — le noter immédiatement :

peertube-1 | info: Username: root
peertube-1 | info: User password: xxxxxxxxxxxxxxxxxxxx

Tester en local : http://192.168.1.XX:9000

5. Certificat SSL dédié

Voir le tuto séparé SSL Let's Encrypt automatisé via API Gandi (DNS-01) pour obtenir un certificat peertube.votredomaine.org avec renouvellement automatique, sur la machine qui héberge PeerTube.

Une fois le certificat obtenu (/etc/letsencrypt/live/peertube.votredomaine.org/), créer un vhost nginx natif sur la même machine :

sudo nano /etc/nginx/sites-available/peertube.votredomaine.org.conf
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name peertube.votredomaine.org;
 
    ssl_certificate     /etc/letsencrypt/live/peertube.votredomaine.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/peertube.votredomaine.org/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
 
    client_max_body_size 12G;
 
    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_buffering off;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}
 
server {
    listen 80;
    listen [::]:80;
    server_name peertube.votredomaine.org;
    return 301 https://$host$request_uri;
}
sudo ln -s /etc/nginx/sites-available/peertube.votredomaine.org.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

<note tip> Ce nginx local sert de terminaison SSL “locale” — utile si on veut accéder à PeerTube en HTTPS directement sur le réseau local sans repasser par le serveur SME distant. En pratique (section 7), le trafic public passera plutôt par le proxy Apache du serveur SME directement vers le port 9000 en HTTP interne — ce nginx reste disponible en secours/accès direct LAN. </note>

6. DNS public

Créer l'enregistrement A dans la zone DNS (registrar, ex: Gandi) :

Type: A
Nom: peertube
Valeur: <IP publique du réseau>
TTL: par défaut

Vérifier la propagation :

dig peertube.votredomaine.org +short

7. Forwarding et reverse proxy sur le serveur SME

<note important> Étape sensible. Le serveur SME héberge potentiellement le mail et plusieurs sites de l'association. Toute modification de httpd.conf redémarre TOUT Apache d'un coup — voir la méthode de test isolé (7.5) avant d'appliquer quoi que ce soit en prod. </note>

7.1 Forwarding des ports sur la box

Forwarder les ports 80, 443, 1935 (RTMP live) depuis la box vers l'IP locale du serveur SME (qui fait déjà tourner Apache en frontal — c'est lui qui reçoit tout le trafic public 80/443, pas la machine PeerTube directement).

7.2 Créer le domaine "vhost" côté SME

Sur le serveur SME, en root, via la base de données e-smith (pas le panneau graphique “Domains”, qui ne gère que du contenu local) :

/sbin/e-smith/db domains set peertube.votredomaine.org vhost \
  Description "PeerTube" \
  Nameservers internet \
  ProxyPassTarget http://192.168.1.XX:9000/ \
  ProxyPreserveHost yes

<note important> type doit être vhost (pas domain) : le template 80VirtualHosts traite les domaines type=domain avec un contenu local (DocumentRoot), tandis que 81SimpleVHosts traite les type=vhost avec le template WebAppVirtualHost, qui sait gérer ProxyPassTarget. </note>

<note warning> ProxyPreserveHost yes est indispensable : sans lui, Apache envoie au backend le Host de la cible (192.168.1.XX:9000) au lieu du nom public — PeerTube rejette alors les requêtes avec une erreur type “Getting client tokens for host X is forbidden (expected Y)”. </note>

Vérifier :

/sbin/e-smith/db domains show peertube.votredomaine.org

7.3 Pourquoi HTTP interne plutôt que HTTPS

Le trafic entre le serveur SME et la machine PeerTube reste sur le réseau local — le chiffrer entre les deux n'est pas nécessaire (le vrai chiffrement public se fait déjà côté client → serveur SME). Utiliser http://IP:9000/ (le port PeerTube direct, pas le nginx local) évite un problème classique : Apache vérifie par défaut la chaîne de certificat du backend (SSLProxyVerify), ce qui échoue si le certificat n'est pas reconnu par la CA système du serveur SME. Passer en HTTP interne élimine ce problème sans compromettre la sécurité publique.

7.4 Régénérer et recharger (backup obligatoire avant)

cp /etc/httpd/conf/httpd.conf /root/httpd.conf.backup-$(date +%Y%m%d-%H%M%S)
/sbin/e-smith/signal-event domain-modify peertube.votredomaine.org
httpd -t

Si “Syntax OK”, identifier le vrai nom du service (souvent httpd-e-smith, pas httpd) :

systemctl list-units --all | grep -i httpd
systemctl restart httpd-e-smith.service
systemctl status httpd-e-smith.service --no-pager
curl -Ik http://votredomaine.org

7.5 Méthode de test isolé (avant toute modif touchant SSL/certificats)

<note important> Cette méthode est obligatoire dès qu'on touche à des directives SSL (SSLCertificateFile, chaînes de certificats). Une erreur de format de certificat peut faire planter tout Apache (mod_ssl fatal error), avec interruption de tous les sites le temps du diagnostic. </note>

# Copier la config réelle, ne jamais éditer l'original en direct
cp /etc/httpd/conf/httpd.conf /tmp/httpd-test.conf
 
# Rediriger vers des ports libres + PID file dédié, DANS le fichier lui-même
sed -i \
  -e 's|^Listen 0\.0\.0\.0:80|Listen 0.0.0.0:8081|' \
  -e 's|^Listen 0\.0\.0\.0:443|Listen 0.0.0.0:8444|' \
  -e 's|^Listen \[::\]:80|Listen [::]:8081|' \
  -e 's|^Listen \[::\]:443|Listen [::]:8444|' \
  -e 's|^PidFile.*|PidFile /tmp/httpd-test.pid|' \
  /tmp/httpd-test.conf
 
grep -n "^Listen\|^PidFile" /tmp/httpd-test.conf   # vérifier avant de lancer
 
/usr/sbin/httpd -f /tmp/httpd-test.conf -DFOREGROUND &
sleep 3
jobs           # "En cours d'exécution" = succès, config saine
tail -15 /var/log/httpd/error_log
 
kill %1        # arrêter le test — le service réel n'a jamais été touché

Seulement si ce test réussit, appliquer pour de vrai (régénérer + systemctl restart httpd-e-smith.service, comme en 7.4).

8. Configuration PeerTube (admin)

8.1 Basculer le ''.env'' en mode public

Une fois le proxy validé :

cd ~/peertube
sed -i \
  -e 's|^PEERTUBE_WEBSERVER_HOSTNAME=.*|PEERTUBE_WEBSERVER_HOSTNAME=peertube.votredomaine.org|' \
  -e 's|^PEERTUBE_WEBSERVER_PORT=.*|PEERTUBE_WEBSERVER_PORT=443|' \
  -e 's|^PEERTUBE_WEBSERVER_HTTPS=.*|PEERTUBE_WEBSERVER_HTTPS=true|' \
  .env
docker compose up -d peertube

<note warning> Ce changement recrée le conteneur — toute tâche de transcoding/live en cours sera interrompue. À faire hors production active. </note>

8.2 Transcoding VOD — réglages recommandés machine modeste

Administration → Configuration → VOD Transcoding :

  • Résolutions à générer : garder le minimum utile (ex: 720p seul, ou 480p+720p). Chaque résolution ajoutée multiplie la charge CPU.
  • “Transcoder aussi la résolution originale” : décocher. Génère un job de transcoding complet en pleine résolution native en plus des résolutions cochées — très coûteux, souvent redondant.
  • “Conserver une version du fichier d'origine” : cocher. Garde le fichier brut uploadé, accessible en téléchargement par les visiteurs (bouton “Télécharger” sous la vidéo, propose l'original + les résolutions transcodées) — coût CPU nul, juste de l'espace disque.
  • Nombre de tâches de transcodage / Concurrence : 1 sur une machine à 2-4 cœurs (évite que plusieurs jobs se battent pour le même CPU).
  • Sortie : HLS avec support P2P (recommandé) — éviter de cocher aussi “Vidéos Web” en plus (double la charge et le stockage pour un gain marginal en usage interne).

<note tip> Mesure réelle observée (CPU i5-6300U, 2 cœurs/4 threads, 720p, radio Liquidsoap tournant en parallèle) : ~1.2-1.4x le temps réel sur du contenu visuellement chargé (bruit, glitch, mouvements rapides). Sur du contenu plus posé, généralement plus proche de 0.8-1x. Le temps de transcoding scale quasi linéairement avec la durée de la vidéo source. </note>

8.3 Accélération matérielle (VAAPI/Quick Sync) — non recommandé en l'état

<note warning> Testé et déconseillé pour l'instant : les plugins VAAPI PeerTube (hardware-transcode-vaapi et forks) sont explicitement documentés comme expérimentaux, l'image Docker officielle ne contient pas les pilotes VAAPI nécessaires (il faut rebuild une image custom via Dockerfile), et plusieurs utilisateurs rapportent des échecs même avec du matériel standard. Sur un CPU faible (2 cœurs), le gain espéré ne compense pas la fragilité du montage. Optimiser plutôt via les réglages logiciels (8.2). </note>

Pour rendre le device GPU accessible malgré tout (prérequis technique, insuffisant seul) :

ls -la /dev/dri   # vérifier la présence de renderD128 sur l'hôte

Dans docker-compose.yml, service peertube, ajouter :

    devices:
      - /dev/dri:/dev/dri

8.4 Formats audio (publication de sons avec image de fond)

Administration → Configuration → VOD Transcoding → “Autorise l'envoi de fichier audio” : coché → le fichier audio est fusionné avec une image de prévisualisation en vidéo fixe à la publication.

Formats fiables : MP3, OGG, FLAC.

<note warning> Le WAV est officiellement listé comme supporté mais s'est révélé peu fiable en pratique (rejeté avec “format vidéo non supporté” sur plusieurs fichiers, y compris du PCM 16-bit standard et après ré-encodage propre). Cause exacte non identifiée. Convertir en FLAC (lossless) ou MP3 avant upload plutôt que de perdre du temps à déboguer un WAV récalcitrant :

ffmpeg -i fichier.wav -c:a flac fichier.flac

</note>

8.5 Chat en direct (plugin livechat)

Installer via Administration → Extensions/Plugins → chercher “livechat” → Installer.

Configuration du plugin (Administration → Plugins → livechat → Configurer) :

Serveur Prosody : laisser l'AppImage intégrée par défaut (ne cocher “utiliser Prosody système” qu'en cas de problème avéré) “Activer le tchat pour toutes les vidéos «non-direct»” et/ou “Activer le tchat pour tous les directs” : à cocher explicitement — ni activé par défaut, ni lié au “type de salon” (groupé par chaîne vs par vidéo), qui n'est qu'un réglage d'organisation. Sans cette case, le chat n'apparaît nulle part. Alternative ciblée : champ “Activer le tchat pour ces vidéos” + UUID court de la vidéo (visible dans l'URL /w/<UUID>) <note warning> Chat qui patine indéfiniment (rond de chargement en boucle) : symptôme d'un échec silencieux de la connexion WebSocket à travers le reverse proxy Apache du serveur SME (visible dans les logs PeerTube par une réponse 200 au lieu de 101 Switching Protocols sur /plugins/livechat/.../ws/xmpp-websocket). Le vhost généré par le template WebAppVirtualHost ne relaie pas les en-têtes Upgrade/Connection nécessaires au WebSocket.

Vérifier d'abord que Prosody tourne bien côté conteneur (élimine cette piste) :

 docker compose logs peertube 2>&1 | grep -i prosody | tail -20 

Chercher Prosody is running. Si c'est le cas, le souci est bien côté proxy, pas côté serveur de chat.

Solution sans toucher à httpd.conf sur bruit : dans la configuration du plugin livechat, section “Paramètres avancés du serveur de tchat”, cocher “Désactiver Websocket”. Le chat bascule automatiquement sur le protocole BOSH (polling HTTP classique), qui passe sans problème à travers le proxy existant. </note>

9. Usage de base

9.1 Se connecter

https://peertube.votredomaine.org — compte root + mot de passe généré au premier démarrage (section 4). Changer le mot de passe dès la première connexion (Mon compte → Mot de passe).

9.2 Publier une vidéo

Bouton “Publier” → glisser le fichier → renseigner titre, description, catégorie, chaîne → Publier. Le transcoding démarre automatiquement (voir 8.2 pour la durée estimée).

9.3 Publier un son

Même bouton “Publier”, sélectionner directement le fichier audio (MP3/OGG/FLAC — voir 8.4) comme fichier principal. Une fois accepté, choisir une image de prévisualisation dans les options (thumbnail) — PeerTube fusionne automatiquement à la publication.

9.4 Télécharger l'original

Sur une vidéo publiée, bouton “Télécharger” sous le lecteur → propose toutes les résolutions générées + l'original (si “conserver le fichier d'origine” est activé, voir 8.2).

9.5 Live streaming

Administration → Configuration → Live Streaming : activer, configurer la sauvegarde de replay. Utiliser un logiciel compatible RTMP (OBS) avec la clé de stream fournie par PeerTube sur la chaîne. Port RTMP : 1935 (forwardé en 7.1).

<note warning> Le transcoding live est obligatoire pour du HLS (pas de mode “sans transcodage” pour le direct). Sur machine modeste, tester en conditions réelles avant un événement important — le CPU doit suivre le flux en temps réel, contrairement au VOD où un léger différé est acceptable. </note>

10. Limites connues et pistes futures

  • Résolution DNS interne (split-horizon) non aboutie : en interne, peertube.votredomaine.org résout vers l'IP publique, ce qui échoue si le routeur/box ne supporte pas le NAT hairpin. Contournement actuel : /etc/hosts sur chaque poste interne (192.168.1.XX peertube.votredomaine.org). Piste non finalisée : activer Nameservers=localhost sur le domaine principal côté SME (dnscache/tinydns), avec les précautions nécessaires vu que c'est le domaine primaire du serveur.
  • Renouvellement du certificat côté serveur SME : si un certificat séparé est copié manuellement sur le serveur SME (cas où le reverse proxy y sert directement le HTTPS plutôt qu'en HTTP interne), penser à resynchroniser ce fichier à chaque renouvellement (~tous les 90 jours) — pas automatique par défaut dans ce montage.
  • Machine dédiée plus puissante : à budgétiser si l'usage grandit — un mini-PC Ryzen H/HS neuf (~350-450€) ou un PC d'occasion (Ryzen 5/i5 récent, vigilance sur le bruit/conso pour du 24/7) apporteraient un vrai confort de transcoding par rapport à un laptop ancien.
nomades/monter_son_peertube.txt · Last modified: 2026/08/14 20:17 by julien