Traefik est réputé pour émettre des certificats automatiquement via ACME. Mais il arrive que vous ayez besoin d’utiliser votre propre certificat à la place — émis par GetHTTPS, une CA d’entreprise/interne, ou un certificat wildcard que vous gérez ailleurs. Ce guide vous montre exactement comment faire, sur Traefik v3.
L’essentiel à comprendre d’emblée : vous ne pouvez pas associer un fichier de certificat avec un label Docker. Les labels Traefik contrôlent le routage et activent TLS, mais le certificat lui-même doit provenir du provider de fichiers sous forme de configuration dynamique. C’est ce qui piège presque tout le monde la première fois. Nous allons le faire de la bonne manière.
Si vous n’avez pas encore de certificat, obtenez-en un gratuitement en 5 minutes.
Quand l’utiliser (par rapport à l’ACME automatique de Traefik)
| Utiliser l’ACME automatique (Let’s Encrypt) | Apporter votre propre certificat (ce guide) |
|---|---|
| Site web public, accessible depuis Internet | Service interne/intranet (pas de DNS public) |
| Un certificat DV standard convient | Vous avez besoin d’une CA spécifique, d’un wildcard ou d’un certificat OV/EV |
| Traefik peut résoudre le challenge HTTP/DNS | Hôte isolé (air-gapped) ou derrière un pare-feu |
| Vous voulez zéro gestion de certificat | Vous avez déjà un certificat de GetHTTPS ou d’ailleurs |
Si l’ACME automatique correspond à votre cas, le certificatesResolvers de Traefik est plus simple. Ce guide concerne le cas « j’ai déjà fullchain.pem + privkey.pem et j’ai besoin que Traefik les serve ».
Prérequis
- Traefik v3 s’exécutant comme conteneur Docker (la configuration ci-dessous utilise Docker, mais la partie configuration dynamique s’applique à n’importe quel environnement)
- Vos fichiers de certificat — au nombre de deux :
fullchain.pem— votre certificat + la chaîne intermédiaireprivkey.pem— votre clé privée
- Un domaine pointant vers l’hôte (ou une entrée dans le fichier hosts local pour un usage interne)
De quels fichiers Traefik a-t-il besoin ? Traefik attend la chaîne complète dans
certFileet la clé danskeyFile. Si vous utilisez uncert.pemcontenant uniquement le certificat feuille, les clients reçoivent des erreurs de « chaîne incomplète » — Traefik n’ajoute pas automatiquement les intermédiaires pour les certificats du provider de fichiers. Utilisezfullchain.pem. Les formats de certificat expliqués →
Comment la configuration de Traefik est répartie
Traefik possède deux types de configuration, et les certificats résident dans le second :
- Configuration statique — définie au démarrage (entrypoints, providers). La modifier nécessite un redémarrage. Cela va dans
traefik.ymlou dans les flags de commande du conteneur. - Configuration dynamique — rechargée à chaud sans redémarrage (routers, services, certificats TLS). C’est ce que lit le provider de fichiers.
Votre certificat relève de la configuration dynamique. Voilà pourquoi un label ne peut pas le porter — les labels sont lus depuis le provider Docker, mais tls.certificates est un concept du provider de fichiers.
Étape 1 : Placer les fichiers de certificat
Placez les fichiers dans un répertoire que vous monterez dans le conteneur :
mkdir -p ./traefik/certs
cp fullchain.pem ./traefik/certs/
cp privkey.pem ./traefik/certs/
# Verrouiller la clé privée
chmod 600 ./traefik/certs/privkey.pem
chmod 644 ./traefik/certs/fullchain.pem
Étape 2 : Écrire la configuration dynamique
Créez ./traefik/dynamic/certs.yml. C’est ici que vous déclarez votre certificat :
# ./traefik/dynamic/certs.yml (configuration dynamique — provider de fichiers)
tls:
certificates:
- certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
# Optionnel : faire de ce certificat celui par défaut pour tout hôte
# qui ne correspond à aucun certificat plus spécifique (par ex. un wildcard ou une CA interne).
stores:
default:
defaultCertificate:
certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
Les chemins (/certs/...) sont des chemins à l’intérieur du conteneur — nous les montons à l’étape suivante. Traefik sélectionne le bon certificat pour chaque requête à l’aide de SNI, en comparant le SAN du certificat au nom d’hôte demandé. Le defaultCertificate est le repli lorsque rien d’autre ne correspond.
Étape 3 : Configurer Traefik (config statique + montages)
Voici un docker-compose.yml complet. Les entrypoints et le provider de fichiers relèvent de la config statique (passés comme flags de commande) ; le certificat est chargé depuis le fichier dynamique que vous venez d’écrire.
services:
traefik:
image: traefik:v3.3
container_name: traefik
restart: unless-stopped
command:
# ─── Entrypoints ───────────────────────────────
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Rediriger tout le trafic HTTP → HTTPS au niveau de l'entrypoint
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
# ─── Providers ─────────────────────────────────
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
# Le provider de fichiers surveille le répertoire de configuration dynamique
- "--providers.file.directory=/dynamic"
- "--providers.file.watch=true"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./traefik/certs:/certs:ro"
- "./traefik/dynamic:/dynamic:ro"
# ─── Service backend d'exemple ──────────────────────
whoami:
image: traefik/whoami
container_name: whoami
labels:
- "traefik.enable=true"
# Router : correspond à l'hôte, sert sur l'entrypoint HTTPS
- "traefik.http.routers.whoami.rule=Host(`example.com`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
# Activer TLS sur ce router — le certificat provient de la
# configuration dynamique, PAS d'un label.
- "traefik.http.routers.whoami.tls=true"
La ligne critique est traefik.http.routers.whoami.tls=true. Elle indique à Traefik « sers ce router via TLS. » Traefik choisit alors le certificat correspondant dans le store du provider de fichiers par SNI. Il n’existe aucun label du type tls.certfile — cela n’existe pas pour les routers.
Étape 4 : Démarrer et vérifier
docker compose up -d
docker compose logs -f traefik
Surveillez le chargement de votre certificat par le provider de fichiers. Vous ne devriez pas voir d’erreurs TLS. Vérifiez ensuite :
Vérification dans le navigateur
Visitez https://example.com. Cliquez sur le cadenas :
- Émis par — votre CA (Let’s Encrypt pour GetHTTPS, ou votre CA interne)
- Validité — dates de début et de fin
- Domaine — correspond à l’URL
Vérification en ligne de commande
# Confirmer que Traefik sert VOTRE certificat, et non son certificat auto-signé par défaut
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
Si vous voyez CN=TRAEFIK DEFAULT CERT, Traefik est revenu à son certificat placeholder intégré — votre certificat n’a pas été chargé. Consultez la section Dépannage ci-dessous.
Étape 5 (optionnelle) : Renforcer TLS
Pour contrôler les versions de protocole et les suites de chiffrement, ajoutez un bloc d’options TLS à votre configuration dynamique et référencez-le depuis le router. Ajoutez à certs.yml :
tls:
options:
modern:
minVersion: VersionTLS12
sniStrict: true
Puis sur le label du router :
- "traefik.http.routers.whoami.tls.options=modern@file"
Le suffixe @file indique à Traefik que ce jeu d’options provient du provider de fichiers. Cela vous restreint à TLS 1.2 et 1.3 et rejette les connexions sans SNI correspondant.
HSTS : Ajoutez l’en-tête
Strict-Transport-Securityvia un middlewareheadersde Traefik une fois que vous êtes certain que HTTPS fonctionne partout. Guide HSTS →
Comment renouveler
Traefik ne renouvelle pas automatiquement les certificats que vous fournissez vous-même — c’est la contrepartie du fait d’apporter le vôtre. Lorsque votre certificat approche de son expiration (jour 60 sur 90 pour Let’s Encrypt) :
- Obtenez un nouveau certificat auprès de GetHTTPS (ou de votre outil de renouvellement).
- Écrasez les fichiers sur place :
cp new-fullchain.pem ./traefik/certs/fullchain.pem cp new-privkey.pem ./traefik/certs/privkey.pem - Rien d’autre. Comme
--providers.file.watch=trueest défini, Traefik détecte la modification du fichier et recharge le certificat à chaud — aucun redémarrage, aucune interruption. C’est l’une des plus belles propriétés de Traefik pour les certificats personnalisés.
Guide complet de renouvellement →
Dépannage
Traefik sert « TRAEFIK DEFAULT CERT » au lieu du mien
Cause : Traefik n’a pas pu charger votre certificat, il est donc revenu à son certificat auto-signé placeholder. C’est presque toujours un problème de chemin ou de montage.
Solution :
# 1. Confirmer que les fichiers existent À L'INTÉRIEUR du conteneur au chemin attendu
docker compose exec traefik ls -l /certs
# 2. Confirmer que le fichier dynamique est monté et lisible
docker compose exec traefik cat /dynamic/certs.yml
# 3. Vérifier les logs pour connaître la vraie raison
docker compose logs traefik | grep -i "certificate\|tls\|error"
Les chemins certFile/keyFile dans certs.yml doivent correspondre aux chemins du conteneur (/certs/...), et non à vos chemins sur l’hôte.
« unable to find certificate for domain » / mauvais certificat servi
Cause : Le SAN d’aucun certificat ne correspond au nom d’hôte demandé, et aucun defaultCertificate n’est défini.
Solution : Soit ajoutez le nom d’hôte à votre certificat, soit définissez un defaultCertificate dans le bloc stores.default (Étape 2) afin que Traefik dispose d’un repli.
Le router renvoie une erreur 404, le certificat n’est même jamais vérifié
Cause : La règle du router ne correspond pas, ou le service n’est pas exposé. TLS n’a aucune importance tant que le routage ne correspond pas.
Solution :
# Vérifier que le router existe et est activé
docker compose exec traefik wget -qO- http://localhost:8080/api/http/routers 2>/dev/null | grep whoami
Assurez-vous que traefik.enable=true est présent sur le conteneur backend et que la règle Host() correspond au domaine que vous testez.
Les modifications de certs.yml ne prennent pas effet
Cause : Le provider de fichiers ne surveille pas, ou vous avez modifié la config statique (qui nécessite un redémarrage).
Solution : Confirmez que --providers.file.watch=true figure dans la config statique. N’oubliez pas : les entrypoints/providers sont statiques (redémarrage requis) ; les routers et tls.certificates sont dynamiques (rechargés à chaud).
« x509: certificate signed by unknown authority » du côté des clients
Cause : Chaîne incomplète — vous avez utilisé un cert.pem contenant uniquement le certificat feuille dans certFile au lieu de fullchain.pem.
Solution : Pointez certFile vers la chaîne complète. Si vous ne disposez que de fichiers séparés, concaténez-les (feuille en premier, puis intermédiaires) :
cat cert.pem intermediate.pem > fullchain.pem
Foire aux questions
Puis-je spécifier le fichier de certificat avec un label Docker ?
Non. C’est l’idée fausse n°1. Les labels définissent traefik.http.routers.<name>.tls=true pour activer TLS, mais les fichiers de certificat doivent être déclarés dans la configuration dynamique via le provider de fichiers (tls.certificates). Il n’existe aucun label de router qui pointe vers un fichier .pem.
Ai-je besoin de tls=true sur le router si j’ai un certificat ?
Oui. Déclarer le certificat dans tls.certificates le rend disponible, mais chaque router a quand même besoin de tls=true (ou doit écouter sur un entrypoint avec TLS activé) pour réellement servir via HTTPS. Définir un certificat seul ne fait pas basculer un router vers TLS.
Puis-je combiner l’ACME automatique et des certificats personnalisés ?
Oui. Traefik peut utiliser un certificatesResolver pour certains routers et des certificats du provider de fichiers pour d’autres. Par requête, une correspondance explicite via tls.certificates par SNI a la priorité sur ACME pour ce nom d’hôte.
Où placer les certificats sur Kubernetes ?
Pas dans le provider de fichiers — sur Kubernetes, vous fournissez les certificats sous forme de TLS Secrets et vous les référencez depuis l’IngressRoute/Ingress. L’approche par provider de fichiers de ce guide est destinée aux environnements Docker et autonomes (non-K8s).
Traefik renouvelle-t-il automatiquement mon certificat personnalisé ?
Non. Le renouvellement automatique ne s’applique qu’aux certificats que Traefik émet lui-même via ACME. Pour vos propres certificats, vous remplacez les fichiers — mais grâce à --providers.file.watch=true, Traefik les recharge à chaud sans aucune interruption, comme décrit dans la section Comment renouveler ci-dessus.
Cela fonctionne-t-il avec les certificats ECDSA/ECC ?
Oui. Traefik sert les certificats ECDSA exactement comme les certificats RSA — même configuration certFile/keyFile. GetHTTPS émet des certificats ECDSA P-256 par défaut pour des handshakes plus petits et plus rapides.