Configuração — application.yml, application-dev.yml e Coolify¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-10
Ficheiros no repositório (src/main/resources)¶
| Ficheiro | Função |
|---|---|
application.yml |
Produção (default do JAR). Tudo o que é comum e valores por omissão; dados sensíveis e por cliente vêm de variáveis de ambiente no Coolify. |
application-dev.yml |
Só com MICRONAUT_ENVIRONMENTS=dev — base local (Postgres em localhost:5432, Flyway com clean-schema, Bearer em /api desligado, Sentry não inicializa sem SENTRY_DSN). |
Não existe application-prod.yml: a produção é o próprio application.yml + ENV.
Ambiente Micronaut¶
| Execução | Variável / nota |
|---|---|
| Produção (Coolify) | Não é obrigatório definir MICRONAUT_ENVIRONMENTS. O JAR usa só application.yml + ENV. (Legado: MICRONAUT_ENVIRONMENTS=prod ainda pode existir; o código não depende dele para Sentry nem para bloquear a UI.) |
| Desenvolvimento local | MICRONAUT_ENVIRONMENTS=dev → carrega application-dev.yml sobre application.yml. |
| Testes | src/test/resources/application-test.yml (perfil test). |
Comportamento da aplicação (resumo)¶
- Sentry (
SentryInitializer): inicializa só se existir DSN válido (SENTRY_DSN/sentry.dsn) e o ambiente não fordevnemtest. Em dev local normalmente não há DSN → não envia eventos. - UI (link Debug, botões de edição na web): permitidos só com perfil
devoutest. Deploy só comapplication.yml(semdev) → interface somente leitura para alterações CRUD.
Coolify — variáveis de ambiente recomendadas¶
Segredos via secrets do Coolify; nomes seguem o mapeamento Micronaut (PROPERTY → ENV em MAIÚSCULAS com _).
Obrigatórias para produção útil¶
| Variável | Descrição |
|---|---|
CLIENTE |
Nome de exibição do cliente, como está no Coolify (ex.: Maxsul, Sul Plata Trading do Brasil, Vantroba). Não é identificador de máquina: onde o sistema precisa do slug (cliente_id do central, slug da Sascar) há env própria (CLIENTE_ID, SASCAR_SLUG) |
DATASOURCES_DEFAULT_URL |
JDBC PostgreSQL |
DATASOURCES_DEFAULT_USERNAME |
Utilizador da BD |
DATASOURCES_DEFAULT_PASSWORD |
Senha da BD |
INTEGRADOR_API_TOKEN |
Segredo fixo para Authorization: Bearer em /api/** — mesmo valor que o adapter CSV do tradutor manda no PUT/DELETE /api/v1/xadm. Sem fallback para o nome antigo API_BEARER_TOKEN, que nada lê: setar só ele deixa app.api-token vazio — fora de dev/test o BearerTokenGuard (xadm-seguranca ≥ 0.7.2) recusa o boot; em dev/test o validador fica dormente e /api/** responde 401 a tudo (nunca fica aberto) |
Recomendadas / opcionais¶
| Variável | Descrição |
|---|---|
MICRONAUT_ENVIRONMENTS |
Opcional em produção. Use dev só para desenvolvimento local. |
PORT |
Porta HTTP no container (muitos hosts definem automaticamente; default no YAML: 8080) |
PUSH_ENABLED |
true / false — notificações FCM. Com true, a credencial é conferida no boot e a instância não sobe se PUSH_CREDENTIALS_PATH não abrir (.ia/017) |
PUSH_EMPRESA |
sulplata | onpetrotrading (tópicos) |
PUSH_CREDENTIALS_PATH |
Caminho absoluto ao JSON Firebase no container (secret montado). A chave não viaja mais no jar: é segredo, e segredo não entra no build (.ia/017). Com o push ligado, path errado derruba o boot — deliberado: melhor falhar o deploy do que rodar meses sem push |
PUSH_NOTIFICATION_IMAGE_URL |
URL da imagem nas notificações (pode ficar vazio) |
PUSH_RETRY_MAX_ATTEMPTS |
Tentativas de envio em erro FCM transitório (INTERNAL/UNAVAILABLE/QUOTA_EXCEEDED). Default 3; 1 desliga o retry. Erro permanente nunca retenta |
PUSH_RETRY_BASE_DELAY_MS |
Base do backoff exponencial + jitter entre tentativas (ms). Default 1000 → ~1 s / 2 s / 4 s. 0 = sem espera. Só reenvio transitório esgotado alarma no Sentry — ver incidentes-comuns |
SENTRY_DSN |
Necessário para o Sentry em produção (não há DSN default no YAML por segurança). Mesmo valor em todos os clientes: projeto GlitchTip único (integrador) — ver dev/observabilidade.md |
SENTRY_ENVIRONMENT |
Ex.: production (default no YAML quando não definido) |
Webhook do tradutor WebStorm-ecom — só o deploy Thoms¶
Liga o poke de saída: quando o estoque muda, o integrador avisa o tradutor da Thoms para ele
varrer na hora (feature 008; ver decisão 0013). Off por
default — só o deploy da Thoms define estas variáveis. Sem elas (ou ENABLED=false/URL vazia),
o listener é no-op (sulplata/onpetro ignoram). Falha do poke não derruba o processamento XADM;
o @Scheduled do tradutor é a rede de segurança.
| Variável | Descrição |
|---|---|
WEBSTORM_WEBHOOK_ENABLED |
true só no deploy Thoms; false/ausente nos demais. É flag (não destino) → não muda de nome |
WEBSTORM_URL |
URL base do tradutor (ex.: https://webstorm.thoms.xadm.biz) — o cliente faz POST {url}/api/integrador/produto, corpo vazio. Fallback: WEBSTORM_WEBHOOK_URL (nome antigo) |
WEBSTORM_API_TOKEN |
Bearer app→app enviado no header Authorization — segredo compartilhado com o tradutor (secret do Coolify), tem que valer o WEBSTORM_API_TOKEN do tradutor. Fallback: WEBSTORM_WEBHOOK_TOKEN (nome antigo) |
Heartbeat do integrador-client — só onde há integrador-client instalado¶
O integrador-client do cliente manda o heartbeat para POST /api/v1/heartbeat desta instância, que
carimba o cliente_id e repassa ao central-backend (contrato). Sem
flag de liga/desliga: com CENTRAL_API_TOKEN vazio, ou sem nenhuma fonte de cliente_id, a rota
responde 503 heartbeat_desligado e loga ERROR a cada heartbeat — por isso elas se cadastram junto
com a instalação do client, e ficam vazias nas instâncias sem client (lá nenhum heartbeat chega).
O cliente_id tem duas fontes, nesta ordem: CLIENTE_ID explícito e, faltando ele, o 1º label
do COOLIFY_FQDN quando o fqdn casa int.<slug>.xadm.biz. Assim uma instância nova nasce
funcionando sem ninguém lembrar da env. O fqdn da perna native (int-native.<cli>.xadm.biz) não
casa de propósito: lá o CLIENTE_ID explícito é copiado da perna jar e vence. Fqdn em qualquer outro
formato deixa o cliente_id vazio e o heartbeat em 503 — melhor desligado do que carimbar o central com
o cliente errado. A resolução mora no HeartbeatController (default aninhado em ${...} não funciona no
Micronaut) e o boot loga, uma vez, de onde o cliente_id saiu.
| Variável | Property | Descrição |
|---|---|---|
CENTRAL_URL |
central.url |
URL base do central-backend. Default https://central-backend.xadm.biz; só muda em teste |
CENTRAL_API_TOKEN |
central.api-token |
Segredo. Bearer para o central — o mesmo valor em todas as instâncias e nos recursos do central (nome pelo destino, <DESTINO>_API_TOKEN) |
CLIENTE_ID |
central.cliente-id |
O cliente_id deste cliente na tabela clientes do central (ex.: maxsul). Faltando, cai no 1º label do COOLIFY_FQDN. Nunca cai no CLIENTE: o nome de exibição não passa na regra do central (^[a-z0-9-]{1,50}$) |
COOLIFY_FQDN |
central.fqdn |
Injetada pelo Coolify. Só é lida como fallback do cliente_id, e só no formato int.<slug>.xadm.biz |
Sentry em produção¶
- Definir
SENTRY_DSNno Coolify (HTTPS) — o DSN público está emdocs/app.json(features.glitchtip.dsn); é o mesmo para todo cliente. - Garantir
CLIENTEsetado: vira a tagclientede todo evento (é como se separa o tenant no projeto único). - Não usar perfil
devno container de produção.
Ficheiros em prod/<cliente>/app/¶
Os exemplos prod/*/app/application.yaml no repositório são referência histórica; a configuração ativa em servidor deve migrar para ENV no Coolify conforme a tabela acima. Não é obrigatório copiar application.yaml para a raiz do deploy se tudo estiver nas variáveis.
Resumo visual¶
Coolify (produção)
application.yml (default) + ENV (CLIENTE, BD, INTEGRADOR_API_TOKEN, SENTRY_DSN, …)
↓
java -jar app.jar → application.yml (defaults + ${ENV:...})
Desenvolvimento
MICRONAUT_ENVIRONMENTS=dev ./gradlew run
↓
application.yml + application-dev.yml
Referências¶
- Deploy e subdomínios: migration-phase4-coolify.md
- Perfis Micronaut (detalhe): micronaut-profiles.md
- API Bearer: migration-phase6-seguranca.md