Sécuriser Nginx avec HTTPS : Un guide étape par étape

Apprenez à sécuriser votre serveur web Nginx avec HTTPS dans ce guide complet étape par étape. Nous couvrons l'obtention de certificats SSL/TLS gratuits de Let's Encrypt avec Certbot, la configuration de Nginx pour des connexions chiffrées et la mise en œuvre de mesures de sécurité essentielles comme HSTS. Protégez vos données, gagnez la confiance des utilisateurs et améliorez votre référencement avec une configuration HTTPS correcte.

Sécuriser Nginx avec HTTPS : Un guide étape par étape

Sécuriser Nginx avec HTTPS est généralement une tâche mineure, mais c'est l'un de ces travaux où les petites erreurs sont bruyantes. Un fichier de certificat manquant empêche Nginx de redémarrer. Une règle de pare-feu oubliée donne l'impression que le site est hors ligne. Un en-tête HSTS précipité peut enfermer les utilisateurs dans une configuration HTTPS défaillante plus longtemps que prévu.

La bonne nouvelle, c'est que le chemin normal est simple. Vous pointez le DNS vers le serveur, vous vous assurez que Nginx répond sur le port 80, vous utilisez Certbot pour demander un certificat Let's Encrypt, vous testez la configuration Nginx générée, vous rechargez, puis vous vérifiez le renouvellement. C'est le chemin que suit ce guide.

J'utiliserai example.com et www.example.com ci-dessous. Remplacez-les par vos vrais noms, et ne sautez pas les vérifications avant de recharger Nginx.

Avant de demander un certificat

Avant de toucher à Certbot, confirmez les éléments ennuyeux. La plupart des problèmes de certificat proviennent du DNS, des pare-feu ou d'un bloc serveur qui ne répond pas pour le domaine demandé.

Vérifiez le DNS depuis un endroit extérieur au serveur :

dig +short example.com
dig +short www.example.com

Les deux noms doivent résoudre l'adresse publique qui atteint votre hôte Nginx ou votre équilibreur de charge.

Assurez-vous que les ports 80 et 443 sont ouverts à chaque couche : groupe de sécurité cloud, pare-feu hôte, pare-feu réseau et tout équilibreur de charge devant l'hôte.

sudo ss -tulnp | grep nginx
sudo ufw status

Sur une VM cloud, vérifiez également la console du fournisseur. J'ai vu beaucoup de configurations Nginx propres échouer parce que le pare-feu de l'instance autorisait le 443 mais que le groupe de sécurité cloud le bloquait toujours.

Enfin, confirmez que Nginx sert déjà le domaine en HTTP simple :

curl -I http://example.com
curl -I http://www.example.com

La réponse n'a pas besoin d'être jolie. Cela peut être une page d'espace réservé. Il faut juste prouver que les requêtes pour ce nom d'hôte arrivent sur ce serveur Nginx.

Installer Certbot

Pour Debian/Ubuntu :

sudo apt update
sudo apt install certbot python3-certbot-nginx

Pour les systèmes compatibles RHEL :

sudo dnf install certbot python3-certbot-nginx

Les systèmes CentOS plus anciens peuvent utiliser yum et peuvent avoir besoin d'activer EPEL d'abord. Les noms de paquets varient également selon la version de la distribution, alors utilisez la documentation des paquets de votre distribution si ces commandes ne trouvent pas le plugin.

Demander le certificat

Le plugin Nginx peut demander le certificat et modifier le bloc serveur correspondant :

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

Certbot demandera une adresse e-mail, l'accord des conditions, et parfois s'il faut rediriger HTTP vers HTTPS. Pour un site web public normal, choisissez la redirection. Pour une API ou un service interne, vérifiez d'abord les clients. Certains clients plus anciens ou vérifications de santé peuvent encore appeler http:// et attendre une réponse spécifique.

Si Certbot dit qu'il ne trouve pas de bloc serveur correspondant, vérifiez server_name. Un bloc comme celui-ci donne à Certbot quelque chose de clair avec quoi travailler :

server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/example.com/public;
    index index.html;

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

Exécutez une vérification de syntaxe avant de demander à Certbot de modifier quoi que ce soit :

sudo nginx -t

Si la configuration actuelle est déjà cassée, corrigez-la d'abord.

À quoi devrait ressembler la configuration Nginx

Après une exécution réussie, vous verrez généralement un bloc HTTP qui redirige et un bloc HTTPS qui sert le site :

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

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    root /var/www/example.com/public;
    index index.html;

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

