💻 Serveur & shell

Héberger une app Node.js en prod (pm2 + reverse proxy)

Mettre en production une application Node.js (Express, Next.js, NestJS) sur un VPS : installation via nvm, gestion des process avec pm2, reverse proxy Apache ou Nginx, HTTPS, logs, monitoring et pièges classiques.

avancé ⏱ 15 min Mise à jour : 2026-04-24

Vous avez développé une application Node.js (Express, Next.js, NestJS, Fastify, Strapi…) et vous voulez la mettre en prod proprement. L'approche classique et robuste : Node écoute en local sur un port haut, un reverse proxy (Apache ou Nginx) expose l'app en HTTPS sur le port 443, et pm2 garde le process vivant : redémarrage automatique en cas de crash, au reboot du serveur, et zero-downtime sur les déploiements.

Ce guide couvre le déploiement sur un VPS ou une offre Datacampus compatible Node.js, avec un utilisateur Linux dédié (jamais root pour l'app).

1. Installer Node.js via nvm

On évite les paquets nodejs d'Ubuntu/Debian qui sont souvent anciens. nvm (Node Version Manager) installe Node dans votre home, sans sudo, et permet de jongler entre plusieurs versions.

# En tant qu'utilisateur applicatif (pas root)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Recharger le shell
source ~/.bashrc

# Installer et activer Node 20 LTS
nvm install 20
nvm use 20
nvm alias default 20

# Vérifier
node -v   # v20.x.x
npm -v
💡
Un nvm par utilisateur
nvm vit dans ~/.nvm. Si vous avez plusieurs apps sous plusieurs utilisateurs Linux, chaque utilisateur aura sa propre installation Node. C'est voulu, et ça évite les conflits de version entre apps.

2. Installer et utiliser pm2

pm2 est un gestionnaire de process Node. Il relance l'app en cas de crash, gère les logs, permet le reload zero-downtime et peut lancer plusieurs instances en mode cluster.

# Installer pm2 globalement dans la version Node courante
npm install -g pm2

# Démarrer l'app
cd ~/apps/mon-app
pm2 start app.js --name mon-app

# Variantes utiles
pm2 start npm --name mon-app -- start           # npm start
pm2 start "node dist/main.js" --name api        # NestJS build
pm2 start "next start -p 3000" --name site      # Next.js prod

# Gestion quotidienne
pm2 status            # liste des apps
pm2 logs mon-app      # logs live
pm2 restart mon-app   # restart brutal
pm2 reload mon-app    # zero-downtime (cluster mode)
pm2 stop mon-app
pm2 delete mon-app

Démarrage automatique au boot

Pour que pm2 relance vos apps après un reboot serveur :

# 1. Sauvegarder la liste d'apps en cours
pm2 save

# 2. Générer la commande systemd (à adapter à votre user)
pm2 startup
# pm2 affiche une ligne du genre :
#   sudo env PATH=... pm2 startup systemd -u monuser --hp /home/monuser
# Copiez-la, vérifiez le user et le home, puis exécutez-la.
⚠️
Ne jamais faire sudo pm2 startup sans précaution
Si vous tapez sudo pm2 startup directement, pm2 s'installe au boot sous root, avec les apps du root, pas les vôtres. Lancez pm2 startup sans sudo d'abord, copiez la commande qu'il vous suggère (elle contient -u votre_user --hp /home/votre_user), et exécutez-la telle quelle.

3. Reverse proxy Apache (hébergement Plesk)

Sur une offre mutualisée Plesk, l'app Node tourne en local sur 127.0.0.1:3000 et Apache relaie les requêtes HTTPS.

Dans Plesk, ouvrez le domaine puis Apache & nginx Settings. Dans le champ Directives Apache additionnelles pour HTTPS :

ProxyPreserveHost On
ProxyRequests Off

ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/

# WebSocket (si votre app utilise socket.io, SSE, etc.)
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L]

Les modules mod_proxy et mod_proxy_http doivent être actifs (ils le sont par défaut sur nos hébergements). Si Nginx est en front d'Apache dans Plesk, désactivez Smart static files processing pour que Nginx ne court-circuite pas le proxy.

4. Reverse proxy Nginx

Sur un VPS avec Nginx en direct, le bloc standard pour proxifier Node :

server {
    listen 80;
    listen [::]:80;
    server_name monapp.exemple.fr;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;

        # Headers standards
        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;

        # WebSocket
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        "upgrade";

        # Timeouts (utile pour du SSE/long polling)
        proxy_read_timeout  60s;
        proxy_send_timeout  60s;
    }
}

