Guide Lego et Challenge DNS
Introduction
Lego est un client Let's Encrypt et une bibliothèque ACME écrite en Go. Il supporte nativement de nombreux providers DNS, dont PowerDNS, ce qui permet de générer des certificats SSL/TLS via le challenge DNS-01.
Documentation officielle : https://go-acme.github.io/lego/dns/
Avantages de Lego
- Écrit en Go : binaire statique unique, pas de dépendances runtime
- Support natif de nombreux providers DNS
- Performance élevée
- Idéal pour l'automatisation et l'intégration dans des pipelines CI/CD
- Compatible avec Docker et Kubernetes
Provider PowerDNS
En utilisant le provider DNS pdns (PowerDNS) de Lego avec l'endpoint SdV https://powerdns-endpoint-dns.sdv.fr/, vous pouvez générer facilement vos certificats SSL.
Installation
Téléchargement du binaire
# Télécharger la dernière version
wget https://github.com/go-acme/lego/releases/download/v4.14.2/lego_v4.14.2_linux_amd64.tar.gz
# Extraire l'archive
tar -xzf lego_v4.14.2_linux_amd64.tar.gz
# Déplacer le binaire dans le PATH
sudo mv lego /usr/local/bin/
# Vérifier l'installation
lego --versionInstallation via Docker
docker pull goacme/lego:latestVérification de l'installation
lego --version
# lego version 4.14.2 darwin/amd64Configuration
Variables d'environnement
Lego utilise des variables d'environnement pour la configuration du provider DNS PowerDNS.
Variables requises
| Variable | Description | Exemple |
|---|---|---|
PDNS_API_URL | URL de l'API PowerDNS | https://powerdns-endpoint-dns.sdv.fr/ |
PDNS_API_KEY | Clé d'API PowerDNS SdV | XXXXXX... |
Variables optionnelles
| Variable | Description | Défaut |
|---|---|---|
PDNS_TTL | TTL des records DNS créés | 120 |
PDNS_PROPAGATION_TIMEOUT | Temps max d'attente de propagation | 2m0s |
PDNS_POLLING_INTERVAL | Intervalle de vérification de propagation | 2s |
PDNS_HTTP_TIMEOUT | Timeout HTTP vers l'API | 30s |
Configuration des variables
export PDNS_API_URL=https://powerdns-endpoint-dns.sdv.fr/
export PDNS_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXPour une configuration persistante, ajoutez ces variables dans votre fichier de profil :
# Ajouter au ~/.bashrc ou ~/.zshrc
echo 'export PDNS_API_URL=https://powerdns-endpoint-dns.sdv.fr/' >> ~/.bashrc
echo 'export PDNS_API_KEY=XXXXXX...' >> ~/.bashrc
source ~/.bashrcObtention de la clé API
Pour obtenir votre clé API PowerDNS, contactez SdV via l'outil de ticket en fournissant :
- Liste des adresses IP sources autorisées
- Liste des domaines concernés
- Environnement (production, préproduction, développement)
- Contexte d'utilisation
Génération de certificats
Certificat simple
Génération d'un certificat pour un seul domaine :
lego --email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
--accept-tos \
runOptions principales
| Option | Description |
|---|---|
--email | Email de contact pour notifications Let's Encrypt |
--dns | Provider DNS à utiliser (pdns pour PowerDNS) |
--domains | Domaine(s) pour le certificat |
--accept-tos | Accepter les conditions d'utilisation Let's Encrypt |
run | Commande pour générer un nouveau certificat |
Certificat multi-domaines (SAN)
lego --email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
--domains www.monsite.fr \
--domains api.monsite.fr \
--accept-tos \
runCertificat wildcard
lego --email admin@monsite.fr \
--dns pdns \
--domains '*.monsite.fr' \
--domains monsite.fr \
--accept-tos \
runTest en environnement staging
Avant de générer un certificat production, testez avec l'environnement staging de Let's Encrypt :
lego --email admin@monsite.fr \
--dns pdns \
--domains test.monsite.fr \
--accept-tos \
--server https://acme-staging-v02.api.letsencrypt.org/directory \
runExemple d'exécution réussie
export PDNS_API_URL=https://powerdns-endpoint-dns.sdv.fr/
export PDNS_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
lego --email admin@monsite.fr --dns pdns --domains keycloak.monsite.fr --accept-tos run
2022/12/12 18:32:41 [INFO] [keycloak.monsite.fr] acme: Obtaining bundled SAN certificate
2022/12/12 18:32:41 [INFO] [keycloak.monsite.fr] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/186475346237
2022/12/12 18:32:41 [INFO] [keycloak.monsite.fr] acme: Could not find solver for: tls-alpn-01
2022/12/12 18:32:41 [INFO] [keycloak.monsite.fr] acme: Could not find solver for: http-01
2022/12/12 18:32:41 [INFO] [keycloak.monsite.fr] acme: use dns-01 solver
2022/12/12 18:32:41 [INFO] [keycloak.monsite.fr] acme: Preparing to solve DNS-01
2022/12/12 18:32:50 [INFO] [keycloak.monsite.fr] acme: Trying to solve DNS-01
2022/12/12 18:32:50 [INFO] [keycloak.monsite.fr] acme: Checking DNS record propagation using [208.67.222.222:53 208.67.220.220:53]
2022/12/12 18:32:52 [INFO] Wait for propagation [timeout: 2m0s, interval: 2s]
2022/12/12 18:32:52 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:32:54 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:32:56 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:32:58 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:33:00 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:33:02 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:33:04 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:33:06 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:33:08 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:33:10 [INFO] [keycloak.monsite.fr] acme: Waiting for DNS record propagation.
2022/12/12 18:33:18 [INFO] [keycloak.monsite.fr] The server validated our request
2022/12/12 18:33:18 [INFO] [keycloak.monsite.fr] acme: Cleaning DNS-01 challenge
2022/12/12 18:33:26 [INFO] [keycloak.monsite.fr] acme: Validations succeeded; requesting certificates
2022/12/12 18:33:27 [INFO] [keycloak.monsite.fr] Server responded with a certificate.Emplacement des certificats
Par défaut, Lego stocke les certificats dans le répertoire .lego du répertoire courant :
.lego/
├── accounts/
│ └── acme-v02.api.letsencrypt.org/
│ └── admin@monsite.fr/
│ ├── account.json
│ └── keys/
├── certificates/
│ ├── monsite.fr.crt # Certificat
│ ├── monsite.fr.key # Clé privée
│ ├── monsite.fr.issuer.crt # Certificat intermédiaire
│ └── monsite.fr.json # MétadonnéesPersonnaliser le chemin
lego --email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
--path /etc/lego \
--accept-tos \
runRenouvellement automatique
Renouvellement manuel
Lego gère automatiquement le renouvellement si le certificat expire dans moins de 30 jours :
lego --email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
renewOptions de renouvellement
| Option | Description |
|---|---|
--days | Nombre de jours avant expiration pour renouveler (défaut: 30) |
--reuse-key | Réutiliser la clé privée existante |
--renew-hook | Script à exécuter après renouvellement |
Renouvellement avec hook
lego --email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
--renew-hook "/usr/local/bin/reload-services.sh" \
renewExemple de script de hook /usr/local/bin/reload-services.sh :
#!/bin/bash
# Script exécuté après renouvellement réussi
DOMAIN="$LEGO_CERT_DOMAIN"
CERT_PATH="$LEGO_CERT_PATH"
KEY_PATH="$LEGO_CERT_KEY_PATH"
# Copier les certificats vers le serveur web
cp "$CERT_PATH" /etc/nginx/ssl/
cp "$KEY_PATH" /etc/nginx/ssl/
# Recharger Nginx
systemctl reload nginx
logger "Certificat $DOMAIN renouvelé et Nginx rechargé"Rendre le script exécutable :
chmod +x /usr/local/bin/reload-services.shAutomatisation via cron
Créez un cron job pour renouveler automatiquement les certificats :
# Éditer la crontab
crontab -e
# Ajouter la ligne suivante (exécution tous les jours à 3h du matin)
0 3 * * * PDNS_API_URL=https://powerdns-endpoint-dns.sdv.fr/ PDNS_API_KEY=XXXX /usr/local/bin/lego --email admin@monsite.fr --dns pdns --domains monsite.fr --renew-hook /usr/local/bin/reload-services.sh renew >> /var/log/lego-renew.log 2>&1Automatisation via systemd timer
Créer le service
Fichier /etc/systemd/system/lego-renew.service :
[Unit]
Description=Renew Let''s Encrypt certificates using Lego
After=network-online.target
[Service]
Type=oneshot
Environment="PDNS_API_URL=https://powerdns-endpoint-dns.sdv.fr/"
Environment="PDNS_API_KEY=XXXXXX"
ExecStart=/usr/local/bin/lego --email admin@monsite.fr --dns pdns --domains monsite.fr --renew-hook /usr/local/bin/reload-services.sh renew
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.targetCréer le timer
Fichier /etc/systemd/system/lego-renew.timer :
[Unit]
Description=Daily renewal of Let''s Encrypt certificates
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.targetActiver le timer
# Recharger systemd
systemctl daemon-reload
# Activer le timer
systemctl enable lego-renew.timer
# Démarrer le timer
systemctl start lego-renew.timer
# Vérifier le statut
systemctl status lego-renew.timer
systemctl list-timers lego-renew.timerUtilisation avec Docker
Génération de certificat
docker run --rm \
-v $(pwd)/.lego:/root/.lego \
-e PDNS_API_URL=https://powerdns-endpoint-dns.sdv.fr/ \
-e PDNS_API_KEY=XXXXXX \
goacme/lego:latest \
--email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
--accept-tos \
runRenouvellement avec Docker
docker run --rm \
-v $(pwd)/.lego:/root/.lego \
-e PDNS_API_URL=https://powerdns-endpoint-dns.sdv.fr/ \
-e PDNS_API_KEY=XXXXXX \
goacme/lego:latest \
--email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
renewDocker Compose
Fichier docker-compose.yml :
services:
lego:
image: goacme/lego:latest
volumes:
- ./lego:/root/.lego
environment:
- PDNS_API_URL=https://powerdns-endpoint-dns.sdv.fr/
- PDNS_API_KEY=${PDNS_API_KEY}
command: >
--email admin@monsite.fr
--dns pdns
--domains monsite.fr
--accept-tos
runExécution :
# Définir la clé API
export PDNS_API_KEY=XXXXXX
# Générer le certificat
docker-compose run --rm lego
# Renouveler
docker-compose run --rm lego \
--email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
renewIntégration Kubernetes
ConfigMap pour la configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: lego-config
namespace: cert-manager
data:
email: admin@monsite.fr
pdns-api-url: https://powerdns-endpoint-dns.sdv.fr/Secret pour la clé API
kubectl create secret generic lego-pdns-secret \
--from-literal=api-key=XXXXXX \
-n cert-managerCronJob pour renouvellement
apiVersion: batch/v1
kind: CronJob
metadata:
name: lego-renew
namespace: cert-manager
spec:
schedule: "0 3 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: lego
image: goacme/lego:latest
args:
- --email
- admin@monsite.fr
- --dns
- pdns
- --domains
- monsite.fr
- --path
- /lego
- renew
env:
- name: PDNS_API_URL
valueFrom:
configMapKeyRef:
name: lego-config
key: pdns-api-url
- name: PDNS_API_KEY
valueFrom:
secretKeyRef:
name: lego-pdns-secret
key: api-key
volumeMounts:
- name: lego-data
mountPath: /lego
volumes:
- name: lego-data
persistentVolumeClaim:
claimName: lego-pvc
restartPolicy: OnFailureTroubleshooting
Erreurs courantes
Erreur d'authentification API
error: failed to create challenge: 401 UnauthorizedVérifications :
# Vérifier les variables d'environnement
echo $PDNS_API_URL
echo $PDNS_API_KEY
# Tester l'accès à l'API
curl -H "X-API-Key: $PDNS_API_KEY" "$PDNS_API_URL/api/v1/servers"Timeout de propagation DNS
error: challenge validation failed: DNS problem: query timed outAugmenter le timeout de propagation :
export PDNS_PROPAGATION_TIMEOUT=5m
export PDNS_POLLING_INTERVAL=5s
lego --email admin@monsite.fr --dns pdns --domains monsite.fr runCertificat déjà existant
error: Certificate already exists for domainForcer le renouvellement :
lego --email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
renew --days 90Mode debug
Activer le mode verbose pour diagnostic :
lego --email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
--accept-tos \
run \
--dns.resolvers 8.8.8.8:53 \
--http.timeout 60Vérification DNS manuelle
# Vérifier la présence du record TXT
dig _acme-challenge.monsite.fr TXT +short
# Interroger les serveurs DNS SdV directement
dig @ns1.sdv.fr _acme-challenge.monsite.fr TXT +shortBonnes pratiques
Sécurité
Protection de la clé API
- Ne jamais committer la clé API dans un repository Git
- Utiliser des variables d'environnement ou un gestionnaire de secrets
- Limiter les permissions de la clé aux domaines strictement nécessaires
- Renouveler régulièrement la clé API
Stockage des certificats
- Protéger les clés privées avec des permissions restrictives (chmod 600)
- Stocker les certificats dans un emplacement sécurisé
- Sauvegarder régulièrement les certificats et clés
# Sécuriser les permissions
chmod 600 .lego/certificates/*.key
chmod 644 .lego/certificates/*.crtOpérationnel
Tests en staging
- Toujours tester avec l'environnement staging avant la production
- Valider le processus de renouvellement en staging
Monitoring
- Surveiller les dates d'expiration des certificats
- Alerter en cas d'échec de renouvellement
- Logger toutes les opérations
Automatisation
- Préférer le renouvellement automatique
- Utiliser des hooks pour déployer automatiquement les certificats
- Intégrer dans votre CI/CD
Architecture
Gestion multi-environnements
| Environnement | Domaine | Clé API | Serveur |
|---|---|---|---|
| Production | monsite.fr, *.monsite.fr | prod_api_key | prod-cert-01 |
| Préproduction | preprod.monsite.fr | preprod_api_key | preprod-cert-01 |
| Développement | dev.monsite.fr | dev_api_key | dev-cert-01 |
Haute disponibilité
- Centraliser le stockage des certificats (NFS, S3, etc.)
- Synchroniser les certificats entre serveurs
- Prévoir un mécanisme de fallback
Points d'attention
Différences avec CertBot
- Lego utilise l'API PowerDNS complète (toutes permissions)
- CertBot SdV utilise une API restreinte (uniquement records
_acme-challenge) - Lego est plus adapté à l'automatisation et aux conteneurs
- CertBot est plus adapté aux installations traditionnelles sur serveur
Permissions PowerDNS
La clé API PowerDNS utilisée par Lego permet de :
- Créer, modifier et supprimer des records DNS
- Gérer les zones DNS complètes
- Modifier la configuration des zones
Implications :
- Une clé compromise peut impacter l'ensemble de vos zones DNS
- Utilisez des clés dédiées par environnement
- Limitez les IP sources autorisées
- Auditez régulièrement l'utilisation des clés
Rate limiting Let's Encrypt
Les mêmes limites que CertBot s'appliquent :
| Type de limite | Valeur | Période |
|---|---|---|
| Certificats par domaine enregistré | 50 | 7 jours |
| Noms par certificat | 100 | - |
| Échecs de validation | 5 | 1 heure |
Recommandation : Utiliser l'environnement staging pour les tests.
Commandes utiles
Gestion des certificats
# Lister les certificats
ls -lh .lego/certificates/
# Afficher les détails d'un certificat
openssl x509 -in .lego/certificates/monsite.fr.crt -text -noout
# Vérifier la date d'expiration
openssl x509 -in .lego/certificates/monsite.fr.crt -noout -enddate
# Vérifier la chaîne de certification
openssl verify -CAfile .lego/certificates/monsite.fr.issuer.crt .lego/certificates/monsite.fr.crtTest SSL en production
# Tester le certificat SSL
openssl s_client -connect monsite.fr:443 -servername monsite.fr
# Vérifier l'émetteur
echo | openssl s_client -connect monsite.fr:443 -servername monsite.fr 2>/dev/null | openssl x509 -noout -issuer
# Tester avec curl
curl -vI https://monsite.frRévocation de certificat
lego --email admin@monsite.fr \
--dns pdns \
--domains monsite.fr \
revokeContact et support
En cas de problème ou pour améliorer cette documentation, contactez :
- Support SdV : Outil de ticket
- Documentation Lego : https://go-acme.github.io/lego/
- Repository Lego : https://github.com/go-acme/lego