Comment mettre en place une application Node.js pour la production sur Ubuntu 20.04

Introduction

Node.js est un environnement d'exécution JavaScript open-source pour la création d'applications côté serveur et de réseau. La plate-forme fonctionne sous Linux, macOS, FreeBSD et Windows. Bien que vous puissiez exécuter les applications Node.js en ligne de commande, ce tutoriel se concentre sur leur exécution en tant que service. Cela signifie qu'ils redémarreront au redémarrage ou en cas d'échec et qu'ils peuvent être utilisés en toute sécurité dans un environnement de production.

Dans ce tutoriel, vous allez mettre en place un environnement Node.js prêt pour la production sur un seul serveur Ubuntu 20.04. 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 le HTTPS en utilisant un certificat gratuit fourni par Let’s Encrypt. 

Conditions préalables

Ce guide suppose que vous disposez des éléments suivants :

  • Une configuration du serveur Ubuntu 20.04, telle que décrite dans le Guide de configuration initiale du serveur pour Ubuntu 20.04. Vous devez avoir un non root user avec des privilèges sudo et un pare-feu actif.
  • Un nom de domaine qui pointe vers l'adresse IP publique de votre serveur. Ce tutoriel utilisera le nom de domaine example.com tout au long du processus.
  • Nginx installé, comme indiqué dans la section Comment installer Nginx sur Ubuntu 20.04. 
  • Nginx configuré avec SSL en utilisant des certificats Let’s Encrypt. Comment sécuriser Nginx avec Let’s Encrypt sur Ubuntu 20.04 vous guidera tout au long du processus. 

Lorsque vous aurez rempli les conditions préalables, vous disposerez d'un serveur desservant la page par défaut de votre domaine à l'adresse https://example.com/. 

Étape 1 — Installation de Node.js

Commençons par installer la dernière version LTS de Node.js, en utilisant les archives des packages NodeSource.

Tout d'abord, installez le NodeSource PPA afin d'avoir accès à son contenu. Assurez-vous que vous êtes dans votre répertoire d'origine et utilisez curl pour récupérer le script d'installation de la version LTS la plus récente de Node.js dans ses archives.

  • cd ~
  • curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh

Vous pouvez inspecter le contenu de ce script avec nano ou votre éditeur de texte préféré :

  • nano nodesource_setup.sh

Lorsque vous avez fini d'inspecter le script, lancez le sous sudo: 

  • sudo bash nodesource_setup.sh

Le PPA sera ajouté à votre configuration et le cache local de votre package sera automatiquement mis à jour. Après avoir exécuté le script d'installation à partir de Nodesource, vous pouvez installer le paquet Node.js :

  • sudo apt install nodejs

Pour vérifier quelle version de Node.js vous avez installée après ces premières étapes, tapez :

  • nodejs -v
Outputv14.4.0 

Note : Lors de l'installation à partir du PPA NodeSource, l'exécutable Node.js est appelé nodejs, plutôt que node.

Le paquet nodejs contient le binaire nodejs ainsi que npm, un gestionnaire de packages pour les modules Node, de sorte que vous n'avez pas besoin d'installer npm séparément.

npm utilise un fichier de configuration dans votre répertoire de base pour suivre les mises à jour. Il sera créé la première fois que vous utiliserez npm. Exécutez cette commande pour vérifier que npm est installé et pour créer le fichier de configuration :

  • npm -v
Output6.14.5 

Pour que certains packages npm fonctionnent (par exemple, ceux qui nécessitent la compilation du code source), vous devrez installer le package build-essential :

  • sudo apt install build-essential

Vous disposez maintenant des outils nécessaires pour travailler avec les packages npm qui nécessitent de compiler du code source.

Une fois le runtime Node.js installé, passons à l'écriture d'une application Node.js.

Étape 2 — Création d'une application Node.js

Écrivons une application Hello World qui renvoie « Hello World » à toute demande HTTP. Cet exemple de demande vous aidera à mettre en place Node.js. Vous pouvez le remplacer par votre propre application : assurez-vous simplement de modifier votre application pour écouter sur les adresses IP et les ports appropriés.

Tout d'abord, créons un exemple de demande appelée hello.js: 

  • cd ~
  • nano hello.js

Ajoutez 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.

Cette application Node.js écoute sur l'adresse (localhost) et le port (3000) spécifiés, et renvoie « Hello World ! » avec un code de réussite de 200 HTTP. Comme nous sommes à l'écoute sur localhost, les clients distants ne pourront pas se connecter à notre application.

Pour tester votre demande, tapez :

  • node hello.js

Vous recevrez le résultat suivant :

OutputServer running at http://localhost:3000/ 

