TeamSpeak 3 en Docker — migrer un serveur vocal standalone vers Docker Compose

Published by David on






TeamSpeak 3 en Docker — migration serveur vocal avec 235 Go de fichiers

TeamSpeak 3 en Docker — migration serveur vocal avec 235 Go de fichiers

Huitième étape : migrer TeamSpeak 3.13.7 (235 Go de fichiers transférés, base SQLite,
licence payante) depuis une installation standalone vers Docker Compose sur le serveur
centralisé, avec transfert progressif rsync.

Contexte

Le serveur TeamSpeak 3 tourne actuellement sur l’ancien serveur dédié
(54.36.51.208, ns3109491) sous le chemin /home/teamspeak3/,
en tant qu’utilisateur système teamspeak3 via un service systemd.

Il utilise une base SQLite (~4,5 Mo), stocke 235 Go
de fichiers transférés par les utilisateurs (icônes, avatars, fichiers de channels),
et possède une licence payante (licensekey.dat).
On migre vers Docker Compose sur le nouveau serveur (141.95.154.67, ns3210379,
SSH port 38592), où tournent déjà Odoo 17, Odoo 8, Akeneo PIM et ownCloud.

Architecture cible : 1 seul conteneur —
teamspeak:3.13.7 avec les 3 ports TeamSpeak exposés directement
(pas de reverse proxy, TeamSpeak n’est pas une application web).

Différence clé avec les applications web :
contrairement à Odoo, Akeneo ou ownCloud, TeamSpeak n’utilise pas
de reverse proxy Nginx. Les clients se connectent directement via UDP (voix)
et TCP (transfert de fichiers, query). Les ports doivent donc être ouverts
dans le firewall du serveur.

Stratégie rsync 2 passes : avec 235 Go de fichiers sur HDD,
un transfert complet prend plusieurs heures. On fait un premier rsync pendant
que l’ancien serveur est encore en production
(aucune interruption du vocal),
puis un second rsync rapide (delta seulement) après l’arrêt du serveur.
Fenêtre de coupure réduite à quelques minutes au lieu de plusieurs heures.


1) Collecter les informations sur l’ancien serveur

1.1 Version et processus

Résultat attendu : TeamSpeak 3 Server 3.13.7 (2022-06-20 12:21:53).

1.2 Ports utilisés

Vérifier les ports réels : le fichier ts3server.ini
de notre serveur contient des ports personnalisés (8767, 10044,
30034), mais le serveur écoute en réalité sur les ports standards
(9987, 10011, 30033).
Cette incohérence peut venir du fait que le fichier ini n’est pas chargé
ou que la base de données prévaut sur la configuration ini pour les serveurs virtuels existants.
Vérifier avec ss quels ports sont réellement utilisés
et les noter — ce sont ceux que les clients TeamSpeak utilisent.

1.3 Contenu du fichier de configuration

1.4 Taille des données

Résumé de notre installation :

  • Version : TeamSpeak 3 Server 3.13.7
  • Base de données : SQLite (ts3server.sqlitedb, ~4,5 Mo)
  • Fichiers transférés : 235 Go dans /home/teamspeak3/files/
  • Licence : payante (licensekey.dat)
  • Identité serveur : serverkey.dat
  • Ports actifs : UDP 9987 (voix), TCP 10011 (query), TCP 30033 (transfert fichiers)
  • Utilisateur système : teamspeak3
  • Service systemd : teamspeak3.service

1.5 Fichiers critiques à préserver

  • ts3server.sqlitedb — la base de données complète (utilisateurs, channels, permissions, bans, tokens)
  • serverkey.datidentité cryptographique du serveur.
    Sans ce fichier, le serveur apparaît comme un NOUVEAU serveur pour tous les clients.
    Les favoris/bookmarks ne fonctionnent plus
  • licensekey.dat — licence payante TeamSpeak. Sans elle, le serveur repasse en licence gratuite (limité à 32 slots)
  • ssh_host_rsa_key — clé SSH pour les connexions ServerQuery via SSH (optionnel mais pratique)
  • files/ — tous les fichiers transférés dans les channels (235 Go)
  • query_ip_whitelist.txt — IPs autorisées pour ServerQuery

serverkey.dat est irremplaçable. Il contient la clé privée
qui génère l’identité unique du serveur. Si ce fichier est perdu, le serveur
aura une nouvelle identité et tous les clients recevront un avertissement
« Server identity changed » et devront re-valider la connexion.
Les bookmarks avec « Connect only to known servers » refuseront de se connecter.


Phase 1 : Préparation (ancien serveur en production)

Toutes les étapes suivantes se font sans interrompre le serveur vocal.
Les utilisateurs continuent à parler normalement.

2) Créer la structure des répertoires Docker

Sur le nouveau serveur :

Docker Compose v2 : si Docker Compose v2 est déjà installé (vérifier avec
docker compose version), pas besoin de le réinstaller.

3) Créer le docker-compose.yml

Contenu :

Points clés :

  • teamspeak:3.13.7 — image Docker officielle TeamSpeak, même version que l’ancien serveur
    pour éviter les problèmes de compatibilité de base de données
  • 9987:9987/udp — port voix, exposé en UDP sur toutes les interfaces
    (les clients s’y connectent directement, pas de reverse proxy)
  • 30033:30033 — port transfert de fichiers, exposé en TCP
  • 127.0.0.1:10011:10011 — port ServerQuery, restreint à localhost
    par sécurité (accès administration uniquement depuis le serveur)
  • TS3SERVER_LICENSE: accept — acceptation automatique de la licence (obligatoire depuis TS 3.1.0)
  • ./data:/var/ts3server — bind mount pour la base SQLite, les fichiers transférés (235 Go),
    la licence et l’identité serveur

Pas de serveradmin_password dans le docker-compose.
L’ancien serveur passait serveradmin_password=teamspeak2many en paramètre de démarrage,
ce qui réinitialise le mot de passe admin à chaque redémarrage.
Après migration, le mot de passe est stocké dans la base SQLite importée.
Il n’est plus nécessaire (ni souhaitable) de le passer en paramètre —
il serait visible dans la liste des processus (ps aux).

Port ServerQuery (10011) restreint à localhost :
le ServerQuery donne un accès administrateur complet au serveur TeamSpeak.
Ne jamais l’exposer sur Internet sans protection. L’ancien serveur avait déjà
une whitelist limitée à 127.0.0.1 et ::1.
En plus de cette whitelist, on restreint le port Docker à localhost.

4) Lancer le rsync initial (en arrière-plan)

Cette étape est la plus longue (plusieurs heures pour 235 Go).
On la lance pendant que l’ancien serveur est encore en production
les utilisateurs continuent à utiliser le vocal normalement.

4.1 Préparer l’accès SSH

Depuis le nouveau serveur :

4.2 Lancer le premier rsync

Depuis le nouveau serveur :

Estimation de durée : entre serveurs OVH (réseau interne ~1 Gbps),
235 Go prennent environ 1h à 2h30.
Le flag -t préserve les timestamps des fichiers.

Pas de risque de corruption : les fichiers dans files/
sont des fichiers statiques (uploads des utilisateurs dans les channels).
Ils ne sont jamais modifiés après l’upload, seulement ajoutés ou supprimés.
Le rsync pendant que le serveur tourne est donc sans risque.


Phase 2 : Basculement (fenêtre de coupure)

À partir d’ici, le serveur vocal est interrompu.
Objectif : terminer en 5 à 10 minutes
(la base SQLite fait seulement 4,5 Mo, le rsync delta est très rapide).

5) Arrêter TeamSpeak sur l’ancien serveur

Prévenir les utilisateurs avant l’arrêt.
On peut envoyer un message global depuis ServerQuery avant la coupure :

6) Rsync final + fichiers critiques

Depuis le nouveau serveur :

