SLBCloud
Intermédiaire9 min de lecture

Héberger une application Node.js

Faire tourner une application derrière nginx, la garder en vie avec systemd ou pm2, et la déployer sans coupure.

Une application Node écoute sur un port local — 3000, par convention. On ne l'expose jamais directement : nginx se place devant, gère le HTTPS, sert les fichiers statiques et transmet le reste. Cette séparation vous permet aussi d'héberger plusieurs applications sur la même machine.

Installer Node

Les paquets de la distribution sont souvent en retard de plusieurs versions. Le dépôt NodeSource donne la version que vous voulez.

bash
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node -v

Garder l'application en vie

Deux écoles, également valables. systemd est déjà là et ne demande aucune dépendance ; pm2 est plus simple à prendre en main et gère plusieurs applications d'un coup.

Avec systemd — /etc/systemd/system/mon-appli.service

ini
[Unit]
Description=Mon application Node
After=network.target

[Service]
Type=simple
User=appli
WorkingDirectory=/var/www/mon-appli
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production
Environment=PORT=3000

[Install]
WantedBy=multi-user.target

Avec pm2

bash
sudo npm install -g pm2
pm2 start server.js --name mon-appli
pm2 save
pm2 startup        # affiche une commande à copier-coller pour le démarrage auto

nginx devant

nginx
server {
    listen 80;
    server_name mon-appli.fr;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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_cache_bypass $http_upgrade;
    }
}

Les en-têtes Upgrade ne sont pas décoratifs

Sans les lignes Upgrade et Connection, les WebSockets ne passent pas : le chat, les notifications en direct et le rechargement à chaud cessent de fonctionner, sans message d'erreur clair. C'est le premier endroit à vérifier quand « ça marche en local mais pas en ligne ».

Écouter en local seulement

Votre application ne doit pas être joignable directement depuis Internet, sinon elle contourne nginx, le HTTPS et vos journaux. Faites-la écouter sur 127.0.0.1.

javascript
app.listen(3000, '127.0.0.1');

Déployer une nouvelle version

bash
cd /var/www/mon-appli
git pull
npm ci --omit=dev
npm run build
sudo systemctl restart mon-appli     # ou : pm2 reload mon-appli

npm ci, pas npm install

npm ci installe exactement ce que décrit le fichier de verrouillage, sans le modifier. npm install peut mettre à jour des dépendances au passage : votre production se met alors à différer de ce que vous avez testé, et le jour où ça casse, personne ne comprend pourquoi.

pm2 reload remplace les processus un par un, sans coupure visible. systemctl restart coupe une seconde — acceptable dans la plupart des cas, mais à savoir.

Bloqué malgré tout ? Ouvrez un ticket : on répond en français, et on regarde votre machine si besoin.

Ouvrir un ticket