guide/ssl-tls.md

Mettre en place SSL/TLS

Ce guide accompagne la mise en HTTPS d'un site derrière Apache avec des certificats Let's Encrypt (Certbot). Il suppose que vous savez déjà administrer un serveur Linux et manipuler des VirtualHosts. Remplacez systématiquement <VOTRE_DOMAINE> par votre domaine réel.

Obtenir un certificat

Installer Certbot

sudo apt install certbot python3-certbot-apache -y

Émettre le certificat

Un seul domaine :

sudo certbot --apache -d <VOTRE_DOMAINE>

Domaine + sous-domaine www (certificat multi-SAN) :

sudo certbot --apache -d <VOTRE_DOMAINE> -d www.<VOTRE_DOMAINE>

Le plugin --apache configure le VirtualHost pour vous. Si vous préférez garder la main sur la configuration, utilisez certonly (voir plus bas) et référencez les certificats manuellement.

Vérifier le renouvellement automatique

Certbot installe un timer de renouvellement. Testez-le Ă  blanc :

sudo certbot renew --dry-run

En cas de certificat désynchronisé ou corrompu, forcez le renouvellement :

# tous les certificats
sudo certbot renew --force-renewal

# un certificat précis
sudo certbot renew --cert-name <VOTRE_DOMAINE> --force-renewal

Configurer Apache

Activer les modules

sudo a2enmod ssl headers http2

VirtualHost HTTP → HTTPS

Redirigez tout le trafic port 80 vers HTTPS :

<VirtualHost *:80>
    ServerName <VOTRE_DOMAINE>
    Redirect permanent / https://<VOTRE_DOMAINE>
</VirtualHost>

VirtualHost HTTPS

<VirtualHost *:443>
    ServerName <VOTRE_DOMAINE>
    Protocols h2 http/1.1

    DocumentRoot /var/www/<VOTRE_SITE>/public

    <Directory /var/www/<VOTRE_SITE>/public>
        AllowOverride None
        Require all granted
    </Directory>

    # Certificats
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/<VOTRE_DOMAINE>/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/<VOTRE_DOMAINE>/privkey.pem

    # Protocoles et chiffrements : on désactive tout ce qui est obsolète
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite HIGH:!aNULL:!MD5
    SSLHonorCipherOrder on

    # En-têtes de sécurité
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
</VirtualHost>

Deux réglages structurants côté sécurité :

  • SSLProtocol ... -TLSv1 -TLSv1.1 coupe les versions de TLS jugĂ©es faibles : on ne garde que TLS 1.2 et au-dessus.
  • HIGH:!aNULL:!MD5 Ă©carte les suites de chiffrement sans authentification et le MD5. Pour un rĂ©glage Ă  jour et gĂ©nĂ©rĂ© selon votre cible, appuyez-vous sur le gĂ©nĂ©rateur Mozilla (voir Ressources).

Publier le VirtualHost

sudo a2ensite <VOTRE_SITE>.conf
sudo apachectl configtest
sudo systemctl reload apache2

Déboguer

Inspecter le certificat sur disque

# domaines couverts (CN et SAN)
sudo openssl x509 -in /etc/letsencrypt/live/<VOTRE_DOMAINE>/fullchain.pem \
    -noout -text | grep -E "(Subject:|DNS:)"

# dates de validité
sudo openssl x509 -in /etc/letsencrypt/live/<VOTRE_DOMAINE>/fullchain.pem \
    -noout -dates

Inspecter le certificat réellement servi

echo | openssl s_client -connect <VOTRE_DOMAINE>:443 -servername <VOTRE_DOMAINE> 2>/dev/null \
    | openssl x509 -noout -subject -dates -ext subjectAltName

Comparer le certificat sur disque et celui servi est la manœuvre de diagnostic la plus utile : la plupart des incidents viennent d'un écart entre les deux.

Vérifier côté client

curl -I --http2 https://<VOTRE_DOMAINE>
curl -Iv https://<VOTRE_DOMAINE>   # voir la négociation TLS

Vérifier la configuration Apache

sudo apachectl -t -D DUMP_VHOSTS | grep 443
sudo apachectl configtest

Erreurs courantes

« no alternative certificate subject name matches target hostname »

Le certificat ne couvre pas le domaine demandé (CN/SAN incomplet). Comparez le certificat sur disque et le certificat servi (commandes ci-dessus). Si le certificat est incomplet, ré-émettez-le avec tous les domaines :

sudo certbot certonly --apache -d <VOTRE_DOMAINE> -d www.<VOTRE_DOMAINE>
sudo systemctl reload apache2

VirtualHost en double (conflit SNI)

Apache sert le certificat d'un autre domaine parce qu'un même ServerName apparaît dans plusieurs VirtualHosts *:443.

# repérer les doublons
sudo apachectl -t -D DUMP_VHOSTS | grep 443
sudo grep -r "ServerName <VOTRE_DOMAINE>" /etc/apache2/sites-enabled/

Règle : un ServerName ne doit apparaître qu'une seule fois parmi les VirtualHosts *:443. Supprimez ou fusionnez les configurations en conflit, puis configtest + reload.

Certificat expiré

sudo certbot certificates          # constater l'expiration
sudo certbot renew --force-renewal
sudo systemctl reload apache2

Mixed content (ressources en HTTP sur une page HTTPS)

Forcez la mise Ă  niveau des requĂŞtes dans le VirtualHost *:443 :

Header always set Content-Security-Policy "upgrade-insecure-requests"

Pages d'erreur mal encodées (ISO-8859-1)

Les pages d'erreur générées par Apache peuvent partir en Latin-1. Forcez l'UTF-8, y compris sur les réponses 4xx/5xx :

Header always edit Content-Type "^text/html(;.*)?$" "text/html; charset=UTF-8"

Le mot-clé always est indispensable pour couvrir les codes d'erreur.

« SSLCertificateFile: file does not exist »

Apache ne démarre pas car le chemin de certificat est faux ou le lien symbolique est cassé :

sudo ls -la /etc/letsencrypt/live/<VOTRE_DOMAINE>/
sudo readlink -f /etc/letsencrypt/live/<VOTRE_DOMAINE>/fullchain.pem

Corrigez le chemin dans le VirtualHost, puis configtest + reload.

Valider le résultat

# HTTP/2 actif
curl -I --http2 https://<VOTRE_DOMAINE> | head -1        # attendu : HTTP/2 200

# HSTS présent
curl -I https://<VOTRE_DOMAINE> | grep -i strict-transport-security

# redirection HTTP → HTTPS
curl -I http://<VOTRE_DOMAINE>                            # attendu : 301 + Location https://

Complétez par un audit externe (SSL Labs) pour noter la chaîne de certificats et les suites de chiffrement.

Checklist

  • Certbot installĂ©, certificat Ă©mis pour tous les domaines
  • VirtualHost 80 → 443 en redirection permanente
  • Certificats correctement rĂ©fĂ©rencĂ©s, aucun doublon de ServerName en *:443
  • TLS 1.2+ uniquement, suites de chiffrement sĂ»res
  • En-tĂŞtes de sĂ©curitĂ© (HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy)
  • HTTP/2 actif
  • Redirection et HSTS validĂ©s (curl + audit externe)
  • Renouvellement automatique testĂ© (--dry-run)

Ressources

Assistant documentaire

Posez une question sur la documentation. Les réponses citent leurs sources — un clic ouvre le document à gauche.