Arrêter le serveur AVANT de copier la base SQLite.
Les fichiers ts3server.sqlitedb-shm et ts3server.sqlitedb-wal
(shared memory + write-ahead log) contiennent des données non encore écrites dans le fichier
principal. Copier la base pendant que le serveur tourne peut donner une base corrompue.
Après l’arrêt propre (systemctl stop), le WAL est flushé dans le fichier principal.

Ne PAS copier les fichiers -shm et -wal :
après un arrêt propre du serveur, ces fichiers sont vides ou inexistants.
Le fichier ts3server.sqlitedb seul est suffisant.

6.1 Vérifier les fichiers copiés

On doit voir :

  • ts3server.sqlitedb (~4,5 Mo)
  • serverkey.dat (112 octets)
  • licensekey.dat (~1,6 Ko)
  • ssh_host_rsa_key
  • query_ip_whitelist.txt
  • files/ (répertoire avec les sous-dossiers virtualserver_1/, etc.)

7) Corriger les permissions

L’image Docker officielle teamspeak s’exécute en tant qu’utilisateur
ts3server. Il faut que tous les fichiers lui appartiennent.

7.1 Déterminer l’UID du conteneur

Noter le uid affiché (typiquement 1000).

7.2 Appliquer les permissions

Cette commande prend du temps sur 235 Go de fichiers (5-15 minutes sur HDD).
C’est une opération unique.

8) Ouvrir les ports dans le firewall

Contrairement aux applications web (routées via le reverse proxy Nginx de MyVestaCP),
TeamSpeak a besoin que ses ports soient ouverts directement dans le firewall du serveur.

8.1 Ajouter les règles dans MyVestaCP

Ces commandes sont l’équivalent CLI de MyVestaCP → FirewallAdd Rule.
Les règles sont stockées dans /usr/local/vesta/data/firewall/
et persistent après un redémarrage.

8.2 Vérifier que les règles sont actives

On doit voir :

Port 10011 (ServerQuery) : pas besoin de l’ouvrir dans le firewall.
Il est déjà restreint à 127.0.0.1 dans le docker-compose
et dans la whitelist TeamSpeak. L’administration se fait uniquement depuis le serveur.

Ne pas ajouter les règles via iptables directement.
MyVestaCP stocke ses règles dans /usr/local/vesta/data/firewall/
et les régénère via v-update-firewall.
Toute règle ajoutée manuellement sera perdue au prochain redémarrage de VestaCP
ou lors d’un v-update-firewall.

9) Démarrer TeamSpeak

Vérifier l’état du conteneur :

Le conteneur doit être en état Up.

Consulter les logs :

On doit voir :

Si le serveur affiche « Server created » au lieu de « Server started »,
cela signifie que la base de données n’a pas été trouvée et le serveur a créé
une nouvelle instance vierge. Vérifier que ts3server.sqlitedb est bien
dans /home/docker/teamspeak3/data/ et que les permissions sont correctes.

10) Tester

10.1 Tester le ServerQuery

Réponse attendue :

10.2 Tester la connectivité UDP (voix)

