Aller au contenu

Nginx : HTTPS et certificats

Activer HTTPS avec un certificat gratuit Let’s Encrypt. Les exemples utilisent le domaine fictif exemple.com.

  • Le DNS de exemple.com (et de www.exemple.com) pointe vers l’adresse IP publique du serveur.
  • Un site Nginx fonctionnel en HTTP, avec un server_name correct (voir Sites virtuels).
  • Les ports 80 et 443 ouverts : sudo ufw allow 'Nginx Full'.
Fenêtre de terminal
sudo apt install certbot python3-certbot-nginx
certbot --version
Ubuntu Version de Certbot
24.04 2.9
26.04 4.0
Fenêtre de terminal
sudo certbot --nginx -d exemple.com -d www.exemple.com

Certbot demande une adresse e-mail (alertes d’expiration), vérifie que le domaine pointe vers le serveur, obtient le certificat, modifie la configuration du site et propose de rediriger HTTP vers HTTPS. Les certificats sont dans /etc/letsencrypt/live/exemple.com/.

Fichier Contenu
fullchain.pem Certificat et chaîne intermédiaire (à utiliser dans ssl_certificate)
privkey.pem Clé privée (secrète)

Autres modes d’obtention, sans modifier la configuration :

Fenêtre de terminal
sudo certbot certonly --webroot -w /var/www/exemple.com -d exemple.com # via le dossier du site
sudo certbot certonly --nginx -d exemple.com # via Nginx, sans modifier le site
sudo certbot certonly --standalone -d exemple.com # serveur temporaire (Nginx arrêté)

Le paquet installe un minuteur systemd qui renouvelle les certificats à moins de 30 jours de l’expiration :

Fenêtre de terminal
systemctl list-timers | grep certbot
sudo certbot renew --dry-run # simulation du renouvellement
sudo certbot certificates # certificats et dates d'expiration

Pour recharger Nginx après un renouvellement :

sudo tee /etc/letsencrypt/renewal-hooks/deploy/recharger-nginx.sh <<'CONF'
#!/bin/sh
systemctl reload nginx
CONF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/recharger-nginx.sh
server {
listen 80;
listen [::]:80;
server_name exemple.com www.exemple.com;
return 301 https://exemple.com$request_uri; # tout passe en HTTPS
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name exemple.com;
ssl_certificate /etc/letsencrypt/live/exemple.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/exemple.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=31536000" always;
root /var/www/exemple.com;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name www.exemple.com;
ssl_certificate /etc/letsencrypt/live/exemple.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/exemple.com/privkey.pem;
return 301 https://exemple.com$request_uri; # www vers le domaine nu
}

Ne pas forcer la suite de chiffrement : les valeurs par défaut de Nginx et d’OpenSSL sur Ubuntu sont adaptées.

Nginx Syntaxe
1.24 (Ubuntu 24.04) listen 443 ssl http2;
1.25.1 et plus (dont 1.28 sur Ubuntu 26.04) listen 443 ssl; puis http2 on; dans le bloc server
# Nginx 1.28 (Ubuntu 26.04)
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
# …
}
# Nginx 1.24 (Ubuntu 24.04)
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
# …
}

Strict-Transport-Security demande au navigateur de n’utiliser que HTTPS pour ce domaine :

add_header Strict-Transport-Security "max-age=31536000" always;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/exemple.com/chain.pem;
resolver 1.1.1.1 9.9.9.9 valid=300s;
Fenêtre de terminal
sudo nginx -t && sudo systemctl reload nginx
curl -I https://exemple.com
curl -I http://exemple.com # 301 vers https
openssl s_client -connect exemple.com:443 -servername exemple.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject
sudo apt install nmap && nmap --script ssl-enum-ciphers -p 443 exemple.com # protocoles TLS acceptés : seuls TLSv1.2 et TLSv1.3 doivent apparaître
curl -I --http2 https://exemple.com # HTTP/2 actif si la réponse commence par HTTP/2

openssl s_client -tls1_1 n’est pas fiable pour ce contrôle : le client OpenSSL d’Ubuntu refuse lui-même ces protocoles (« no protocols available ») sans tester le serveur. Un test externe complet est proposé par ssllabs.com/ssltest.

Symptôme Piste
Challenge failed / Timeout during connect Le DNS ne pointe pas vers le serveur, ou le port 80 est fermé (UFW, pare-feu de l’hébergeur)
Too many certificates already issued Limite de Let’s Encrypt atteinte : attendre ; utiliser --dry-run ou --staging pour les essais
nginx: [emerg] cannot load certificate Chemin incorrect, ou droits : sudo ls -l /etc/letsencrypt/live/exemple.com/
unknown directive "http2" Nginx 1.24 : utiliser listen 443 ssl http2;
Avertissement the "listen ... http2" directive is deprecated Nginx 1.25.1 et plus : utiliser http2 on;
Boucle de redirection La redirection HTTPS est aussi active derrière un proxy qui parle HTTP : tester $scheme ou X-Forwarded-Proto
Le certificat expire sudo certbot renew, vérifier systemctl list-timers et journalctl -u certbot
Erreur de contenu mixte dans le navigateur Des ressources http:// dans la page : les passer en https://

Ubuntu 24.04 et 26.04 : différences à connaître

Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »