Guide Let's Encrypt - Certificats SSL/TLS
1. Qu'est-ce que Let's Encrypt
Let's Encrypt est une autorite de certification gratuite, automatisee et ouverte, lancee en avril 2016. Elle permet a quiconque d'obtenir un certificat SSL/TLS pour securiser son site web en HTTPS, sans frais et sans procedures administratives complexes.
Principes fondamentaux
- Gratuit : aucun cout pour l'obtention ou le renouvellement des certificats
- Automatise : le processus d'emission et de renouvellement peut etre entierement automatise
- Ouvert : le protocole et les outils sont open source
- Securise : les certificats emis sont reconnus par tous les navigateurs majeurs
Le protocole ACME
Let's Encrypt utilise le protocole ACME (Automatic Certificate Management Environment) pour verifier que vous controlez bien le domaine pour lequel vous demandez un certificat. Ce protocole repose sur des challenges (defis) :
- HTTP-01 : Let's Encrypt verifie un fichier place sur votre serveur web (port 80)
- DNS-01 : Let's Encrypt verifie un enregistrement TXT dans votre zone DNS
- TLS-ALPN-01 : verification via une connexion TLS sur le port 443
2. Installation de Certbot
Certbot est le client ACME officiel recommande par Let's Encrypt. Il gere l'obtention, l'installation et le renouvellement des certificats.
Methode recommandee : via Snap
Snap est la methode officielle recommandee car elle garantit d'avoir toujours la derniere version de Certbot :
# Installer snapd si necessaire
sudo apt install snapd
# Mettre a jour snap
sudo snap install core && sudo snap refresh core
# Supprimer l'ancienne version de certbot si presente
sudo apt remove certbot
# Installer Certbot via snap
sudo snap install --classic certbot
# Creer le lien symbolique
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Debian / Ubuntu (via apt)
sudo apt update
sudo apt install certbot
CentOS / RHEL (via dnf)
# Activer le depot EPEL si necessaire
sudo dnf install epel-release
# Installer Certbot
sudo dnf install certbot
Alternative : acme.sh
acme.sh est un client ACME ecrit entierement en shell, leger et sans dependances :
# Installation
curl https://get.acme.sh | sh -s email=admin@example.com
# Obtenir un certificat
~/.acme.sh/acme.sh --issue -d example.com -w /var/www/html
3. Configuration Apache
Installation du plugin Apache
# Debian / Ubuntu
sudo apt install python3-certbot-apache
# CentOS / RHEL
sudo dnf install python3-certbot-apache
Obtenir et installer le certificat
Certbot peut automatiquement configurer Apache pour utiliser le certificat SSL :
# Certificat pour un seul domaine
sudo certbot --apache -d example.com
# Certificat pour un domaine et son sous-domaine www
sudo certbot --apache -d example.com -d www.example.com
# Certificat pour plusieurs domaines
sudo certbot --apache -d example.com -d www.example.com -d api.example.com
Ce que fait Certbot automatiquement
- Obtient le certificat aupres de Let's Encrypt
- Modifie le VirtualHost Apache pour activer SSL sur le port 443
- Configure la redirection automatique HTTP (port 80) vers HTTPS (port 443)
- Recharge la configuration Apache
VirtualHost SSL resultant
Apres l'execution de Certbot, le fichier VirtualHost SSL genere ressemble a ceci :
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public
<Directory /var/www/example.com/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>
Redirection HTTP vers HTTPS
Certbot ajoute egalement la redirection dans le VirtualHost port 80 :
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com [OR]
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
sudo apache2ctl -t pour valider la syntaxe, puis sudo systemctl reload apache2 si necessaire.
4. Configuration Nginx
Installation du plugin Nginx
# Debian / Ubuntu
sudo apt install python3-certbot-nginx
# CentOS / RHEL
sudo dnf install python3-certbot-nginx
Obtenir et installer le certificat
# Certificat pour un domaine et son www
sudo certbot --nginx -d example.com -d www.example.com
# Mode interactif : Certbot vous demandera si vous souhaitez
# rediriger le trafic HTTP vers HTTPS (recommande)
Configuration Nginx SSL resultante
Apres l'execution de Certbot, le bloc serveur Nginx est modifie comme suit :
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/public;
index index.html index.php;
# Certificats Let's Encrypt
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;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
access_log /var/log/nginx/example.com-access.log;
error_log /var/log/nginx/example.com-error.log;
}
# Redirection HTTP vers HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
if ($host = www.example.com) {
return 301 https://$host$request_uri;
}
if ($host = example.com) {
return 301 https://$host$request_uri;
}
return 404;
}
Headers de securite recommandes
Ajoutez ces headers dans votre bloc server SSL pour renforcer la securite :
server {
listen 443 ssl http2;
server_name example.com;
# ... certificats SSL ...
# HSTS - Force HTTPS pendant 1 an
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Empecher le clickjacking
add_header X-Frame-Options "SAMEORIGIN" always;
# Protection XSS
add_header X-XSS-Protection "1; mode=block" always;
# Empecher le MIME sniffing
add_header X-Content-Type-Options "nosniff" always;
# Politique de referrer
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Permissions Policy
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# ... reste de la configuration ...
}
Strict-Transport-Security (HSTS) avec l'option preload est irreversible une fois soumis a la liste de preload des navigateurs. Testez d'abord avec un max-age court (ex: 300 secondes) avant de passer a 1 an.
5. Mode Standalone et Webroot
Ces modes permettent d'obtenir un certificat sans que Certbot modifie la configuration de votre serveur web. Vous configurez ensuite le SSL manuellement.
Mode Standalone
Certbot lance son propre serveur web temporaire pour repondre au challenge HTTP-01 :
# Le port 80 doit etre libre (arretez Apache/Nginx avant)
sudo systemctl stop nginx # ou apache2
# Obtenir le certificat
sudo certbot certonly --standalone -d example.com -d www.example.com
# Redemarrer le serveur web
sudo systemctl start nginx # ou apache2
Mode Webroot
Certbot place un fichier de verification dans le repertoire racine de votre site web, sans interrompre le serveur :
# Le serveur web doit etre en cours d'execution
# -w specifie le document root de votre site
sudo certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com
# Pour plusieurs domaines avec des racines differentes
sudo certbot certonly --webroot \
-w /var/www/example.com -d example.com -d www.example.com \
-w /var/www/api.example.com -d api.example.com
.well-known/acme-challenge/ est accessible publiquement sur le port 80.
Comparaison des modes
| Critere | Standalone | Webroot | Plugin (Apache/Nginx) |
|---|---|---|---|
| Interruption du service | Oui (port 80 requis) | Non | Non |
| Configuration auto du serveur | Non | Non | Oui |
| Serveur web requis | Non | Oui | Oui (Apache ou Nginx) |
| Renouvellement auto facile | Difficile (arret requis) | Facile | Facile |
| Cas d'usage ideal | Serveurs sans web | Serveur web en production | Configuration standard |
6. Certificat Wildcard
Un certificat wildcard couvre un domaine et tous ses sous-domaines de premier niveau (ex: *.example.com couvre app.example.com, api.example.com, mail.example.com, etc.).
Obtention manuelle
# Demander un certificat wildcard + domaine racine
sudo certbot certonly --manual --preferred-challenges dns \
-d "*.example.com" \
-d example.com
Certbot vous demandera de creer un enregistrement DNS TXT :
# Certbot affichera quelque chose comme :
# Please deploy a DNS TXT record under the name:
# _acme-challenge.example.com
# with the following value:
# xYz1AbC2dEf3GhI4jKl5MnO6pQr7StU8vWx
# Ajoutez l'enregistrement TXT dans votre zone DNS :
# Nom : _acme-challenge.example.com
# Type : TXT
# Valeur : xYz1AbC2dEf3GhI4jKl5MnO6pQr7StU8vWx
# Verifiez la propagation avant de valider :
dig -t TXT _acme-challenge.example.com
# ou
nslookup -type=TXT _acme-challenge.example.com
dig ou un outil en ligne pour verifier que l'enregistrement est bien visible avant de confirmer dans Certbot.
Plugins DNS automatises
Pour automatiser le renouvellement des certificats wildcard, utilisez un plugin DNS specifique a votre fournisseur :
Cloudflare
# Installer le plugin
sudo snap install certbot-dns-cloudflare
# Creer le fichier de credentials
sudo mkdir -p /etc/letsencrypt
sudo nano /etc/letsencrypt/cloudflare.ini
# Contenu de /etc/letsencrypt/cloudflare.ini
dns_cloudflare_api_token = votre_token_api_cloudflare
# Proteger le fichier
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
# Obtenir le certificat wildcard automatiquement
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d "*.example.com" \
-d example.com
OVH
# Installer le plugin
sudo snap install certbot-dns-ovh
# Creer le fichier de credentials
sudo nano /etc/letsencrypt/ovh.ini
# Contenu de /etc/letsencrypt/ovh.ini
dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = votre_application_key
dns_ovh_application_secret = votre_application_secret
dns_ovh_consumer_key = votre_consumer_key
# Proteger le fichier et obtenir le certificat
sudo chmod 600 /etc/letsencrypt/ovh.ini
sudo certbot certonly --dns-ovh \
--dns-ovh-credentials /etc/letsencrypt/ovh.ini \
-d "*.example.com" \
-d example.com
Autres plugins DNS disponibles
| Fournisseur DNS | Plugin Certbot | Installation (snap) |
|---|---|---|
| Cloudflare | certbot-dns-cloudflare | snap install certbot-dns-cloudflare |
| OVH | certbot-dns-ovh | snap install certbot-dns-ovh |
| Google Cloud DNS | certbot-dns-google | snap install certbot-dns-google |
| Amazon Route 53 | certbot-dns-route53 | snap install certbot-dns-route53 |
| DigitalOcean | certbot-dns-digitalocean | snap install certbot-dns-digitalocean |
7. Renouvellement automatique
Les certificats Let's Encrypt expirent apres 90 jours. Il est essentiel de configurer un renouvellement automatique pour eviter les interruptions de service.
Tester le renouvellement
Avant de configurer l'automatisation, effectuez un test a blanc :
# Simulation de renouvellement (ne modifie rien)
sudo certbot renew --dry-run
--dry-run reussit, le renouvellement reel fonctionnera de la meme maniere. Executez cette commande apres chaque modification de configuration.
Methode 1 : Cron job
Ajoutez une tache cron pour verifier et renouveler les certificats automatiquement :
# Editer le crontab root
sudo crontab -e
# Renouvellement a 3h du matin chaque jour, rechargement Apache
0 3 * * * certbot renew --quiet --post-hook "systemctl reload apache2"
# Variante pour Nginx
0 3 * * * certbot renew --quiet --post-hook "systemctl reload nginx"
# Variante avec log
0 3 * * * certbot renew --quiet --post-hook "systemctl reload nginx" >> /var/log/certbot-renew.log 2>&1
Methode 2 : Timer Systemd
Lorsque Certbot est installe via Snap ou les paquets systeme, un timer Systemd est generalement configure automatiquement :
# Verifier si le timer est actif
sudo systemctl list-timers | grep certbot
# Resultat attendu :
# NEXT LEFT LAST PASSED UNIT ACTIVATES
# mer. 2025-01-15 03:22:00 6h left mar. 2025-01-14 15:22:00 5h ago snap.certbot.renew.timer snap.certbot.renew.service
# Verifier le statut du timer
sudo systemctl status snap.certbot.renew.timer
# Activer le timer si necessaire
sudo systemctl enable --now snap.certbot.renew.timer
Hooks de renouvellement
Les hooks permettent d'executer des commandes avant, pendant ou apres le renouvellement :
# --pre-hook : execute AVANT le renouvellement
# --post-hook : execute APRES le renouvellement (seulement si renouvele)
# --deploy-hook : execute seulement si un certificat a ete effectivement renouvele
# Exemple : recharger Nginx apres renouvellement
sudo certbot renew --deploy-hook "systemctl reload nginx"
# Hooks permanents via fichier de configuration
# Creer /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash
systemctl reload nginx
# Rendre le hook executable
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
certbot renew est donc sans risque : les certificats encore valides seront ignores.
8. Fichiers et emplacements
Les certificats et les cles sont stockes dans le repertoire /etc/letsencrypt/. Voici l'arborescence et l'utilite de chaque fichier :
Fichiers du certificat
| Fichier | Chemin complet | Description |
|---|---|---|
fullchain.pem |
/etc/letsencrypt/live/example.com/fullchain.pem |
Certificat complet (certificat du serveur + chaine intermediaire). A utiliser dans la configuration du serveur web. |
privkey.pem |
/etc/letsencrypt/live/example.com/privkey.pem |
Cle privee du certificat. Fichier confidentiel, ne jamais le partager. |
cert.pem |
/etc/letsencrypt/live/example.com/cert.pem |
Certificat du serveur seul (sans la chaine intermediaire). Rarement utilise directement. |
chain.pem |
/etc/letsencrypt/live/example.com/chain.pem |
Chaine intermediaire de l'autorite de certification (Let's Encrypt). Necessaire pour certaines configurations specifiques. |
Arborescence complete
/etc/letsencrypt/
├── accounts/ # Comptes ACME enregistres
├── archive/ # Historique de tous les certificats (versions numerotees)
│ └── example.com/
│ ├── cert1.pem
│ ├── chain1.pem
│ ├── fullchain1.pem
│ └── privkey1.pem
├── live/ # Liens symboliques vers les certificats actuels
│ └── example.com/
│ ├── cert.pem -> ../../archive/example.com/cert1.pem
│ ├── chain.pem -> ../../archive/example.com/chain1.pem
│ ├── fullchain.pem -> ../../archive/example.com/fullchain1.pem
│ ├── privkey.pem -> ../../archive/example.com/privkey1.pem
│ └── README
├── renewal/ # Configuration de renouvellement par domaine
│ └── example.com.conf
├── renewal-hooks/ # Scripts de hooks
│ ├── pre/
│ ├── deploy/
│ └── post/
└── options-ssl-*.conf # Configurations SSL recommandees
Droits d'acces
# Le repertoire /etc/letsencrypt est accessible uniquement par root
sudo ls -la /etc/letsencrypt/live/example.com/
# Droits par defaut :
# drwxr-xr-x root root /etc/letsencrypt/
# drwx------ root root /etc/letsencrypt/live/
# drwx------ root root /etc/letsencrypt/archive/
# -rw-r--r-- root root fullchain.pem, cert.pem, chain.pem
# -rw------- root root privkey.pem (lecture root uniquement)
privkey.pem. Si un service non-root a besoin d'y acceder, ajoutez son utilisateur au groupe ssl-cert ou utilisez un mecanisme de copie securise dans un hook de deploiement.
9. Depannage
Erreur : port 80 bloque
Si Certbot ne peut pas valider le challenge HTTP-01 :
# Verifier quel processus utilise le port 80
sudo ss -tlnp | grep :80
# ou
sudo lsof -i :80
# Verifier les regles du firewall
sudo ufw status
# ou
sudo iptables -L -n | grep 80
# S'assurer que le port 80 est ouvert
sudo ufw allow 80/tcp
Erreur DNS : domaine non resolu
# Verifier que le domaine pointe vers votre serveur
dig +short example.com
nslookup example.com
# Verifier la propagation DNS (utile apres un changement)
dig example.com @8.8.8.8
dig example.com @1.1.1.1
# S'assurer que l'enregistrement A ou CNAME est correct
dig +short A example.com
dig +short CNAME www.example.com
dnschecker.org pour verifier la propagation mondiale.
Rate limits (limites de taux)
Let's Encrypt impose des limites pour prevenir les abus :
| Limite | Valeur | Detail |
|---|---|---|
| Certificats par domaine enregistre | 50 par semaine | Par domaine racine (example.com) |
| Certificats dupliques | 5 par semaine | Meme ensemble exact de noms de domaines |
| Echecs de validation | 5 par heure par compte par hostname | Par nom d'hote et par compte |
| Comptes par adresse IP | 10 par 3 heures | Creation de nouveaux comptes ACME |
certbot --staging .... Les certificats de staging ne sont pas valides pour les navigateurs, mais permettent de valider toute la chaine.
Consulter les logs
# Fichier de log principal de Certbot
sudo cat /var/log/letsencrypt/letsencrypt.log
# Voir les dernieres lignes
sudo tail -100 /var/log/letsencrypt/letsencrypt.log
# Suivre en temps reel pendant une operation
sudo tail -f /var/log/letsencrypt/letsencrypt.log
Lister les certificats actifs
# Afficher tous les certificats geres par Certbot
sudo certbot certificates
# Resultat attendu :
# Found the following certs:
# Certificate Name: example.com
# Domains: example.com www.example.com
# Expiry Date: 2025-04-15 (VALID: 89 days)
# Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
# Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
Revoquer un certificat
# Revoquer un certificat (le marquer comme invalide)
sudo certbot revoke --cert-name example.com
# Revoquer avec une raison specifique
sudo certbot revoke --cert-name example.com --reason keycompromise
Supprimer un certificat
# Supprimer un certificat et ses fichiers de configuration de renouvellement
sudo certbot delete --cert-name example.com
Tester la connexion SSL
# Test basique de la connexion SSL
openssl s_client -connect example.com:443 -servername example.com
# Verifier la date d'expiration
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates
# Verifier le certificat complet
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -text
# Verifier la chaine de certificats
openssl s_client -connect example.com:443 -servername example.com -showcerts
# Tester avec curl en mode verbose
curl -vI https://example.com 2>&1 | grep -E "SSL|certificate|expire"
Problemes courants et solutions
| Probleme | Cause probable | Solution |
|---|---|---|
Connection refused sur le challenge |
Port 80 bloque par un firewall | Ouvrir le port 80 : ufw allow 80/tcp |
DNS problem: NXDOMAIN |
Le domaine ne pointe pas vers le serveur | Verifier l'enregistrement A/CNAME dans la zone DNS |
Too many certificates |
Rate limit atteint | Attendre une semaine ou utiliser --staging |
Unauthorized |
Fichier de challenge non accessible | Verifier la conf du serveur web pour /.well-known/acme-challenge/ |
| Certificat expire malgre le renouvellement | Le serveur web n'a pas ete recharge | Ajouter un --deploy-hook pour recharger le service |
SSL: error:0A000086 |
Certificat et cle ne correspondent pas | Regenerer le certificat avec certbot certonly --force-renewal |