DEV Community

Cover image for 🚀 Deploy d'une App Node.js avec NGINX et PM2 + Config Linux Server + Certificat SSL
Grégory CHEVALLIER
Grégory CHEVALLIER

Posted on

🚀 Deploy d'une App Node.js avec NGINX et PM2 + Config Linux Server + Certificat SSL

« Mise en prod' » , « Deploy », « Push ».. Tant d'expressions qui permettent de signifier l'aboutissement d'un long chemin de développement : ça y est, votre code est fin prêt à être déployé dans un environnement de production et votre application/serveur exposé(e) au monde entier.

Si vous n'avez jamais mis d'applications en ligne auparavant, les appréhensions peuvent être nombreuses.

Comment configurer un serveur Linux pour exécuter des applications Node.js ? Pourquoi utiliser un gestionnaire de processus ? Comment mettre en place un certificat SSL et profiter du protocole HTTPS ? Comment configurer la zone DNS d'un nom de domaine ?


⚙️ Pré-configuration de votre serveur

L'utilisation d'un VPS (= Virtual Private Server) est l'une des solutions les plus adaptées lorsque l'on doit déployer par exemple une ou plusieurs applications Node.js.

Vulgairement parlant, un VPS : c'est une machine comme la votre exposée via une adresse IPv4 dédiée, qui a pour vocation d'être allumée 24h/24 - 7j/7. Elle a généralement la particularité d'intégrer un système d'exploitation minimaliste, léger et nécessitant peu de ressources : Linux.

📶 La connexion à ce serveur distant est effectuée via le protocole SSH (Port 22), c'est par l'intermédiaire d'une invite de commande que notre serveur va être configurable.

Lorsque vous commandez un VPS, les informations suivantes vous sont communiquées :

  • Adresse IP (Host)
  • Username
  • Password
  • Port (22)

Ces informations permettent d'établir une connexion SSH. La plupart des systèmes d'exploitations intègrent aujourd'hui un client SSH mais certains nécessitent l'utilisation d'un client SSH tierce, c'est le cas avec Windows par exemple : l'installation du logiciel PuTTY est alors requise.

Si votre VPS est livré avec un système d'authentification : hôte / nom d'utilisateur / mot de passe, il n'a cependant pas pour vocation à le rester. Ce type d'authentification est exposé à de nombreux types d'attaques, le bruteforce notament.

Pour pallier à cette problématique : l'autorisation d'un client par le serveur depuis une pair de clé SSH préalablement générée

La première mise à niveau du serveur implique alors les actions suivantes :

  • Autoriser une/des clé(s) pour s'authentifier au protocole SSH
  • Supprimer l'authentification par mot de passe du protocole SSH

🔑 Générer une nouvelle pair de clé SSH, localement

🌕 Si vous utilisez Linux

Accédez localement à votre dossier ~/.ssh puis générez une nouvelle clé si vous n'en n'avez pas déjà une :

    cd ~/.ssh
    ssh-keygen -t rsa -b 4096 -C "your_label"

Enter fullscreen mode Exit fullscreen mode

Vous n'êtes pas obligé(e) d'inclure une passphrase à votre nouvelle clé, appuyez sur ENTRER sans même saisir de phrase de sécurité, celle-ci est souvent négligée par les développeurs, notament lorsqu'une clé est sollicitée en guise d'authentification via un processus automatisé.

    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/yourusername/.ssh/id_rsa):
    Created directory '/home/yourusername/.ssh'.
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /home/yourusername/.ssh/id_rsa.
    Your public key has been saved in /home/yourusername/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:2m0FfefEAFeJ31mFw87DAfef3FA113ge your_label
    The key's randomart image is:
    +---[RSA 4096]----+
    |      .          |
    |                 |
    | .               |
    |. . . .          |
    |. .=.o .S.       |
    | =o.o. ..   .    |
    |o +   .  . o ..  |
    |.. .      oEoo . |
    |o.        .o+oo  |
    +-----------------+
Enter fullscreen mode Exit fullscreen mode

Votre pair de clé est à présent créée.

Récupérez votre clé publique grâce à la commande suivante : cat ~/.ssh/id_rsa.pub.

C'est cette clé que nous autoriserons côté serveur, nous pourrons ainsi nous authentifier à notre serveur distant sans même avoir à justifier d'un mot de passe*.
(*) sous réserve qu'aucune phrase de sécurité n'ai été définie

🌑 Si vous utilisez Windows

Le logiciel PuTTYGen va vous permettre de générer une nouvelle pair de clé.

Une fois le logiciel ouvert, cliquez sur "Generate", agitez la souris aux 4 coins de la fenêtre (stimulation cryptographique) et patientez un instant durant la génération de votre clé.

Image description

