Comment configurer une application Node.js pour la production sur Rocky Linux 9

Introduction

Node.js est un environnement d’exécution JavaScript open-source pour la construction d’applications côté serveur et de réseau. La plateforme fonctionne sous Linux, macOS, FreeBSD et Windows. Bien que vous puissiez exécuter des applications Node.js en ligne de commande, ce tutoriel se concentrera sur leur exécution en tant que service. Cela signifie qu’elles redémarreront au démarrage ou en cas de panne et sont sécurisées pour une utilisation en environnement de production.

Dans ce tutoriel, vous configurerez un environnement Node.js prêt pour la production sur un seul serveur Rocky Linux 9. Ce serveur exécutera une application Node.js gérée par PM2, et fournira aux utilisateurs un accès sécurisé à l’application via un proxy inverse Nginx. Le serveur Nginx offrira HTTPS en utilisant un certificat gratuit fourni par Let’s Encrypt.

Prérequis

Ce guide suppose que vous avez ce qui suit:

Une fois que vous avez terminé les prérequis, vous aurez un serveur servant la page de placeholder par défaut de votre domaine à https://example.com/.

Étape 1 — Création d’une application Node.js

Écrivons une application Hello World qui renvoie « Hello World » à toutes les requêtes HTTP. Cette application d’exemple vous aidera à démarrer avec Node.js. Vous pouvez la remplacer par votre propre application — assurez-vous simplement de modifier votre application pour écouter sur les adresses IP et les ports appropriés.

L’éditeur de texte par défaut fourni avec Rocky Linux 9 est vi. vi est un éditeur de texte extrêmement puissant, mais il peut être quelque peu obscur pour les utilisateurs qui manquent d’expérience avec lui. Vous voudrez peut-être installer un éditeur plus convivial comme nano pour faciliter l’édition des fichiers de configuration sur votre serveur Rocky Linux 9 :

  1. sudo dnf install nano

Maintenant, utilisez \texttt{nano} ou votre éditeur de texte préféré pour créer une application d’exemple appelée \texttt{hello.js} :

  1. nano hello.js

Insérez le code suivant dans le fichier :

~/hello.js
const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Enregistrez le fichier et quittez l’éditeur. Si vous utilisez \texttt{nano}, appuyez sur \texttt{Ctrl+X}, puis, lorsque vous y êtes invité, sur \texttt{Y}, puis sur Entrée.

Cette application Node.js écoute sur l’adresse spécifiée (\texttt{localhost}) et le port (\texttt{3000}), et renvoie « Hello World! » avec un code de succès HTTP \texttt{200}. Comme nous écoutons sur \texttt{localhost}, les clients distants ne pourront pas se connecter à notre application.

Pour tester votre application, tapez :

  1. node hello.js

Vous recevrez la sortie suivante :

Output
Server running at http://localhost:3000/

Note : Exécuter une application Node.js de cette manière bloquera les commandes supplémentaires jusqu’à ce que l’application soit arrêtée en appuyant sur \texttt{CTRL+C}.

Pour tester l’application, ouvrez une autre session terminal sur votre serveur et connectez-vous à \texttt{localhost} avec \texttt{curl} :

  1. curl http://localhost:3000

Si vous obtenez la sortie suivante, l’application fonctionne correctement et écoute sur l’adresse et le port corrects :

Output
Hello World!

Si vous n’obtenez pas la sortie attendue, assurez-vous que votre application Node.js est en cours d’exécution et configurée pour écouter sur l’adresse et le port appropriés.

Une fois que vous êtes sûr que cela fonctionne, arrêtez l’application (si ce n’est pas déjà fait) en appuyant sur \texttt{CTRL+C}.

Étape 2 — Installation de PM2

Ensuite, installons PM2, un gestionnaire de processus pour les applications Node.js. PM2 permet de démoniser les applications afin qu’elles s’exécutent en arrière-plan en tant que service.

Utilisez npm pour installer la dernière version de PM2 sur votre serveur:

  1. sudo npm install pm2@latest -g

L’option -g indique à npm d’installer le module globalement, afin qu’il soit disponible à l’échelle du système.

Commençons par utiliser la commande pm2 start pour exécuter votre application, hello.js, en arrière-plan:

  1. pm2 start hello.js

Cela ajoute également votre application à la liste des processus de PM2, qui est affichée à chaque fois que vous démarrez une application:

Output
... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Comme indiqué ci-dessus, PM2 attribue automatiquement un Nom de l'application (basé sur le nom du fichier, sans l’extension .js) et un id PM2. PM2 conserve également d’autres informations, telles que le PID du processus, son statut actuel et l’utilisation de la mémoire.

Les applications en cours d’exécution sous PM2 seront redémarrées automatiquement si l’application plante ou est arrêtée, mais nous pouvons prendre une mesure supplémentaire pour lancer l’application au démarrage du système en utilisant la sous-commande startup. Cette sous-commande génère et configure un script de démarrage pour lancer PM2 et ses processus gérés au démarrage du serveur:

  1. pm2 startup systemd
