Files
Matheus 4480e9265e feat(infra): apps/api e apps/frontend como services systemd
Fecha um risco documentado desde a PHASE 01: os dois processos de host
(fora do Docker) não sobreviviam a um reboot da VM, precisando ser
religados manualmente toda vez. Agora são b2bcall-api.service e
b2bcall-frontend.service (infrastructure/systemd/), enabled, sobrevivem a
reboot como os containers Docker já sobreviviam via restart:
unless-stopped.

Achado real resolvido antes de instalar: sem porta fixa, os dois
disputavam a 3000 por padrão — quem perdesse crashava com EADDRINUSE em
vez de cair pra 3001. Fixado API_PORT=3000 (.env) e PORT=3001
(Environment= direto na unit do frontend — confirmado que colocar em
apps/frontend/.env.local não funciona, o CLI do Next.js decide a porta
antes de aplicar esse arquivo). A ordem de start deixa de importar.

Rodam em modo dev (pnpm dev), não build de produção — decisão deliberada
documentada no README, virar produção é escopo maior.

Testado ponta a ponta: units instaladas e habilitadas, subiram nas portas
certas sem fallback nem crash, journalctl com logs limpos, smoke test de
regressão nas 19 telas do tenant + platform via os processos
supervisionados, todas 200. Achado incidental: as rotas do Next.js dev
levam 10-15s pra compilar na primeira visita — explica os TimeoutError
intermitentes do Puppeteer vistos ao longo da sessão, não é um bug.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFaBaBSQGhyXGEgtTYZGV8
2026-08-30 00:33:44 -03:00

2.7 KiB

systemd — apps/api e apps/frontend

apps/api e apps/frontend rodam direto no host (fora do Docker — só Postgres/Redis/FreeSWITCH/fs-config/fs-events/predictive-dialer/ai-worker são containers, e esses já voltam sozinhos via restart: unless-stopped do docker-compose.yml + docker.service habilitado). Até a PHASE 38 os dois processos de host tinham que ser religados manualmente depois de qualquer reboot — estas units resolvem isso.

Por que os dois rodam em pnpm dev, não build de produção

Decisão deliberada: o ambiente inteiro (ACESSO_TESTE.md) já é descrito como desenvolvimento/teste, não produção. Migrar apps/api pra pnpm build && node dist/main.js e apps/frontend pra next build && next start é uma mudança maior (variar comportamento de erro, HMR, etc.) fora do escopo de "sobreviver a um reboot" — fica pra quando o projeto realmente for pra produção.

Instalação

sudo cp infrastructure/systemd/b2bcall-api.service /etc/systemd/system/
sudo cp infrastructure/systemd/b2bcall-frontend.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now b2bcall-api.service
sudo systemctl enable --now b2bcall-frontend.service

Por que a ordem nunca mais importa

API_PORT=3000 fixo em .env (lido via EnvironmentFile= na unit do b2bcall-api) e PORT=3001 fixo via Environment= na unit do b2bcall-frontend — achado real desta sessão: sem os dois explícitos, os dois processos disputavam a porta 3000 por padrão, e quem perdesse a corrida caía pra 3001 (Next.js) ou crashava direto (EADDRINUSE, Nest/Fastify não tem fallback automático). Com as duas portas fixas, a ordem de start deixa de importar — cada um já nasce na porta certa, nunca compete pela mesma.

Note-se que PORT=3001 só funciona quando setado no ambiente do processo (Environment= na unit, ou PORT=3001 pnpm dev manual) — colocar em apps/frontend/.env.local sozinho não basta: o CLI do Next.js decide a porta antes de aplicar esse arquivo, então só o fallback automático (achar 3000 ocupada, tentar 3001) resolveria, e só por sorte de ordem.

Comandos úteis

sudo systemctl status b2bcall-api.service b2bcall-frontend.service
journalctl -u b2bcall-api.service -f
journalctl -u b2bcall-frontend.service -f
sudo systemctl restart b2bcall-api.service      # depois de mudar código do backend
sudo systemctl restart b2bcall-frontend.service # depois de mudar dependencias do frontend

apps/api recompila (tsc) toda vez que a unit inicia/reinicia — leva uns 15-20s. apps/frontend (next dev) é bem mais rápido pra subir, mas cada rota ainda compila na primeira vez que é visitada (comportamento normal do modo dev do Next.js, não um problema desta unit).