Cette clé publique générée a vocation d'être autorisée auprès de notre serveur. Notre clé privée permettra de nous authentifier avec PuTTY via le protocole SSH sans utiliser de mot de passe*.
(*) sous réserve qu'aucune phrase de sécurité n'ai été définie

Cliquez ensuite sur le bouton "Save private key" pour enregistrer votre clé au format .ppk (Putty Private Key - format dédié à PuTTY).


🚦 Connexion au serveur et autorisation de notre nouvelle clé

Il est temps de se connecter pour la première fois à notre serveur, nous utiliserons logiquement l'adresse distante de notre machine, l'identifiant et le mot de passe fournis par notre hébergeur.

    ssh ubuntu@102.49.82.203
    ...

    login as: ubuntu
    ubuntu@102.49.82.203's password: 
Enter fullscreen mode Exit fullscreen mode

Une fois connecté(e),

Ouvrez le fichier authorized_keys via la commande : sudo nano ~/.ssh/authorized_keys

[...] Et ajoutez votre clé publique, précédemment générée, en la collant.

ℹ️ Voici un exemple de ce à quoi pourrait ressembler votre fichier ~/.ssh/authorized_keys si vous aviez autorisé plusieurs clés; toutes les clés autorisées peuvent permettre de s'authentifier au serveur sans mot de passe :

    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAQQCo9+BpMRYQ/dL3DS2CyJxRF+j6ctbT3/Qp84+KeFhnii7NT7fELilKUSnxS30WAvQCCo2yU1orfgqr41mM70MB your_label
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCb4oUsXZ51L9DmH3UqSnwOAUr9w6AOZa8bYH8qsJAhypAjH9YvQteVXXQEY0ybaVE1cmpIKEyC2jmC/jOJ4b7bivlo2hgnLOrj3FPkDWO2yNNio9RnPXREBx7 special_key
Enter fullscreen mode Exit fullscreen mode

Sauvegardez à présent votre fichier, félicitations 🎉

Vous pouvez dorénavant vous authentifier auprès de votre serveur en utilisant la clé précédemment générée.

Voyons à présent comment s'authentifier à notre serveur.


🔒 S'authentifier à notre serveur via SSH grâce à notre nouvelle clé

🌕 Si vous utilisez Linux

Connectez-vous à votre serveur via la commande traditionnelle : ssh user@host

✅ Aucun mot de passe n'est à présent requis, l'authentification est directement effectuée.

Si une phrase de sécurité (= passphrase) a été configurée lors de la génération de votre clé, cette dernière sera requise lors de la tentative de connexion :

    login as: ubuntu
    Authenticating with public key "id_rsa"
    Passphrase for key "id_rsa":
Enter fullscreen mode Exit fullscreen mode

🌑 Si vous utilisez Windows

Ouvrez le logiciel PuTTY (à ne pas confondre avec PuTTYGen permettant de générer des clés) et renseignez l'adresse de votre serveur distant, définissez le port SSH (22).

Rendez-vous dans la catégorie : Connection > SSH > Auth > Credentials.

Localisez votre clé privée (au format .ppk) préalablement enregistrée lors de l'étape de la génération de clé.

Retournez dans la catégorie "Sessions" puis cliquez sur "Save". Vos informations de connexion (y compris votre clé privée) seront alors gardés en mémoire.

Image description

Séléctionnez à présent la session que vous venez de sauvegarder et lancez-là.

Vous êtes à présent authentifié(e) à votre serveur*.
(*) sous réserve qu'aucune phrase de sécurité n'ai été définie


⛔ Désactiver l'authentification par identifiant / mot de passe

Notre authentification via clé SSH est à présent fonctionnelle ✅

L'authentification par l'intermédiaire d'une combinaison identifiant / mot de passe peut alors être supprimée, elle est la potentielle porte d'entrée à d'éventuelles intrustions malveillantes.

Commencons par modifier le fichier /etc/ssh/sshd_config en utilisant la commande :

sudo nano /etc/ssh/sshd_config

Notre mission : repérer les variables suivantes :

  • PasswordAuthentication
  • ChallengeResponseAuthentication
  • UsePAM

[...] et leur attribuer la valeur suivante : no.

ℹ️ Si l'une de ces variables est absente, rajoutez-là manuellement et définissez-là à no.

La variable PubkeyAuthentication quant à elle doit être définie à yes.

Dès lorsque les modifications sont terminées, utilisez généralement CTRL + X pour fermer et saisissez "Y" pour confirmer les changements.

ℹ️ Vérifiez parallèlement qu'aucun fichier .conf ne soit inclus dans les répertoires suivants : /etc/ssh/ssh_config.d et /etc/ssh/sshd_config.d. Certains hébergeurs définissent parfois des variables dans des fichiers de configuration à ces endroits pour, entre autre, autoriser la connexion via identifiant / mot de passe.

