API, site Next.js ou Express, bot Discord : une application Node.js ne se lance pas avec un simple node index.js sur un serveur. Il faut qu'elle redémarre après un plantage, qu'elle se relance au démarrage du VPS, que ses journaux soient conservés, et qu'elle soit publiée en HTTPS. PM2 gère les trois premiers points, Nginx le dernier.
1. Installer Node.js
La version de Node.js fournie par Ubuntu et Debian est souvent ancienne. Installez la version LTS (support long terme) actuelle depuis le dépôt NodeSource, puis vérifiez :
curl -fsSL https://deb.nodesource.com/setup_lts.x -o nodesource_setup.sh
bash nodesource_setup.sh
apt install -y nodejs
node -v && npm -v
Utilisez toujours une version LTS en production : les versions intermédiaires ne sont maintenues que quelques mois.
2. Déployer le code
Faites tourner l'application sous un utilisateur dédié, jamais en root. Récupérez le code, idéalement depuis un dépôt Git, puis installez les dépendances :
adduser --disabled-password --gecos "" app
su - app
git clone https://github.com/votre-compte/votre-projet.git monapp
cd monapp
npm ci --omit=dev
npm ci installe exactement les versions du fichier package-lock.json, ce qui garantit que le serveur utilise les mêmes dépendances que votre poste. Si le projet doit être compilé, comme une application Next.js ou TypeScript, installez toutes les dépendances puis lancez npm run build.
Placez les secrets, comme le jeton d'un bot ou les accès à la base, dans un fichier .env hors du dépôt Git, lisible par ce seul utilisateur : chmod 600 .env.
3. Lancer avec PM2
Installez PM2 globalement, en root, puis lancez l'application avec l'utilisateur app :
npm install -g pm2
su - app
cd monapp
pm2 start index.js --name monapp
pm2 status
Si l'application plante, PM2 la relance immédiatement. Pour un projet qui se lance avec un script npm, utilisez pm2 start npm --name monapp -- start.
4. Redémarrage automatique au démarrage du VPS
Toujours avec l'utilisateur app, demandez à PM2 la commande qui l'enregistre comme service système :
pm2 startup systemd
PM2 affiche une commande commençant par sudo env PATH=... : copiez-la et exécutez-la en root. Puis, de nouveau en tant que app, enregistrez la liste des applications à relancer :
pm2 save
Redémarrez le VPS une fois pour vérifier que l'application revient seule. Pensez à relancer pm2 save après chaque ajout ou suppression d'application.
5. Un fichier de configuration pour tout décrire
Plutôt que de longues lignes de commande, décrivez vos applications dans ecosystem.config.js, à la racine du projet :
module.exports = {
apps: [{
name: "monapp",
script: "index.js",
instances: 1,
max_memory_restart: "400M",
env: { NODE_ENV: "production", PORT: 3000 }
}]
};
pm2 start ecosystem.config.js
pm2 save
max_memory_restart relance l'application si elle dépasse la mémoire indiquée, un garde-fou utile contre les fuites de mémoire. Pour une API sans état, instances: "max" et exec_mode: "cluster" lancent une copie par cœur de processeur. Ne faites pas cela pour un bot Discord : chaque copie se connecterait séparément et répondrait en double.
6. Journaux
pm2 logs monapp --lines 100 # journaux en direct
pm2 monit # processeur et mémoire en direct
Par défaut, PM2 conserve les journaux sans limite. Installez son module de rotation pour éviter qu'ils ne remplissent le disque :
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 20M
pm2 set pm2-logrotate:retain 7
7. Publier l'application avec Nginx et HTTPS
Un bot Discord n'a pas besoin de cette étape : il se connecte lui-même à Discord. Pour une API ou un site, faites écouter l'application sur l'adresse locale uniquement, par exemple 127.0.0.1:3000, et placez Nginx devant. Créez /etc/nginx/sites-available/api.monsite.fr :
server {
listen 80;
server_name api.monsite.fr;
location / {
proxy_pass http://127.0.0.1:3000;
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";
}
}
ln -s /etc/nginx/sites-available/api.monsite.fr /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
certbot --nginx -d api.monsite.fr --redirect
Avec Express, ajoutez app.set("trust proxy", 1) pour que l'application voie l'adresse réelle des visiteurs et non celle de Nginx. Détails du certificat dans Nginx et HTTPS.
8. Mettre à jour l'application
su - app
cd monapp
git pull
npm ci --omit=dev
pm2 reload monapp
pm2 reload redémarre les instances une par une en mode cluster, sans coupure. En mode simple, il équivaut à un redémarrage rapide. Pour des déploiements plus sûrs, conteneurisez l'application : voir Docker et Docker Compose.