Let’s Encrypt délivre plus de 10 millions de certificats TLS par jour. Pourtant, des milliers de serveurs Nginx tournent encore en HTTP simple, exposant les données de leurs visiteurs à des interceptions. Ce tutoriel vous guide de l’installation de Certbot jusqu’à un score A+ sur SSL Labs, en 12 étapes reproductibles sur Ubuntu 22.04 ou 24.04.

En juin 2026, Let’s Encrypt entre dans la phase d’opt-in pour des certificats de 45 jours (contre 90 actuellement), avec une généralisation prévue en février 2028. Un renouvellement automatique fiable n’a jamais été aussi indispensable.

Prérequis

Avant de commencer, assurez-vous de disposer de l’environnement suivant :

ComposantVersion minimaleRôle
Ubuntu22.04 LTS ou 24.04 LTSSystème d’exploitation du serveur
Nginx1.18 ou ultérieurServeur web à sécuriser
Certbot2.9 ou ultérieur (via snap)Client ACME pour Let’s Encrypt
SnapdInstallé et actifGestionnaire de paquets pour Certbot
Nom de domaineTout registrarDoit pointer vers l’IP publique du serveur
Ports ouverts80/TCP et 443/TCPValidation HTTP-01 et trafic HTTPS
Accès administrateursudo ou rootRequis pour Certbot et Nginx

Connaissances supposées : manipuler un terminal SSH, éditer des fichiers avec nano ou vim, comprendre les bases du DNS (enregistrement A, TTL).

Pourquoi HTTPS est obligatoire en 2026

Google Chrome affiche depuis 2018 l’avertissement “Non sécurisé” sur tous les sites HTTP. En 2026, cette politique est durcie : les navigateurs modernes bloquent par défaut les contenus mixtes (scripts et images chargés en HTTP depuis une page HTTPS) et certains d’entre eux affichent une page d’interstitielle sur les sites sans HTTPS avant même d’afficher le contenu. Les conséquences sont concrètes : perte de confiance des visiteurs, pénalité de référencement naturel et risques juridiques au regard du RGPD, qui exige la protection des données personnelles en transit.

TLS remplit quatre fonctions distinctes. L’authentification garantit que le serveur est bien celui qu’il prétend être, grâce au certificat signé par une autorité de confiance. La confidentialité chiffre les données échangées, les rendant illisibles pour un observateur tiers. L’intégrité détecte toute altération en transit via des codes d’authentification de message (MAC). La non-répudiation est assurée via les journaux de certification publics (Certificate Transparency), qui archuvent chaque certificat émis.

Let’s Encrypt, géré par l’Internet Security Research Group (ISRG), a franchi le cap du milliard de certificats émis depuis son lancement en 2015. Son modèle entièrement gratuit et automatisé repose sur le protocole ACME (Automatic Certificate Management Environment, RFC 8555). Le client officiel recommandé par l’EFF est Certbot, qui implémente ce protocole et s’intègre directement avec Nginx via un plugin dédié.

Étape 1 : Mettre à jour le système et installer Nginx

Commencez par mettre à jour la liste des paquets et installer Nginx. Cette étape est importante pour éviter les conflits de version lors de l’installation de Certbot.

sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx curl snapd

Vérifiez que Nginx est actif et configuré pour démarrer automatiquement :

sudo systemctl enable --now nginx
sudo systemctl status nginx

Résultat attendu :

● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
     Active: active (running) since Tue 2026-06-17 10:00:00 UTC; 5s ago

Testez l’accès HTTP depuis votre navigateur ou via curl :

curl -I http://monsite.com

Vous devez obtenir un code 200 OK. Si la réponse est un timeout ou une erreur de connexion, vérifiez que le DNS de votre domaine pointe bien vers l’adresse IP publique de votre serveur avant de continuer. La validation HTTP-01 de Let’s Encrypt échouera si ce n’est pas le cas, et vous risquez de consommer inutilement du quota d’émission.

Étape 2 : Configurer le pare-feu UFW

Let’s Encrypt doit atteindre votre serveur sur le port 80 pour valider la propriété du domaine via la méthode HTTP-01. Nginx doit également écouter sur le port 443 après l’obtention du certificat. UFW (Uncomplicated Firewall) propose des profils d’application prédéfinis pour Nginx, ce qui simplifie la configuration.

sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status

Résultat attendu :

Status: active

To                         Action      From
--                         ------      ----
Nginx Full                 ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere

Le profil “Nginx Full” ouvre les ports 80 (HTTP) et 443 (HTTPS). Si vous hébergez votre serveur chez un fournisseur cloud (AWS, GCP, Scaleway, OVH, Hetzner), pensez à ouvrir également ces ports dans le groupe de sécurité ou le pare-feu réseau du fournisseur. Les deux niveaux de filtrage, UFW et le pare-feu cloud, s’appliquent de façon indépendante et cumulative.

Avertissement : n’activez jamais UFW sans avoir préalablement autorisé OpenSSH (port 22). Activer UFW sans cette règle vous verrouillera hors du serveur si vous êtes connecté via SSH depuis une session non encore établie.

Étape 3 : Créer la configuration Nginx de base

Avant de demander un certificat, Certbot a besoin d’un bloc server Nginx fonctionnel avec le bon nom de domaine. Créez un fichier de configuration dédié :

sudo nano /etc/nginx/sites-available/monsite.com

Contenu minimal à coller dans le fichier :

server {
    listen 80;
    listen [::]:80;
    server_name monsite.com www.monsite.com;

    root /var/www/monsite.com/html;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }
}

Activez le site et rechargez Nginx :

sudo ln -s /etc/nginx/sites-available/monsite.com /etc/nginx/sites-enabled/
sudo mkdir -p /var/www/monsite.com/html
echo '<h1>Bienvenue</h1>' | sudo tee /var/www/monsite.com/html/index.html
sudo nginx -t && sudo systemctl reload nginx

La commande nginx -t teste la syntaxe de la configuration sans redémarrer le service. Adoptez cette habitude avant chaque rechargement. Si le test retourne une erreur, corrigez-la avant de continuer. Nginx ne rechargera pas une configuration syntaxiquement incorrecte, ce qui protège les sites déjà en production sur le même serveur.

Si vous utilisez Nginx comme reverse proxy devant une application Node.js ou Python, ajoutez maintenant une exception pour le chemin de validation Let’s Encrypt. Sans cette exception, le bloc location / qui proxifie le trafic interceptera les requêtes de validation HTTP-01 :

    location /.well-known/acme-challenge/ {
        root /var/www/html;
        allow all;
    }

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

Étape 4 : Installer Certbot via Snap

L’EFF recommande depuis 2020 d’installer Certbot via Snap plutôt que via le gestionnaire de paquets apt. Le paquet snap reçoit les mises à jour directement de l’équipe Certbot, indépendamment du cycle de publication d’Ubuntu. C’est particulièrement important en 2026, car la gestion des ACME Renewal Information (ARI) nécessite Certbot 4.1.0 ou ultérieur. ARI permet à Let’s Encrypt d’indiquer au client exactement quand renouveler un certificat, ce qui sera indispensable avec les certificats de 45 jours prévus à partir de mai 2026.

Si vous avez une ancienne installation Certbot via apt, supprimez-la d’abord pour éviter les conflits :

sudo apt remove certbot python3-certbot-nginx -y

Installez ensuite Certbot via Snap :

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Le flag --classic accorde à Certbot l’accès au système de fichiers complet, ce dont il a besoin pour modifier les fichiers de configuration Nginx et écrire les certificats dans /etc/letsencrypt/. Vérifiez la version installée :

certbot --version
snap list certbot

Le snap se met à jour automatiquement plusieurs fois par jour via le daemon snapd. Vous bénéficiez donc en permanence des dernières corrections de sécurité sans intervention manuelle, ce qui est un avantage majeur par rapport au paquet apt d’Ubuntu qui n’est mis à jour qu’à chaque nouvelle version LTS.

Étape 5 : Obtenir le certificat Let’s Encrypt

Certbot intègre un plugin Nginx qui modifie automatiquement la configuration du serveur pour activer HTTPS. C’est la méthode la plus directe pour la grande majorité des cas d’usage.

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

Certbot vous pose plusieurs questions interactives :

  1. Votre adresse email (pour les alertes d’expiration envoyées par Let’s Encrypt)
  2. Acceptation des conditions d’utilisation de Let’s Encrypt
  3. Partage optionnel de votre email avec l’EFF
  4. Si vous souhaitez rediriger automatiquement le trafic HTTP vers HTTPS (répondez oui)

Si la demande réussit, Certbot affiche le message de confirmation suivant :

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/monsite.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/monsite.com/privkey.pem
This certificate expires on 2026-09-15.

Deploying certificate
Successfully deployed certificate for monsite.com to /etc/nginx/sites-enabled/monsite.com
Congratulations! You have successfully enabled HTTPS on https://monsite.com