Le serveur SSH aura besoin d'être redémarré pour que les changements soient pris en compte, saisissez la commande suivante : sudo systemctl restart sshd ssh.

Notre serveur n'accepte dorénavant plus les connexions avec mot de passe. Seules les clés autorisées via notre registre ~/.ssh/authorized_keys pourront s'authentifier au protocole SSH de notre serveur.


📥 Télécharger et installer la dernière version de Node.js

Node.js est souvent téléchargé depuis les dépôts officiels / PPA (= Personal Package Archives) Ubuntu.

Nous délaisserons cette méthode en téléchargeant directement Node.js depuis la page de téléchargement du site officiel, selon la version souhaitée. Ainsi, nous sommes certains de pouvoir profiter d'une version up-to-date.

ℹ️ Dans un environnement de production, il est recommandé d'utiliser l'une des dernières versions de Node.js.

Dans ce tutoriel, nous utiliserons la version 18.15.0.

1️⃣ Localisez-vous au chemin d'accès par défaut ~ de votre serveur grâce à cd ~/ puis téléchargez la version Node.js cible depuis le site officiel grâce à la commande :

wget https://nodejs.org/dist/v18.15.0/node-v18.15.0-linux-x64.tar.xz

    --2023-04-01 12:49:28
    --`https://nodejs.org/dist/v18.15.0/node-v18.15.0-linux-x64.tar.xz`
    Resolving nodejs.org (nodejs.org)... 2606:4700:10::6814:162e, 2606:4700:10::6814:172e, 104.20.23.46, ...
    Connecting to nodejs.org (nodejs.org)|2606:4700:10::6814:162e|:443... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 23637576 (23M) [application/x-xz]
    Saving to: ‘node-v18.15.0-linux-x64.tar.xz’

    `node-v18.15.0-linux` 100%[===================>]  22.54M  28.9MB/s    in 0.8s    

    2023-04-01 12:49:28 (28.9 MB/s) - ‘node-v18.15.0-linux-x64.tar.xz’ saved [23637576/23637576]
Enter fullscreen mode Exit fullscreen mode

2️⃣ Décompressez le fichier .tar.xz téléchargé en utilisant :

sudo tar -xvf node-v18.15.0-linux-x64.tar.xz

3️⃣ Puis transférez les fichiers source de Node.js dans le répertoire /usr/ en utilisant la commande :

sudo cp -r node-v18.15.0-linux-x64/{bin,include,lib,share} /usr/

4️⃣ Supprimons sans tarder notre fichier node-v18.15.0-linux-x64.tar.xz ainsi que le répertoire décompressé node-v18.15.0-linux-x64, ils ne nous seront plus d'aucune utilité.

sudo rm -rf node-v18.15.0-linux-x64 node-v18.15.0-linux-x64.tar.xz

5️⃣ Ouvrez à présent le script de votre shell via sudo nano ~/.bashrc et exposez Node.js en ajoutant la ligne suivante, à la fin :

export PATH=/usr/node-v18.15.0-linux-x64/bin:$PATH

6️⃣ Rechargez à présent le script shell ~/.bashrc en utilisant source ~/.bashrc.

Node.js est normalement installé ✅

Vérifiez que l'installation soit conforme en saisissant node -v dans votre terminal.


🔐 Authentification auprès de Github

Git est et restera sans doûte le meilleur ami de celles & ceux qui pratiquent la programmation. Il est un outil indispensable du quotidien et sert notament d'intermédiaire entre votre environnement de développement et votre environnement de production.

La configuration de l'authentification avec Github est particulièrement importante.

L'authentification via pair de clé SSH peut par exemple outrepasser la nécessité de justifier d'un mot de passe. Elle peut alors permettre la manipulation automatisée d'un 🌐 repository grâce à un processus de CI/CD (= Continuous Integration/Continuous Delivery).

🔒 Intéressons-nous à l'authentification via pair de clé SSH.

Lors de la configuration de notre serveur Linux : nous avions généré, localement, une pair de clé SSH et nous avions autorisé notre clé publique depuis le serveur.

Cette fois, c'est sur le serveur que la pair de clé SSH va devoir être générée. La clé publique sera transmise à Github via les paramètres de notre compte et les échanges avec Github seront dès lors authentifiés.

Localisez-vous dans le dossier ~/.ssh de votre machine distante puis générez votre nouvelle pair de clé SSH :

    cd ~/.ssh
    ssh-keygen -t rsa -b 4096 -C "your_email@domain.com"
Enter fullscreen mode Exit fullscreen mode

