Aller au contenu principal

Renouvellement automatique SSL

Ce guide explique comment configurer le renouvellement automatique des certificats SSL Let's Encrypt.

Vérifier l'état actuel

Certificats installés

sudo certbot certificates

Exemple de sortie :

Certificate Name: mondomaine.com
Domains: mondomaine.com www.mondomaine.com
Expiry Date: 2024-03-15 10:30:00+00:00 (VALID: 45 days)
Certificate Path: /etc/letsencrypt/live/mondomaine.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/mondomaine.com/privkey.pem

Vérifier l'expiration d'un certificat

# Via certbot
sudo certbot certificates | grep -A 3 "Certificate Name"

# Via openssl (sur un domaine)
echo | openssl s_client -servername mondomaine.com -connect mondomaine.com:443 2>/dev/null | openssl x509 -noout -dates

# Via openssl (fichier local)
sudo openssl x509 -enddate -noout -in /etc/letsencrypt/live/mondomaine.com/cert.pem

Renouvellement automatique avec Certbot

Vérifier le timer systemd

Certbot installe automatiquement un timer :

# Vérifier que le timer est actif
sudo systemctl status certbot.timer

# Voir les timers programmés
sudo systemctl list-timers | grep certbot

Tester le renouvellement

# Test sans renouveler réellement
sudo certbot renew --dry-run

Si le test réussit, le renouvellement automatique fonctionnera.

Configuration du renouvellement

Le fichier de configuration se trouve dans /etc/letsencrypt/renewal/mondomaine.com.conf :

[renewalparams]
authenticator = nginx
account = xxxxxxxxxxxxx
server = https://acme-v02.api.letsencrypt.org/directory

[webroot]
# ou autres options selon votre configuration

Hooks de renouvellement

Les hooks permettent d'exécuter des commandes avant/après le renouvellement.

Structure des hooks

/etc/letsencrypt/renewal-hooks/
├── pre/ # Avant le renouvellement
├── deploy/ # Après un renouvellement réussi
└── post/ # Après le renouvellement (succès ou échec)

Hook pour recharger Nginx

sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash
systemctl reload nginx
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Hook pour recharger Apache

sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-apache.sh
#!/bin/bash
systemctl reload apache2
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-apache.sh

Hook de notification

sudo nano /etc/letsencrypt/renewal-hooks/deploy/notify.sh
#!/bin/bash

DOMAIN=$RENEWED_DOMAINS
EXPIRY=$(openssl x509 -enddate -noout -in "$RENEWED_LINEAGE/cert.pem" | cut -d= -f2)

# Notification par email
echo "Le certificat pour $DOMAIN a été renouvelé. Nouvelle expiration: $EXPIRY" | \
mail -s "SSL renouvelé: $DOMAIN" admin@votredomaine.com

# Notification Discord (optionnel)
curl -H "Content-Type: application/json" \
-d "{\"content\": \"Le certificat SSL pour **$DOMAIN** a été renouvelé. Expire le: $EXPIRY\"}" \
"VOTRE_WEBHOOK_DISCORD"
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/notify.sh

Renouvellement avec Cron (alternative)

Si le timer systemd ne fonctionne pas :

sudo crontab -e
# Renouvellement SSL 2x par jour
0 3,15 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx"

Monitoring des certificats

Script de vérification

sudo nano /usr/local/bin/check-ssl.sh
#!/bin/bash

ALERT_DAYS=14
EMAIL="admin@votredomaine.com"

for cert in /etc/letsencrypt/live/*/cert.pem; do
DOMAIN=$(basename $(dirname $cert))

EXPIRY_DATE=$(openssl x509 -enddate -noout -in "$cert" | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))

if [ $DAYS_LEFT -lt $ALERT_DAYS ]; then
echo "ALERTE: $DOMAIN expire dans $DAYS_LEFT jours ($EXPIRY_DATE)" | \
mail -s "SSL ALERTE: $DOMAIN" $EMAIL
fi

echo "$DOMAIN: $DAYS_LEFT jours restants"
done
sudo chmod +x /usr/local/bin/check-ssl.sh

Ajouter au cron :

# Vérification quotidienne à 9h
0 9 * * * /usr/local/bin/check-ssl.sh

Monitoring avec curl

Vérifier un certificat distant :

#!/bin/bash
# check-remote-ssl.sh

DOMAIN="$1"
ALERT_DAYS=14

EXPIRY=$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | \
openssl x509 -noout -enddate | cut -d= -f2)

EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))

echo "$DOMAIN: $DAYS_LEFT jours restants (expire le $EXPIRY)"

if [ $DAYS_LEFT -lt $ALERT_DAYS ]; then
exit 1 # Pour alerter dans un système de monitoring
fi

Dépannage

Le renouvellement échoue

Erreur de validation HTTP

# Vérifier que le challenge est accessible
curl http://mondomaine.com/.well-known/acme-challenge/test

# Vérifier la configuration Nginx
location /.well-known/acme-challenge/ {
root /var/www/html;
}

Port 80 bloqué

# Vérifier que le port 80 est ouvert
sudo ufw status | grep 80
sudo ufw allow 80/tcp

Trop de tentatives (rate limit)

Let's Encrypt limite à 5 échecs par heure. Attendez avant de réessayer.

# Utiliser le serveur de staging pour les tests
sudo certbot certonly --staging -d mondomaine.com

Forcer le renouvellement

# Renouveler un certificat spécifique
sudo certbot renew --cert-name mondomaine.com --force-renewal

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

Vérifier les logs

# Logs Certbot
sudo cat /var/log/letsencrypt/letsencrypt.log

# Logs récents
sudo journalctl -u certbot -f

Certificats Wildcard

Les certificats wildcard nécessitent une validation DNS :

sudo certbot certonly --manual --preferred-challenges dns -d "*.mondomaine.com" -d "mondomaine.com"

Automatisation avec API DNS

Pour Cloudflare :

sudo apt install python3-certbot-dns-cloudflare

Créer le fichier de credentials :

sudo nano /etc/letsencrypt/cloudflare.ini
dns_cloudflare_api_token = VOTRE_TOKEN_API
sudo chmod 600 /etc/letsencrypt/cloudflare.ini

Obtenir le certificat :

sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d "*.mondomaine.com" \
-d "mondomaine.com"

Bonnes pratiques

  1. Toujours tester avec --dry-run avant de modifier la configuration
  2. Configurer des alertes pour être prévenu avant l'expiration
  3. Utiliser les hooks deploy plutôt que post pour les actions post-renouvellement
  4. Garder le port 80 ouvert même si vous redirigez vers HTTPS
  5. Monitorer les logs régulièrement
Conseil

Les certificats Let's Encrypt sont valides 90 jours. Certbot renouvelle automatiquement quand il reste moins de 30 jours.