Pular para conteúdo

0039 — Chamada de app para app: URL pública e DNS local por host

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-30 · Decidido em: 2026-09-30

Contexto

A 0020 fixou o contrato, a autenticação e o nome das envs de uma chamada entre apps (<APP>_URL + <APP>_API_TOKEN). Por onde a chamada passa ficou sem regra, e só dois casos tinham norma: banco pelo nome do serviço Docker e API do Coolify por http://coolify:8080.

O resto chamava o domínio público, que de dentro do host volta pelo roteador (hairpin NAT). Desde 2026-09-22 a zona *.xadm.biz tem dois registros A, e o hairpin só funciona por um deles. Cada chamada sorteia um IP e falha às vezes, com No route to host. O GlitchTip #1356 (thoms-webstorm → int.thoms.xadm.biz) mostrou o sintoma, e a varredura das envs achou o mesmo caminho em integradores, pied, central-backend, apps de planilha e no SENTRY_DSN, onde o próprio aviso de erro se perdia. É a família da pegadinha do jwks_uri do PowerSync, curada caso a caso (PowerSync).

Decisão

App chama app da casa sempre pela URL pública (https://<fqdn>.xadm.biz), e cada host resolve os domínios que ele mesmo serve para o próprio Traefik.

  • URL pública, nunca IP, alias de rede Docker nem --add-host. A URL vem da env <APP>_URL; o TLS e o domínio são os mesmos de fora.
  • Todo host Coolify roda o xadm-dns: um CoreDNS que responde os *.xadm.biz roteados pelo Traefik daquele host com o IP do host, e repassa o resto ao DNS público. A lista é gerada das labels dos containers e dos arquivos dinâmicos do Traefik, a cada minuto.
  • A rede coolify de todo host usa 10.0.1.0/24, o padrão do Coolify, e o xadm-dns escuta no gateway 10.0.1.1. O endereço é o mesmo em qualquer host.
  • Todo recurso de app leva --dns 10.0.1.1 --dns 1.1.1.1 em Custom Docker Options; serviço de recurso compose leva dns: [10.0.1.1, 1.1.1.1].
  • Continuam valendo as exceções já normatizadas: banco pelo nome do serviço Docker, e API do Coolify por http://coolify:8080, que segue preferível por dispensar TLS e allowlist.

Receita, provisionamento do host e diagnóstico em Operação no Coolify.

Alternativas descartadas

  • --add-host fqdn:<IP que funciona>. Troca um link frágil por outro: se aquele link cair, a chamada entre dois apps da mesma máquina para junto.
  • Alias de rede Docker + http://<alias>:8080. Só resolve no mesmo host, quebra no site de DR e em serviço que existe num site só, e deixa cada app com uma URL diferente da pública e sem TLS.
  • Retry no cliente HTTP. Código em cada app, e o resolver da JVM não garante tentar o outro IP.
  • NAT loopback no roteador. Vale como complemento, mas não cobre queda de link nem o DR.

Consequências

  • Nenhum app muda código: a <APP>_URL pública continua a mesma.
  • Serviço presente no host resolve para o Traefik local; serviço ausente segue o DNS público. No DR, o mesmo setup em cada host funciona sem mudança nos apps.
  • Se o xadm-dns cair, o container usa o segundo servidor (1.1.1.1), que é o caminho antigo. O CoreDNS não vira ponto único de falha. Nomes de container e de serviço seguem no DNS embutido do Docker.
  • A API do Coolify chamada por admin.xadm.biz chega com IP interno; a allowlist tem 10.0.1.0/24.
  • O lint do pipeline-config.yml avisa serviço de compose sem dns:. Recurso de app sem --dns aparece na checagem periódica do coolify.md; o aviso no deploy é pendência do control-plane.