Suivez la procédure de génération, ajoutez ou non une phrase de sécurité puis patientez un instant.

    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/ubuntu/.ssh/id_rsa): 
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /home/ubuntu/.ssh/id_rsa
    Your public key has been saved in /home/ubuntu/.ssh/id_rsa.pub
    The key fingerprint is:
    SHA256:c7bEyoefeR09TZ9vnEmddK2LwD4XRo4ZCLfmE3kKKTWoM your_email@domain.com
    The key's randomart image is:
    +---[RSA 4096]----+
    |    o . oo  .    |
    |  .  o     . o   |
    | o .  o   . + .  |
    |o      . + + .  .|
    |E s.    S X .   +|
    |.o     . B T..+.+|
    |.       = *.+o.* |
    |  ..  .  *.  .o o|
    |        ..o.     |
    +----[SHA256]-----+
Enter fullscreen mode Exit fullscreen mode

Il ne vous reste plus qu'à copier votre clé publique en utilisant : cat ~/.ssh/id_rsa.pub.

Rendez-vous sur https://github.com/settings/keys, cliquez sur "Nouvelle clé SSH" puis ajoutez votre clé publique en l'identifiant par un nom de référence.

Image description

Vérifiez, dans le terminal de votre serveur, que vous êtes bien authentifié en utilisant la commande : ssh -T git@github.com.

Si vous êtes authentifié, vous reçevrez un message similaire à celui-ci 👇

Hi {username}! You've successfully authenticated, but GitHub does not provide shell access.

[...] Vous pouvez à présent cloner votre projet sur votre serveur.


🟰 Cloner une application depuis un repository Git

A la racine ~ de votre serveur distant, clônez votre application grâce à la commande :

git clone git@github.com:{username}/{project}.git

ℹ️ Prenez soin d'actualiser les variables { } par vos données (= nom d'utilisateur Git et nom de projet).

Une fois votre application clônée et accessible en local, localisez-vous à la racine de votre projet à l'aide du nom de votre projet précédé par la commande cd.

ℹ️ Supposons que notre application soit une simple application React.

Créez votre fichier d'environnement de production (dotenv) à la racine (= .env ou .env.local).

Installez vos dépendances et lancez le build de votre projet à l'aide de npm i et npm run build.

⚙️ Vérifiez que votre application puisse se lancer via npm run start et tentez de joindre votre application via l'adresse de votre machine depuis le port utilisé par Node.js.

Mettez fin au processus (CTRL + C).

⚠️ Soyez sûre que votre application soit fonctionnelle en installant les éventuels services dépendants (= (No)SQL database, Redis, Docker, API..)


📂 Utiliser le protocole SFTP dédié aux transferts de fichiers

Que vous utilisiez Mac OS, Windows ou Linux, le logiciel de transfert de fichiers FileZilla vous permettra via une interface graphique de gérer les ressources de votre serveur (répertoires/fichiers).

ℹ️ Le transfert de fichiers se révèle particulièrement indispensable pour les sites web basiques incluant un système d'upload de fichiers. Ces derniers n'utilisant pas de solutions liées au cloud comme S3 AWS / Azure / Google Storage etc.. Les fichiers sont alors stockés sur le serveur.

Le transfert de fichiers requiert l'utilisation d'un protocole FTP (= File Transfert Protocol). Un serveur FTP (Port 21) doit alors être installé sur le serveur.

Pour pallier à cette épreuve, une alternative s'offre à nous : le SFTP (= SSH File Transfert Protocol).

Le SFTP accompli les missions du FTP mais en utilisant un autre protocole : le SSH (Port 22), le même que nous utilisons quotidiennement pour intéragir via shell avec notre serveur distant. Nous bénéficions dès lors des atouts qu'offre le SSH : à savoir une connexion sécurisée via pair de clé SSH.

En principe et selon notre mode opératoire, FileZilla charge notre clé SSH (préalablement générée) et la transmet à notre serveur qui nous autorise à établir la connexion.

Renseignez dès-lors l'adresse IPv4 de votre serveur, votre identifiant, le port : 22 puis procédez à la connexion.

✅ Votre clé SSH est détectée, transmise et approuvée par le serveur, vous êtes authentifié(e).

La clé n'est pas détectée ?

Si la clé n'est pas détectée, vous utilisez probablement Windows. Dans FileZilla, localisez la clé .ppk que vous aviez générée avec PuTTYGen depuis :

Filezilla > Fichier > Gestionnaire de sites > Type d'authentification > Fichier de clef

Image description

[...] Et chargez votre clé, la connexion devrait à présent aboutir.


📥 Installer et configurer le gestionnaire de processus PM2

Le gestionnaire de processus va permettre d'initialiser chacune de vos applications Node.js en les répertoriant dans des conteneurs centralisés. Il va occuper un rôle majeur en ce qui concerne la maintenance et le processus de déploiement de vos applications.

