SSL Automático com Traefik e Let's Encrypt no Docker

10 min de leitura Infraestrutura e Segurança

Traefik é um reverse proxy e load balancer moderno, feito especificamente para ambientes de microserviços e containers. Diferente de soluções tradicionais como Nginx ou Apache, que exigem configuração manual de arquivos estáticos para cada novo domínio ou serviço, o Traefik é "cloud-native". Ele se integra nativamente ao Docker, observando as mudanças em tempo real e configurando rotas automaticamente.

A combinação do Traefik com a certificação automática via Let's Encrypt elimina a dor de cabeça mais comum na administração de servidores web: a renovação de certificados SSL/TLS. Neste tutorial, você aprenderá a configurar um ambiente completo usando Docker e Docker Compose em uma VPS, garantindo que todos os seus serviços expostos tenham HTTPS ativado por padrão, sem intervenção manual.

Pré-requisitos e Visão Geral da Arquitetura

Antes de começar, certifique-se de que você possui:

  • Uma VPS com Linux (Ubuntu, Debian ou CentOS) atualizado.
  • Docker e Docker Compose instalados na máquina.
  • Um domínio apontando para o IP público da sua VPS (ex: seudominio.com e www.seudominio.com). Para testes locais, você pode usar subdomínios como app1.teste.com.
  • Portas 80 (HTTP) e 443 (HTTPS) abertas no firewall da sua VPS.

A arquitetura será simples: o Traefik atuará como a porta de entrada. Ele receberá as requisições HTTP/HTTPS e as encaminhará para os containers internos baseados nas tags das redes Docker. A grande vantagem é que, ao adicionar um novo container com as labels corretas, o Traefik criará a rota e solicitará o certificado SSL automaticamente.

Passo 1: Preparando o Ambiente de Configuração

Crie um diretório dedicado para gerenciar a infraestrutura do Traefik. Isso manterá sua organização limpa e facilitará backups.

mkdir -p ~/traefik-demo
cd ~/traefik-demo
mkdir data

Dentro deste diretório, criaremos dois arquivos principais: docker-compose.yml para orquestrar os serviços e traefik.yml (ou configurações inline no compose) para definir o comportamento do proxy.

Passo 2: Configurando o Docker Compose

O coração da configuração reside no arquivo docker-compose.yml. Vamos definir o serviço do Traefik e um container de exemplo (como o Whoami) para testar a conectividade.

version: '3.8'

services:
  traefik:
    image: traefik:v2.10
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/traefik.yml:ro
      - ./data/acme.json:/acme.json
    networks:
      - proxy

  whoami:
    image: containous/whoami
    container_name: whoami_service
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`seu-dominio.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=le"
    networks:
      - proxy

networks:
  proxy:
    external: true

Analisemos os pontos críticos deste arquivo:

  1. Montagem do Socket: O volume /var/run/docker.sock:/var/run/docker.sock:ro é essencial. Ele permite que o Traefik "ouça" os eventos do Docker (containers sendo criados, parados ou removidos).
  2. Segurança do ACME: O arquivo ./data/acme.json armazenará as chaves privadas e certificados obtidos do Let's Encrypt. Este arquivo deve ter permissões restritas (600) para evitar vazamento de dados sensíveis.
  3. Labels: As tags traefik.enable=true, Host(), entrypoints=websecure e tls.certresolver=le são o que tornam o SSL automático possível. Elas dizem ao Traefik: "Monitore este container, ele responde a requisições para meu domínio, use HTTPS e resolva o certificado usando o provedor 'le'".

Passo 3: Criando o Arquivo de Configuração do Traefik

Embora possamos configurar tudo inline no Compose, é boa prática separar a configuração central do Traefik em um arquivo traefik.yml. Crie este arquivo na pasta data.

api:
  dashboard: true

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: proxy

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

certificatesResolvers:
  le:
    acme:
      email: "seu-email@exemplo.com"
      storage: "/acme.json"
      httpChallenge:
        entryPoint: web

Nesta configuração, definimos:

  • providers.docker: exposedByDefault: false é crucial. Isso garante que apenas containers com traefik.enable=true sejam expostos publicamente, aumentando a segurança.
  • certificatesResolvers.le: Define o resolvedor de certificados chamado "le". Ele usa HTTP-01 Challenge (via porta 80) para validar a propriedade do domínio junto ao Let's Encrypt. O email é usado para notificações de expiração e recuperação de chave.

Passo 4: Ajustando Permissões de Segurança

O arquivo acme.json contém suas chaves privadas. Se alguém acessar este arquivo, poderá falsificar certificados para seu domínio. Defina permissões rigorosas imediatamente após a criação do arquivo vazio.

touch data/acme.json
chmod 600 data/acme.json

Isso garante que apenas o root (ou o usuário que está executando o Docker) possa ler e gravar neste arquivo. O container do Traefik, ao rodar, tentará escrever nele, mas não permitirá leitura por outros usuários.

Passo 5: Iniciando os Serviços

Agora, basta subir a stack com o Docker Compose.

docker-compose up -d

O Traefik iniciará e criará a rede proxy (se ainda não existir). Ele se registrará no Docker e começará a observar os containers. Como definimos o container whoami com as labels apropriadas, o Traefik irá:

  1. Criar uma regra de roteamento para seu-dominio.com.
  2. Solicitar um certificado SSL ao Let's Encrypt.
  3. Encaminhar o tráfego HTTPS para o container whoami.

Você pode verificar se o container está rodando com:

docker ps

Passo 6: Verificando a Instalação e o Certificado SSL

Aguarde alguns segundos para que o Let's Encrypt processe a solicitação. Em seguida, teste a conexão.

curl -I https://seu-dominio.com

Você deve receber um cabeçalho HTTP 200 OK. Para verificar os detalhes do certificado, use:

openssl s_client -connect seu-dominio.com:443 -servername seu-dominio.com

Se a configuração estiver correta, você verá informações sobre o emissor (Let's Encrypt) e o período de validade. O Traefik gerencia a renovação automaticamente 30 dias antes do expirar, então não há nada mais a fazer.

Passo 7: Redirecionando HTTP para HTTPS

Embora o HTTPS esteja funcionando, ainda é possível acessar o site via HTTP (porta 80). Para melhorar a segurança e conformidade com padrões modernos, devemos forçar o redirecionamento de todo tráfego HTTP para HTTPS.

Para isso, precisamos adicionar uma regra de middleware ao Traefik. Isso pode ser feito diretamente no docker-compose.yml ou via arquivo de configuração dinâmico. A maneira mais simples é adicionar labels ao próprio serviço do Traefik ou criar um container dedicado para a configuração estática, mas vamos usar uma abordagem prática dentro do compose.

Atualize o serviço traefik no docker-compose.yml para incluir as regras de redirecionamento:

  traefik:
    image: traefik:v2.10
    # ... outras configurações anteriores ...
    command:
      - "--api.dashboard=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.le.acme.email=seu-email@exemplo.com"
      - "--certificatesresolvers.le.acme.storage=/acme.json"
      - "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
    # Remova o volume do traefik.yml estático se estiver usando command inline
    # volumes:
    #   - ./data/traefik.yml:/traefik.yml:ro

Agora, para redirecionar, adicione um serviço de middleware ou use as labels globais. Uma maneira limpa é criar uma regra global. No entanto, a forma mais comum e recomendada no ecossistema Docker é usar o http.middlewares. Vamos adicionar isso ao arquivo traefik.yml se estiver usando arquivos estáticos/dinâmicos separados, ou via labels.

Vamos simplificar: adicione as seguintes labels a todos os serviços que você quer proteger no futuro, ou crie um serviço dummy para o redirecionamento global. Mas o método mais robusto é configurar isso no próprio Traefik via arquivo de configuração dinâmico.

Crie o arquivo data/dynamic.yml:

http:
  middlewares:
    redirect-to-https:
      redirectScheme:
        scheme: https
        permanent: true

  routers:
    dashboard-redirect:
      rule: "Host(`seu-dominio.com`)"
      entrypoints:
        - web
      middlewares:
        - redirect-to-https
      service: noop@internal
    dashboard-secure:
      rule: "Host(`seu-dominio.com`)"
      entrypoints:
        - websecure
      tls: {}
      service: api@internal

E atualize o docker-compose.yml para montar este arquivo:

volumes:
  - /var/run/docker.sock:/var/run/docker.sock:ro
  - ./data/acme.json:/acme.json
  - ./data/dynamic.yml:/dynamic.yml:ro

E adicione ao command do Traefik (ou no traefik.yml estático):

--providers.file.filename=/dynamic.yml

Com isso, qualquer acesso HTTP será redirecionado permanentemente (301) para HTTPS.

Passo 8: Adicionando Novos Serviços com SSL Automático

A beleza do Traefik é a escalabilidade. Para adicionar um novo serviço, como um WordPress ou um aplicativo Node.js, você não precisa tocar na configuração do proxy. Apenas adicione o container ao docker-compose.yml com as labels corretas.

  meu-app:
    image: node:latest
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.meuapp.rule=Host(`app.seudominio.com`)"
      - "traefik.http.routers.meuapp.entrypoints=websecure"
      - "traefik.http.routers.meuapp.tls.certresolver=le"
    networks:
      - proxy

Ao subir este container (docker-compose up -d meu-app), o Traefik detectará a mudança, criará a rota para app.seudominio.com, solicitará o certificado SSL e começará a servir o conteúdo via HTTPS. Tudo em questão de segundos.

Boas Práticas e Troubleshooting

1. Testes com Let's Encrypt Staging:
O Let's Encrypt possui limites de taxa (rate limits). Se você estiver desenvolvendo e testando muito, use o ambiente de staging para evitar bloqueios temporários.

certificatesResolvers:
  le:
    acme:
      caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
      # ... restante da config

2. Verificando Logs:
Se o SSL não estiver funcionando, verifique os logs do Traefik para erros de validação HTTP-01.

docker logs traefik -f

3. DNS e Firewalls:
O desafio HTTP-01 requer que a porta 80 seja acessível publicamente pelo servidor do Let's Encrypt. Se você usa um firewall restritivo ou um CDN (como Cloudflare) que não encaminha o desafio corretamente, o SSL falhará. No caso do Cloudflare, é necessário configurar o modo de proxy "DNS Only" para os domínios que usam o Traefik, ou usar o desafio DNS-01 (mais complexo, requer integração com API de DNS).

Conclusão

Configurar SSL automático com Traefik e Let's Encrypt transforma a gestão de segurança em um processo invisível e eficiente. Ao adotar essa abordagem baseada em containers e infraestrutura como código, você garante que seus serviços estejam sempre protegidos com HTTPS moderno, sem sobrecarregar sua equipe operacional com tarefas manuais de renovação de certificados.

Esta configuração é a base ideal para ambientes de produção escaláveis em VPS, permitindo que desenvolvedores e sysadmins foquem na lógica da aplicação, enquanto a infraestrutura lida com roteamento e criptografia de forma transparente e robusta.

Esse tutorial foi útil?

Comentários (0)

Seja o primeiro a comentar.

Deixe seu comentário

Seu comentário será analisado antes de ser publicado.

0/2000
WhatsApp