Ce guide montre comment automatiser le renouvellement de certificats TLS sans redémarrage de service. Vous allez déployer Traefik avec des certificats émis par Vault PKI, renouvelés automatiquement par Vault Agent, et rechargés dynamiquement par Traefik.
À la fin de ce guide, vous saurez :
- Configurer Vault PKI pour émettre des certificats courts (5 min pour la démo)
- Utiliser Vault Agent pour écrire
cert.pemetkey.pemsur disque - Configurer Traefik pour recharger les certificats sans restart
- Observer le renouvellement automatique en action
Prérequis : Docker Compose, un terminal Linux/macOS.
Pourquoi combiner Vault PKI, Vault Agent et Traefik ?
Section intitulée « Pourquoi combiner Vault PKI, Vault Agent et Traefik ? »Le problème des certificats statiques
Section intitulée « Le problème des certificats statiques »La gestion classique des certificats TLS pose plusieurs problèmes :
| Problème | Conséquence |
|---|---|
| Certificats longue durée (1-2 ans) | Fenêtre d’exploitation large si compromis |
| Renouvellement manuel | Oublis, expirations, interruptions de service |
| Clés privées dans les repos/configs | Risque de fuite |
| Redémarrage requis pour recharger | Downtime lors du renouvellement |
Ce que cette intégration change
Section intitulée « Ce que cette intégration change »Avec Vault PKI + Vault Agent + Traefik :
| Aspect | Avant | Après |
|---|---|---|
| Durée de vie | 1-2 ans | 24h-72h (ou moins) |
| Renouvellement | Manuel | Automatique |
| Impact sur le service | Restart requis | Aucun (rechargement dynamique) |
| Stockage des clés | Statique | Éphémère (généré à la demande) |
Architecture de la démo
Section intitulée « Architecture de la démo »Voici comment les composants interagissent :
Le flux complet :
- Vault PKI émet un certificat TLS avec un TTL court
- Vault Agent écrit
cert.pem,key.pemet met à jourtls.yml - Traefik détecte le changement de
tls.ymlet recharge les certificats - Le service (whoami) reste accessible sans interruption
- Avant expiration, Vault Agent répète le cycle
Ce que Traefik sait recharger dynamiquement
Section intitulée « Ce que Traefik sait recharger dynamiquement »Traefik distingue deux types de configuration :
| Type | Exemples | Rechargeable à chaud ? |
|---|---|---|
| Statique | Entrypoints, providers, logs | ❌ Non (restart requis) |
| Dynamique | Routers, services, middlewares, TLS | ✅ Oui |
Les certificats TLS font partie de la configuration dynamique. Traefik
peut les recharger sans redémarrage grâce au file provider avec
l’option watch: true.
Préparer l’environnement de démo
Section intitulée « Préparer l’environnement de démo »Créer la structure du projet
Section intitulée « Créer la structure du projet »-
Créer les répertoires :
Fenêtre de terminal mkdir -p lab-vault-traefik/{vault-agent,traefik/{dynamic,certs},scripts}cd lab-vault-traefik -
Créer le fichier
docker-compose.yml:docker-compose.yml services:# Vault en mode dev pour la démovault:image: hashicorp/vault:1.18container_name: vaultcap_add:- IPC_LOCKenvironment:VAULT_DEV_ROOT_TOKEN_ID: rootVAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200VAULT_ADDR: http://127.0.0.1:8200ports:- "8200:8200"networks:- vault-traefikhealthcheck:test: ["CMD", "vault", "status"]interval: 5stimeout: 3sretries: 10# Service de démowhoami:image: traefik/whoami:latestcontainer_name: whoaminetworks:- vault-traefik# Traefik avec file providertraefik:image: traefik:v3.3container_name: traefikcommand:- "--api.insecure=true"- "--providers.file.directory=/etc/traefik/dynamic"- "--providers.file.watch=true"- "--entrypoints.web.address=:80"- "--entrypoints.websecure.address=:443"- "--log.level=INFO"ports:- "9080:80"- "9443:443"- "9088:8080" # Dashboardvolumes:- ./traefik/dynamic:/etc/traefik/dynamic:ro- ./traefik/certs:/etc/traefik/certs:ronetworks:- vault-traefikdepends_on:- whoami# Vault Agent pour le renouvellement des certificatsvault-agent:image: hashicorp/vault:1.18container_name: vault-agententrypoint: ["vault", "agent", "-config=/etc/vault-agent/config.hcl"]environment:VAULT_ADDR: http://vault:8200volumes:- ./vault-agent:/etc/vault-agent:ro- ./traefik/certs:/output/certs- ./traefik/dynamic:/output/dynamic- vault-agent-token:/run/vaultnetworks:- vault-traefikdepends_on:vault:condition: service_healthynetworks:vault-traefik:driver: bridgevolumes:vault-agent-token: -
Créer un certificat placeholder pour le démarrage initial :
Fenêtre de terminal openssl req -x509 -nodes -days 1 -newkey rsa:2048 \-keyout traefik/certs/key.pem \-out traefik/certs/cert.pem \-subj "/CN=placeholder.local.test"
Ce certificat temporaire permet à Traefik de démarrer. Vault Agent le remplacera par un vrai certificat signé par Vault PKI.
Configurer Traefik
Section intitulée « Configurer Traefik »Configuration dynamique des routes
Section intitulée « Configuration dynamique des routes »Créez le fichier de routes pour le service whoami :
http: routers: whoami: rule: Host(`whoami.local.test`) service: whoami entryPoints: - websecure tls: {}
# Redirection HTTP vers HTTPS whoami-redirect: rule: Host(`whoami.local.test`) service: whoami entryPoints: - web middlewares: - redirect-to-https
middlewares: redirect-to-https: redirectScheme: scheme: https permanent: true
services: whoami: loadBalancer: servers: - url: http://whoami:80Configurer Vault Agent
Section intitulée « Configurer Vault Agent »Configuration principale
Section intitulée « Configuration principale »Vault Agent utilise AppRole pour s’authentifier auprès de Vault et des templates pour écrire les certificats sur disque.
vault { address = "http://vault:8200"}
auto_auth { method "approle" { mount_path = "auth/approle" config = { role_id_file_path = "/etc/vault-agent/role_id" secret_id_file_path = "/etc/vault-agent/secret_id" remove_secret_id_file_after_reading = false } }
sink "file" { config = { path = "/run/vault/token" mode = 0644 } }}
# Template pour le certificat (cert.pem)template { source = "/etc/vault-agent/cert.tpl" destination = "/output/certs/cert.pem" perms = 0644}
# Template pour la clé privée (key.pem)template { source = "/etc/vault-agent/key.tpl" destination = "/output/certs/key.pem" perms = 0600}
# Template TLS pour Traefik - force le rechargement du file providertemplate { source = "/etc/vault-agent/traefik-tls.tpl" destination = "/output/dynamic/tls.yml" perms = 0644}
template_config { static_secret_render_interval = "5m" exit_on_retry_failure = true}Templates pour les certificats
Section intitulée « Templates pour les certificats »Ces templates demandent un nouveau certificat à Vault PKI et extraient les données nécessaires.
Template pour le certificat (cert.pem) :
{{- with secret "pki_int/issue/traefik-web" "common_name=whoami.local.test" "alt_names=whoami.local.test" "ttl=5m" -}}{{ .Data.certificate }}{{ .Data.issuing_ca }}{{- end -}}Template pour la clé privée (key.pem) :
{{- with secret "pki_int/issue/traefik-web" "common_name=whoami.local.test" "alt_names=whoami.local.test" "ttl=5m" -}}{{ .Data.private_key }}{{- end -}}Template pour la config TLS Traefik (tls.yml) :
{{- with secret "pki_int/issue/traefik-web" "common_name=whoami.local.test" "alt_names=whoami.local.test" "ttl=5m" -}}# Configuration TLS - regénéré automatiquement par Vault Agent# Serial: {{ .Data.serial_number }}# Expiration: {{ .Data.expiration }}
tls: certificates: - certFile: /etc/traefik/certs/cert.pem keyFile: /etc/traefik/certs/key.pem
stores: default: defaultCertificate: certFile: /etc/traefik/certs/cert.pem keyFile: /etc/traefik/certs/key.pem{{- end -}}Configurer Vault PKI
Section intitulée « Configurer Vault PKI »Script d’initialisation
Section intitulée « Script d’initialisation »Ce script configure Vault PKI (Root CA + Intermediate CA), crée un rôle pour Traefik, et génère les credentials AppRole pour Vault Agent.
#!/bin/bashset -e
echo "=== Configuration Vault PKI + AppRole pour Traefik ==="
# Fonction pour exécuter vault via dockervault() { docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=root vault vault "$@"}
# 1. Activer et configurer PKI Root CAecho ">>> 1. Activation PKI Root CA..."vault secrets enable -path=pki pki 2>/dev/null || echo " (pki déjà activé)"vault secrets tune -max-lease-ttl=87600h pki
vault write -field=certificate pki/root/generate/internal \ common_name="Demo Root CA" \ issuer_name="root-ca" \ ttl=87600h > /dev/null
vault write pki/config/urls \ issuing_certificates="http://vault:8200/v1/pki/ca" \ crl_distribution_points="http://vault:8200/v1/pki/crl"
echo " ✓ PKI Root CA configuré"
# 2. Activer et configurer PKI Intermediate CAecho ">>> 2. Activation PKI Intermediate CA..."vault secrets enable -path=pki_int pki 2>/dev/null || echo " (pki_int déjà activé)"vault secrets tune -max-lease-ttl=43800h pki_int
vault write -field=csr pki_int/intermediate/generate/internal \ common_name="Demo Intermediate CA" \ issuer_name="intermediate-ca" \ > /tmp/pki_int.csr
vault write -field=certificate pki/root/sign-intermediate \ csr=@/tmp/pki_int.csr \ format=pem_bundle \ ttl="43800h" \ > /tmp/int.cert.pem
vault write pki_int/intermediate/set-signed \ certificate=@/tmp/int.cert.pem
echo " ✓ PKI Intermediate CA configuré"
# 3. Créer le rôle PKI pour Traefikecho ">>> 3. Création du rôle PKI 'traefik-web'..."vault write pki_int/roles/traefik-web \ allowed_domains="local.test" \ allow_subdomains=true \ allow_bare_domains=false \ max_ttl="24h" \ ttl="5m" # TTL court pour la démo
echo " ✓ Rôle traefik-web créé (TTL: 5 min)"
# 4. Créer la policy pour Vault Agentecho ">>> 4. Création de la policy 'traefik-pki'..."vault policy write traefik-pki - <<POLICYpath "pki_int/issue/traefik-web" { capabilities = ["create", "update"]}POLICYecho " ✓ Policy traefik-pki créée"
# 5. Activer et configurer AppRoleecho ">>> 5. Configuration AppRole..."vault auth enable approle 2>/dev/null || echo " (approle déjà activé)"
vault write auth/approle/role/traefik-agent \ token_policies="traefik-pki" \ token_ttl=1h \ token_max_ttl=4h \ secret_id_ttl=0
echo " ✓ Rôle AppRole traefik-agent créé"
# 6. Récupérer les credentials AppRoleecho ">>> 6. Génération des credentials AppRole..."SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROLE_ID=$(vault read -field=role_id auth/approle/role/traefik-agent/role-id)SECRET_ID=$(vault write -f -field=secret_id auth/approle/role/traefik-agent/secret-id)
echo "$ROLE_ID" > "$SCRIPT_DIR/../vault-agent/role_id"echo "$SECRET_ID" > "$SCRIPT_DIR/../vault-agent/secret_id"
echo " ✓ Credentials sauvegardés dans vault-agent/"
echo ""echo "=== Configuration terminée ==="echo ""echo "Prochaines étapes :"echo " 1. docker compose up -d vault-agent"echo " 2. Ajouter '127.0.0.1 whoami.local.test' à /etc/hosts"echo " 3. curl -k https://whoami.local.test:9443"Rendez le script exécutable :
chmod +x scripts/init-vault.shDéployer et tester
Section intitulée « Déployer et tester »Lancer l’infrastructure
Section intitulée « Lancer l’infrastructure »-
Démarrer Vault, Traefik et whoami :
Fenêtre de terminal docker compose up -d vault whoami traefikAttendez que Vault soit healthy :
Fenêtre de terminal docker compose ps -
Configurer Vault PKI :
Fenêtre de terminal ./scripts/init-vault.shVous devriez voir :
=== Configuration terminée ===Prochaines étapes :1. docker compose up -d vault-agent2. Ajouter '127.0.0.1 whoami.local.test' à /etc/hosts3. curl -k https://whoami.local.test:9443 -
Démarrer Vault Agent :
Fenêtre de terminal docker compose up -d vault-agent -
Vérifier les certificats générés :
Fenêtre de terminal ls -la traefik/certs/Vous devriez voir
cert.pemetkey.pemavec des timestamps récents. -
Ajouter l’entrée DNS locale :
Fenêtre de terminal echo "127.0.0.1 whoami.local.test" | sudo tee -a /etc/hosts
Vérifier le certificat
Section intitulée « Vérifier le certificat »Examinez le certificat émis par Vault PKI :
openssl x509 -in traefik/certs/cert.pem -noout -subject -issuer -datesRésultat attendu :
subject=CN = whoami.local.testissuer=CN = Demo Intermediate CAnotBefore=Mar 16 16:56:40 2026 GMTnotAfter=Mar 16 17:01:40 2026 GMTLe certificat est signé par “Demo Intermediate CA” et valide 5 minutes.
Tester l’accès HTTPS
Section intitulée « Tester l’accès HTTPS »curl -k https://whoami.local.test:9443Résultat :
Hostname: 9b134b252f36IP: 127.0.0.1IP: 172.23.0.3RemoteAddr: 172.23.0.4:44418GET / HTTP/1.1Host: whoami.local.test:9443...Observer le renouvellement automatique
Section intitulée « Observer le renouvellement automatique »Surveiller les changements de certificat
Section intitulée « Surveiller les changements de certificat »Exécutez ce script pour observer le renouvellement :
echo "=== Observation du renouvellement ==="LAST_SERIAL=""while true; do SERIAL=$(openssl s_client -connect whoami.local.test:9443 \ -servername whoami.local.test </dev/null 2>/dev/null \ | openssl x509 -noout -serial | cut -d= -f2)
DATES=$(openssl s_client -connect whoami.local.test:9443 \ -servername whoami.local.test </dev/null 2>/dev/null \ | openssl x509 -noout -enddate | cut -d= -f2)
NOW=$(date "+%H:%M:%S")
if [[ "$SERIAL" != "$LAST_SERIAL" ]] && [[ -n "$LAST_SERIAL" ]]; then echo "" echo ">>> CERTIFICAT RENOUVELÉ ! <<<" echo "" fi
LAST_SERIAL="$SERIAL" echo "[$NOW] Serial: ${SERIAL:0:20}... | Expire: $DATES"
sleep 30doneAprès environ 3-4 minutes, vous verrez le certificat changer :
[17:57:07] Serial: 2F92FE700EA7F45AFAA8... | Expire: Mar 16 17:01:39 2026 GMT[17:57:37] Serial: 2F92FE700EA7F45AFAA8... | Expire: Mar 16 17:01:39 2026 GMT[17:58:07] Serial: 2F92FE700EA7F45AFAA8... | Expire: Mar 16 17:01:39 2026 GMT
>>> CERTIFICAT RENOUVELÉ ! <<<
[17:58:37] Serial: 5193A369CE35F6173E6F... | Expire: Mar 16 17:06:11 2026 GMTVérifier les logs de Vault Agent
Section intitulée « Vérifier les logs de Vault Agent »docker compose logs vault-agent --tail=20 | grep renderedVous verrez les moments de renouvellement :
vault-agent | 2026-03-16T16:56:40.091Z [INFO] agent: (runner) rendered "/etc/vault-agent/cert.tpl" => "/output/certs/cert.pem"vault-agent | 2026-03-16T16:56:40.094Z [INFO] agent: (runner) rendered "/etc/vault-agent/key.tpl" => "/output/certs/key.pem"vault-agent | 2026-03-16T16:56:40.096Z [INFO] agent: (runner) rendered "/etc/vault-agent/traefik-tls.tpl" => "/output/dynamic/tls.yml"vault-agent | 2026-03-16T17:01:11.620Z [INFO] agent: (runner) rendered "/etc/vault-agent/cert.tpl" => "/output/certs/cert.pem"vault-agent | 2026-03-16T17:01:11.623Z [INFO] agent: (runner) rendered "/etc/vault-agent/key.tpl" => "/output/certs/key.pem"vault-agent | 2026-03-16T17:01:11.625Z [INFO] agent: (runner) rendered "/etc/vault-agent/traefik-tls.tpl" => "/output/dynamic/tls.yml"Ce que cette démo montre réellement
Section intitulée « Ce que cette démo montre réellement »| Composant | Responsabilité |
|---|---|
| Vault PKI | Émet des certificats courts, signés par une CA interne |
| Vault Agent | Demande et renouvelle les certificats, écrit sur disque |
| Traefik | Sert le trafic HTTPS, recharge les certificats dynamiquement |
| whoami | Service de démo, ne connaît pas l’existence de Vault |
Points clés :
- Le service (
whoami) n’a aucune dépendance directe sur Vault - Traefik recharge les certificats sans redémarrage
- Vault Agent gère tout le cycle de vie des certificats
- Si Vault est temporairement indisponible, les certificats existants restent valides jusqu’à expiration
Limites et points d’attention en production
Section intitulée « Limites et points d’attention en production »Sécurité
Section intitulée « Sécurité »| Aspect | Recommandation |
|---|---|
| Clé privée | Protéger key.pem avec les permissions 0600 |
| AppRole secrets | Ne pas committer role_id/secret_id dans Git |
| Vault en mode dev | Utiliser un cluster Vault en production avec TLS |
Disponibilité
Section intitulée « Disponibilité »| Risque | Mitigation |
|---|---|
| Vault down au démarrage | Le certificat existant reste valide jusqu’à expiration |
| Vault down au renouvellement | Vault Agent réessaie. Prévoir un TTL assez long |
| Perte du stockage Vault | Backups réguliers, cluster HA |
Configuration
Section intitulée « Configuration »| Paramètre | Recommandation production |
|---|---|
| TTL certificat | 24h-72h (pas trop court pour éviter les paniques) |
| max_ttl | 7-30 jours selon les besoins |
| allowed_domains | Restreindre aux domaines réellement utilisés |
Adapter pour la production
Section intitulée « Adapter pour la production »TTL réaliste
Section intitulée « TTL réaliste »Modifiez le rôle PKI pour un TTL de 24h :
vault write pki_int/roles/traefik-web \ allowed_domains="votre-domaine.com" \ allow_subdomains=true \ max_ttl="168h" \ # 7 jours max ttl="24h" # 24h par défautTemplates de production
Section intitulée « Templates de production »Mettez à jour les templates avec votre domaine :
{{- with secret "pki_int/issue/traefik-web" "common_name=app.votre-domaine.com" "alt_names=app.votre-domaine.com,api.votre-domaine.com" "ttl=24h" -}}{{ .Data.certificate }}{{ .Data.issuing_ca }}{{- end -}}Authentification Kubernetes
Section intitulée « Authentification Kubernetes »En environnement Kubernetes, remplacez AppRole par l’auth Kubernetes :
auto_auth { method "kubernetes" { mount_path = "auth/kubernetes" config = { role = "traefik-pki" } } # ...}À retenir
Section intitulée « À retenir »- Vault PKI génère des certificats TLS courts et signés
- Vault Agent renouvelle automatiquement avant expiration
- Traefik recharge les certificats sans redémarrage grâce au file provider
- Le template tls.yml force Traefik à détecter le changement
- Le service backend n’a aucune dépendance sur Vault
- En production, utilisez des TTL de 24-72h et un Vault sécurisé