Note : L'exécution d'une application Node.js de cette manière bloquera les commandes supplémentaires jusqu'à ce que l'application soit tuée en appuyant sur CTRL+C.

Pour tester l'application, ouvrez une autre session de terminal sur votre serveur, et connectez-vous à localhost avec curl :

  • curl http://localhost:3000

Si vous obtenez le résultat suivant, l'application fonctionne correctement et écoute à la bonne adresse et sur le bon port :

OutputHello World! 

Si vous n'obtenez pas le résultat attendu, 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 CTRL+C.

Étape 3 — Installer PM2

Ensuite, nous allons installer 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 comme un service.

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

L'option -g indique à npm d'installer le module dans le monde entier, afin qu'il soit disponible dans tout le système.

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

  • pm2 start hello.js

Cela ajoute également votre demande à la liste de processus de PM2, qui est produite chaque fois que vous lancez une demande :

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 d'application (basé sur le nom de fichier, sans l'extension .js) et un identifiant PM2. PM2 conserve également d'autres informations, telles que le PID du processus, son état actuel et l'utilisation de la mémoire.

Les applications qui tournent sous PM2 seront redémarrées automatiquement si l'application crashe ou est arrêtée, mais nous pouvons prendre une mesure supplémentaire pour que l'application soit lancée 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 aux démarrages du serveur :

  • pm2 startup systemd

La dernière ligne de la sortie résultante comprendra une commande à exécuter avec les privilèges de superuser afin de configurer PM2 pour qu'il démarre au démarrage :

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

Exécutez la commande à partir de la sortie, avec votre nom d'utilisateur à la place de sammy : 

  • sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

Comme étape supplémentaire, nous pouvons sauvegarder la liste des processus PM2 et les environnements correspondants :

  • pm2 save

Vous avez maintenant créé une unité systemd qui exécute pm2 pour votre utilisateur au démarrage. Cette instance pm2, à son tour, lance hello.js.

Démarrer le service avec systemctl: 

  • sudo systemctl start pm2-sammy

Si, à ce stade, un message d'erreur s'affiche, vous devrez peut-être redémarrer, ce que vous pouvez faire avec sudo reboot. 

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

  • systemctl status pm2-sammy

Pour un aperçu détaillé de systemd, veuillez consulter Les Fondamentaux de Systemd : Travailler avec les services, les unités et le journal. 

En plus de celles que nous avons couvertes, PM2 fournit de nombreuses sous-commandes qui vous permettent de gérer ou de rechercher des informations sur vos demandes.

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

  • pm2 stop app_name_or_id

Redémarrer une application :

  • pm2 restart app_name_or_id

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

  • pm2 list

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

  • pm2 info app_name

Le moniteur du processus PM2 peut être remonté avec la sous-commande monit. Il affiche l'état de l'application, l'unité centrale et l'utilisation de la mémoire :

  • pm2 monit

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

Maintenant que votre application Node.js est exécutée et gérée par PM2, mettons en place le proxy inverse.

Étape 4 — Configurer 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. Pour cela, nous allons mettre en place le serveur web Nginx comme proxy inverse.

Dans le tutoriel inclus dans les conditions préalables, vous configurez votre Nginx dans le fichier /etc/nginx/sites available/example.com. Ouvrez ce fichier pour le modifier :

  • sudo nano /etc/nginx/sites-available/example.com

Dans le bloc de serveurs, vous devez avoir un location/bloc 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/sites-available/example.com

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 permet de configurer le serveur pour qu'il réponde aux demandes à son root. En supposant que notre serveur soit disponible à l'adresse example.com, l'accès à https://example.com/ via un navigateur web enverrait la demande à hello.js, en écoute sur le port 3000 de localhost.

Vous pouvez ajouter des blocs d’location supplémentaires au même bloc de serveur pour permettre l'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 localisation pour y accéder via https://example.com/app2 :

/etc/nginx/sites-available/example.com — 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 fini d'ajouter les blocs de localisation pour vos applications, enregistrez le fichier et quittez votre éditeur.

Assurez-vous que vous n'avez pas introduit d'erreurs de syntaxe en tapant :

  • sudo nginx -t

Redémarrez Nginx :

  • sudo systemctl restart nginx

En supposant que votre application Node.js fonctionne, et que votre application et les configurations Nginx sont correctes, vous devriez maintenant pouvoir accéder à votre application via le proxy inverse Nginx. Essayez-le 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 fonctionnant derrière un proxy inverse Nginx sur un serveur Ubuntu 20.04. Cette configuration de proxy inverse est suffisamment souple pour permettre à vos utilisateurs d'accéder à d'autres applications ou à du contenu web statique que vous souhaitez partager.