Introduction
La configuration SSL/TLS est bien plus qu'une simple case a cocher dans la liste des taches d'un administrateur système. C'est le fondement de la sécurité de toutes les communications entre vos utilisateurs et votre serveur. Un certificat mal configure peut exposer vos visiteurs a des attaques man-in-the-middle, afficher des avertissements effrayants dans les navigateurs, ou simplement empecher l'accès a votre site.
Dans ce guide complet, nous allons voir comment configurer Apache et Nginx de maniere optimale avec Let's Encrypt, en suivant les meilleures pratiques de 2026. Que vous soyez débutant ou administrateur experimente cherchant a optimiser votre configuration, ce guide est fait pour vous.
Pourquoi Let's Encrypt ?
Avant de plonger dans la configuration, rappelons pourquoi Let's Encrypt est devenu le choix par defaut pour les certificats SSL :
- Gratuit : Aucun cout, ce qui democratise HTTPS pour tous les sites
- Automatise : Renouvellement automatique grâce à Certbot
- Reconnu : Accepte par tous les navigateurs modernes
- Securise : Memes standards de sécurité que les certificats payants
- Rapide : Emission en quelques secondes
Prerequis
Avant de commencer, assurez-vous d'avoir :
- Un serveur Linux (Ubuntu 22.04/24.04 ou Debian 11/12 recommande)
- Un nom de domaine pointant vers l'IP de votre serveur (enregistrement A ou AAAA)
- Apache 2.4+ ou Nginx 1.18+ installe
- Les ports 80 et 443 ouverts dans votre firewall
- Un accès root ou sudo au serveur
Verifier les prerequis
# Verifier la version d'Apache
apache2 -v
# Apache/2.4.52 (Ubuntu)
# Ou la version de Nginx
nginx -v
# nginx version: nginx/1.24.0
# Verifier que le domaine pointe vers le serveur
dig +short votredomaine.com
# Doit retourner l'IP de votre serveur
# Verifier les ports ouverts
sudo ufw status
# 80/tcp ALLOW
# 443/tcp ALLOWInstallation de Certbot
Certbot est l'outil officiel de Let's Encrypt pour obtenir et gérer les certificats.
Sur Ubuntu/Debian
# Méthode recommandee : via snap
sudo apt update
sudo apt install snapd
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
# Alternative : via apt (version potentiellement plus ancienne)
sudo apt install certbotInstaller les plugins serveur web
# Pour Apache
sudo apt install python3-certbot-apache
# Ou via snap
sudo snap install certbot-apache
# Pour Nginx
sudo apt install python3-certbot-nginx
# Ou via snap
sudo snap install certbot-nginxObtenir un certificat
Méthode 1 : Plugin Apache (recommande)
Le plugin Apache configure automatiquement votre serveur :
# Obtenir et installer le certificat
sudo certbot --apache -d votredomaine.com -d www.votredomaine.com
# Options utiles :
# --dry-run : Tester sans modifier
# --staging : Utiliser le serveur de test (pas de limite de rate)
# --email : Specifier l'email pour les notifications
# --agree-tos : Accepter les conditions d'utilisation
# --no-redirect : Ne pas configurer la redirection HTTP vers HTTPSMéthode 2 : Plugin Nginx (recommande)
# Obtenir et installer le certificat
sudo certbot --nginx -d votredomaine.com -d www.votredomaine.comMéthode 3 : Webroot (pour configurations complexes)
Si vous avez une configuration personnalisee, utilisez le mode webroot :
# Créer le répertoire de challenge
sudo mkdir -p /var/www/html/.well-known/acme-challenge
# Obtenir le certificat
sudo certbot certonly --webroot -w /var/www/html \
-d votredomaine.com -d www.votredomaine.comMéthode 4 : Standalone (sans serveur web)
# Arrete temporairement le serveur web
sudo systemctl stop nginx # ou apache2
# Obtenir le certificat
sudo certbot certonly --standalone -d votredomaine.com
# Redemarrer le serveur
sudo systemctl start nginxConfiguration SSL optimale pour Apache
Une fois le certificat obtenu, optimisons la configuration. Voici une configuration complete et securisee :
Virtual Host HTTPS complet
<VirtualHost *:443>
ServerName votredomaine.com
ServerAlias www.votredomaine.com
DocumentRoot /var/www/html
# Logs
ErrorLog ${APACHE_LOG_DIR}/votredomaine-error.log
CustomLog ${APACHE_LOG_DIR}/votredomaine-accèss.log combined
# ===== CERTIFICAT SSL =====
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/votredomaine.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/votredomaine.com/privkey.pem
# ===== PROTOCOLES TLS =====
# Desactiver les anciens protocoles vulnerables
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# Résultat : TLSv1.2 et TLSv1.3 uniquement
# ===== CIPHERS =====
# Suite de chiffrement moderne
SSLCipherSuite 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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off
# ===== HEADERS DE SECURITE =====
# HSTS : Forcer HTTPS pendant 1 an
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Empecher le MIME sniffing
Header always set X-Content-Type-Options "nosniff"
# Protection clickjacking
Header always set X-Frame-Options "SAMEORIGIN"
# XSS Protection (pour anciens navigateurs)
Header always set X-XSS-Protection "1; mode=block"
# Referrer Policy
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Permissions Policy
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# ===== VOTRE CONFIGURATION =====
<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Pour PHP-FPM
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
</FilesMatch>
</VirtualHost>Redirection HTTP vers HTTPS
<VirtualHost *:80>
ServerName votredomaine.com
ServerAlias www.votredomaine.com
# Redirection permanente vers HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Alternative plus simple :
# Redirect permanent / https://votredomaine.com/
</VirtualHost>Activer les modules nécessaires
# Activer les modules Apache requis
sudo a2enmod ssl
sudo a2enmod headers
sudo a2enmod rewrite
sudo a2enmod http2 # Pour HTTP/2
# Activer le site
sudo a2ensite votredomaine-ssl.conf
# Tester la configuration
sudo apache2ctl configtest
# Syntax OK
# Recharger Apache
sudo systemctl reload apache2Configuration SSL optimale pour Nginx
Nginx a une syntaxe différente mais les principes sont les memes.
Configuration complete
# Redirection HTTP vers HTTPS
server {
listen 80;
listen [::]:80;
server_name votredomaine.com www.votredomaine.com;
# Redirection 301 permanente
return 301 https://votredomaine.com$request_uri;
}
# Redirection www vers non-www (optionnel)
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.votredomaine.com;
ssl_certificate /etc/letsencrypt/live/votredomaine.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/votredomaine.com/privkey.pem;
return 301 https://votredomaine.com$request_uri;
}
# Serveur principal HTTPS
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name votredomaine.com;
root /var/www/html;
index index.html index.php;
# ===== CERTIFICAT SSL =====
ssl_certificate /etc/letsencrypt/live/votredomaine.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/votredomaine.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/votredomaine.com/chain.pem;
# ===== PROTOCOLES ET CIPHERS =====
ssl_protocols TLSv1.2 TLSv1.3;
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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# ===== SESSION SSL =====
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# ===== HEADERS DE SECURITE =====
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# ===== OPTIMISATIONS =====
# Gzip
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# ===== LOCATIONS =====
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# Cacher les fichiers sensibles
location ~ /\.(ht|git|env) {
deny all;
}
}Tester et recharger
# Tester la configuration Nginx
sudo nginx -t
# nginx: configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is succèssful
# Recharger Nginx
sudo systemctl reload nginxRenouvellement automatique
Les certificats Let's Encrypt expirent après 90 jours. Certbot configure automatiquement le renouvellement.
Verifier le timer systemd
# Verifier que le timer est actif
sudo systemctl status certbot.timer
# Active: active (waiting)
# Voir quand le prochain renouvellement est prevu
sudo systemctl list-timers | grep certbotTester le renouvellement
# Simulation de renouvellement (ne modifie rien)
sudo certbot renew --dry-run
# Si tout est OK, vous verrez :
# Congratulations, all simulated renewals succeededRenouvellement manuel
# Forcer le renouvellement d'un certificat spécifique
sudo certbot renew --cert-name votredomaine.com --force-renewal
# Renouveler tous les certificats proches de l'expiration
sudo certbot renewHook de rechargement
Après le renouvellement, le serveur web doit etre recharge. Ajoutez un hook :
# Pour Nginx
sudo sh -c 'echo "nginx -s reload" > /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh'
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
# Pour Apache
sudo sh -c 'echo "systemctl reload apache2" > /etc/letsencrypt/renewal-hooks/deploy/reload-apache.sh'
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-apache.shHeaders de sécurité expliques
Comprendre chaque header est essentiel pour une configuration securisee.
| Header | Valeur recommandee | Role |
|---|---|---|
| Strict-Transport-Security | max-age=31536000; includeSubDomains | Force HTTPS pendant 1 an, inclut les sous-domaines |
| X-Content-Type-Options | nosniff | Empeche le navigateur de deviner le type MIME |
| X-Frame-Options | SAMEORIGIN | Empeche l'intégration dans une iframe externe |
| X-XSS-Protection | 1; mode=block | Active le filtre XSS des anciens navigateurs |
| Referrer-Policy | strict-origin-when-cross-origin | Contrôle les infos envoyees dans le header Referer |
| Permissions-Policy | geolocation=(), camera=() | Desactive les APIs sensibles non utilisees |
Tester votre configuration
Outils en ligne
- SSL Labs : ssllabs.com/ssltest - Analyse complete, note de A a F
- Security Headers : securityheaders.com - Verifie les headers HTTP
- Mozilla Observatory : observatory.mozilla.org - Test de sécurité global
Tests en ligne de commande
# Verifier le certificat et la chaine
echo | openssl s_client -connect votredomaine.com:443 -servername votredomaine.com 2>/dev/null | openssl x509 -noout -dates -subject -issuer
# Verifier les protocoles supportes
nmap --script ssl-enum-ciphers -p 443 votredomaine.com
# Tester un protocole spécifique
openssl s_client -connect votredomaine.com:443 -tls1_2
openssl s_client -connect votredomaine.com:443 -tls1_3
# Verifier les headers
curl -I https://votredomaine.com 2>/dev/null | grep -E "(Strict|X-Content|X-Frame|X-XSS)"Erreurs courantes et solutions
ERR_SSL_PROTOCOL_ERROR
Le port 443 n'est pas accèssible.
# Verifier le firewall
sudo ufw status
sudo ufw allow 443/tcp
# Verifier que le serveur ecoute
sudo ss -tlnp | grep 443Certificate chain incomplete
Vous utilisez cert.pem au lieu de fullchain.pem.
# Mauvais
SSLCertificateFile /etc/letsencrypt/live/domain/cert.pem
# Correct
SSLCertificateFile /etc/letsencrypt/live/domain/fullchain.pemMixed content warnings
Des ressources sont chargees en HTTP au lieu d'HTTPS.
# Trouver les ressources HTTP dans votre code
grep -r "http://" /var/www/html --include="*.html" --include="*.php" --include="*.css" --include="*.js"
# Remplacer par des URLs relatives ou HTTPS
# http://example.com/style.css -> /style.css ou https://example.com/style.cssToo many redirects
Bouclé de redirection entre HTTP et HTTPS.
# Verifier que la redirection n'est que sur le port 80
# et non sur le port 443Optimisations avancées
Activer HTTP/2
# Nginx : ajouter http2 a la directive listen
listen 443 ssl http2;
# Apache : activer le module
sudo a2enmod http2Activer TLS 1.3 0-RTT (avec precaution)
Le 0-RTT reduit la latence mais peut etre vulnerable aux replay attacks.
# Nginx
ssl_early_data on;
proxy_set_header Early-Data $ssl_early_data;Conclusion
Une configuration SSL bien faite est la base de la sécurité web moderne. Les points essentiels a retenir :
- Utilisez toujours
fullchain.pemet noncert.pem - Desactivez les anciens protocoles (SSLv3, TLS 1.0, TLS 1.1)
- Configurez les headers de sécurité (HSTS est le plus important)
- Testez regulierement avec SSL Labs pour maintenir une note A+
- Verifiez que le renouvellement automatique fonctionne
Avec cette configuration, vous aurez une note A ou A+ sur SSL Labs et vos visiteurs seront proteges contre les principales attaques web.