Skip to content

Rede e exposição (Cloudflare, Traefik e VPN)

Como o tráfego entra no cluster k3s da VPS Hostinger, como resolvemos o domínio technodevbr.com na Cloudflare e o que fica público vs. interno (VPN). Decisão em ADR-0006.

Princípio de exposição

  • Público (via Cloudflare → internet): apenas a ferramenta de gerenciamento do cluster, ex.: portainer.technodevbr.com, sempre com autenticação (e, de preferência, Cloudflare Access).
  • Interno (somente pela VPN): todo o resto — app/frontend, API, Argo CD, Grafana, RabbitMQ management, etc.
Internet ──> Cloudflare (DNS + proxy) ──> VPS (IP público) ──> Traefik ──> portainer (público)
Usuário ──> VPN ──────────────────────> VPS (IP interno) ──> Traefik ──> busca-busca/argo/grafana/... (interno)

DNS na Cloudflare

Domínio technodevbr.com gerenciado na Cloudflare. Subdomínios:

HostDestinoExposiçãoProxy Cloudflare
portainer.technodevbr.comUI de gerenciamento (Portainer)PúblicoProxied (laranja)
busca-busca.technodevbr.comFrontend AngularInterno (VPN)DNS only (cinza)
api.technodevbr.comAPI JavaInterno (VPN)DNS only
argo.technodevbr.comArgo CDInterno (VPN)DNS only
traefik.technodevbr.comDashboard do TraefikInterno (VPN)DNS only
grafana.technodevbr.comGrafanaInterno (VPN)DNS only
rabbit.technodevbr.comRabbitMQ mgmtInterno (VPN)DNS only

Hosts internos podem apontar para o IP privado da VPN (ex.: faixa Tailscale/WireGuard) em vez do IP público, garantindo que só resolvem/funcionam dentro da VPN.

Ingress: Traefik (subido por nós)

  • O Traefik é um serviço que nós mesmos subimos (Helm, com values próprios, versionado no GitOps). O Traefik embutido do k3s fica desabilitado (--disable traefik no install/config) para não conflitar.
  • Expomos serviços com Ingress / IngressRoute (CRD do Traefik).
  • Um único ponto de entrada (portas 80/443 da VPS) roteia por host/path.
  • Exemplo de Ingress para um serviço interno:
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-cloudflare
spec:
  rules:
    - host: busca-busca.technodevbr.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: busca-busca-frontend
                port:
                  number: 80
  tls:
    - hosts: [busca-busca.technodevbr.com]
      secretName: busca-busca-tls

TLS: cert-manager + DNS-01 da Cloudflare

Como os hosts internos não são acessíveis pela internet, o desafio HTTP-01 não funciona para eles. Usamos DNS-01 via Cloudflare, que valida criando um registro TXT — funciona para qualquer host do domínio.

yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-cloudflare
spec:
  acme:
    email: admin@technodevbr.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-cloudflare-key
    solvers:
      - dns01:
          cloudflare:
            apiTokenSecretRef:
              name: cloudflare-api-token
              key: api-token

O token da Cloudflare (escopo Zone.DNS:Edit na zona technodevbr.com) entra como Secret, gerenciado por Sealed Secrets/External Secrets — nunca em claro no Git. Alternativa: ACME embutido do Traefik com provider Cloudflare (dispensa o cert-manager).

VPN (acesso interno)

Opção recomendada: Tailscale (malha WireGuard, simples de instalar na VPS e nos clientes; tem inclusive operador para Kubernetes). Alternativa self-hosted: WireGuard puro.

  • Instalar o cliente na VPS e nos dispositivos; hosts internos resolvem/roteiam pela faixa da VPN.
  • Só o painel público fica fora da VPN.

Alternativa sem VPN tradicional: como o DNS já está na Cloudflare, dá para usar Cloudflare Tunnel + Access (Zero Trust) — o túnel sai da VPS para a Cloudflare (sem abrir portas) e o Access aplica login (SSO/OTP) por aplicação. Bom substituto à VPN para acesso interno.

Firewall da VPS

  • Expor apenas 80/443 publicamente (Traefik) + porta da VPN (ex.: WireGuard 51820/udp).
  • Bloquear acesso direto ao kube-apiserver (6443) na internet; administrar via VPN.
  • Se usar Cloudflare Tunnel, é possível não abrir 80/443 publicamente.