Testez la config puis rechargez :

sudo nginx -t && sudo systemctl reload nginx

5. HTTPS

Le reverse proxy gère le TLS : Node reste en HTTP sur 127.0.0.1, c'est voulu. Deux cas :

  • Plesk : onglet Certificats SSL/TLSLet's Encrypt, activez le certificat, Plesk le renouvelle automatiquement.
  • VPS Nginx : utilisez certbotsudo certbot --nginx -d monapp.exemple.fr ajoute le bloc 443 et planifie le renouvellement.

Dans votre app Node, si vous lisez req.protocol ou req.ip, activez la confiance du proxy. Exemple Express :

app.set('trust proxy', 1);  // fait confiance au 1er proxy en amont

6. Logs

pm2 centralise stdout et stderr de chaque app :

pm2 logs mon-app              # live, les deux flux
pm2 logs mon-app --err        # erreurs seulement
pm2 logs mon-app --lines 200  # historique
pm2 flush                     # vider les fichiers de log

Sans rotation, les logs grossissent indéfiniment. Installez le module officiel :

pm2 install pm2-logrotate

# Config recommandée
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 14
pm2 set pm2-logrotate:compress true

7. Monitoring

Un dashboard terminal en temps réel :

pm2 monit

CPU, RAM, logs, uptime, nombre de restarts. Pour du monitoring externe, pm2 s'interface avec Keymetrics (pm2.io), Datadog, New Relic ou tout exporter Prometheus tiers.

8. Déploiement sans coupure

Après un git pull + npm ci + build :

# Zero-downtime (cluster mode uniquement)
pm2 reload mon-app

# Brutal : tue puis relance
pm2 restart mon-app

Pour que reload soit réellement sans coupure, démarrez l'app en cluster mode — pm2 lance plusieurs workers, en remplace un à la fois :

pm2 start app.js --name mon-app -i max   # un worker par coeur CPU
# ou
pm2 start app.js --name mon-app -i 2     # 2 workers

Attention : votre app doit être stateless côté mémoire (sessions en Redis, pas en app.locals).

9. Ecosystem file : la config propre

Pour plusieurs apps ou une config stable versionnée, créez ecosystem.config.js à la racine du projet :

module.exports = {
  apps: [
    {
      name: 'api',
      script: './dist/main.js',
      instances: 2,
      exec_mode: 'cluster',
      max_memory_restart: '500M',
      env: {
        NODE_ENV: 'production',
        PORT: 3000,
      },
    },
    {
      name: 'worker',
      script: './dist/worker.js',
      instances: 1,
      env: {
        NODE_ENV: 'production',
      },
    },
  ],
};

Puis :

pm2 start ecosystem.config.js
pm2 reload ecosystem.config.js   # après un deploy
pm2 save

10. Pièges classiques

⚠️
Les erreurs qu'on voit le plus souvent
  1. Port déjà utilisé : EADDRINUSE. Un ancien process traîne, pm2 delete all ou lsof -i :3000 pour identifier.
  2. Firewall interne, le port applicatif (3000, 3001…) ne doit pas être ouvert sur l'extérieur. Bindez sur 127.0.0.1, pas sur 0.0.0.0.
  3. NODE_ENV=production oublié — Express sert les stack traces complètes en dev, les frameworks désactivent les optimisations. Définissez-le dans env du ecosystem file.
  4. Memory leak qui coule le serveur : pm2 start app.js --max-memory-restart 500M redémarre proprement dès que l'app dépasse un seuil, en attendant que vous trouviez la fuite.
  5. pm2 installé sous une autre version Node, si vous changez de Node via nvm use, réinstallez pm2 et régénérez le startup.
  6. Permissions sur le home — le script systemd généré par pm2 startup contient le path du home ; si vous migrez l'app, régénérez-le.
Chez Datacampus
Nos VPS et clusters Proxmox dédiés sont adaptés aux apps Node.js de production — accès root, choix du runtime, ressources garanties. Sur nos offres mutualisées Plesk, Node.js est supporté et nous configurons le reverse proxy Apache sur demande. Besoin d'un coup de main pour le déploiement ou la mise à l'échelle ? Écrivez-nous.

Pour aller plus loin

Besoin d'aide ?

Cette documentation ne couvre pas votre cas ? Notre support humain est là.