Traefik es famoso por emitir certificados automáticamente mediante ACME. Pero a veces necesitas usar tu propio certificado en su lugar: uno emitido por GetHTTPS, una CA corporativa/interna, o un comodín que gestionas en otro sitio. Esta guía te muestra exactamente cómo hacerlo, en Traefik v3.
Lo fundamental que hay que entender desde el principio: no puedes adjuntar un archivo de certificado con una etiqueta de Docker. Las etiquetas de Traefik controlan el enrutamiento y activan TLS, pero el certificado en sí debe provenir del proveedor de archivos como configuración dinámica. Esto desconcierta a casi todo el mundo la primera vez. Lo haremos de la forma correcta.
Si todavía no tienes un certificado, consigue uno gratis en 5 minutos.
Cuándo usar esto (frente al ACME automático de Traefik)
| Usa ACME automático (Let’s Encrypt) | Usa tu propio certificado (esta guía) |
|---|---|
| Sitio web público, accesible desde internet | Servicio interno/intranet (sin DNS público) |
| Un certificado DV estándar es suficiente | Necesitas una CA específica, un comodín o un certificado OV/EV |
| Traefik puede completar el desafío HTTP/DNS | Host aislado (air-gapped) o tras un firewall |
| Quieres cero gestión de certificados | Ya tienes un certificado de GetHTTPS u otro sitio |
Si el ACME automático encaja con tu caso, certificatesResolvers de Traefik es más sencillo. Esta guía es para el caso “ya tengo fullchain.pem + privkey.pem y necesito que Traefik los sirva”.
Requisitos previos
- Traefik v3 ejecutándose como contenedor de Docker (la configuración de abajo usa Docker, pero la parte de configuración dinámica se aplica a cualquier instalación)
- Tus archivos de certificado — dos de ellos:
fullchain.pem— tu certificado + la cadena intermediaprivkey.pem— tu clave privada
- Un dominio apuntando al host (o una entrada local en el archivo hosts para uso interno)
¿Qué archivos necesita Traefik? Traefik quiere la cadena completa en
certFiley la clave enkeyFile. Si usas uncert.pemque solo contiene la hoja, los clientes obtendrán errores de “cadena incompleta”: Traefik no añade automáticamente los intermedios para los certificados del proveedor de archivos. Usafullchain.pem. Formatos de certificado explicados →
Cómo se divide la configuración de Traefik
Traefik tiene dos tipos de configuración, y los certificados viven en el segundo:
- Configuración estática — establecida al arranque (entrypoints, providers). Cambiarla requiere reiniciar. Esto va en
traefik.ymlo en los flags del comando del contenedor. - Configuración dinámica — recargada en vivo sin reiniciar (routers, servicios, certificados TLS). Esto es lo que lee el proveedor de archivos.
Tu certificado es configuración dinámica. Por eso una etiqueta no puede llevarlo: las etiquetas se leen desde el proveedor de Docker, pero tls.certificates es un concepto del proveedor de archivos.
Paso 1: Coloca los archivos de certificado
Pon los archivos en un directorio que montarás dentro del contenedor:
mkdir -p ./traefik/certs
cp fullchain.pem ./traefik/certs/
cp privkey.pem ./traefik/certs/
# Restringe el acceso a la clave privada
chmod 600 ./traefik/certs/privkey.pem
chmod 644 ./traefik/certs/fullchain.pem
Paso 2: Escribe la configuración dinámica
Crea ./traefik/dynamic/certs.yml. Aquí es donde declaras tu certificado:
# ./traefik/dynamic/certs.yml (configuración dinámica — proveedor de archivos)
tls:
certificates:
- certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
# Opcional: convierte este certificado en el predeterminado para cualquier host que no
# coincida con un certificado más específico (p. ej. un comodín o una CA interna).
stores:
default:
defaultCertificate:
certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
Las rutas (/certs/...) son rutas dentro del contenedor: las montamos en el siguiente paso. Traefik selecciona el certificado correcto por solicitud usando SNI, haciendo coincidir el SAN del certificado con el nombre de host solicitado. El defaultCertificate es el recurso de reserva cuando nada más coincide.
Paso 3: Configura Traefik (configuración estática + montajes)
Aquí tienes un docker-compose.yml completo. Los entrypoints y el proveedor de archivos son configuración estática (pasados como flags del comando); el certificado se carga desde el archivo dinámico que acabas de escribir.
services:
traefik:
image: traefik:v3.3
container_name: traefik
restart: unless-stopped
command:
# ─── Entrypoints ───────────────────────────────
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Redirige todo el tráfico HTTP → HTTPS a nivel de 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"
# El proveedor de archivos vigila el directorio de configuración dinámica
- "--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"
# ─── Servicio backend de ejemplo ──────────────────
whoami:
image: traefik/whoami
container_name: whoami
labels:
- "traefik.enable=true"
# Router: coincide con el host, sirve en el entrypoint HTTPS
- "traefik.http.routers.whoami.rule=Host(`example.com`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
# Activa TLS en este router — el certificado proviene de la
# configuración dinámica, NO de una etiqueta.
- "traefik.http.routers.whoami.tls=true"
La línea crítica es traefik.http.routers.whoami.tls=true. Le indica a Traefik “sirve este router a través de TLS”. Traefik elige entonces el certificado coincidente del almacén del proveedor de archivos mediante SNI. No existe ninguna etiqueta como tls.certfile: eso no existe para los routers.
Paso 4: Arranca y verifica
docker compose up -d
docker compose logs -f traefik
Fíjate en que el proveedor de archivos cargue tu certificado. No deberías ver errores de TLS. Luego verifica:
Comprobación en el navegador
Visita https://example.com. Haz clic en el candado:
- Emitido por — tu CA (Let’s Encrypt para GetHTTPS, o tu CA interna)
- Válido — fechas de inicio y fin
- Dominio — coincide con la URL
Comprobación por línea de comandos
# Confirma que Traefik está sirviendo TU certificado, no su predeterminado autofirmado
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
Si ves CN=TRAEFIK DEFAULT CERT, Traefik recurrió a su marcador de posición integrado: tu certificado no se cargó. Consulta la sección Resolución de problemas más abajo.
Paso 5 (opcional): Refuerza TLS
Para controlar las versiones de protocolo y los cifrados, añade un bloque de opciones TLS a tu configuración dinámica y referéncialo desde el router. Añade a certs.yml:
tls:
options:
modern:
minVersion: VersionTLS12
sniStrict: true
Luego en la etiqueta del router:
- "traefik.http.routers.whoami.tls.options=modern@file"
El sufijo @file le indica a Traefik que este conjunto de opciones proviene del proveedor de archivos. Esto te restringe a TLS 1.2 y 1.3 y rechaza las conexiones sin un SNI coincidente.
HSTS: Añade la cabecera
Strict-Transport-Securitymediante un middlewareheadersde Traefik una vez que tengas la certeza de que HTTPS funciona en todas partes. Guía de HSTS →
Cómo renovar
Traefik no renueva automáticamente los certificados que proporcionas tú mismo: ese es el precio de usar el tuyo propio. Cuando tu certificado se acerque a su caducidad (día 60 de 90 para Let’s Encrypt):
- Consigue un certificado nuevo de GetHTTPS (o tu herramienta de renovación).
- Sobrescribe los archivos en su sitio:
cp new-fullchain.pem ./traefik/certs/fullchain.pem cp new-privkey.pem ./traefik/certs/privkey.pem - Nada más. Como
--providers.file.watch=trueestá establecido, Traefik detecta el cambio en el archivo y recarga el certificado en caliente: sin reinicio, sin tiempo de inactividad. Esta es una de las mejores cualidades de Traefik para los certificados personalizados.
Resolución de problemas
Traefik sirve “TRAEFIK DEFAULT CERT” en lugar del mío
Causa: Traefik no pudo cargar tu certificado, así que recurrió a su marcador de posición autofirmado. Casi siempre es un problema de ruta o de montaje.
Solución:
# 1. Confirma que los archivos existen DENTRO del contenedor en la ruta esperada
docker compose exec traefik ls -l /certs
# 2. Confirma que el archivo dinámico está montado y es legible
docker compose exec traefik cat /dynamic/certs.yml
# 3. Revisa los logs para encontrar la razón real
docker compose logs traefik | grep -i "certificate\|tls\|error"
Las rutas certFile/keyFile en certs.yml deben coincidir con las rutas del contenedor (/certs/...), no con las rutas de tu host.
”unable to find certificate for domain” / se sirve el certificado equivocado
Causa: Ningún SAN de certificado coincide con el nombre de host solicitado, y no hay ningún defaultCertificate establecido.
Solución: O bien añade el nombre de host a tu certificado, o bien establece un defaultCertificate en el bloque stores.default (Paso 2) para que Traefik tenga un recurso de reserva.
El router devuelve 404 y el certificado ni siquiera se comprueba
Causa: La regla del router no coincide, o el servicio no está expuesto. TLS es irrelevante hasta que el enrutamiento coincide.
Solución:
# Verifica que el router existe y está activado
docker compose exec traefik wget -qO- http://localhost:8080/api/http/routers 2>/dev/null | grep whoami
Asegúrate de que traefik.enable=true esté en el contenedor backend y de que la regla Host() coincida con el dominio que estás probando.
Los cambios en certs.yml no surten efecto
Causa: El proveedor de archivos no está vigilando, o has editado la configuración estática (que necesita un reinicio).
Solución: Confirma que --providers.file.watch=true está en la configuración estática. Recuerda: los entrypoints/providers son estáticos (requieren reinicio); los routers y tls.certificates son dinámicos (se recargan en caliente).
“x509: certificate signed by unknown authority” desde los clientes
Causa: Cadena incompleta: usaste un cert.pem que solo contiene la hoja en certFile en lugar de fullchain.pem.
Solución: Apunta certFile a la cadena completa. Si solo tienes archivos por separado, concaténalos (primero la hoja, luego los intermedios):
cat cert.pem intermediate.pem > fullchain.pem
Preguntas frecuentes
¿Puedo especificar el archivo de certificado con una etiqueta de Docker?
No. Este es el malentendido número 1. Las etiquetas establecen traefik.http.routers.<name>.tls=true para activar TLS, pero los archivos de certificado deben declararse en la configuración dinámica mediante el proveedor de archivos (tls.certificates). No existe ninguna etiqueta de router que apunte a un archivo .pem.
¿Necesito tls=true en el router si ya tengo un certificado?
Sí. Declarar el certificado en tls.certificates lo hace disponible, pero cada router sigue necesitando tls=true (o escuchar en un entrypoint con TLS activado) para servir realmente a través de HTTPS. Definir un certificado por sí solo no cambia un router a TLS.
¿Puedo combinar ACME automático y certificados personalizados?
Sí. Traefik puede usar un certificatesResolver para algunos routers y certificados del proveedor de archivos para otros. Por solicitud, una coincidencia explícita de tls.certificates por SNI tiene prioridad sobre ACME para ese nombre de host.
¿Dónde van los certificados en Kubernetes?
No en el proveedor de archivos: en Kubernetes proporcionas los certificados como TLS Secrets y los referencias desde el IngressRoute/Ingress. El enfoque del proveedor de archivos de esta guía es para Docker e instalaciones independientes (no K8s).
¿Traefik renueva automáticamente mi certificado personalizado?
No. La renovación automática solo se aplica a los certificados que Traefik emite por sí mismo mediante ACME. Para tus propios certificados, reemplazas los archivos, pero gracias a --providers.file.watch=true, Traefik los recarga en caliente sin tiempo de inactividad, tal como se describe en la sección Cómo renovar más arriba.
¿Funciona esto con certificados ECDSA/ECC?
Sí. Traefik sirve los certificados ECDSA exactamente igual que los RSA: la misma configuración de certFile/keyFile. GetHTTPS emite ECDSA P-256 de forma predeterminada para handshakes más pequeños y rápidos.