Ingress e TLS automático

Como expor aplicações pela porta 443 com certificados emitidos e renovados automaticamente, sem operar um roteador externo.

Rede·7 min·
Antes de começar

O HeroCtl traz um roteador integrado embutido no plano de controle. Você não instala, não configura, não atualiza. Ao subir o cluster, o roteador já está ativo nas portas 80 e 443 de cada nó servidor.

Isso significa que expor uma aplicação na internet é uma linha no spec do job.

O caminho mais curto

job: minha-api
ingress:
  host: api.exemplo.com
  port: http
  tls: true

Com isso o cluster faz três coisas em sequência:

  1. Resolve o host api.exemplo.com para qualquer alocação saudável do job.
  2. Solicita um certificado válido para esse domínio na primeira requisição.
  3. Renova esse certificado antes do vencimento, sem intervenção.

Você só precisa apontar o DNS de api.exemplo.com para os IPs dos nós servidores. O resto roda sozinho.

Como o certificado é emitido

O HeroCtl usa Let's Encrypt como autoridade certificadora padrão. Por trás disso há dois mecanismos de validação suportados.

HTTP-01 (default)

Funciona para qualquer domínio público que aponta para o cluster. Quando uma autoridade pede prova de posse, o roteador integrado responde no caminho /.well-known/acme-challenge/ automaticamente. Nada precisa ser configurado.

Atenção: HTTP-01 exige que a porta 80 esteja acessível externamente. Se o firewall bloqueia 80, a emissão falha.

DNS-01 (para wildcards)

Se você precisa de um certificado wildcard (*.exemplo.com), use DNS-01. Configure o provedor DNS no spec do cluster:

acme:
  challenge: dns-01
  provider: cloudflare
  credentials:
    api_token: ${secret.cloudflare_token}

Provedores suportados nativamente: Cloudflare, Route53, DigitalOcean, Hostinger, Hetzner. Outros vão por plugin externo.

Com DNS-01 ativo, basta declarar:

ingress:
  host: "*.exemplo.com"
  tls: true

Redirecionamento HTTP → HTTPS

Quando tls: true, todo tráfego que chega na porta 80 é redirecionado com 301 para 443. Você não precisa duplicar configuração.

Para forçar HSTS:

ingress:
  host: api.exemplo.com
  tls: true
  hsts:
    enabled: true
    max_age: 31536000
    include_subdomains: true
    preload: false

Não habilite preload sem entender o compromisso. É difícil reverter.

Múltiplos domínios para o mesmo app

Padrão comum: www.exemplo.com e exemplo.com apontando para a mesma aplicação, com um sendo canônico.

ingress:
  host: exemplo.com
  redirect_from:
    - www.exemplo.com
  tls: true

Cada domínio em redirect_from recebe seu próprio certificado e responde 301 para o host canônico.

Roteamento por path

Mesmo host, aplicações diferentes em paths diferentes:

# job: site-marketing
ingress:
  host: exemplo.com
  path: /
  tls: true

# job: api-publica
ingress:
  host: exemplo.com
  path: /api
  tls: true

O roteador resolve a precedência por especificidade. /api/users cai em api-publica. /sobre cai em site-marketing.

Cabeçalhos customizados

Para adicionar ou remover headers na resposta:

ingress:
  host: api.exemplo.com
  tls: true
  headers:
    add:
      X-Frame-Options: DENY
      X-Content-Type-Options: nosniff
      Referrer-Policy: strict-origin
    remove:
      - Server
      - X-Powered-By

Rate limiting básico

Defesa em primeira linha contra abuso:

ingress:
  host: api.exemplo.com
  tls: true
  rate_limit:
    requests_per_second: 100
    burst: 200
    by: ip

Limites mais elaborados (por token, por endpoint, com bypass para parceiros) ficam na aplicação.

Troubleshooting

Certificado não foi emitido

Cheque três coisas, em ordem:

SintomaCausa provávelO que fazer
dial tcp: timeout no log do challengePorta 80 fechadaLiberar 80/tcp inbound nos nós servidores
unauthorized: Invalid responseDNS aponta para outro lugardig +short api.exemplo.com deve retornar IP de nó servidor
too many failed authorizationsVocê bateu o rate limit do Let's EncryptAguardar 1h e revisar a config antes de tentar de novo

Inspecione o estado da emissão:

heroctl ingress cert-status api.exemplo.com

O certificado venceu sem renovar

Renovação roda 30 dias antes do vencimento. Se passou disso, há erro acumulado:

heroctl ingress cert-renew api.exemplo.com --force

Verifique também se redirect_from ainda aponta para o cluster. Domínio que foi movido para outro provedor sem ser removido do spec quebra a renovação silenciosamente.

ACME challenge intermitente

Sintoma: às vezes emite, às vezes falha. Geralmente é DNS round-robin com um IP que não responde na 80, ou um Cloudflare na frente em modo proxy. Para HTTP-01, o domínio precisa resolver direto para o cluster durante o desafio. Use DNS-01 se mantiver Cloudflare proxy ligado.

Próximos passos

  • Configurar firewall para liberar só o necessário.
  • Entender o modelo de secrets antes de injetar tokens DNS no spec.
#ingress#tls#https#acme#lets-encrypt#rede