Pular para conteúdo

Estado atual e histórico

Foto do que está pronto, do que falta e do que já deu problema. Atualize esta página quando algo mudar: ela é a memória do projeto.

Em produção desde 25/10/2026

https://braggo.com.br abre pela internet (testado em rede de fora de casa). Fluxo: Cloudflare → túnel → Nginx → Angular e API → PostgreSQL.

Feito

  • [x] Domínio braggo.com.br registrado e pago no Registro.br
  • [x] DNS do domínio na Cloudflare (status Ativo)
  • [x] Túnel braggo como serviço, rotas para a raiz e o www
  • [x] Swagger e dashboard do Hangfire fora do alcance público (verificação)
  • [x] Chave do JWT e Setup__Secret próprios de produção, fora do repositório
  • [x] E-mail pelo Resend com domínio verificado; recuperação de senha testada de ponta a ponta (E-mail)
  • [x] Script de backup do banco e teste de restauração com sucesso (14 tabelas) (Backup)

Pendências

Marque conforme concluir.

Conferir (já feito, falta confirmar)

  • [ ] Reserva de IP no roteador (menu Rede local > LAN > Ligação DHCP, servidor → 192.168.1.14): confirme que está salva na lista e que a VM volta com o mesmo IP depois de sudo reboot
  • [ ] Cron do backup: systemctl is-active cron e, depois da primeira madrugada, uma linha ok em sudo tail /var/log/braggo-backup.log

Segurança da VM

  • [ ] Firewall ufw, nesta ordem: sudo ufw allow OpenSSH, sudo ufw allow 80/tcp, sudo ufw enable. A porta 80 só precisa atender a rede local, porque o túnel é conexão de saída
  • [ ] SSH por chave e depois desligar login por senha (passo a passo em Servidor base)
  • [ ] sudo apt update && sudo apt upgrade -y e reinício (havia atualização pendente)

Resiliência

  • [ ] Cópia do backup para fora da VM (adiada de propósito; hoje o backup morre junto com a VM)
  • [ ] Guardar cópia de /etc/braggo-api.env e dos arquivos de configuração em local seguro (como)
  • [ ] Snapshot novo, tirado com a VM desligada, depois que tudo acima estiver pronto

Código e dependências

  • [ ] Atualizar o pacote Microsoft.OpenApi 2.4.1 (o build avisou vulnerabilidade de severidade alta)
  • [ ] Tirar do appsettings.json versionado qualquer senha ou chave real (deixar valores fictícios) e trocar essas credenciais onde elas existem
  • [ ] Opcional: mover a connection string de produção do appsettings.Production.json para o .env, para a senha do banco não ficar em arquivo junto do build
  • [ ] Observar os avisos do Hangfire (server was considered dead) se voltarem com a VM ligada direto

Produto

  • [ ] Definir como o cliente final chega ao agendamento de uma barbearia (hoje a página inicial é o login e o cadastro de barbearia)

Decisões

Data Decisão Motivo
24/10/2026 Hospedar em VM no PC de casa custo zero de hospedagem para validar o produto
24/10/2026 Túnel Cloudflare em vez de IP público o IP WAN do roteador está em CGNAT (faixa 100.64.0.0/10), então não há port forwarding; a operadora cobra R$ 50/mês por IP público e a escolha foi não contratar
24/10/2026 Domínio .com.br no Registro.br cerca de R$ 40 por ano
25/10/2026 Cloudflare como DNS do domínio o túnel cria e serve os registros automaticamente
25/10/2026 Segredos no /etc/braggo-api.env fora do repositório e fora da pasta que o deploy sobrescreve
25/10/2026 Backup .dump (pg_dump -Fc), 14 dias, às 3h formato custom permite restaurar tabelas isoladas e é validado antes de ser aceito
25/10/2026 Cópia externa do backup adiada decisão do dono; segue como risco aceito até ser feita
25/10/2026 DMARC mantido em p=reject e-mails legítimos passaram nos testes

Incidentes e lições

Erro 500: relation "barbearia" does not exist O banco novo estava sem tabelas. Foi achado com journalctl -u braggo-api. Correção: gerar o script com dotnet ef migrations script --idempotent e rodar com psql (Banco).

Migrations falharam no psql Várias chamadas migrationBuilder.Sql("...") não terminavam com ;. No script idempotente, o EF coloca os comandos dentro de blocos DO $EF$ ... END $EF$, onde cada comando precisa terminar com ;. Aplicando pelo dotnet ef database update isso costuma passar despercebido, mas rodando o .sql no psql quebra. Correção: terminar todo comando SQL das migrations com ;. Regra daqui para frente: toda migrationBuilder.Sql termina com ;.

Erro 500: Resend:ApiKey não configurada A chave só existia no ambiente de desenvolvimento. Correção: variável Resend__ApiKey no /etc/braggo-api.env, ligado ao serviço com EnvironmentFile. Regra: tudo que a API lê do ambiente e não está no appsettings precisa de linha no .env.

Snapshots do VMware apagados por engano O estado atual da VM não foi afetado (conferidos serviços, tabelas e arquivos), mas se perdeu a rede de segurança. Lição: snapshot não é backup. Ele fica no mesmo disco da VM, depende da cadeia de snapshots e não protege contra falha do disco. Por isso existe o backup do banco.

Cloudflare: "Invalid nameservers" Depois de trocar os servidores DNS no Registro.br, o domínio fica "em transição" por cerca de 1h15 antes de publicar a troca. Nesse período a Cloudflare mostra o status inválido. Não refazer a troca: apenas esperar e clicar em Check nameservers.

/swagger abre a tela inicial do app Não é falha de segurança: o Nginx devolve o index.html do Angular para qualquer caminho fora de /api/. Para testar a API de verdade, use /api/....

Todos deslogados depois de trocar a chave do JWT Esperado: os tokens antigos foram assinados com a chave anterior. Avisar os usuários antes, quando houver usuários reais.

Permission denied ao listar o backup A pasta é 700, só o root entra. Use sudo. Para glob (*.dump), rode dentro de sudo bash -c '...', porque o shell expande o * antes do sudo.