Les certificats sont stockés dans /etc/letsencrypt/live/votre-domaine/ et contiennent quatre fichiers : cert.pem (certificat du serveur seul), chain.pem (chaîne intermédiaire Let’s Encrypt), fullchain.pem (certificat + chaîne, utilisé dans Nginx), et privkey.pem (clé privée RSA ou ECDSA 256 bits). Ne partagez jamais le fichier privkey.pem et ne le copiez pas dans des dossiers accessibles au serveur web.

Pour tester sans consommer de quota de production, utilisez toujours l’environnement de staging lors des premières tentatives :

sudo certbot --nginx --staging -d monsite.com -d www.monsite.com

Étape 6 : Vérifier la configuration Nginx générée

Certbot modifie automatiquement votre fichier de configuration Nginx. Examinez le résultat pour comprendre ce qui a été ajouté :

sudo cat /etc/nginx/sites-enabled/monsite.com

La configuration générée ressemble à ceci :

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name monsite.com www.monsite.com;

    root /var/www/monsite.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    ssl_certificate /etc/letsencrypt/live/monsite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/monsite.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

server {
    listen 80;
    listen [::]:80;
    server_name monsite.com www.monsite.com;
    return 301 https://$host$request_uri;
}

Trois points méritent attention. Premièrement, le fichier /etc/letsencrypt/options-ssl-nginx.conf contient les paramètres TLS recommandés par Certbot. Il est mis à jour avec chaque renouvellement de snap. La directive include le charge dynamiquement, garantissant que votre serveur bénéficie des paramètres les plus récents sans intervention manuelle.

Deuxièmement, le second bloc server gère la redirection HTTP vers HTTPS via une réponse 301. Le code 301 (redirection permanente) est essentiel pour le SEO, car il indique aux moteurs de recherche que l’URL canonique est celle en HTTPS et qu’il faut transférer le jus de lien vers la nouvelle adresse.

Troisièmement, Certbot n’ajoute pas http2 au bloc listen par défaut. Nous l’ajouterons manuellement à l’étape suivante.

Étape 7 : Renforcer les protocoles TLS

La configuration par défaut de Certbot est fonctionnelle mais pas optimale pour un score A+ sur SSL Labs. Modifiez votre bloc server HTTPS pour ajouter les paramètres TLS stricts recommandés par Mozilla et l’ANSSI :

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name monsite.com www.monsite.com;

    ssl_certificate     /etc/letsencrypt/live/monsite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/monsite.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/monsite.com/chain.pem;

    # TLS 1.2 et 1.3 uniquement (TLS 1.0 et 1.1 désactivés)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    # Suites chiffrées modernes - ECDHE + AEAD uniquement
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';

    # Courbes elliptiques recommandées
    ssl_ecdh_curve X25519:secp384r1:prime256v1;

    root /var/www/monsite.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Quelques points techniques importants sur ces paramètres :

  • ssl_prefer_server_ciphers off : avec TLS 1.3, la sélection des suites chiffrées est gérée par le client. Mettre cette directive à off suit les recommandations Mozilla pour les profils “intermédiaire” et “moderne” de 2026. Cela permet aux clients d’utiliser ChaCha20-Poly1305 quand ils y sont optimisés (appareils mobiles sans accélération AES matérielle).
  • ssl_ecdh_curve X25519 : X25519 offre de meilleures performances que P-256 pour les échanges de clés ECDHE, avec une sécurité considérée équivalente. C’est la courbe recommandée en priorité par les guides de hardening TLS actuels.
  • http2 : HTTP/2 nécessite TLS pour fonctionner dans les navigateurs. Il apporte le multiplexage des requêtes, réduisant la latence de 20 à 50% pour les pages chargeant de nombreuses ressources.

Après chaque modification de configuration Nginx, testez puis rechargez :

sudo nginx -t && sudo systemctl reload nginx

Étape 8 : Activer l’OCSP Stapling et le cache de sessions SSL

L’OCSP Stapling (agrafage OCSP) permet au serveur de joindre une réponse de vérification du statut de révocation du certificat directement dans la poignée de main TLS. Sans cette fonctionnalité, chaque navigateur doit interroger le serveur OCSP de Let’s Encrypt lors de chaque nouvelle connexion, ajoutant une latence de 50 à 200ms selon la localisation géographique. Avec l’agrafage, le serveur pré-récupère cette réponse (valide 48h) et la fournit directement au client, éliminant ce délai.

Ajoutez ces directives dans votre bloc server HTTPS :

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 1.1.1.1 8.8.8.8 valid=300s;
    resolver_timeout 5s;

    # Cache de sessions SSL
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;

