Héberger un bot Discord discord.js en ligne en continu
Un bot qui tourne sur votre ordinateur s'arrête quand vous l'éteignez. Pour qu'il réponde jour et nuit, il doit tourner sur un serveur, redémarrer seul après une erreur et lire son jeton ailleurs que dans le code. Ce guide part d'un bot discord.js v14 qui fonctionne en local et le met en ligne.
Deux façons de faire chez HebergHub :
- l'hébergement applicatif : vous indiquez un dépôt Git dans votre espace client, l'application est construite et publiée pour vous (la voie la plus simple) ;
- un VPS : vous gérez vous-même Node.js et le service (plus de contrôle, plus d'entretien).
Avant de commencer
- Une application créée sur le portail développeur Discord, avec un bot et son jeton (onglet Bot, bouton Reset Token).
- Les intents nécessaires activés dans ce même onglet. Message Content Intent n'est utile que si votre bot lit le texte des messages ; les commandes slash n'en ont pas besoin.
- Le bot invité sur votre serveur Discord avec les bonnes permissions (onglet OAuth2, portées
botetapplications.commands). - Un dépôt Git contenant le code : public (adresse en
https://), ou GitHub privé partagé avec HebergHub.
Préparer le dépôt
Structure minimale
mon-bot/
├── package.json
├── package-lock.json
├── .gitignore
├── .env.example
└── src/
└── index.jspackage.json
Le script start est ce qui sera lancé sur le serveur. Indiquez aussi la version de Node.js attendue.
{
"name": "mon-bot",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js"
},
"engines": {
"node": ">=20"
},
"dependencies": {
"discord.js": "^14.16.0"
}
}Validez le package-lock.json dans Git : l'installation sur le serveur utilisera exactement les mêmes versions qu'en local.
Le jeton hors du code
Le jeton ne doit jamais apparaître dans un fichier suivi par Git. Le bot le lit dans une variable d'environnement :
// src/index.js
const { Client, GatewayIntentBits, Events } = require('discord.js');
const token = process.env.DISCORD_TOKEN;
if (!token) {
console.error('DISCORD_TOKEN manquant : le bot ne peut pas démarrer.');
process.exit(1);
}
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once(Events.ClientReady, (c) => {
console.log(`Connecté en tant que ${c.user.tag}`);
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
await interaction.reply('Pong.');
}
});
process.on('unhandledRejection', (err) => console.error('Promesse rejetée :', err));
client.login(token).catch((err) => {
console.error('Connexion impossible :', err.message);
process.exit(1);
});Le .catch est important sur un serveur : sans lui, un jeton invalide est seulement journalisé, le programme se termine normalement (code 0) et systemd ne le relance pas. Avec process.exit(1), l'échec est visible et Restart=on-failure s'applique.
En local, mettez le jeton dans un fichier .env et lancez node --env-file=.env src/index.js (Node.js 20.6 et plus), ou utilisez le paquet dotenv. Le fichier .env reste chez vous :
# .gitignore
node_modules/
.envLe fichier .env.example, lui, est versionné et documente les variables attendues, sans valeur :
DISCORD_TOKEN=Tout le détail est dans le guide Variables d'environnement et jetons.
Enregistrer les commandes slash
Les commandes slash s'enregistrent une fois auprès de Discord, pas à chaque démarrage. Gardez un script séparé (deploy-commands.js) que vous lancez depuis votre poste quand vous ajoutez ou modifiez une commande. Le bot hébergé n'a qu'à répondre aux interactions.
Option 1 : l'hébergement applicatif
Tout se passe dans la boutique et dans votre espace client : vous n'avez pas d'autre interface à apprendre.
- Commandez la formule Application Starter (1,99 € TTC par mois). Le seul champ à remplir est le nom du projet.
- Ouvrez le service dans votre espace client, puis cliquez sur « Nouvelle application ». Le formulaire « Déployer une application » demande :
- le nom de l'application et, si vous le souhaitez, un sous-domaine en
.apps.heberghub.fr; - la source : Dépôt public (adresse https) ou Mes dépôts GitHub (privés), et la branche ;
- le type de build : laissez Automatique (détecté dans le dépôt) pour un projet Node.js avec
package.json; Nixpacks, Dockerfile et Site statique sont aussi proposés ; - le port de l'application (facultatif, détecté automatiquement) ;
- les variables d'environnement, une par ligne au format
NOM=valeur: ajoutezDISCORD_TOKEN=votre_jeton; - dans Options avancées, les commandes d'installation, de build et de démarrage si la détection ne vous convient pas (par exemple
npm start).
- le nom de l'application et, si vous le souhaitez, un sous-domaine en
- Cliquez sur « Déployer ». Le premier déploiement prend 5 à 15 minutes, le temps de préparer et de mettre en cache l'environnement de construction ; les suivants sont beaucoup plus rapides.
- Cliquez sur « Journaux » et vérifiez que la ligne
Connecté en tant que …apparaît.
La formule Starter donne jusqu'à 2 Go de RAM et 2 vCPU à votre application, ce qui couvre largement un bot discord.js classique. Si le bot plante, il est relancé automatiquement ; vous pouvez aussi le redémarrer, l'arrêter ou le redéployer depuis les boutons de l'application. En cas d'échec de déploiement, un encadré « Pourquoi ça a échoué » résume la cause.
Pour modifier le jeton plus tard, cliquez sur « Variables » : une variable par ligne, puis « Enregistrer ». Le changement s'applique au prochain redéploiement : cliquez ensuite sur « Redéployer ».
Si vous préférez maîtriser l'image, choisissez le type de build Dockerfile et placez ce fichier à la racine du dépôt :
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["npm", "start"]Un bot Discord n'écoute aucun port HTTP : il ouvre lui-même une connexion vers Discord.
Option 2 : sur un VPS
Sur un VPS Debian, installez Node.js (Debian 13 fournit Node.js 20 par apt), clonez le dépôt dans /opt/mon-bot, puis confiez le démarrage à systemd : il relance le bot après un plantage et au redémarrage du serveur.
apt install -y git nodejs npm
adduser --system --group --home /opt/mon-bot bot
git clone https://exemple.org/vous/mon-bot.git /opt/mon-bot
cd /opt/mon-bot && npm ci --omit=dev
install -m 600 -o root -g root /dev/null /etc/mon-bot.env
nano /etc/mon-bot.env # DISCORD_TOKEN=...
chown -R bot:bot /opt/mon-bot# /etc/systemd/system/mon-bot.service
[Unit]
Description=Bot Discord
After=network-online.target
Wants=network-online.target
[Service]
User=bot
WorkingDirectory=/opt/mon-bot
EnvironmentFile=/etc/mon-bot.env
ExecStart=/usr/bin/node src/index.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetsystemctl daemon-reload
systemctl enable --now mon-bot
journalctl -u mon-bot -fSéquence vérifiée sur un VPS conteneur et sur un VPS machine virtuelle Debian 13 (Node.js 20.19, npm 9.2, discord.js 14.27) : installation, unité systemd, démarrage. Avec un jeton invalide, le service échoue proprement (Connexion impossible : An invalid token was provided., code de sortie 1) et systemd le relance toutes les 5 secondes (journalctl -u mon-bot) ; un processus tué par kill -9 est relancé ; le service démarre de lui-même après un redémarrage du VPS. L'installation de npm apporte beaucoup de paquets et peut prendre plusieurs minutes.
Pour se connecter au VPS, voir Première connexion SSH par clé.
Mettre à jour le bot
- Applicatif : poussez vos modifications sur la branche suivie. Avec un dépôt GitHub privé partagé avec HebergHub, chaque push redéploie automatiquement l'application ; avec un dépôt public, cliquez sur « Redéployer ». Si un redéploiement normal ne suffit pas, « Reconstruire à neuf » reconstruit tout sans le cache.
- VPS :
git pull,npm ci --omit=dev, puissystemctl restart mon-bot.
Problèmes fréquents
| Symptôme | Cause probable |
|---|---|
TokenInvalid au démarrage |
Jeton absent, mal copié ou régénéré depuis. |
Used disallowed intents |
Un intent privilégié est demandé dans le code mais non activé sur le portail. |
| Les commandes slash n'apparaissent pas | Le script d'enregistrement n'a pas été lancé, ou les commandes globales mettent du temps à se propager. |
| Le bot s'arrête sans message | Erreur non interceptée : regardez les dernières lignes du journal (bouton « Journaux » sur l'applicatif). |
| Le jeton modifié n'est pas pris en compte | Les variables s'appliquent au prochain redéploiement : cliquez sur « Redéployer ». |
Si votre jeton a été publié par erreur, régénérez-le immédiatement sur le portail Discord : l'ancien cesse alors de fonctionner.
Besoin d'aide ?
Ouvrez un ticket depuis votre espace client en précisant le nom de l'application et l'heure du problème. Ne collez jamais votre jeton dans un ticket ni sur Discord.