Chacun de ces conteneurs peut alors être (re)démarré/arrêté et exploité individuellement.

🔁 En cas de redémarrage impromptu du serveur, le gestionnaire de processus permet de redémarrage de l'intégralité de vos applications afin d'éviter une indisponibilité prolongée de vos services. Il donne également accès aux logs et à un système de monitoring efficace concernant vos processus.

Nous utiliserons PM2, une librairie disponible sur yarn et npm, simple, complète et efficace d'utilisation.

💡 Et si nous n'utilisions pas de gestionnaire de processus ?

Si par exemple vous démarriez votre application via une session SSH sans utiliser de gestionnaire de processus (via npm run start par exemple) : un processus serait alors lancé.

Dans l'hypothèse où vous abandonneriez ce(tte) terminal/session, vous perderiez la main sur le processus mais celui-ci continuerai alors d'être exécuté en arrière plan (vous pourriez évidement le reprendre dans une session ultérieure).

Si hasardeusement, vous oublieriez qu'une application Node.js était déjà en cours d'exécution, vous la lanceriez une nouvelle fois et il n'existerait alors pas moins de deux occurences d'une même application Node.js (x2 processus en arrière plan).

Autrement, si vous aviez par exemple plusieurs applications Node.js sur le même serveur, vous ne pourriez même pas les distinguer dans la liste des processus en cours d'exécution.

C'est à ces problématiques que le gestionnaire de processus PM2 apporte des solutions 🔥

💹 Comment ça fonctionne ?

Installons maintenant notre gestionnaire de processus, sur notre serveur distant, via la commande :

sudo npm i pm2 -g

Vérifiez que PM2 soit installé sur votre machine en exécutant : pm2 -v.

ℹ️ Le drapeau -g permet d'installer la librairie globalement et d'enregistrer la nouvelle variable d'environnement pm2.

Le mode de fonctionnement de PM2 permet d'initialiser un nouveau processus depuis la racine d'une application Node.js, au même niveau que notre traditionnel package.json.

Il intègre d'ailleurs la reconnaissance d'un fichier de configuration intitulé ecosystem.config.js. Dès lorsque ce fichier est présent à la racine de votre projet, il va permettre au gestionnaire de processus de démarrer votre application avec les différentes propriétés spécifiées.

ℹ️ La documentation des différentes propriétés disponibles pour la configuration du fichier ecosystem.config.js est disponible en ligne.

Avant d'initialiser votre application dans PM2, prenez-soin de créer un fichier ecosystem.config.js à la racine de votre projet puis d'y apporter la configuration requise minimale :

    module.exports = {
        apps : [{
            name: 'my-process-name',
            script : "npm run start",
        }]
    };
Enter fullscreen mode Exit fullscreen mode

Exécutez à présent la commande pm2 start à la racine de votre projet.

    [PM2][WARN] Applications my-process-name not running, starting...
    [PM2] App [my-process-name] launched (1 instances)
    ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
    │ id │ name               │ mode     │  ↺   │ status    │ cpu      │ memory   │
    ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
    │ 0  │ my-process-name    │ fork     │ 0    │ online    │ 0%       │ 10.2mb   │
    └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
Enter fullscreen mode Exit fullscreen mode

Le nouveau processus est créé et démarré 🎉

D'autres applications peuvent ainsi être ajoutées à la liste des processus PM2.

ℹ️ La commande pm2 startup ubuntu permet de garantir le redémarrage de vos processus après un éventuel crash/reboot intempestif de votre machine.

L'exécution, l'arrêt et le redémarrage de votre application devra à présent passer par PM2.

    // Lister les processus référencés
    pm2 list

    // Démarrer une application
    pm2 start my-process-name

    // Arrêter une application
    pm2 stop my-process-name

    // Redémarrer une application
    pm2 restart my-process-name

    // Accéder aux logs d'une application
    pm2 logs my-process-name

    // Accéder au panel de monitoring instantanée
    pm2 monit

    // Sauvegarder le référencement des applications chargées
    pm2 save

    // Restaurer des applications depuis une sauvegarde
    pm2 resurrect

    // Démarrer les processus lors du démarrage du système
    pm2 startup ubuntu
Enter fullscreen mode Exit fullscreen mode

📥 Installer et configurer le serveur web NGINX

L'utilisation d'un serveur web en guise de surcouche à Node.js est tout à fait recommandé. Le serveur web Nginx offre par exemple de nombreux avantages :

  • Concentrer l'audience de vos applications sur un même port (80 par défaut)
  • Intégrer d'indénombrables fichiers de configuration clairs et documentés. (Voir la documentation officielle)
  • Optimiser le traitement des requêtes
  • Gérer la mise en cache et la compression des données