Explications des paramètres :

  • resolver : Nginx a besoin d’un résolveur DNS pour interroger le serveur OCSP de Let’s Encrypt. 1.1.1.1 (Cloudflare) et 8.8.8.8 (Google) sont les choix standards. Pour une meilleure confidentialité en contexte d’entreprise, utilisez le résolveur interne de votre fournisseur d’hébergement.
  • ssl_session_cache shared:SSL:50m : alloue 50 Mo de mémoire partagée entre les workers Nginx pour stocker les paramètres de session TLS. Chaque mégaoctet stocke environ 4 000 sessions, soit 200 000 sessions simultanées avec 50 Mo.
  • ssl_session_tickets off : les tickets de session TLS posent un problème de confidentialité persistante si la clé de chiffrement du ticket fuite. Les désactiver est recommandé par Mozilla pour toutes les configurations intermédiaires et modernes, sauf si vous avez mis en place une rotation de clés de ticket.

Rechargez Nginx après ces ajouts. Pour vérifier que l’OCSP Stapling fonctionne, attendez quelques minutes (Nginx doit d’abord récupérer la réponse OCSP), puis testez :

echo | openssl s_client -connect monsite.com:443 -status 2>/dev/null | grep -A 10 "OCSP response"

Résultat attendu si l’agrafage fonctionne :

OCSP response:
======================================
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
...

Étape 9 : Ajouter les en-têtes de sécurité HTTP

Les en-têtes HTTP de sécurité renforcent la protection côté navigateur. Ils sont indépendants de TLS mais font partie d’une configuration HTTPS complète et sont pris en compte par certains scanners de sécurité (Mozilla Observatory, SecurityHeaders.com). Ajoutez ces directives dans votre bloc server HTTPS :

    # HSTS : force HTTPS pendant 1 an
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Empêche le sniffing de type MIME
    add_header X-Content-Type-Options "nosniff" always;

    # Protection contre le clickjacking
    add_header X-Frame-Options "SAMEORIGIN" always;

    # Politique de référant pour la confidentialité
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Permissions des fonctionnalités navigateur
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

Détail des en-têtes les plus critiques :

  • Strict-Transport-Security (HSTS) : indique au navigateur de ne jamais contacter le domaine en HTTP, même si l’utilisateur tape manuellement http://. La valeur max-age=31536000 représente 365 jours. Avec includeSubDomains, cette règle s’applique à tous les sous-domaines. N’activez includeSubDomains que si tous vos sous-domaines disposent d’un certificat valide, car un sous-domaine sans HTTPS deviendrait inaccessible pour les visiteurs ayant mémorisé la règle HSTS.
  • X-Content-Type-Options: nosniff : empêche les navigateurs d’interpréter un fichier dans un type MIME différent de celui déclaré par le serveur, bloquant certaines attaques XSS basées sur l’upload de fichiers.
  • X-Frame-Options: SAMEORIGIN : bloque l’intégration de vos pages dans des iframes depuis des domaines tiers, contrant les attaques de clickjacking.

Étape 10 : Tester avec SSL Labs pour valider le score A+

SSL Labs de Qualys est la référence mondiale pour évaluer la qualité d’une configuration TLS. Rendez-vous sur ssllabs.com/ssltest, entrez votre domaine et attendez 60 à 90 secondes pour obtenir le rapport complet.

Critère SSL LabsExigence pour A+Ce que nous avons configuré
Protocoles supportésTLS 1.2 et TLS 1.3 uniquementssl_protocols TLSv1.2 TLSv1.3
HSTS activémax-age supérieur à 180 jours31 536 000 s (365 jours)
Forward SecrecyRequis sur tous navigateursECDHE sur toutes les suites
CertificatValide, chaîne complètefullchain.pem de Let’s Encrypt
Vulnérabilités connuesAucune (BEAST, POODLE, ROBOT)TLS 1.0 et 1.1 désactivés
Échange de clésScore supérieur à 90X25519, secp384r1
Algorithme de chiffrementScore supérieur à 90AEAD uniquement (GCM, CHACHA20)

Si SSL Labs retourne une note A mais pas A+, la cause la plus fréquente est l’absence ou la mauvaise valeur de HSTS. Vérifiez que l’en-tête est envoyé avec la bonne valeur :

curl -I https://monsite.com | grep -i strict

Résultat attendu :

strict-transport-security: max-age=31536000; includeSubDomains

