LGSL v6.2.1 sur VestaCP — monitorer ses serveurs CS 1.6 et TeamSpeak 3 en temps réel
Installer LGSL v6.2.1 sur VestaCP
Guide complet pour {{DOMAINE_GAMING}} — serveur {{IP_NOUVEAU}} — Mise a jour : mars 2026
Paramètres à personnaliser
Remplacez chaque {{VARIABLE}} par vos propres valeurs avant d’utiliser ce guide.
| Variable | Description | Exemple |
|---|---|---|
{{IP_NOUVEAU}} |
IP du serveur | 198.51.100.20 |
{{PORT_SSH_NOUVEAU}} |
Port SSH du serveur | 22223 |
{{DOMAINE_GAMING}} |
Domaine gaming | exemple-gaming.fr |
{{USER_VESTA}} |
Utilisateur MyVestaCP | admin |
1. Contexte
LGSL (Live Game Server List) est un script PHP open-source qui interroge des serveurs de jeux en temps reel et affiche leur statut (en ligne / hors ligne), le nombre de joueurs connectes, la carte en cours, le ping, etc. La version 6.2.1 est disponible sur GitHub.
Dans le cadre de {{DOMAINE_GAMING}}, LGSL sera utilise pour surveiller :
- 8 serveurs Counter-Strike 1.6 (protocol
halflife) sur les ports 27015 a 27022 - 2 serveurs TeamSpeak 3 (protocol
ts3) sur les ports 9987 et 9988 (query : 10011) - 1 serveur EmuLinker / Kaillera (protocol personnalise
kaillera) sur le port 27888 UDP
Le serveur EmuLinker / Kaillera n’est pas supporte nativement par LGSL. Un patch personnalise du fichier lgsl_protocol.php est presente en section 8 pour l’integrer completement.
2. Prerequis
| Composant | Requis | Remarque |
|---|---|---|
| Serveur web | Apache 2.4+ | Gere par VestaCP |
| PHP | 7.4 ou 8.x | Avec extensions sockets et prise en charge UDP |
| MySQL / MariaDB | 5.6+ | Pour stocker la liste des serveurs |
| Acces SSH | Oui | Port {{PORT_SSH_NOUVEAU}} sur {{IP_NOUVEAU}} |
| VestaCP | Installe | Pour creer la base de donnees et gerer les vhosts |
Verifier les extensions PHP requises
Connectez-vous en SSH et executez :
|
1 2 3 |
ssh -p {{PORT_SSH_NOUVEAU}} {{USER_VESTA}}@{{IP_NOUVEAU}} php -m | grep -E "sockets|pdo|mysqli|mbstring" |
Les extensions sockets, pdo_mysql (ou mysqli) et mbstring doivent apparaitre. Si sockets est absent :
|
1 2 3 4 5 6 7 8 |
# Debian / Ubuntu apt-get install php-sockets # CentOS / RHEL (remplacer X par votre version de PHP) yum install php-X-sockets # Puis recharger Apache service apache2 reload # ou : service httpd reload |
fsockopen() et les sockets UDP directement. La fonction allow_url_fopen doit etre activee dans php.ini (valeur par defaut : On).
3. Creer la base de donnees MySQL via VestaCP
- Connectez-vous au panel VestaCP : https://{{IP_NOUVEAU}}:8083
- Cliquez sur l’onglet DB dans la barre superieure.
- Cliquez sur le bouton vert Add Database.
- Remplissez le formulaire :
| Champ | Valeur recommandee |
|---|---|
| Database | lgsl (VestaCP prefixe automatiquement : admin_lgsl) |
| User | lgsl (prefixe : admin_lgsl) |
| Password | Choisissez un mot de passe fort |
| Host | localhost |
| Charset | utf8mb4 |
Cliquez sur Add. VestaCP cree la base et l’utilisateur. Notez les informations :
- Nom de la base :
admin_lgsl - Utilisateur :
admin_lgsl - Mot de passe : (celui que vous avez saisi)
- Host :
localhost
admin_). Tenez-en compte lors de la configuration de LGSL.
4. Telecharger et installer LGSL
4.1 Connexion SSH
|
1 |
ssh -p {{PORT_SSH_NOUVEAU}} {{USER_VESTA}}@{{IP_NOUVEAU}} |
4.2 Creer le dossier cible
|
1 |
mkdir -p /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl |
4.3 Telecharger LGSL v6.2.1
|
1 2 3 4 5 |
cd /tmp # Telecharger l'archive depuis GitHub wget -O lgsl-6.2.1.zip \ https://github.com/tltneon/lgsl/archive/refs/tags/v6.2.1.zip |
wget n’est pas disponible, utilisez curl -L -o lgsl-6.2.1.zip https://github.com/tltneon/lgsl/archive/refs/tags/v6.2.1.zip
4.4 Extraire et copier les fichiers
|
1 2 3 4 5 6 7 8 9 |
# Extraire unzip lgsl-6.2.1.zip # Le dossier extrait s'appelle lgsl-6.2.1 # Copier tout son contenu dans le sous-dossier lgsl du site cp -r lgsl-6.2.1/. /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/ # Nettoyer rm -rf /tmp/lgsl-6.2.1 /tmp/lgsl-6.2.1.zip |
4.5 Verifier les permissions
|
1 2 3 4 5 6 |
# Le proprietaire doit etre l'utilisateur web (admin sous VestaCP) chown -R {{USER_VESTA}}:{{USER_VESTA}} /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/ # Permissions standards find /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/ -type d -exec chmod 755 {} \; find /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/ -type f -exec chmod 644 {} \; |
4.6 Verifier la structure
|
1 |
ls /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/ |
Vous devriez voir, entre autres : index.php, install.php, admin.php, lgsl_config.php, lgsl/ (dossier du moteur), themes/.
5. Configuration initiale via install.php
Ouvrez votre navigateur et accedez a :
|
1 |
http://{{DOMAINE_GAMING}}/lgsl/install.php |
Le script d’installation vous demande les informations de connexion MySQL. Remplissez le formulaire :
| Champ | Valeur |
|---|---|
| Database Host | localhost |
| Database Name | admin_lgsl |
| Database User | admin_lgsl |
| Database Password | (votre mot de passe) |
| Table Prefix | lgsl_ (valeur par defaut, laisser tel quel) |
| Admin Password | Choisissez un mot de passe pour admin.php |
Cliquez sur Install. LGSL cree les tables dans la base de donnees et genere le fichier lgsl_config.php.
admin_ ajoute par VestaCP.
Verification manuelle du fichier de configuration
Apres l’installation, vous pouvez inspecter le fichier genere :
|
1 |
cat /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/lgsl_config.php |
Il doit contenir les constantes DB_HOST, DB_NAME, DB_USER, DB_PASS correctement renseignees.
6. Supprimer install.php (securite obligatoire)
install.php accessible apres l’installation est un risque de securite majeur. N’importe qui pourrait reinitialiser votre configuration. Supprimez-le immediatement apres l’installation.
|
1 |
rm /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/install.php |
Verifiez que la suppression est effective :
|
1 2 |
ls /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/install.php # Doit retourner : No such file or directory |
7. Ajouter les serveurs via admin.php
Accedez a l’interface d’administration :
|
1 |
http://{{DOMAINE_GAMING}}/lgsl/admin.php |
Connectez-vous avec le mot de passe admin choisi lors de l’installation.
7.1 Tableau de configuration des serveurs
Ajoutez chaque serveur via Add Server en utilisant les parametres suivants :
| # | Nom | Protocole | IP / Host | Port jeu | Port query |
|---|---|---|---|---|---|
| 1 | CS 1.6 Deathmatch | halflife |
{{IP_NOUVEAU}} |
27015 |
27015 |
| 2 | CS 1.6 GunGame | halflife |
{{IP_NOUVEAU}} |
27016 |
27016 |
| 3 | CS 1.6 Deathrun | halflife |
{{IP_NOUVEAU}} |
27017 |
27017 |
| 4 | CS 1.6 HNS | halflife |
{{IP_NOUVEAU}} |
27018 |
27018 |
| 5 | CS 1.6 Kreedz | halflife |
{{IP_NOUVEAU}} |
27019 |
27019 |
| 6 | CS 1.6 WAR | halflife |
{{IP_NOUVEAU}} |
27020 |
27020 |
| 7 | CS 1.6 Retro (CS 1.0) | halflife |
{{IP_NOUVEAU}} |
27021 |
27021 |
| 8 | CS 1.6 Surf | halflife |
{{IP_NOUVEAU}} |
27022 |
27022 |
| 9 | TeamSpeak 3 (principal) | ts3 |
{{IP_NOUVEAU}} |
9987 |
10011 |
| 10 | TeamSpeak 3 (secondaire) | ts3 |
{{IP_NOUVEAU}} |
9988 |
10011 |
halflife utilise le protocole Valve A2S (UDP). Le port query est generalement identique au port de jeu pour CS 1.6.
7.2 Particularites TeamSpeak 3
Pour TS3, LGSL a besoin d’acceder au port ServerQuery (10011) en TCP. Ce port est distinct du port vocal (9987 UDP). Dans le formulaire d’ajout :
- Game Port :
9987(port vocal TS3) - Query Port :
10011(port ServerQuery TCP) - Protocol :
ts3
Le port 10011 doit etre joignable depuis PHP. Voir la section 10 pour le cas particulier d’un TS3 tourne dans Docker.
8. EmuLinker / Kaillera — patch personnalise LGSL
LGSL ne supporte pas nativement le protocole EmuLinker / Kaillera. Il n’existe pas de plugin officiel pour ce protocole dans LGSL v6.x. Nous avons cree un patch qui ajoute le support Kaillera directement dans lgsl_protocol.php, en utilisant le handshake beacon du protocole Kaillera (HELLO0.83).
8.1 Principe du protocole
Le protocole Kaillera utilise UDP en deux phases :
- Beacon (detection online) : le client envoie
HELLO0.83\x00sur le port UDP du serveur, qui repondHELLOD00D{port}\x00avec un port prive - Protocole v086 (donnees completes) : sur le port prive, le client effectue un mini-login binaire (UserInfo → echange ACK → ServerStatus) pour recuperer la liste des joueurs connectes (noms, ping, statut) et des parties en cours
LGSL utilise le beacon pour la detection online/offline, et un script Python cron (kaillera_poll.py) pour le protocole v086 complet qui ecrit les donnees joueurs dans un fichier JSON.
8.2 Sauvegarde avant modification
lgsl_protocol.php :
|
1 2 |
cp /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/lgsl_protocol.php \ /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/lgsl_protocol.php.bak |
8.3 Script de patch
Ce script PHP ajoute 6 elements au fichier lgsl_protocol.php (apres les entrees teaspeak) sans modifier le code existant :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
<?php /** * Patch LGSL : ajout du protocole Kaillera / EmuLinker * A executer une seule fois avec : php patch_kaillera.php */ $file = '/home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/lgsl_protocol.php'; $code = file_get_contents($file); if (strpos($code, 'kaillera') !== false) { echo "Patch deja applique !\n"; exit(0); } $replacements = [ // 1. Nom du type [ '"teaspeak" => "TeaSpeak"', "\"teaspeak\" => \"TeaSpeak\",\n \"kaillera\" => \"Kaillera / EmuLinker\"" ], // 2. Numero de requete (query 49) [ '"teaspeak" => "33"', "\"teaspeak\" => \"33\",\n \"kaillera\" => \"49\"" ], // 3. URL de connexion [ '"teaspeak" => ""', "\"teaspeak\" => \"\",\n \"kaillera\" => \"\"" ], // 4. Schema UDP [ '"teaspeak" => "tcp"', "\"teaspeak\" => \"tcp\",\n \"kaillera\" => \"udp\"" ], // 5. Configuration des ports [ 'case "teaspeak": $c_to_q = -9987; $c_def = 9987; $q_def = 10011; $c_to_s = 0; break;', "case \"teaspeak\": \$c_to_q = -9987; \$c_def = 9987; \$q_def = 10011; \$c_to_s = 0; break;\n case \"kaillera\": \$c_to_q = 0; \$c_def = 27888; \$q_def = 27888; \$c_to_s = 0; break;" ], ]; foreach ($replacements as $r) { $code = str_replace($r[0], $r[1], $code); } // 6. Ajout des fonctions lgsl_query_49 (beacon + JSON status) $function = ' //------------------------------------------------------------------------------------------------------------+ //---- KAILLERA / EMULINKER (lgsl_query_49) ---------------------------------------------------------------+ //------------------------------------------------------------------------------------------------------------+ function lgsl_query_49_json_fetch($json_file, $max_age = 60) { if (!file_exists($json_file)) { return false; } $json_data = @file_get_contents($json_file); if (!$json_data) { return false; } $data = @json_decode($json_data, true); if (!$data || !isset($data["last_updated"])) { return false; } if ((time() - $data["last_updated"]) > $max_age) { return false; } return $data; } function lgsl_query_49(&$server, &$lgsl_need, &$lgsl_fp) // Kaillera / EmuLinker { // Phase 1: Beacon HELLO (detection online) fwrite($lgsl_fp, "HELLO0.83\x00"); $buffer = fread($lgsl_fp, 4096); if (!$buffer || strpos($buffer, "HELLOD00D") === FALSE) { return FALSE; } // Phase 2: Lire ou rafraichir le JSON du poller Python (kaillera_poll.py) $json_file = dirname(__FILE__) . "/lgsl_kaillera_status.json"; // Si le JSON est perime (> 30s) ou absent, le rafraichir a la demande $needs_refresh = !file_exists($json_file) || (time() - filemtime($json_file)) > 30; if ($needs_refresh) { $script_path = dirname(__FILE__) . "/kaillera_poll.py"; if (file_exists($script_path)) { shell_exec("python3 " . escapeshellarg($script_path) . " --ip " . escapeshellarg($server["b"]["ip"]) . " --port " . escapeshellarg(intval($server["b"]["q_port"])) . " --output " . escapeshellarg($json_file) . " 2>/dev/null"); } } $status = lgsl_query_49_json_fetch($json_file, 60); if ($status && $status["online"]) { $server["s"]["name"] = !empty($status["server_name"]) ? $status["server_name"] : "Kaillera / EmuLinker"; $server["s"]["map"] = $status["games_count"] > 0 ? $status["games_count"] . " game(s)" : "Kaillera"; $server["s"]["players"] = intval($status["players"]); $server["s"]["playersmax"] = intval($status["max_players"]); $server["s"]["password"] = 0; if (!empty($status["users"])) { $status_labels = array(0 => "Idle", 1 => "Playing", 2 => "Away"); foreach ($status["users"] as $key => $user) { $server["p"][$key]["name"] = $user["name"]; $server["p"][$key]["ping"] = isset($user["ping"]) ? $user["ping"] : 0; $server["p"][$key]["score"] = isset($status_labels[$user["status"]]) ? $status_labels[$user["status"]] : "Unknown"; } } } else { // Fallback : beacon seul, pas de donnees joueurs $server["s"]["name"] = "Kaillera / EmuLinker"; $server["s"]["map"] = "Kaillera"; $server["s"]["players"] = 0; $server["s"]["playersmax"] = 100; $server["s"]["password"] = 0; } $lgsl_need["s"] = FALSE; $lgsl_need["e"] = FALSE; $lgsl_need["p"] = FALSE; return TRUE; } '; // Inserer la fonction avant la derniere accolade fermante du fichier $pos = strrpos($code, '?>'); if ($pos !== false) { $code = substr($code, 0, $pos) . $function . "\n?>"; } else { $code .= $function; } file_put_contents($file, $code); echo "Patch Kaillera applique avec succes !\n"; |
kaillera). Il est donc sans danger de le relancer.
8.4 Ajouter le serveur dans LGSL
Apres avoir applique le patch, ajoutez le serveur Kaillera via le panneau d’administration LGSL :
| Champ | Valeur |
|---|---|
| Type | kaillera |
| IP | 127.0.0.1 |
| Port (c_port) | 27888 |
| Port query (q_port) | 27888 |
127.0.0.1 car EmuLinker tourne avec network_mode: host dans Docker, donc il ecoute directement sur l’interface locale du serveur.
8.5 Icone personnalisee
LGSL affiche une icone pour chaque type de serveur. Les icones sont des fichiers GIF 64×64 pixels stockes dans icons/{type}/{type}.gif. Pour Kaillera, il faut creer le dossier et generer l’icone :
|
1 |
mkdir -p /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/icons/kaillera |
Script PHP pour generer une icone manette retro (style NES) avec un « K » pour Kaillera :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<?php // Genere une icone manette retro 64x64 pour Kaillera $img = imagecreate(64, 64); // Couleurs $transparent = imagecolorallocate($img, 0, 0, 0); imagecolortransparent($img, $transparent); $darkgray = imagecolorallocate($img, 50, 50, 50); $gray = imagecolorallocate($img, 100, 100, 100); $white = imagecolorallocate($img, 220, 220, 220); $red = imagecolorallocate($img, 220, 50, 50); $darkred = imagecolorallocate($img, 180, 30, 30); $black = imagecolorallocate($img, 30, 30, 30); imagefilledrectangle($img, 0, 0, 63, 63, $transparent); // Corps de la manette imagefilledrectangle($img, 6, 18, 57, 48, $darkgray); imagefilledellipse($img, 14, 22, 16, 10, $darkgray); imagefilledellipse($img, 50, 22, 16, 10, $darkgray); imagefilledellipse($img, 14, 44, 16, 10, $darkgray); imagefilledellipse($img, 50, 44, 16, 10, $darkgray); // Poignees imagefilledrectangle($img, 2, 24, 10, 42, $darkgray); imagefilledrectangle($img, 53, 24, 61, 42, $darkgray); // D-Pad (croix directionnelle) $cx = 19; $cy = 33; imagefilledrectangle($img, $cx-3, $cy-9, $cx+3, $cy+9, $black); imagefilledrectangle($img, $cx-9, $cy-3, $cx+9, $cy+3, $black); imagefilledrectangle($img, $cx-2, $cy-2, $cx+2, $cy+2, $gray); // Boutons A et B (rouges) imagefilledellipse($img, 40, 35, 10, 10, $red); imagefilledellipse($img, 40, 34, 8, 8, $darkred); imagefilledellipse($img, 52, 31, 10, 10, $red); imagefilledellipse($img, 52, 30, 8, 8, $darkred); // Boutons Select / Start imagefilledrectangle($img, 28, 38, 34, 41, $gray); imagefilledrectangle($img, 28, 43, 34, 46, $gray); // Lettre "K" en blanc (Kaillera) $kx = 28; $ky = 8; imagefilledrectangle($img, $kx, $ky, $kx+2, $ky+8, $white); imagefilledrectangle($img, $kx+3, $ky+3, $kx+5, $ky+4, $white); imagefilledrectangle($img, $kx+5, $ky+1, $kx+7, $ky+3, $white); imagefilledrectangle($img, $kx+7, $ky, $kx+9, $ky+1, $white); imagefilledrectangle($img, $kx+3, $ky+4, $kx+5, $ky+5, $white); imagefilledrectangle($img, $kx+5, $ky+5, $kx+7, $ky+7, $white); imagefilledrectangle($img, $kx+7, $ky+7, $kx+9, $ky+8, $white); // Cable imageline($img, 31, 18, 31, 12, $darkgray); imageline($img, 32, 18, 32, 10, $darkgray); imageline($img, 33, 18, 33, 12, $darkgray); $path = '/home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/icons/kaillera/kaillera.gif'; imagegif($img, $path); imagedestroy($img); echo "Icone Kaillera generee : $path\n"; |
L’icone represente une manette NES stylisee avec croix directionnelle, boutons A/B rouges, boutons Select/Start, et un « K » blanc au-dessus pour identifier Kaillera.
8.6 Verification
Apres le patch, l’ajout du serveur et la generation de l’icone :
- Rechargez la page LGSL — le serveur Kaillera doit apparaitre avec le statut En ligne
- Verifiez que l’icone s’affiche correctement a cote du nom du serveur
- Pour tester l’etat hors ligne, arretez EmuLinker :
cd /home/docker/emulinker && docker compose stop
HELLO0.83) ne fournit que le statut online/offline.Pour les noms de joueurs et le nombre en temps reel, voir la section 8.7 ci-dessous.
8.7 Nombre de joueurs en temps reel (protocole v086)
Le beacon HELLO0.83 ne retourne aucune donnee sur les joueurs.
Pour obtenir les noms, ping et statut des joueurs en temps reel,
un script Python (kaillera_poll.py) implemente le protocole binaire Kaillera v086 complet :
- Envoie
HELLO0.83→ recoit le port prive - Se connecte au port prive et envoie un
UserInformation(type 0x03) - Echange des paquets
ACK(types 0x05/0x06) pour mesurer le ping - Recoit le paquet
ServerStatus(type 0x04) contenant la liste complete des joueurs et parties - Envoie un
Quit(type 0x01) propre et se deconnecte
Le script ecrit le resultat dans lgsl_kaillera_status.json que lgsl_query_49 lit directement.
8.7.1 Architecture
|
1 2 3 4 5 6 7 8 9 10 11 12 |
[LGSL requete web] → lgsl_query_49() ├── Beacon HELLO (detection online) ├── JSON perime (> 30s) ou absent ? │ ├── OUI → declenche kaillera_poll.py via shell_exec() │ │ ├── Protocole v086 complet → users + games │ │ ├── Filtre le bot "lgsl_poll" de la liste │ │ └── Ecrit lgsl_kaillera_status.json (ecriture atomique) │ └── NON → lecture directe du JSON existant ├── Lecture lgsl_kaillera_status.json │ ├── Frais (< 60s) → noms + ping + statut │ └── Perime → fallback master server kaillera.com └── Affichage dans LGSL |
8.7.2 Deploiement du script
Le script kaillera_poll.py est inclus dans le fork GitHub
(smkerz/lgsl-kaillera)
dans le dossier lgsl_files/.
Copier le script dans le dossier LGSL du serveur :
|
1 2 |
cp kaillera_poll.py /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/ chmod +x /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/kaillera_poll.py |
Test manuel :
|
1 2 3 4 5 |
python3 /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/kaillera_poll.py \ --ip 127.0.0.1 --port 27888 # Verifier le JSON produit cat /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/lgsl_kaillera_status.json |
Le JSON contient pour chaque joueur : nom, ping, statut (0=Idle, 1=Playing, 2=Away), ID et type de connexion.
8.7.3 Verification
- Connectez-vous au serveur Kaillera avec un client (ex: Kaillera P2P ou SupraclientC)
- Rechargez la page LGSL — la requete declenche
kaillera_poll.pyautomatiquement si le JSON est absent ou perime (> 30s). Verifiez ensuite le JSON :
1cat /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl_files/lgsl_kaillera_status.json
Votre nom doit apparaitre dans la listeusers. - Le compteur doit afficher
1/100et votre nom dans la liste des joueurs. - Deconnectez-vous du serveur Kaillera, rechargez la page LGSL, verifiez que le compteur revient a
0/100.
--ip (defaut: 127.0.0.1),--port (defaut: 27888),--output (chemin du JSON),--username (nom du bot, defaut: lgsl_poll — filtre de la liste des joueurs).
8.7.4 Depannage
| Probleme | Cause | Solution |
|---|---|---|
Poll failed: timed out |
EmuLinker ne repond pas sur le port 27888 | Verifier que le conteneur tourne : docker ps | grep emulinker |
Poll failed: Server is full |
Le serveur a atteint server.maxUsers |
Augmenter server.maxUsers dans emulinker.cfg |
Never received ServerStatus |
Le serveur n’envoie pas le paquet 0x04 | Verifier la version EmuLinker et les logs du conteneur |
| JSON montre 0 joueurs alors qu’il y en a | kaillera_poll.py absent ou shell_exec() desactive |
Verifier que kaillera_poll.py est dans le dossier LGSL et que shell_exec est autorise dans php.ini |
| LGSL affiche 0/100 malgre un JSON correct | JSON trop ancien (> 60s) ou chemin incorrect | Verifier que le JSON est dans le meme dossier que lgsl_protocol.php |
9. Personnalisation
9.1 Changer la langue en francais
Editez le fichier lgsl_config.php et cherchez la ligne de configuration de la langue :
|
1 |
nano /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/lgsl_config.php |
Modifiez ou ajoutez :
|
1 |
define('LGSL_LANGUAGE', 'fr'); |
Verifiez que le fichier de langue francais existe :
|
1 |
ls /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/lgsl/languages/ |
9.2 Changer le theme
Les themes sont dans le dossier themes/. Pour appliquer un theme, editez lgsl_config.php :
|
1 |
define('LGSL_THEME', 'default'); // Remplacez 'default' par le nom du dossier du theme |
9.3 CSS personnalise
Pour personnaliser l’apparence sans modifier les fichiers du theme (afin de faciliter les mises a jour), creez un fichier CSS personnalise dans le dossier du theme actif :
|
1 |
nano /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/themes/default/custom.css |
Puis incluez-le dans le template du theme (themes/default/header.php ou equivalent) :
|
1 |
<link rel="stylesheet" href="themes/default/custom.css"> |
9.4 Intervalle de rafraichissement
Dans lgsl_config.php, l’intervalle de cache (en secondes) entre deux interrogations des serveurs :
|
1 |
define('LGSL_CACHE_TIME', 60); // 60 secondes par defaut |
10. Probleme courant : port ServerQuery TS3 (10011)
Contexte du probleme
Si votre TeamSpeak 3 tourne dans un conteneur Docker, le fichier docker-compose.yml lie probablement le port ServerQuery 10011 uniquement a l’interface locale du conteneur ou a 127.0.0.1 de l’hote :
|
1 2 3 4 |
# Exemple de configuration docker-compose.yml restrictive ports: - "127.0.0.1:10011:10011" # Query TCP - lie a localhost uniquement - "0.0.0.0:9987:9987/udp" # Vocal UDP - accessible publiquement |
Pourquoi LGSL peut quand meme fonctionner
Dans votre configuration, Apache et PHP s’executent directement sur l’hote (pas dans un conteneur). Le PHP de LGSL peut donc atteindre 127.0.0.1:10011 car ce port est expose sur l’interface loopback de l’hote, et PHP tourne sur ce meme hote.
Si LGSL etait lui aussi dans Docker
Si LGSL tournait dans son propre conteneur Docker, il ne pourrait PAS atteindre 127.0.0.1:10011 de l’hote via cette adresse. Il faudrait alors :
- Soit lier le port TS3 a
0.0.0.0:10011dans le docker-compose (expose publiquement) - Soit placer les deux conteneurs sur le meme reseau Docker et utiliser le nom du service TS3 comme hostname
- Soit utiliser l’IP interne du reseau Docker bridge (
172.17.0.1par defaut)
Verifier que le port 10011 est accessible depuis PHP
|
1 2 3 |
# Depuis l'hote, tester la connexion TCP au port ServerQuery nc -zv 127.0.0.1 10011 # Reponse attendue : Connection to 127.0.0.1 10011 port [tcp/*] succeeded! |
Ou via PHP en ligne de commande :
|
1 2 3 4 5 6 7 8 9 |
php -r " \$fp = fsockopen('127.0.0.1', 10011, \$errno, \$errstr, 5); if (\$fp) { echo 'Port 10011 accessible' . PHP_EOL; fclose(\$fp); } else { echo 'ERREUR : ' . \$errstr . PHP_EOL; } " |
Si le port 10011 n’est pas accessible
Modifiez votre docker-compose.yml pour exposer le port sur toutes les interfaces :
|
1 2 3 |
ports: - "10011:10011" # Accessible depuis l'hote sur toutes les interfaces - "9987:9987/udp" |
Puis relancez le conteneur :
|
1 2 |
cd /chemin/vers/votre/teamspeak/ docker-compose down && docker-compose up -d |
Configurer les permissions ServerQuery pour LGSL
Meme si le port 10011 est accessible, LGSL peut afficher les serveurs TS3 en rouge / hors ligne si les permissions ServerQuery ne sont pas correctement configurees.
Le probleme
LGSL se connecte au ServerQuery sans authentification. Il est donc affecte au groupe Guest Server Query. Par defaut, ce groupe n’a pas la permission d’executer la commande serverinfo, ce qui provoque l’erreur :
|
1 |
error id=2568 msg=insufficient\sclient\spermissions failed_permid=25 |
Piege : identifier le bon groupe
Les groupes ServerQuery (type=2) dans TeamSpeak ont des ID parfois contre-intuitifs :
| sgid | Nom | Type | Role |
|---|---|---|---|
| 1 | Guest Server Query | 2 (ServerQuery) | Connexions non authentifiees (LGSL) |
| 2 | Admin Server Query | 2 (ServerQuery) | Connexions authentifiees (serveradmin) |
Permissions requises
LGSL a besoin de 3 permissions pour interroger un serveur virtuel TeamSpeak 3 :
| Permission | Commande TS3 | Usage LGSL |
|---|---|---|
b_virtualserver_info_view (permid=25) |
serverinfo |
Nom du serveur, joueurs, slots, uptime |
b_virtualserver_select |
use port=XXXX |
Selectionner le serveur virtuel par port |
b_virtualserver_client_list |
clientlist |
Liste des joueurs connectes |
Appliquer les permissions
Les permissions doivent etre accordees sur chaque serveur virtuel (sid). Utilisez ce script PHP depuis le serveur :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
php -r ' $fp = @fsockopen("tcp://{{IP_NOUVEAU}}", 10011, $errno, $errstr, 2); stream_set_timeout($fp, 2); fread($fp, 4096); fread($fp, 4096); fwrite($fp, "login serveradmin MOT_DE_PASSE\n"); fread($fp, 4096); // Pour chaque serveur virtuel (sid=1, sid=2, etc.) foreach ([1, 2] as $sid) { fwrite($fp, "use sid=$sid\n"); fread($fp, 4096); fwrite($fp, "servergroupaddperm sgid=1 permsid=b_virtualserver_info_view permvalue=1 permnegated=0 permskip=0\n"); echo "sid=$sid info_view: " . trim(fread($fp, 4096)) . "\n"; fwrite($fp, "servergroupaddperm sgid=1 permsid=b_virtualserver_select permvalue=1 permnegated=0 permskip=0\n"); echo "sid=$sid select: " . trim(fread($fp, 4096)) . "\n"; fwrite($fp, "servergroupaddperm sgid=1 permsid=b_virtualserver_client_list permvalue=1 permnegated=0 permskip=0\n"); echo "sid=$sid client_list: " . trim(fread($fp, 4096)) . "\n"; } fclose($fp); ' |
MOT_DE_PASSE par le mot de passe serveradmin, et adaptez la liste [1, 2] selon vos serveurs virtuels. Chaque ligne doit retourner error id=0 msg=ok.
Verifier que LGSL peut interroger TS3
Testez en simulant exactement le comportement de LGSL (connexion non authentifiee, timeout 0.5s) :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
php -r ' $fp = @fsockopen("tcp://{{IP_NOUVEAU}}", 10011, $errno, $errstr, 2); stream_set_timeout($fp, 0, 500000); stream_set_blocking($fp, TRUE); $b = fread($fp, 4096); echo "Banner: " . (strpos($b, "TS") !== FALSE ? "OK" : "FAIL") . "\n"; fread($fp, 4096); fwrite($fp, "use port=9987\n"); $r = fread($fp, 4096); echo "Use: " . trim($r) . "\n"; fwrite($fp, "serverinfo\n"); $r = fread($fp, 4096); echo "Serverinfo: " . substr(trim($r), 0, 120) . "\n"; fclose($fp); ' |
Resultat attendu : la ligne Serverinfo: doit afficher les informations du serveur (nom, joueurs, etc.) et non une erreur de permission.
Diagnostic : lister les groupes ServerQuery
En cas de doute sur les ID de groupes, connectez-vous en serveradmin et listez les groupes :
|
1 2 3 4 5 |
# Apres login + use sid=1 : servergrouplist # Les groupes de type=2 sont les groupes ServerQuery # sgid=1 type=2 → Guest Server Query (connexions non authentifiees) # sgid=2 type=2 → Admin Server Query (apres login serveradmin) |
11. Verification du fonctionnement
11.1 Verifier l’affichage de la liste
Ouvrez dans un navigateur :
|
1 |
http://{{DOMAINE_GAMING}}/lgsl/ |
Vous devriez voir la liste des serveurs avec leur statut. Les serveurs allumes affichent le nombre de joueurs et la carte.
11.2 Tester l’interrogation d’un serveur CS 1.6 manuellement
|
1 2 3 4 5 |
# Tester la joignabilite UDP du port 27015 nc -uzv {{IP_NOUVEAU}} 27015 # Ou avec nmap nmap -sU -p 27015 {{IP_NOUVEAU}} |
11.3 Verifier les logs PHP / Apache
|
1 2 3 4 5 |
# Logs Apache pour le domaine tail -50 /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/log/error.log # Logs Apache access tail -50 /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/log/access.log |
11.4 Tester depuis PHP
Creez un script de test temporaire /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/test_query.php :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php // Test rapide d'une socket UDP vers CS 1.6 $host = '{{IP_NOUVEAU}}'; $port = 27015; $fp = fsockopen('udp://' . $host, $port, $errno, $errstr, 5); if ($fp) { // Paquet A2S_INFO Valve $packet = "\xFF\xFF\xFF\xFF\x54Source Engine Query\x00"; fwrite($fp, $packet); stream_set_timeout($fp, 3); $data = fread($fp, 1400); fclose($fp); echo strlen($data) > 0 ? "Serveur repond (" . strlen($data) . " octets recus)" : "Pas de reponse (timeout ou serveur eteint)"; } else { echo "Impossible d'ouvrir la socket : $errstr"; } |
Accedez a http://{{DOMAINE_GAMING}}/lgsl/test_query.php puis supprimez-le apres le test :
|
1 |
rm /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/test_query.php |
11.5 Verifier les tables MySQL
|
1 |
mysql -u admin_lgsl -p admin_lgsl -e "SELECT * FROM lgsl_servers;" |
Cela liste tous les serveurs enregistres avec leur dernier statut connu.
12. Securite
12.1 Proteger admin.php par .htaccess
La methode la plus simple est de restreindre l’acces a admin.php par IP ou par authentification HTTP :
|
1 |
nano /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/.htaccess |
Ajoutez (en remplacant VOTRE_IP par votre adresse IP publique) :
|
1 2 3 4 5 6 |
# Protection admin.php par IP <Files "admin.php"> Order Deny,Allow Deny from all Allow from VOTRE_IP </Files> |
Ou par authentification HTTP basique :
|
1 2 3 4 5 6 7 8 9 10 |
# Generer le fichier de mots de passe htpasswd -c /home/{{USER_VESTA}}/.lgsl_htpasswd admin_lgsl # Puis dans .htaccess <Files "admin.php"> AuthType Basic AuthName "LGSL Administration" AuthUserFile /home/{{USER_VESTA}}/.lgsl_htpasswd Require valid-user </Files> |
12.2 Mot de passe admin fort
Le mot de passe admin de LGSL est stocke dans lgsl_config.php. Si vous souhaitez le changer sans repasser par install.php :
|
1 |
php -r "echo password_hash('NOUVEAU_MOT_DE_PASSE', PASSWORD_BCRYPT);" |
Copiez le hash genere et remplacez la valeur LGSL_ADMIN_PASSWORD dans lgsl_config.php.
12.3 Permissions fichiers
|
1 2 |
# lgsl_config.php ne doit pas etre lisible publiquement chmod 640 /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/lgsl_config.php |
12.4 Mises a jour LGSL
Surveillez les nouvelles versions sur github.com/tltneon/lgsl/releases. Pour mettre a jour :
- Sauvegardez
lgsl_config.phpet le dossierthemes/(vos personnalisations) - Telechargez la nouvelle version et extrayez-la
- Remplacez les fichiers du dossier LGSL (sauf
lgsl_config.phpet vos themes personnalises) - Verifiez si la structure de la base de donnees a change (voir le fichier
CHANGELOGouinstall.phpde la nouvelle version)
|
1 2 3 |
# Sauvegarde avant mise a jour cp /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/lgsl_config.php /tmp/lgsl_config.php.bak cp -r /home/{{USER_VESTA}}/web/{{DOMAINE_GAMING}}/public_html/lgsl/themes/ /tmp/lgsl_themes_bak/ |
12.5 Pare-feu et ports exposes
Verifiez quels ports sont actuellement exposes sur le serveur :
|
1 |
ss -tlnp | grep -E "10011|27015|27016|27017|27018|27019|27020|27021|27022|9987" |
Recapitulatif des URLs
| Page | URL | Remarque |
|---|---|---|
| Liste des serveurs (publique) | http://{{DOMAINE_GAMING}}/lgsl/ |
Page principale |
| Administration | http://{{DOMAINE_GAMING}}/lgsl/admin.php |
Proteger par IP ou .htaccess |
| Installation | http://{{DOMAINE_GAMING}}/lgsl/install.php |
A supprimer apres installation |
| Panel VestaCP | https://{{IP_NOUVEAU}}:8083 |
Gestion base de donnees |
| Statut Kaillera | http://{{DOMAINE_GAMING}}/lgsl/kaillera_status.php |
Script personnalise (optionnel) |
0 commentaire