[...] Et surtout : permettre l'utilisation d'un Reverse Proxy 🔥

Le proxy inverse permet de :

  • Rediriger des requêtes entrantes vers différents serveurs internes utilisant différents protocoles.
  • Agir en tant que répartiteur de charge entre plusieurs serveurs, si configuré comme tel.
  • Décharger les serveurs d'une charge d'objets/pages statiques via la gestion d'un cache web local.
  • Agir en tant que point de terminaison TLS et permettre le chiffrement via certificat SSL.
  • Réduire la charge de traitement cryptographique (= HTTPS) si installé sur une machine différente des serveurs applicatifs.
  • [...]

ℹ️ L'utilisation du reverse proxy a pour vocation de n'exposer que le port 80. Ainsi, les différents ports qu'occupent nos applications internes pourront être bloqués par notre pare-feu.

Procédons à l'installation de Nginx sur notre machine distante :

sudo apt install nginx

    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    The following packages were automatically installed and are no longer required:
      javascript-common libc-ares2 libjs-highlight.js libnode72 nodejs-doc
    Use 'sudo apt autoremove' to remove them.
    The following additional packages will be installed:
      libnginx-mod-http-geoip2 libnginx-mod-http-image-filter
      libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream
      libnginx-mod-stream-geoip2 nginx-common nginx-core
    Suggested packages:
      fcgiwrap nginx-doc ssl-cert
    The following NEW packages will be installed:
      libnginx-mod-http-geoip2 libnginx-mod-http-image-filter
      libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream
      libnginx-mod-stream-geoip2 nginx nginx-common nginx-core
    0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
    Need to get 696 kB of archives.
    After this operation, 2395 kB of additional disk space will be used.
    Do you want to continue? [Y/n]
Enter fullscreen mode Exit fullscreen mode

Saisissez "Y" et appuyez sur ENTRER.

✅ Nginx est à présent installé sur votre machine.

Remplacez intégralement le contenu du fichier /etc/nginx/sites-available/default :

sudo nano /etc/nginx/sites-available/default

[...] par le code suivant :

    server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name yourdomain.com www.yourdomain.com;
        location / {
            proxy_pass 'http://127.0.0.1:{port}';
            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_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Port $server_port;
        }
    }
Enter fullscreen mode Exit fullscreen mode

ℹ️ Soyez certain(e) d'avoir remplacer la variable {port} par le port utilisé par votre application Node.js et (www.)yourdomain.com par votre nom de domaine. Nous pourrons ensuite installer un certificat SSL.

Lorsque vous installez Nginx, la taille maximale d'une requête prise en charge par Nginx est restreinte à 1MB par défaut. Au delà, le requête sera rejetée ou ignorée.

Pour modifier ce paramètre, ouvrez le fichier de configuration /etc/nginx/nginx.conf et ajoutez la ligne suivante dans la section http si elle n'existe pas déjà :

client_max_body_size 50M;

⚠️ Vérifiez que la configuration globale soit conforme en exécutant sudo nginx -t puis redémarrez Nginx pour intégrer les modifications.

Utilisez sudo service nginx restart ou sudo systemctl restart nginx.

Lancez à présent votre application via PM2 et essayez de joindre votre application via HTTP (port 80 de votre machine).

ℹ️ L'installation d'un certificat SSL via la librairie Certbot viendra compléter le fichier de configuration /etc/nginx/sites-available/default pour permettre l'utilisation et la redirection HTTPS.

Si vous vouliez par exemple créer des sous-domaines et utiliser plusieurs méthodes de Proxy Reverse, vous pourriez configurer votre fichier /etc/nginx/sites-available/default selon le principe suivant :

    # Domain | www.domain.com

    server {
        server_name domain.com www.domain.com;
        location / {
            proxy_pass 'http://hostname:{port}';
        }
    }

    # Sub-domain n°1 | subdomain1.domain.com

    server {
        server_name subdomain1.domain.com www.subdomain1.domain.com;
        location / {
            proxy_pass 'http://hostname:{port}';
        }
    }

    # Sub-domain n°2 | subdomain2.domain.com

    server {
        server_name subdomain2.domain.com www.subdomain2.domain.com;
        location / {
            proxy_pass 'http://hostname:{port}';
        }
    }
Enter fullscreen mode Exit fullscreen mode

Pour garantir de bonnes conditions de maintenance et renforcer l'organisation structurelle de notre Reverse Proxy, il serait préférable de supprimer notre fichier /etc/nginx/sites-available/default et de créer un fichier pour chaque (sous-)domaine.

L'arborescence des (sous-)domaines serait alors plus simple à distinguer.

    # Domain | www.domain.com

    server {
        server_name domain.com www.domain.com;
        location / {
            proxy_pass 'http://hostname:{port}';
        }
    }
Enter fullscreen mode Exit fullscreen mode
    # Sub-domain n°1 | subdomain1.domain.com

    server {
        server_name subdomain1.domain.com www.subdomain1.domain.com;
        location / {
            proxy_pass 'http://hostname:{port}';
        }
    }
Enter fullscreen mode Exit fullscreen mode

Une fois les fichiers de configurations référents à vos différents (sous-)domaines créés dans le répertoire /etc/nginx/sites-available, créez un lien symbolique pour chacun de vos fichiers depuis ce répertoire, au répertoire /etc/nginx/sites-enabled/ en utilisant :

    cd ~
    sudo ln -s /etc/nginx/sites-available/domain.com /etc/nginx/sites-enabled/domain.com
    sudo ln -s /etc/nginx/sites-available/subdomain1.domain.com /etc/nginx/sites-enabled/subdomain1.domain.com
    ...
Enter fullscreen mode Exit fullscreen mode

⚠️ Vérifiez que la configuration globale soit conforme en exécutant sudo nginx -t puis redémarrez Nginx pour intégrer les modifications.

Utilisez sudo service nginx restart ou sudo systemctl restart nginx.


🛡️ Activation du pare-feu serveur

Dès lorsque nos applications Node.js sont accessible via le port 80 qu'utilise notre serveur web Nginx, il est judicieux d'activer le pare-feu et ainsi n'autoriser que les protocoles ayant pour vocation d'être exploités sur notre machine tels que :

  • SSH / SFTP (22)
  • HTTP(S) (80 / 443)

Exécutez les commandes suivantes :

    sudo ufw enable
    sudo ufw allow ssh
    sudo ufw allow http
    sudo ufw allow https
Enter fullscreen mode Exit fullscreen mode

Utilisez la commande sudo ufw status pour obtenir une synthèse des réglementations.

    Status: active

    To                         Action      From
    --                         ------      ----
    22/tcp                     ALLOW       Anywhere                  
    80                         ALLOW       Anywhere                  
    443                        ALLOW       Anywhere                  
    22/tcp (v6)                ALLOW       Anywhere (v6)             
    80 (v6)                    ALLOW       Anywhere (v6)             
    443 (v6)                   ALLOW       Anywhere (v6)      
Enter fullscreen mode Exit fullscreen mode

🌐 Configuration de la zone DNS d'un nom de domaine

C'est une étape primordiale lorsqu'une activitée prend naissance sur le web : la configuration de la zone DNS du nom de domaine.

La zone DNS d'un nom de domaine est un espace administratif gérée par une organisation ou un administrateur spécifique qui permet le contrôle sur les différentes entrées du nom de domaine.

Lorsque vous reçevez votre nouveau nom de domaine, la zone DNS de votre nom de domaine est souvent pré-configuré par votre hébergeur de telle sorte à ce que vous puissiez dors et déjà par exemple accéder au protocole FTP du serveur cible via la pré-configuration d'un enregistrement CNAME (= ftp.domain.com).

ℹ️ Retrouvez la liste des différents enregistrements DNS existants

Exemple d'espace d'administration de la zone DNS d'un nom de domaine (OVH) 👇

Image description

Ci-dessous, un aperçu textuel de la configuration de la zone DNS de notre nom de domaine :

    $TTL 3600
    @   IN SOA dns200.anycast.me. tech.ovh.net. (2023020018 86400 3600 3600000 60)
                              IN NS     ns200.anycast.me.
                              IN NS     dns200.anycast.me.
                              IN MX     1 mx4.mail.ovh.net.
                              IN MX     10 mx3.mail.ovh.net.
                              IN A      164.132.50.110
                              IN TXT    "1|www.domain.com"
    _autodiscover._tcp        IN SRV    0 0 443 mailconfig.ovh.net.
    _imaps._tcp               IN SRV    0 0 993 ssl0.ovh.net.
    _submission._tcp          IN SRV    0 0 465 ssl0.ovh.net.
    subdomain1                IN CNAME  domain.com.
    autoconfig                IN CNAME  mailconfig.ovh.net.
    autodiscover              IN CNAME  mailconfig.ovh.net.
    ftp                       IN CNAME  domain.com.
    subdomain2                IN CNAME  domain.com.
    www                       IN A      164.132.50.110
    www                       IN TXT    "3|welcome"
Enter fullscreen mode Exit fullscreen mode

La première action à entreprendre : modifier l'adresse IPv4 cible de l'enregistrement de Type A en renseignant l'adresse IPv4 de votre serveur distant, pour les deux entrées existantes : domain.com (Type A) et www.domain.com (Type A).

Le nom de domaine sera dès lors reconnu par n'importe quel naviguateur et dirigera le client à votre serveur distant.

