Héberger un bot Discord 24h/24 sans le surveiller : systemd, token et logs
Un bot Discord qui tourne sur ton portable est un bot qui disparaît quand tu fermes le capot. Le faire tourner jour et nuit demande quatre choses : une machine qui reste allumée, un moyen de relancer le bot quand il plante ou que la machine redémarre, un endroit sûr pour son token, et des logs. Rien de tout ça n’est difficile, mais chacun a son erreur classique. Ce guide les couvre pour Node.js comme pour Python.
Si tu ne veux pas t’occuper d’une machine, un bot hébergé te donne une console et un gestionnaire de fichiers à la place d’un shell, et la suite de cet article explique quand même ce qui se passe derrière.
Ce qu’est vraiment un bot
Un bot est un programme ordinaire qui se connecte à Discord avec un token secret, puis garde ouverte une connexion de longue durée vers la passerelle (gateway) de Discord. Deux conséquences comptent pour l’hébergement :
- Il se connecte vers l’extérieur. Personne ne se connecte à ton bot, donc tu n’as aucun port à ouvrir. Sur un serveur dont le pare-feu refuse le trafic entrant, le bot fonctionne tel quel.
- Il lui faut une connexion stable et un processus constant. Si le processus meurt, le bot passe hors ligne, et rien ne le remet en marche si tu ne l’as pas prévu.
1. Le code : un bot minimal dans chaque langage
Avec Node.js, le guide de discord.js dit d’utiliser la dernière version LTS de Node, et d’installer la bibliothèque avec npm :
npm init -y
npm install discord.js
Un bot qui se contente de dire qu’il est prêt :
import { Client, Events, GatewayIntentBits } from 'discord.js';
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once(Events.ClientReady, (c) => console.log(`Ready as ${c.user.tag}`));
client.login(process.env.DISCORD_TOKEN);
Ajoute "type": "module" dans package.json pour la syntaxe import. Vérifie quelles versions de Node sont encore supportées sur la page des versions de Node.js plutôt que de recopier un numéro de version trouvé sur un blog : il change chaque année.
Avec Python, la documentation de discord.py recommande un environnement virtuel pour que les bibliothèques du bot n’entrent pas en conflit avec celles du système :
python3 -m venv bot-env
source bot-env/bin/activate
python3 -m pip install -U discord.py
La page indique aussi la version minimale de Python que la bibliothèque supporte ; lis-la là-bas, car elle évolue avec les versions. Dans les deux cas, le token vient de l’environnement, jamais d’une chaîne écrite dans le fichier. C’est l’étape suivante.
2. Le token : le seul secret qui compte
Celui qui détient le token contrôle le bot, dans tous les serveurs qu’il a rejoints. Le guide de discord.js est direct sur le sujet : ne partage jamais le token, ni volontairement ni par accident, et s’il fuit (dépôt public, capture d’écran, forum d’entraide), retourne dans le Developer Portal, ouvre la page Bot de ton application et utilise Reset Token, qui invalide l’ancien. Mets ensuite le nouveau dans ta configuration.
Les règles qui évitent la plupart des fuites :
- Garde-le hors du code. Lis-le avec
process.env.DISCORD_TOKENouos.environ["DISCORD_TOKEN"]. - Garde-le hors de Git. Si tu utilises un fichier
.envpour les tests en local, ajoute.envà.gitignoreavant le premier commit. La documentation de GitHub sur un secret poussé donne l’ordre des opérations : change d’abord l’identifiant, nettoie l’historique ensuite, si tant est que tu le fasses. - Fais-le lire par le moins de choses possible. Sur le serveur, le fichier qui le contient doit appartenir à root avec le mode 600, comme ci-dessous.
- Ne le colle pas dans un ticket, un salon de discussion ou une ligne de log. Si tu affiches ta configuration pour déboguer, affiche tout sauf le token.
3. Le lancer sous systemd
Sur la plupart des serveurs Linux, systemd est déjà le superviseur. Il démarre le bot au boot, le relance après un plantage et collecte sa sortie. Crée un utilisateur dédié pour qu’un bug du bot ne puisse rien toucher d’autre :
sudo adduser --system --group --home /opt/mybot mybot
Mets le code dans /opt/mybot, installes-y ses dépendances (npm ci ou le venv), et place le secret dans un fichier à part :
sudo touch /etc/mybot.env
sudo chmod 600 /etc/mybot.env
sudoedit /etc/mybot.env
avec une seule ligne, sans guillemets et sans export :
DISCORD_TOKEN=paste-the-token-here
systemd lit lui-même ce fichier, en root, avant de lancer le processus sous son propre utilisateur : l’utilisateur du bot n’a donc pas besoin de la permission de le lire. Voici maintenant l’unité, dans /etc/systemd/system/mybot.service :
[Unit]
Description=My Discord bot
After=network-online.target
Wants=network-online.target
[Service]
User=mybot
WorkingDirectory=/opt/mybot
EnvironmentFile=/etc/mybot.env
ExecStart=/usr/bin/node index.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Pour Python, remplace la ligne ExecStart par l’interpréteur de l’environnement virtuel, par exemple ExecStart=/opt/mybot/bot-env/bin/python bot.py. Ensuite, charge et démarre l’unité :
sudo systemctl daemon-reload
sudo systemctl enable --now mybot
systemctl status mybot
Les réglages viennent du manuel de systemd.service : Restart=on-failure relance sur un code de sortie non nul, une fin anormale ou un dépassement de délai, RestartSec fixe le délai entre les tentatives (la valeur par défaut n’est que de 100 ms, donc fixe-la), EnvironmentFile charge les variables, et User et WorkingDirectory font ce que leur nom dit. Le manuel précise aussi que les redémarrages sont soumis à une limitation du rythme de démarrage, StartLimitIntervalSec et StartLimitBurst : un service qui plante encore et encore en très peu de temps est laissé à l’arrêt par systemd au lieu d’être relancé indéfiniment. Avec un RestartSec de quelques secondes, tu atteindras rarement cette limite, mais si tu vois un jour le service en état d’échec avec un message disant que la demande de démarrage a été répétée trop vite, c’est ce qui s’est passé, et ça veut dire que quelque chose va très mal.
N’utilise Restart=always que si le bot peut volontairement sortir avec le statut 0, par exemple pour appliquer une mise à jour, et que tu veux quand même qu’il revienne.
4. Les logs
Tout ce que le bot écrit sur la sortie standard et la sortie d’erreur est capturé par le journal de systemd. Lis-le avec :
journalctl -u mybot -f # follow live
journalctl -u mybot --since "1 hour ago"
journalctl -u mybot -p err # errors only
Fais en sorte que le bot journalise quelque chose d’utile : une ligne au démarrage avec la version de la bibliothèque, une ligne quand il se reconnecte, et l’erreur complète quand une commande échoue, avec le serveur et le nom de la commande mais jamais le token ni le contenu privé des utilisateurs. Un bot qui ne journalise rien transforme chaque incident en devinette.
5. Pourquoi les bots meurent, et quoi faire
La plupart des pannes viennent d’une courte liste :
- Une erreur non gérée. Dans Node.js, un rejet de promesse non géré termine le processus par défaut. C’est exactement à ça que sert
Restart=on-failure, mais corrige aussi la cause : attrape les erreurs dans les gestionnaires de commandes pour qu’une mauvaise commande ne fasse pas tomber le bot. - Un token qui a fuité ou qui a été réinitialisé. Le bot se connecte avec un token que Discord n’accepte plus. Il échouera à chaque redémarrage tant que tu n’auras pas mis à jour
/etc/mybot.envet lancésudo systemctl restart mybot. Redémarrer sans mettre à jour le fichier tourne simplement en boucle. - La croissance de la mémoire. Une fuite, ou un cache qui n’expire jamais, mange lentement la machine. Surveille la mémoire du processus dans
systemctl status mybotune fois par semaine au début. Si elle monte sans limite, cherche des objets stockés par message ou par utilisateur. - Une mise à jour qui l’a cassé. Fige tes dépendances (
package-lock.json,requirements.txt) et mets à jour volontairement, pas un vendredi soir. - La machine elle-même. Un redémarrage, ça passe, puisque le service démarre au boot. Un disque plein, non : les logs et les bases de données remplissent les disques.
df -hest une bonne habitude.
6. Mettre le bot à jour
La routine simple et fiable : copier le nouveau code, installer les dépendances, redémarrer.
cd /opt/mybot
sudo -u mybot git pull
sudo -u mybot npm ci
sudo systemctl restart mybot
journalctl -u mybot -n 30
La dernière ligne est la plus importante : regarde le log juste après un redémarrage, et vérifie qu’il dit qu’il est prêt.
Quand arrêter de le faire toi-même
Gérer sa propre machine est une bonne façon d’apprendre, et une mauvaise façon de passer un dimanche si tu voulais juste un bot en ligne. Une offre gérée t’enlève des mains le superviseur, les relances et la gestion des redémarrages, au prix de la liberté d’installer ce que tu veux. Regarde ce que propose la section logiciels d’Alama pour les bots, ou demande sur le Discord avant d’acheter. Si tu gères ta propre machine, la première chose à faire est le durcissement décrit dans les 30 premières minutes sur un serveur Ubuntu neuf.
La checklist
- Dernière LTS de Node ou un environnement virtuel Python, dépendances figées.
- Le token dans un fichier appartenant à root avec le mode 600, jamais dans le code ni dans Git.
- Une unité systemd avec
Restart=on-failure,RestartSec, un utilisateur dédié. journalctl -ucomme premier réflexe quand quelque chose semble anormal.- Une procédure connue pour réinitialiser le token, testée avant d’en avoir besoin.