Si la ligne est absente, le problème vient presque toujours de l’absence du mot-clé always dans la directive add_header. Sans always, Nginx n’envoie l’en-tête HSTS que sur les réponses 200, mais pas sur les redirections 301 qui constituent l’essentiel du trafic HTTP vers HTTPS.

Étape 11 : Automatiser le renouvellement des certificats

Les certificats Let’s Encrypt expirent après 90 jours (avec une transition vers 45 jours prévue en 2028). Certbot installe automatiquement un timer systemd qui tente le renouvellement deux fois par jour. Vérifiez que ce mécanisme est bien actif :

sudo systemctl status snap.certbot.renew.timer
sudo certbot renew --dry-run

Résultat attendu d’un dry-run réussi :

Simulating renewal of an existing certificate for monsite.com and www.monsite.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/monsite.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Certbot tente le renouvellement 30 jours avant l’expiration. Cette fenêtre vous laisse le temps de réagir si le renouvellement automatique rencontre un problème. Let’s Encrypt envoie également des alertes par email 20 jours, puis 10 jours avant l’expiration, à l’adresse fournie lors de l’inscription.

Ajoutez un hook de déploiement pour recharger Nginx automatiquement après chaque renouvellement réussi. Sans ce hook, Nginx continue de servir l’ancien certificat jusqu’au prochain rechargement manuel :

sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh << 'EOF'
#!/bin/bash
systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Consultez les journaux de renouvellement pour diagnostiquer les problèmes :

sudo journalctl -u snap.certbot.renew.service --since "7 days ago" --no-pager

Étape 12 : Certificats wildcard avec validation DNS

Un certificat wildcard couvre tous les sous-domaines d’un niveau (*.monsite.com). Il est utile quand vous gérez plusieurs sous-domaines (blog, api, admin, staging) avec le même certificat. La validation HTTP-01 ne suffit pas pour les wildcards : Let’s Encrypt exige la validation DNS-01, qui prouve le contrôle de la zone DNS du domaine.

Pour Cloudflare, installez d’abord le plugin DNS :

sudo snap install certbot-dns-cloudflare

Créez le fichier de configuration avec votre token API Cloudflare :

sudo tee /etc/letsencrypt/cloudflare.ini << 'EOF'
dns_cloudflare_api_token = VOTRE_TOKEN_API_CLOUDFLARE
EOF
sudo chmod 600 /etc/letsencrypt/cloudflare.ini

Demandez un certificat wildcard :

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
  -d "monsite.com" \
  -d "*.monsite.com"

Le renouvellement automatique fonctionne de la même façon que pour les certificats standards. Certbot met à jour l’enregistrement DNS TXT _acme-challenge.monsite.com via l’API Cloudflare à chaque renouvellement. Configurez le TTL de cet enregistrement à 60 secondes ou moins pour une propagation DNS rapide. Des plugins équivalents existent pour OVH (certbot-dns-ovh), Gandi (certbot-dns-gandi) et AWS Route 53 (certbot-dns-route53).

Limites de débit Let’s Encrypt à connaître

Let’s Encrypt impose des limites strictes pour prévenir les abus. Les connaître vous évitera des blocages imprévus en production.

LimiteValeurFenêtreRemarque
Certificats par domaine enregistré507 jours glissantsEx. : 50 certs pour *.monsite.com
Certificats pour un jeu de domaines identique57 jours glissantsLa révocation ne réinitialise pas ce compteur
Nouvelles commandes par compte3003 heuresEndpoint /acme/new-order
Comptes par adresse IP103 heuresLimité par IP source
Requêtes renewal-info1 000Fenêtre glissanteEndpoint ARI
Domaines par certificat SAN100N/AUn seul certificat peut couvrir 100 domaines

Consultez la page officielle des limites Let’s Encrypt pour les valeurs à jour, notamment si vous gérez des environnements multi-tenant ou des déploiements automatisés à grande échelle.

7 pièges courants et comment les éviter

Piège 1 : DNS pas encore propagé. Lancer Certbot avant que le DNS de votre domaine pointe vers le serveur est l’erreur numéro un. La validation HTTP-01 de Let’s Encrypt doit pouvoir atteindre votre serveur depuis Internet. Vérifiez la propagation avec dig monsite.com +short avant de lancer Certbot. Si l’IP affichée n’est pas celle de votre serveur, attendez que le TTL expire.

Piège 2 : Coexistence de l’ancienne installation apt et du nouveau snap. Ubuntu installe parfois python3-certbot-nginx via des dépendances. La coexistence des deux versions provoque des comportements imprévisibles. Vérifiez avec which certbot que le binaire pointe vers /snap/bin/certbot. Si ce n’est pas le cas, supprimez le paquet apt et reliez le symlink.