Doit afficher Connection to 141.95.154.67 9987 port [udp/*] succeeded!
(ou open).

10.3 Se connecter avec le client TeamSpeak

Ouvrir le client TeamSpeak 3 et se connecter à 141.95.154.67 (port par défaut 9987).
Vérifier :

  • Les channels sont présents avec leur hiérarchie
  • Les permissions et groupes de serveur sont intacts
  • Les icônes de channels et de groupes s’affichent
  • Les fichiers dans les channels sont accessibles (onglet « Files »)
  • Le micro et le son fonctionnent

10.4 Vérifier la licence

Si la licence n’est pas détectée, le serveur sera limité à 32 slots.
Vérifier que licensekey.dat est bien dans /home/docker/teamspeak3/data/.

11) Désactiver l’ancien serveur

Une fois la migration validée, empêcher l’ancien serveur de redémarrer :

Pas de bascule DNS pour TeamSpeak.
Les clients se connectent par IP (pas par domaine).
Il faudra mettre à jour les bookmarks/favoris des utilisateurs
avec la nouvelle IP 141.95.154.67.
Alternativement, configurer un enregistrement DNS
(ex : ts.mcdtoolbox.com) pointant vers la nouvelle IP
pour faciliter les futures migrations.


Dépannage

Le serveur crée une nouvelle instance au lieu de charger l’ancienne

Les logs affichent « Server created » et un nouveau token admin est généré.

Diagnostiquer :

Cause : la base SQLite n’est pas au bon emplacement
ou n’est pas lisible par l’utilisateur du conteneur.
Corriger les permissions : chown 1000:1000 /home/docker/teamspeak3/data/ts3server.sqlitedb.

Licence non détectée (limité à 32 slots)

Vérifier que licensekey.dat est dans le répertoire de données :

Si le fichier est présent mais la licence n’est pas chargée, vérifier
les logs pour des erreurs de lecture. Redémarrer le conteneur après avoir
corrigé les permissions.

Impossible de se connecter en UDP (voix)

Diagnostiquer :

Cause fréquente : le firewall bloque le port UDP 9987.
Ajouter la règle (section 8) et vérifier qu’elle n’est pas écrasée par MyVestaCP.

Transfert de fichiers échoue

Les fichiers ne se téléchargent pas ou ne s’uploadent pas.

Erreur database is locked dans les logs

Vérifier qu’il n’y a pas de fichiers -shm ou -wal résiduels :

Si les fichiers -shm et -wal existent et sont non vides,
la base a été copiée pendant que le serveur tournait encore.
Recopié la base après arrêt propre du serveur (section 6).

Identité serveur différente (clients affichent un warning)

Le client affiche « Server identity changed » à la connexion.

Cause : serverkey.dat est manquant ou différent.
Le serveur a généré une nouvelle identité au premier démarrage.
Arrêter le conteneur, remplacer serverkey.dat par celui de l’ancien serveur,
et redémarrer.


Récapitulatif de l’architecture finale

Ports utilisés sur le serveur :

  • 8069-8369 — Odoo 17 (4 instances, via reverse proxy)
  • 8469 — Odoo 8 (via reverse proxy)
  • 8480 — Akeneo PIM 7 (via reverse proxy)
  • 8490 — ownCloud 10 (via reverse proxy)
  • 9987/udp — TeamSpeak 3 voix (direct, pas de proxy)
  • 10011/tcp — TeamSpeak 3 ServerQuery (localhost seulement)
  • 30033/tcp — TeamSpeak 3 transfert de fichiers (direct)

Astuce : créer un enregistrement DNS pour TeamSpeak

Pour éviter que les utilisateurs doivent mettre à jour leurs bookmarks
à chaque migration, créer un enregistrement DNS :

  • Type : A
  • Nom : ts (ou vocal, teamspeak, etc.)
  • Valeur : 141.95.154.67

Les utilisateurs se connectent alors à ts.mcdtoolbox.com.
Lors de la prochaine migration, il suffit de changer l’IP dans le DNS
sans toucher aux bookmarks des clients.

SRV record pour port personnalisé :
si le port n’est pas le défaut (9987), créer un enregistrement SRV :
_ts3._udp.mcdtoolbox.com 0 5 9987 ts.mcdtoolbox.com.
Avec le port 9987 (standard), l’enregistrement A suffit.


À suivre

TeamSpeak 3 est maintenant opérationnel en Docker.
Dans les prochains articles :

  • Autres serveurs de jeux (Counter-Strike 1.6, EmuLinker)
  • Sauvegardes automatisées et stratégie de rétention
  • Monitoring et alertes

Article précédent : ownCloud 10 en Docker — migration 568 Go avec rsync progressif.



Catégories : Non classé

0 commentaire

Laisser un commentaire

Emplacement de l’avatar

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *