Aller au contenu principal
Accueil AngleFormation - Experts IA et Automatisation
Automatiser Votre Croissance
Tech-Cloud

Certificat SSL/TLS pour Node.js, Docker et VPS : guide 2026

2026-08-21 Par Jallal Tahiri
Illustration : Certificat SSL/TLS pour Node.js, Docker et VPS : guide 2026

💡 En résumé (TL;DR)

  • On parle encore de « certificat SSL », mais le protocole moderne est TLS. Le certificat relie un nom de domaine à une clé publique et permet au client de vérifier le serveur.
  • Pour une application Node.js sur VPS, la solution la plus simple est généralement de terminer TLS dans un reverse proxy comme Caddy, puis de joindre Node.js sur une interface privée.
  • Let's Encrypt valide le contrôle du domaine via ACME. HTTP-01 exige que le domaine atteigne le serveur ; DNS-01 publie un TXT et permet les certificats wildcard.
  • Le renouvellement doit être automatique et surveillé. Tester seulement l'émission initiale ne suffit pas.
  • Le verdict AngleFormation : gardez Node.js non exposé, utilisez un proxy maintenu, faites confiance uniquement aux bons en-têtes proxy et vérifiez HTTPS depuis l'extérieur.

Un certificat expiré rend un site inaccessible ou déclenche un avertissement. Un proxy mal configuré peut provoquer des boucles de redirection, des cookies non sécurisés ou une fausse adresse client. Mettre HTTPS en production demande donc plus que l'obtention d'un fichier.

Ce guide présente une architecture simple pour un site Node.js ou Express déployé en Docker sur un VPS.


SSL, TLS, HTTPS et ACME

Terme Rôle
TLS protocole de chiffrement et d'authentification
HTTPS HTTP transporté dans TLS
Certificat associe identité, clé publique, domaines et validité
ACME protocole d'automatisation de l'émission et du renouvellement
Let's Encrypt autorité de certification publique utilisant ACME
Reverse proxy reçoit le trafic puis le transmet à l'application

SNI permet à plusieurs domaines d'utiliser la même adresse avec des certificats différents. ALPN aide le client et le serveur à négocier le protocole, par exemple HTTP/2. Node.js documente ces fonctions dans son module TLS.


Étape 1 — Vérifier DNS et réseau

Avant toute émission :

  • le domaine A ou AAAA doit pointer vers le bon serveur ;
  • l'IPv6 publiée doit fonctionner ;
  • les ports 80 et 443 doivent atteindre le proxy ;
  • aucun autre service ne doit occuper ces ports ;
  • le pare-feu de l'hébergeur et celui du VPS doivent les autoriser ;
  • l'heure du serveur doit être correcte.

Vérifications :

dig A app.exemple.fr
dig AAAA app.exemple.fr
curl -I http://app.exemple.fr/
ss -lntp

Pour HTTP-01, Let's Encrypt recommande de laisser le port 80 accessible et de rediriger les requêtes ordinaires vers HTTPS. Si le site ne peut pas exposer le port 80 ou nécessite un wildcard, utilisez DNS-01 avec une automatisation DNS sécurisée.


Étape 2 — Choisir où terminer TLS

Option recommandée : reverse proxy

Le proxy :

  • écoute sur 80 et 443 ;
  • obtient et renouvelle les certificats ;
  • redirige HTTP vers HTTPS ;
  • applique les en-têtes ;
  • transmet vers Node.js en privé.

Node.js peut aussi servir directement HTTPS avec le module node:https, mais l'application doit alors charger les clés, gérer le rechargement et les renouvellements. Pour plusieurs services, le proxy central est souvent plus simple.


Étape 3 — Déployer Node.js sans exposition publique

Compose minimal :

services:
  app:
    build: .
    restart: unless-stopped
    environment:
      NODE_ENV: production
      PORT: "3000"
    ports:
      - "127.0.0.1:3000:3000"

Le port écoute seulement sur la boucle locale de l'hôte. Si Caddy est lui-même dans Docker, n'utilisez pas localhost pour joindre un autre conteneur : Caddy rappelle que localhost désigne son propre conteneur. Placez les services sur un réseau Docker et utilisez le nom du service.


Étape 4 — Configurer Caddy

Sur l'hôte :

app.exemple.fr {
    encode zstd gzip
    reverse_proxy 127.0.0.1:3000
}

Avec un nom public valide, Caddy active automatiquement HTTPS, obtient un certificat et gère son renouvellement. Il redirige aussi HTTP vers HTTPS selon ses valeurs par défaut.

Avant le rechargement :

caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
sudo journalctl -u caddy --since "10 minutes ago"

Les commandes supposent une installation système Caddy. Utilisez les chemins et droits de votre environnement.

Caddy et Docker sur le même réseau

services:
  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    networks: [web]

  app:
    build: .
    restart: unless-stopped
    expose:
      - "3000"
    networks: [web]

volumes:
  caddy_data:
  caddy_config:

networks:
  web:

Caddyfile :

app.exemple.fr {
    reverse_proxy app:3000
}

Les volumes Caddy doivent être persistants. Ne supprimez pas leur contenu pendant une mise à jour ordinaire.


Étape 5 — Configurer Express derrière le proxy

Express utilise trust proxy pour interpréter l'adresse client et le protocole transmis. La documentation avertit que la valeur true est dangereuse si le dernier proxy ne remplace pas correctement les en-têtes.

Si le proxy est local :

import express from "express";

const app = express();
app.set("trust proxy", "loopback");

app.get("/health", (req, res) => {
  res.json({
    ok: true,
    protocol: req.protocol
  });
});

app.listen(3000, "0.0.0.0");

Adaptez la liste de confiance à votre topologie exacte. S'il existe plusieurs chemins réseau, une simple profondeur en nombre de sauts peut être contournée.

Cookies

En production :

  • Secure pour envoyer uniquement sur HTTPS ;
  • HttpOnly pour réduire l'accès JavaScript ;
  • SameSite selon le flux d'authentification ;
  • domaine et chemin minimaux ;
  • rotation de session.

Le proxy de confiance doit être correct pour qu'Express reconnaisse HTTPS et applique les cookies comme prévu.


Étape 6 — Choisir le défi ACME

Défi Fonctionnement À choisir quand
HTTP-01 fichier temporaire servi sur HTTP site public simple, port 80 accessible
DNS-01 TXT sous _acme-challenge wildcard, serveurs multiples, port 80 indisponible

DNS-01 demande des droits sur la zone DNS. Créez un jeton limité à la zone et aux opérations nécessaires. Ne donnez pas une clé globale au serveur si le fournisseur permet une portée plus restreinte.

Pour de nombreux frontends, Let's Encrypt explique que DNS-01 peut être plus facile, mais la propagation du TXT doit être prise en compte.


Étape 7 — Tester HTTPS

Depuis une autre machine :

curl -I http://app.exemple.fr/
curl -I https://app.exemple.fr/
openssl s_client -connect app.exemple.fr:443 -servername app.exemple.fr </dev/null

Vérifiez :

  • redirection HTTP vers HTTPS ;
  • nom de domaine présent dans le certificat ;
  • chaîne de certification ;
  • dates de validité ;
  • aucun contenu mixte ;
  • cookie Secure ;
  • bonnes URL canoniques ;
  • absence de boucle ;
  • WebSocket si l'application l'utilise.

Testez depuis Internet et pas uniquement depuis le VPS.


Renouvellement et supervision

Un client ACME fiable renouvelle avant expiration. Ajoutez une alerte indépendante qui vérifie :

  • jours restants ;
  • statut HTTPS ;
  • nom couvert ;
  • erreurs du proxy ;
  • échec répété de validation ;
  • espace disque du volume de certificats.

Évitez de redemander sans cesse un nouveau certificat lors d'un test : Let's Encrypt applique des limites. Utilisez l'environnement de staging pour les essais de configuration et lisez les limites actuelles.

Ne dépendez pas d'une durée fixe dans vos procédures. Let's Encrypt propose plusieurs profils de durée et fait évoluer son infrastructure ; l'automatisation et la surveillance sont la bonne réponse.


Cas Cloudflare ou autre CDN

Lorsqu'un CDN se place devant le VPS, deux connexions existent :

  1. navigateur vers CDN ;
  2. CDN vers origine.

Chiffrez les deux. Évitez un mode qui accepte HTTP non authentifié vers l'origine. Limitez l'accès direct au VPS si possible, mais assurez-vous que le mécanisme ACME choisi continue de fonctionner.

Le certificat vu par le navigateur peut être celui du CDN, tandis que l'origine possède un certificat distinct.


En-têtes de sécurité

Le proxy ou l'application peut ajouter :

  • HSTS après validation complète de HTTPS ;
  • Content-Security-Policy adaptée au site ;
  • X-Content-Type-Options ;
  • Referrer-Policy ;
  • Permissions-Policy.

N'activez pas HSTS avec une longue durée ou includeSubDomains avant de confirmer que tous les sous-domaines fonctionnent en HTTPS. Une erreur HSTS peut bloquer l'accès durablement côté navigateur.


Diagnostic des erreurs

Validation ACME échoue

  • DNS pointe vers l'ancienne IP ;
  • IPv6 incorrecte ;
  • port 80 bloqué ;
  • proxy non démarré ;
  • WAF intercepte le challenge ;
  • TXT DNS-01 non propagé ;
  • limite d'émission atteinte.

Boucle de redirection

  • l'application ne fait pas confiance au bon proxy ;
  • le proxy transmet un protocole incorrect ;
  • plusieurs couches redirigent contradictoirement ;
  • une variable d'URL publique est en HTTP.

Mauvaise IP client

  • trust proxy absent ou trop large ;
  • en-tête transmis sans être nettoyé ;
  • proxy supplémentaire non documenté.

Certificat expiré

  • tâche de renouvellement arrêtée ;
  • volume non persistant ;
  • changement DNS ;
  • permissions ;
  • client ACME ou proxy obsolète.

Checklist de production

  • A/AAAA corrects ;
  • ports 80/443 maîtrisés ;
  • application non exposée publiquement ;
  • proxy et images épinglés ;
  • certificat valide ;
  • renouvellement automatique ;
  • alerte avant expiration ;
  • proxy de confiance précis ;
  • cookies sécurisés ;
  • HSTS activé seulement après validation ;
  • sauvegarde de configuration ;
  • procédure de rollback ;
  • test après chaque changement DNS ou proxy.

FAQ

Let's Encrypt est-il gratuit ?

Oui pour l'émission publique, mais l'exploitation du serveur et l'automatisation restent à votre charge. Respectez ses limites et utilisez un client ACME maintenu.

Faut-il copier le certificat dans le conteneur Node.js ?

Pas si le reverse proxy termine TLS et joint Node.js sur un réseau privé. Cette architecture simplifie les renouvellements et évite de partager la clé avec l'application.

Comment obtenir un wildcard ?

Let's Encrypt exige le défi DNS-01 pour un wildcard. Automatisez la création du TXT avec un jeton DNS limité.

Peut-on fermer le port 80 après émission ?

Si vous utilisez HTTP-01, il reste nécessaire pour les validations et renouvellements. Let's Encrypt recommande de garder 80 ouvert pour le web et de rediriger vers HTTPS. DNS-01 suit une autre logique.

Conclusion

Le meilleur certificat est celui dont l'émission, le renouvellement et le diagnostic sont automatisés. Pour Node.js et Docker, un reverse proxy comme Caddy réduit la complexité : l'application reste privée, le proxy gère TLS et la configuration Express reflète précisément la topologie.

Pour choisir l'hébergement, consultez notre comparatif de VPS backend et notre pilier Tech-Cloud.

Sources officielles consultées le 21 août 2026

JT
Cet article d'ingénierie a été rédigé par Jallal TAHIRI, consultant expert en architectures cloud, IA agentique et automatisation des processus B2B pour PME.