Piège 3 : Activer HSTS avec includeSubDomains prématurément. Si un sous-domaine ne dispose pas d’un certificat HTTPS valide, les navigateurs qui ont mémorisé la règle HSTS rendront ce sous-domaine totalement inaccessible jusqu’à l’expiration du max-age. Testez d’abord sans includeSubDomains, et ajoutez cette directive uniquement quand tous vos sous-domaines sont couverts.

Piège 4 : Oublier le hook de rechargement Nginx. Après un renouvellement, Nginx continue de servir l’ancien certificat jusqu’au prochain redémarrage. Sans le hook dans /etc/letsencrypt/renewal-hooks/deploy/, votre site affichera un certificat expiré à 90 jours précis, en pleine nuit, sans que vous l’ayez anticipé.

Piège 5 : Tester avec le domaine de production sans passer par le staging. Cinq demandes de certificat identiques échouées en 7 jours déclenchent un blocage de 7 jours. Utilisez toujours le flag --staging pour les premières tentatives, puis supprimez le certificat de staging (sudo certbot delete --cert-name monsite.com) avant d’émettre le certificat de production.

Piège 6 : add_header sans le mot-clé always. En Nginx, la directive add_header sans always n’envoie l’en-tête que sur les réponses de code 200, 201, 204, 206, 301, 302, 303, 304, 307 et 308. Mais si vous avez un bloc location enfant qui définit ses propres add_header, les en-têtes du bloc parent sont complètement écrasés pour ce contexte. La solution : regroupez tous vos en-têtes de sécurité dans un fichier séparé (/etc/nginx/security-headers.conf) et incluez-le dans chaque bloc location qui en a besoin.

Piège 7 : Chemin de challenge ACME inaccessible derrière un reverse proxy. Si Nginx proxifie vers une application backend, le bloc location / intercepte les requêtes ACME de validation HTTP-01 avant qu’elles n’atteignent le répertoire de challenge. Ajoutez toujours une exception explicite avant le bloc de proxy :

    location /.well-known/acme-challenge/ {
        root /var/www/html;
        allow all;
    }

    location / {
        proxy_pass http://localhost:3000;
    }

Dépannage : 8 erreurs fréquentes et leurs solutions

Erreur “Connection refused” lors de la validation HTTP-01

Let’s Encrypt ne peut pas joindre votre serveur sur le port 80. Vérifiez dans cet ordre : UFW autorise le port 80 (sudo ufw status), Nginx est lancé (sudo systemctl status nginx), aucune règle de pare-feu externe ne bloque le port 80. Testez depuis une machine externe avec curl -v http://monsite.com/.well-known/acme-challenge/test.

Erreur “too many certificates already issued”

Vous avez atteint la limite de 5 certificats identiques en 7 jours. La seule solution est d’attendre la fin de la fenêtre glissante. Pour débloquer la situation, vous pouvez ajouter ou supprimer un domaine du jeu de SANs pour créer un nouveau jeu unique. Pour l’avenir, utilisez systématiquement --staging pour tester.

Erreur “nginx: [emerg] unknown directive ssl_stapling”

Nginx a été compilé sans le module SSL. Vérifiez avec nginx -V 2>&1 | grep with-http_ssl_module. Le paquet Nginx standard d’Ubuntu inclut ce module. Si vous avez compilé Nginx manuellement depuis les sources, recompilez avec les flags --with-http_ssl_module --with-http_v2_module --with-http_stub_status_module.

OCSP Stapling retourne “no response sent”

Deux causes fréquentes. Première : Nginx n’a pas encore récupéré la réponse OCSP (attendez 5 minutes après le rechargement). Deuxième : la directive ssl_trusted_certificate pointe vers fullchain.pem au lieu de chain.pem. La vérification de la chaîne OCSP nécessite la chaîne intermédiaire seule, sans le certificat du serveur.

SSL Labs retourne “B” à cause de TLS 1.0 ou 1.1

Votre configuration inclut encore des protocoles obsolètes. Vérifiez le contenu de /etc/letsencrypt/options-ssl-nginx.conf pour détecter une ancienne version. Mettez à jour Certbot (sudo snap refresh certbot) et rechargez Nginx. Si le problème persiste, votre directive ssl_protocols personnalisée écrase peut-être celle du fichier include.

Le renouvellement automatique échoue silencieusement

Consultez les journaux du service de renouvellement :

