🛠 Outils IT

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
Validite : les certificats Let's Encrypt sont valides 90 jours. Il est fortement recommande de configurer un renouvellement automatique (generalement tous les 60 jours) pour eviter toute interruption de service.

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
Conseil : privilegiez l'installation via Snap sur les systemes compatibles. Cela vous assure de toujours disposer de la version la plus recente de Certbot et facilite les mises a jour automatiques.

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>
Conseil : apres l'installation, verifiez manuellement le VirtualHost genere avec 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 ...
}
Attention : le header 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
Quand utiliser Standalone : ideal pour les serveurs qui n'hebergent pas de site web (serveur mail, serveur de base de donnees, etc.) ou pour des tests ponctuels. Le principal inconvenient est qu'il faut arreter le serveur web existant pendant l'obtention du certificat.

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
Quand utiliser Webroot : ideal lorsque vous avez deja un serveur web en production et que vous ne souhaitez pas l'interrompre. Assurez-vous que le repertoire .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.).

Important : les certificats wildcard necessitent obligatoirement une validation DNS (DNS-01 challenge). La validation HTTP ne fonctionne pas pour les wildcards.

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
Conseil : attendez quelques minutes apres l'ajout de l'enregistrement DNS pour permettre la propagation. Utilisez 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
Conseil : si le --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
Info : Certbot ne tentera le renouvellement que pour les certificats qui expirent dans moins de 30 jours. L'execution quotidienne de 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)
Securite : ne modifiez jamais les permissions du fichier 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
Info : la propagation DNS peut prendre de quelques minutes a 48 heures selon les fournisseurs. Utilisez un outil comme 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
Conseil : utilisez l'environnement de staging (test) pour vos essais afin de ne pas atteindre les rate limits de production : 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
Attention : avant de supprimer un certificat, assurez-vous qu'aucun service ne l'utilise. La suppression retire le certificat de Certbot mais ne modifie pas la configuration de votre serveur web.

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