O Traefik é famoso por emitir certificados automaticamente via ACME. Mas, às vezes, você precisa trazer o seu próprio certificado — um emitido pelo GetHTTPS, por uma CA corporativa/interna ou um wildcard que você gerencia em outro lugar. Este guia mostra exatamente como fazer isso, no Traefik v3.
A coisa fundamental para entender desde já: você não pode anexar um arquivo de certificado com uma label do Docker. As labels do Traefik controlam o roteamento e habilitam o TLS, mas o certificado em si deve vir do file provider como configuração dinâmica. Isso confunde quase todo mundo na primeira vez. Vamos fazer da maneira certa.
Se você ainda não tem um certificado, obtenha um gratuitamente em 5 minutos.
Quando usar isto (vs. o ACME automático do Traefik)
| Usar ACME automático (Let’s Encrypt) | Trazer o seu próprio certificado (este guia) |
|---|---|
| Site público, acessível pela internet | Serviço interno/intranet (sem DNS público) |
| Um certificado DV padrão é suficiente | Você precisa de uma CA específica, wildcard ou certificado OV/EV |
| O Traefik consegue concluir o desafio HTTP/DNS | Host isolado (air-gapped) ou atrás de firewall |
| Você quer zero gerenciamento de certificados | Você já tem um certificado do GetHTTPS ou de outro lugar |
Se o ACME automático se adequa ao seu caso, o certificatesResolvers do Traefik é mais simples. Este guia é para o caso “eu já tenho fullchain.pem + privkey.pem e preciso que o Traefik os sirva”.
Pré-requisitos
- Traefik v3 rodando como um container Docker (a configuração abaixo usa Docker, mas a parte da configuração dinâmica se aplica a qualquer ambiente)
- Seus arquivos de certificado — dois deles:
fullchain.pem— seu certificado + a cadeia intermediáriaprivkey.pem— sua chave privada
- Um domínio apontando para o host (ou uma entrada local no arquivo hosts para uso interno)
De quais arquivos o Traefik precisa? O Traefik quer a cadeia completa em
certFilee a chave emkeyFile. Se você usar umcert.pemapenas com a folha (leaf-only), os clientes recebem erros de “cadeia incompleta” — o Traefik não anexa intermediários automaticamente para certificados do file provider. Usefullchain.pem. Formatos de certificado explicados →
Como a configuração do Traefik é dividida
O Traefik tem dois tipos de configuração, e os certificados ficam no segundo:
- Configuração estática — definida na inicialização (entrypoints, providers). Alterá-la exige um reinício. Isso vai no
traefik.ymlou nas flags de comando do container. - Configuração dinâmica — recarregada ao vivo sem reinício (routers, services, certificados TLS). É isto que o file provider lê.
Seu certificado é configuração dinâmica. É por isso que uma label não pode carregá-lo — as labels são lidas a partir do provider do Docker, mas tls.certificates é um conceito do file provider.
Passo 1: Coloque os arquivos de certificado
Coloque os arquivos em um diretório que você montará dentro do container:
mkdir -p ./traefik/certs
cp fullchain.pem ./traefik/certs/
cp privkey.pem ./traefik/certs/
# Restringe o acesso à chave privada
chmod 600 ./traefik/certs/privkey.pem
chmod 644 ./traefik/certs/fullchain.pem
Passo 2: Escreva a configuração dinâmica
Crie o arquivo ./traefik/dynamic/certs.yml. É aqui que você declara o seu certificado:
# ./traefik/dynamic/certs.yml (configuração dinâmica — file provider)
tls:
certificates:
- certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
# Opcional: torna este certificado o padrão para qualquer host que não
# corresponda a um certificado mais específico (ex.: um wildcard ou CA interna).
stores:
default:
defaultCertificate:
certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
Os caminhos (/certs/...) são caminhos dentro do container — nós os montamos no próximo passo. O Traefik seleciona o certificado correto por requisição usando SNI, comparando o SAN do certificado com o hostname solicitado. O defaultCertificate é o fallback quando nada mais corresponde.
Passo 3: Configure o Traefik (configuração estática + montagens)
Aqui está um docker-compose.yml completo. Os entrypoints e o file provider são configuração estática (passados como flags de comando); o certificado é carregado a partir do arquivo dinâmico que você acabou de escrever.
services:
traefik:
image: traefik:v3.3
container_name: traefik
restart: unless-stopped
command:
# ─── Entrypoints ───────────────────────────────
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Redireciona todo HTTP → HTTPS no nível do 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"
# O file provider monitora o diretório de configuração 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"
# ─── Serviço de backend de exemplo ──────────────────────
whoami:
image: traefik/whoami
container_name: whoami
labels:
- "traefik.enable=true"
# Router: corresponde ao host, serve no entrypoint HTTPS
- "traefik.http.routers.whoami.rule=Host(`example.com`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
# Habilita o TLS neste router — o certificado vem da
# configuração dinâmica, NÃO de uma label.
- "traefik.http.routers.whoami.tls=true"
A linha crítica é traefik.http.routers.whoami.tls=true. Ela informa ao Traefik “sirva este router por TLS”. O Traefik então escolhe o certificado correspondente no store do file provider por SNI. Não há nenhuma label como tls.certfile — isso não existe para routers.
Passo 4: Inicie e verifique
docker compose up -d
docker compose logs -f traefik
Observe o file provider carregando o seu certificado. Você não deve ver erros de TLS. Em seguida, verifique:
Verificação no navegador
Acesse https://example.com. Clique no cadeado:
- Emitido por — sua CA (Let’s Encrypt para o GetHTTPS, ou sua CA interna)
- Válido — datas de início e término
- Domínio — corresponde à URL
Verificação na linha de comando
# Confirma que o Traefik está servindo o SEU certificado, não o padrão autoassinado
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
Se você ver CN=TRAEFIK DEFAULT CERT, o Traefik recorreu ao seu placeholder embutido — o seu certificado não foi carregado. Veja a seção Resolução de problemas abaixo.
Passo 5 (opcional): Reforce o TLS
Para controlar as versões de protocolo e as cifras, adicione um bloco de opções de TLS à sua configuração dinâmica e referencie-o a partir do router. Adicione ao certs.yml:
tls:
options:
modern:
minVersion: VersionTLS12
sniStrict: true
Depois, na label do router:
- "traefik.http.routers.whoami.tls.options=modern@file"
O sufixo @file informa ao Traefik que este conjunto de opções vem do file provider. Isso restringe você ao TLS 1.2 e 1.3 e rejeita conexões sem um SNI correspondente.
HSTS: Adicione o cabeçalho
Strict-Transport-Securitypor meio de um middlewareheadersdo Traefik assim que você tiver certeza de que o HTTPS funciona em todos os lugares. Guia de HSTS →
Como renovar
O Traefik não renova automaticamente os certificados que você mesmo fornece — esse é o trade-off de trazer o seu próprio. Quando o seu certificado se aproximar da expiração (dia 60 de 90 para o Let’s Encrypt):
- Obtenha um novo certificado no GetHTTPS (ou na sua ferramenta de renovação).
- Sobrescreva os arquivos no lugar:
cp new-fullchain.pem ./traefik/certs/fullchain.pem cp new-privkey.pem ./traefik/certs/privkey.pem - Nada mais. Como
--providers.file.watch=trueestá definido, o Traefik detecta a alteração do arquivo e recarrega o certificado a quente — sem reinício, sem downtime. Esta é uma das propriedades mais agradáveis do Traefik para certificados personalizados.
Resolução de problemas
O Traefik serve “TRAEFIK DEFAULT CERT” em vez do meu
Causa: O Traefik não conseguiu carregar o seu certificado, então recorreu ao seu placeholder autoassinado. Quase sempre é um problema de caminho ou de montagem.
Solução:
# 1. Confirma que os arquivos existem DENTRO do container no caminho esperado
docker compose exec traefik ls -l /certs
# 2. Confirma que o arquivo dinâmico está montado e legível
docker compose exec traefik cat /dynamic/certs.yml
# 3. Verifica os logs em busca do motivo real
docker compose logs traefik | grep -i "certificate\|tls\|error"
Os caminhos certFile/keyFile no certs.yml devem corresponder aos caminhos do container (/certs/...), não aos caminhos do seu host.
”unable to find certificate for domain” / certificado errado servido
Causa: Nenhum SAN de certificado corresponde ao hostname solicitado, e nenhum defaultCertificate está definido.
Solução: Adicione o hostname ao seu certificado ou defina um defaultCertificate no bloco stores.default (Passo 2) para que o Traefik tenha um fallback.
O router retorna 404, o certificado nem chega a ser verificado
Causa: A regra do router não corresponde, ou o serviço não está exposto. O TLS é irrelevante até que o roteamento corresponda.
Solução:
# Verifica se o router existe e está habilitado
docker compose exec traefik wget -qO- http://localhost:8080/api/http/routers 2>/dev/null | grep whoami
Certifique-se de que traefik.enable=true está no container de backend e que a regra Host() corresponde ao domínio que você está testando.
As alterações no certs.yml não têm efeito
Causa: O file provider não está monitorando, ou você editou a configuração estática (que precisa de um reinício).
Solução: Confirme que --providers.file.watch=true está na configuração estática. Lembre-se: entrypoints/providers são estáticos (reinício necessário); routers e tls.certificates são dinâmicos (recarregados a quente).
“x509: certificate signed by unknown authority” vindo dos clientes
Causa: Cadeia incompleta — você usou um cert.pem apenas com a folha (leaf-only) em certFile em vez de fullchain.pem.
Solução: Aponte certFile para a cadeia completa. Se você só tem arquivos separados, concatene-os (a folha primeiro, depois os intermediários):
cat cert.pem intermediate.pem > fullchain.pem
Perguntas frequentes
Posso especificar o arquivo de certificado com uma label do Docker?
Não. Este é o equívoco número 1. As labels definem traefik.http.routers.<name>.tls=true para habilitar o TLS, mas os arquivos de certificado devem ser declarados na configuração dinâmica via file provider (tls.certificates). Não existe nenhuma label de router que aponte para um arquivo .pem.
Preciso de tls=true no router se eu tiver um certificado?
Sim. Declarar o certificado em tls.certificates o torna disponível, mas cada router ainda precisa de tls=true (ou de escutar em um entrypoint com TLS habilitado) para de fato servir por HTTPS. Definir um certificado sozinho não muda um router para TLS.
Posso combinar ACME automático e certificados personalizados?
Sim. O Traefik pode usar um certificatesResolver para alguns routers e certificados do file provider para outros. Por requisição, uma correspondência explícita de tls.certificates por SNI tem precedência sobre o ACME para aquele hostname.
Onde os certificados ficam no Kubernetes?
Não no file provider — no Kubernetes você fornece os certificados como TLS Secrets e os referencia a partir do IngressRoute/Ingress. A abordagem do file provider neste guia é para ambientes Docker e standalone (não-K8s).
O Traefik renova automaticamente o meu certificado personalizado?
Não. A renovação automática só se aplica a certificados que o próprio Traefik emite via ACME. Para os seus próprios certificados, você substitui os arquivos — mas, graças a --providers.file.watch=true, o Traefik os recarrega a quente com zero downtime, conforme descrito na seção Como renovar acima.
Isto funciona com certificados ECDSA/ECC?
Sim. O Traefik serve certificados ECDSA exatamente como RSA — a mesma configuração certFile/keyFile. O GetHTTPS emite ECDSA P-256 por padrão para handshakes menores e mais rápidos.