sudo journalctl -u snap.certbot.renew.service --since "30 days ago" --no-pager
sudo journalctl -u snap.certbot.renew.timer

Une erreur de permission indique souvent que le hook de rechargement Nginx n’est pas exécutable (chmod +x manquant). Une erreur de connexion indique un problème réseau intermittent ou un pare-feu bloquant l’accès Let’s Encrypt.

Erreur “Snap store cannot be reached” lors de l’installation

Certains VPS ou environnements réseau restreignent l’accès au snap store. Diagnostiquez avec curl -v https://api.snapcraft.io/api/v1/. Si votre serveur est derrière un proxy, configurez les variables d’environnement dans /etc/environment : https_proxy=http://proxy.exemple.com:3128. Alternative si le snap reste inaccessible : pip (pip3 install certbot certbot-nginx).

Erreur “certificate verify failed” lors du renouvellement

Erreur fréquente lors de la mise à jour de la chaîne de certification intermédiaire de Let’s Encrypt. Let’s Encrypt a modifié sa chaîne intermédiaire en 2021 (fin du cross-sign avec IdenTrust). Si votre serveur utilise encore l’ancien certificat racine, mettez à jour les certificats CA du système : sudo update-ca-certificates. Vérifiez également que ssl_trusted_certificate pointe vers le bon fichier chain.pem.

TLS 1.2 vs TLS 1.3 : ce qui change concrètement

CritèreTLS 1.2TLS 1.3
Tours de poignée de main (RTT)2 RTT pour une nouvelle connexion1 RTT (0-RTT en reprise de session)
Algorithmes d’échange de clésRSA, DH, ECDHE au choix du serveurECDHE uniquement (perfect forward secrecy garantie)
Chiffrement du handshakeCertificat visible en clairChiffré après ServerHello (Encrypted Client Hello en cours)
Nombre de suites chiffréesDes dizaines, dont des suites faibles5 suites AEAD uniquement (AES-GCM, ChaCha20)
Compatibilité navigateurs100% (IE 11 inclus)Plus de 97% des navigateurs modernes
Recommandation ANSSI 2026Autorisé (profil intermédiaire)Recommandé (profil moderne)

En pratique, activer les deux protocoles (ssl_protocols TLSv1.2 TLSv1.3) est le bon compromis pour 2026. TLS 1.3 sera négocié avec les navigateurs modernes. TLS 1.2 assure la compatibilité avec des clients plus anciens, notamment certains appareils Android sous des versions datant d’avant 2016, des bibliothèques HTTP d’entreprise vieillissantes ou des équipements IoT industriels.

L’ANSSI publie des recommandations TLS détaillant les profils de sécurité selon le contexte. Pour un serveur web public, le profil “intermédiaire” (TLS 1.2 + 1.3, suites ECDHE-AEAD) est adapté. Le profil “strict” (TLS 1.3 uniquement) est recommandé pour les applications traitant des données de santé, financières ou gouvernementales. Le générateur de configuration Mozilla produit des exemples de configuration Nginx pour ces deux profils, en sélectionnant automatiquement les paramètres adaptés à la version de Nginx détectée.

Conseils avancés

Surveillance proactive de l’expiration des certificats

Le renouvellement automatique peut échouer pendant des semaines sans alerter l’administrateur. Mettez en place une vérification active depuis un serveur de monitoring externe. Ce script vérifie la date d’expiration du certificat en production et alerte si elle est inférieure à 30 jours :

#!/bin/bash
DOMAIN="monsite.com"
JOURS_ALERTE=30
expiry=$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null \
  | openssl x509 -noout -enddate | cut -d= -f2)
expiry_epoch=$(date -d "$expiry" +%s)
now_epoch=$(date +%s)
jours_restants=$(( (expiry_epoch - now_epoch) / 86400 ))
if [ $jours_restants -lt $JOURS_ALERTE ]; then
  echo "ALERTE : certificat $DOMAIN expire dans $jours_restants jours"
  exit 1
fi
echo "OK : certificat $DOMAIN expire dans $jours_restants jours"

Intégrez ce script à cron avec une exécution quotidienne, ou connectez-le à votre système de monitoring (Zabbix, Nagios, Prometheus avec le module ssl_exporter).

Gérer plusieurs sites sur le même serveur

Certbot peut gérer plusieurs certificats indépendants sur un seul serveur. Chaque domaine possède son propre répertoire dans /etc/letsencrypt/live/. Listez tous les certificats gérés avec sudo certbot certificates. Pour ajouter un domaine à un certificat existant, utilisez le flag --expand. Pour révoquer et supprimer un certificat qui n’est plus nécessaire : sudo certbot revoke --cert-name monanciendomaine.com && sudo certbot delete --cert-name monanciendomaine.com.