Ne copiez pas cela aveuglément sur une configuration de production. Préservez vos règles location existantes, paramètres de proxy, journaux et limites de téléchargement. Les parties importantes sont le listen 443 ssl, les chemins des certificats et le comportement de redirection sur le port 80.

Tester, recharger et vérifier

Testez toujours avant de recharger :

sudo nginx -t

Puis rechargez :

sudo systemctl reload nginx

Vérifiez depuis la ligne de commande :

curl -I http://example.com
curl -I https://example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates

La requête HTTP doit rediriger si vous avez choisi cette option. La requête HTTPS doit renvoyer le statut attendu. La commande openssl doit afficher un certificat dont le sujet ou les noms alternatifs du sujet couvrent le domaine et dont les dates sont actuelles.

Les tests dans le navigateur comptent toujours. Ouvrez le site dans une fenêtre privée et cliquez sur l'icône du cadenas pour inspecter le certificat. Si votre site charge des actifs depuis d'anciennes URL http://, la page peut afficher des avertissements de contenu mixte même si le certificat principal est correct. Corrigez ces URL d'actifs dans l'application, le CMS ou la couche de template.

Renouvellement

Les certificats Let's Encrypt ont une durée de vie courte, donc le renouvellement doit fonctionner sans que vous ayez à vous en souvenir. Certbot installe normalement une minuterie systemd ou une tâche cron. Vérifiez-la :

systemctl list-timers | grep certbot
sudo certbot renew --dry-run

L'exécution à sec est la partie utile. Elle effectue une simulation de renouvellement et détecte les problèmes courants tels que la validation HTTP cassée, les modifications DNS, les plugins manquants ou une configuration qui ne peut pas être rechargée.

Si vous terminez TLS au niveau d'un équilibreur de charge ou d'un CDN plutôt que directement sur l'hôte Nginx, le renouvellement peut nécessiter un défi DNS ou un chemin de déploiement différent. Ne supposez pas que le défi HTTP par défaut fonctionnera si le trafic public n'atteint jamais ce serveur.

Paramètres TLS qui valent la peine d'être vérifiés

Pour la plupart des sites publics modernes, TLS 1.2 et TLS 1.3 sont la base pratique :

ssl_protocols TLSv1.2 TLSv1.3;

Évitez de paramétrer manuellement les listes de chiffrement sauf si vous savez pourquoi. Le fichier options-ssl-nginx.conf inclus par Certbot et le générateur de configuration SSL de Mozilla sont de meilleurs points de départ qu'une chaîne de chiffrement copiée depuis un vieux billet de blog. Les recommandations de chiffrement changent avec le temps, et les exigences de compatibilité diffèrent entre un site marketing public et une API interne héritée.

HSTS est utile, mais il mérite de la prudence :

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Commencez par une valeur courte pendant les tests :

add_header Strict-Transport-Security "max-age=300" always;

N'utilisez includeSubDomains que lorsque chaque sous-domaine peut servir du HTTPS valide. Si old.example.com, mail.example.com ou un sous-domaine spécifique à un client n'est pas prêt, cette option peut casser de vrais utilisateurs.

Échecs courants

Si Certbot ne peut pas vérifier le domaine, vérifiez d'abord le DNS, puis le port 80, puis le bloc serveur Nginx. Le défi HTTP-01 nécessite que Let's Encrypt atteigne un jeton sous /.well-known/acme-challenge/. Les redirections sont correctes lorsqu'elles sont configurées correctement, mais un proxy, un CDN ou un bloc fourre-tout peut accidentellement envoyer le défi ailleurs.

Si Nginx ne parvient pas à recharger après les modifications de Certbot, exécutez :

sudo nginx -t
sudo journalctl -u nginx -n 80 --no-pager

Le test de syntaxe vous indique généralement le fichier et la ligne exacts. Les causes courantes sont des blocs listen 443 ssl en double, un chemin de certificat supprimé ou un snippet inclus depuis un chemin qui n'existe pas sur ce serveur.

Si HTTPS fonctionne localement mais pas pour les utilisateurs, vérifiez le chemin public. Un équilibreur de charge peut encore pointer vers un ancien groupe cible. Un CDN peut avoir mis en cache une redirection. Le DNS IPv6 peut pointer vers un hôte différent de l'IPv4. Testez les deux :

curl -4 -I https://example.com
curl -6 -I https://example.com

La configuration HTTPS la plus propre est ennuyeuse : le DNS pointe au bon endroit, Nginx a un bloc serveur évident pour le domaine, le renouvellement Certbot passe en simulation, et les en-têtes ne sont ajoutés qu'après que les bases fonctionnent.