Output
… [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

Copiez et exécutez la commande fournie (cela évite les problèmes de permissions lors de l’exécution des outils Node.js en tant que sudo):

  1. sudo env PATH=$PATH:/usr/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy
Output
… [ 'systemctl enable pm2-sammy' ] [PM2] Writing init configuration in /etc/systemd/system/pm2-sammy.service [PM2] Making script booting at startup... [PM2] [-] Executing: systemctl enable pm2-sammy... Created symlink /etc/systemd/system/multi-user.target.wants/pm2-sammy.service → /etc/systemd/system/pm2-sammy.service. [PM2] [v] Command successfully executed. +---------------------------------------+ [PM2] Freeze a process list on reboot via: $ pm2 save [PM2] Remove init script via: $ pm2 unstartup systemd

Maintenant, vous devrez apporter une modification au service système qui vient d’être généré pour le rendre compatible avec le système de sécurité SELinux de Rocky Linux. À l’aide de nano ou de votre éditeur de texte préféré, ouvrez /etc/systemd/system/pm2-sammy.service :

  1. sudo nano /etc/systemd/system/pm2-sammy.service

Dans le bloc [Service] du fichier de configuration, remplacez le contenu de l’option PIDFile par /run/pm2.pid tel que surligné ci-dessous, et ajoutez la ligne Environment surlignée supplémentaire :

/etc/systemd/system/pm2-sammy.service
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=sammy
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/home/sammy/.local/bin:/home/sammy/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/sammy/.pm2
PIDFile=/run/pm2.pid
Restart=on-failure
Environment=PM2_PID_FILE_PATH=/run/pm2.pid

ExecStart=/usr/local/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/local/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/local/lib/node_modules/pm2/bin/pm2 kill

[Install]

Enregistrez et fermez le fichier. Vous avez maintenant créé une unité systemd qui exécute pm2 pour votre utilisateur au démarrage. Cette instance de pm2, à son tour, exécute hello.js.

Démarrez le service avec systemctl :

  1. sudo systemctl start pm2-sammy

Vérifiez l’état de l’unité systemd :

  1. systemctl status pm2-sammy

Pour un aperçu détaillé de systemd, veuillez consulter Systemd Essentials: Working with Services, Units, and the Journal.

En plus de ce que nous avons couvert, PM2 propose de nombreuses sous-commandes qui vous permettent de gérer ou de consulter des informations sur vos applications.

Arrêtez une application avec cette commande (spécifiez le nom de l'application ou id PM2) :

  1. pm2 stop app_name_or_id

Redémarrez une application :

  1. pm2 restart app_name_or_id

Liste des applications actuellement gérées par PM2 :

  1. pm2 list

Obtenez des informations sur une application spécifique en utilisant son nom d'application :

  1. pm2 info app_name

Le moniteur de processus PM2 peut être ouvert avec la sous-commande monit. Cela affiche l’état de l’application, l’utilisation du CPU et de la mémoire :

  1. pm2 monit

Notez que l’exécution de pm2 sans argument affichera également une page d’aide avec des exemples d’utilisation.

Maintenant que votre application Node.js fonctionne et est gérée par PM2, configurons le proxy inverse.

Étape 3 — Configuration de Nginx en tant que serveur proxy inverse

Votre application fonctionne et écoute sur localhost, mais vous devez mettre en place un moyen pour que vos utilisateurs y accèdent. Nous allons configurer le serveur web Nginx en tant que proxy inverse à cette fin.

Dans le tutoriel préalable, vous avez configuré votre fichier de configuration Nginx dans le dossier /etc/nginx/conf.d/your_domain.conf. Ouvrez ce fichier pour l’éditer :

  1. sudo nano /etc/nginx/conf.d/your_domain.conf

Au sein du bloc server, vous devriez avoir un bloc location / existant. Remplacez le contenu de ce bloc par la configuration suivante. Si votre application est configurée pour écouter sur un port différent, mettez à jour la partie en surbrillance avec le numéro de port correct :

/etc/nginx/conf.d/your_domain.conf
server {
...
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

Cela configure le serveur pour répondre aux demandes à sa racine. En supposant que notre serveur soit disponible à l’adresse your_domain, accéder à https://your_domain/ via un navigateur web enverrait la demande à hello.js, écoutant sur le port 3000 à localhost.

Vous pouvez ajouter des blocs location supplémentaires au même bloc serveur pour fournir un accès à d’autres applications sur le même serveur. Par exemple, si vous exécutez également une autre application Node.js sur le port 3001, vous pourriez ajouter ce bloc de location pour permettre l’accès via https://your_domain/app2:

/etc/nginx/conf.d/your_domain.conf — Optional
server {
...
    location /app2 {
        proxy_pass http://localhost:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

Une fois que vous avez ajouté les blocs de location pour vos applications, enregistrez le fichier et quittez votre éditeur.

Assurez-vous de ne pas avoir introduit d’erreurs de syntaxe en tapant:

  1. sudo nginx -t

Redémarrez Nginx:

  1. sudo systemctl restart nginx

En supposant que votre application Node.js fonctionne et que vos configurations d’application et de Nginx sont correctes, vous devriez maintenant pouvoir accéder à votre application via le proxy inverse Nginx. Essayez en accédant à l’URL de votre serveur (son adresse IP publique ou son nom de domaine).

Conclusion

Félicitations! Vous avez maintenant votre application Node.js qui s’exécute derrière un proxy inverse Nginx sur un serveur Rocky Linux 9. Cette configuration de proxy inverse est suffisamment flexible pour permettre à vos utilisateurs d’accéder à d’autres applications ou à du contenu web statique que vous souhaitez partager.

Ensuite, vous voudrez peut-être vous pencher sur Comment construire une application Node.js avec Docker.

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-rocky-linux-9