Couverture associée

FAQ

Les certificats Let’s Encrypt sont-ils vraiment fiables pour la production ?

Oui. Let’s Encrypt est une autorité de certification publique reconnue par tous les navigateurs majeurs (Chrome, Firefox, Safari, Edge). Elle est gérée par l’Internet Security Research Group (ISRG), une organisation à but non lucratif soutenue par Mozilla, Google, Cisco et l’EFF. Les certificats DV (Domain Validation) de Let’s Encrypt sont techniquement identiques à ceux vendus par Comodo ou DigiCert. La seule différence réside dans le niveau de validation : DV prouve uniquement le contrôle du domaine, OV valide l’organisation, EV valide l’organisation de façon étendue. Pour un blog, une boutique en ligne ou une API, DV est suffisant.

Quelle est la différence entre certbot –nginx et certbot certonly ?

certbot --nginx obtient le certificat ET modifie automatiquement la configuration Nginx pour activer HTTPS. C’est la méthode recommandée pour les débutants. certbot certonly obtient uniquement le certificat sans toucher à la configuration Nginx : vous devez ensuite modifier manuellement votre bloc server pour pointer vers fullchain.pem et privkey.pem. Cette deuxième méthode est préférable quand vous gérez la configuration Nginx via Ansible, Puppet ou Terraform, afin d’éviter que Certbot n’écrase vos fichiers gérés par votre outil d’automatisation.

Pourquoi mon score SSL Labs est A et non A+ ?

La note A+ nécessite HSTS avec un max-age d’au moins 180 jours (15 552 000 secondes). Vérifiez avec curl -I https://monsite.com | grep strict que l’en-tête est présent. Si absent, vérifiez que le mot-clé always figure dans votre directive add_header. S’il est présent mais avec une valeur trop faible, augmentez le max-age à 31536000 (1 an) et rechargez Nginx.

Que se passe-t-il si le certificat expire ?

Dès l’expiration, les navigateurs affichent l’erreur bloquante “NET::ERR_CERT_DATE_INVALID” et les visiteurs ne peuvent plus accéder au site sans contourner manuellement l’avertissement de sécurité. Pour les API HTTPS, les clients reçoivent une erreur TLS et toutes les requêtes échouent. Pour renouveler manuellement un certificat expiré, lancez sudo certbot renew --force-renewal puis rechargez Nginx.

Let’s Encrypt fonctionne-t-il avec des protocoles non-HTTP (MQTT, gRPC, IMAP) ?

Oui. Let’s Encrypt émet des certificats X.509 standards qui fonctionnent avec n’importe quel protocole basé sur TLS : HTTPS, SMTPS, IMAPS, MQTTS, WebSockets sécurisés (WSS), gRPC-TLS. La validation du domaine se fait via HTTP ou DNS, mais le certificat émis n’est pas limité à un usage web. Pour des services non-HTTP, obtenez le certificat avec certbot certonly et configurez manuellement le démon concerné pour pointer vers les fichiers de certificat dans /etc/letsencrypt/live/.

Quelle est la transition vers les certificats de 45 jours ?

Let’s Encrypt a annoncé un calendrier de réduction progressive de la durée de vie des certificats. En mai 2026, une phase d’opt-in permet aux early adopters d’obtenir des certificats de 45 jours. En février 2027, la durée passe à 64 jours pour tous. En février 2028, la durée finale de 45 jours sera généralisée. Cette évolution renforce la sécurité (un certificat compromis expire plus vite) mais exige un renouvellement automatique parfaitement fiable. Certbot 4.1.0 ou ultérieur prend en charge les ACME Renewal Information (ARI), permettant à Let’s Encrypt de recommander exactement quand renouveler.

Comment tester la configuration Nginx sans rechargement en production ?

Utilisez toujours sudo nginx -t avant tout rechargement. Cette commande teste la syntaxe et la cohérence de la configuration complète (fichier principal + includes) sans perturber le serveur en cours d’exécution. En cas d’erreur, Nginx affiche le fichier et le numéro de ligne concernés. Pour tester une nouvelle configuration sur un port différent avant de basculer, utilisez nginx -c /chemin/vers/nginx-test.conf -t.

Pour approfondir, consultez les instructions officielles Certbot pour Ubuntu et Nginx, le générateur de configuration SSL Mozilla et les limites de débit Let’s Encrypt.