Pour créer un sous-domaine, créez une nouvelle entrée de Type CNAME, ciblez votre nom de domaine et spécifiez l'intitulé du sous-domaine à créer, puis validez.

ℹ️ Un délai de propagation implique parfois d'attendre jusqu'à 24 heures avant de garantir l'accessibilité à votre nouveau sous-domaine.

Lorsque vous requêterez votre sous-domaine, Nginx sera capable d'interprêter l'origine de la requête et vous redirigera auprès de l'application cible (selon votre configuration via proxy).


🔒 Mise en place d'un certificat SSL avec Certbot

Maintenant que notre nom de domaine nous redirige vers notre serveur distant, que le serveur web Nginx interprête l'origine de notre requête et nous redirige vers l'application cible ;

Etablissons une connexion sécurisée entre client/serveur grâce au protocole HTTPS.

L'utilisation du protocole HTTPS nécessite l'utilisation d'un certificat numérique permettant aux navigateurs de vérifier l'identité des serveurs web. Des tiers de confiance, soit des autorités de certification (AC) sont chargées de déléguer les certificats aux serveurs web.

Une librairie nommée « Certbot » récupère des certificats depuis l'autorité de certification Let's Encrypt, (autorité de certification lancée à l'initiative de Mozilla notament). Nous l'utiliserons pour implémenter rapidement notre certificat SSL avec Nginx.

Installons Certbot, depuis notre machine distante :

sudo apt install certbot python3-certbot-nginx

Procédons à l'installation de notre certificat SSL en utilisant Certbot :

sudo certbot --nginx -d domain.com -d www.domain.com

    Saving debug log to '/var/log/letsencrypt/letsencrypt.log'
    Enter email address (used for urgent renewal and security notices)
     (Enter 'c' to cancel): your_email@domain.com

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Please read the Terms of Service at
    https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
    agree in order to register with the ACME server. Do you agree?
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    (Y)es/(N)o: y

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Would you be willing, once your first certificate is successfully issued, to
    share your email address with the Electronic Frontier Foundation, a founding
    partner of the Lets Encrypt project and the non-profit organization that
    develops Certbot? We would like to send you email about our work encrypting the web,
    EFF news, campaigns, and ways to support digital freedom.
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    (Y)es/(N)o: y
    Account registered.
    Requesting a certificate for 'domain.com' and 'www.domain.com'

    Successfully received certificate.
    Certificate is saved at: '/etc/letsencrypt/live/domain.com/fullchain.pem'
    Key is saved at:         '/etc/letsencrypt/live/domain.com/privkey.pem'
    This certificate expires on 2023-07-01.
    These files will be updated when the certificate renews.
    Certbot has set up a scheduled task to automatically renew this certificate in the background.

    Deploying certificate
    Successfully deployed certificate for 'domain.com to' '/etc/nginx/sites-enabled/default'
    Successfully deployed certificate for 'www.domain.com' to '/etc/nginx/sites-enabled/default'
    Congratulations! You have successfully enabled HTTPS on 'https://domain.com' and 'https://www.domain.com'

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    If you like Certbot, please consider supporting our work by:
     * Donating to ISRG / Lets Encrypt:   https://letsencrypt.org/donate
     * Donating to EFF:                    https://eff.org/donate-le
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Enter fullscreen mode Exit fullscreen mode

Une règle a été créée auprès de votre serveur web pour rediriger le client du protocole HTTP au HTTPS. Une tâche pour renouveller le certificat a quant à elle été initialisée et sera renouvellée chaque 90 jours.

Vérifiez que celle-ci soit créée via sudo systemctl status certbot.timer

    ● certbot.timer - Run certbot twice daily
    Loaded: loaded ('/lib/systemd/system/certbot.timer'; enabled; vendor preset:>
    Active: active (waiting) since Sun 2023-04-02 10:50:45 UTC; 4min 58s ago
    Trigger: Sun 2023-04-02 15:19:19 UTC; 4h 23min left
    Triggers: ● certbot.service

    Apr 02 10:50:45 vps systemd[1]: Started Run certbot twice daily.
Enter fullscreen mode Exit fullscreen mode

Un email de Let's Encrypt devrait vous parvenir avant l'expiration de votre certificat.

Utilisez sudo certbot renew --dry-run à l'avenir pour renouveller votre certificat.

ℹ️ Vous pourrez remarquer que le fichier de configuration Nginx lié au nom de domaine que vous avez certifié à été modifié par Certbot. Notre fichier /etc/nginx/sites-available/default ou /etc/nginx/sites-available/domain.com a hérité de nouvelles propriétés pour permettre l'utilisation du protocole HTTPS.

Félicitations 🎉

Vous pouvez dorénavant profiter de votre application depuis le protocole HTTPS.

Top comments (0)