Backup e recuperação
Plano de backup e recuperação de desastres
Metas (propostas — validar com a TI do hospital)
- RPO (Recovery Point Objective): até 24h de dados perdidos no pior caso (backup diário). Para um RPO menor, aumentar a frequência do backup (ver abaixo) ou habilitar WAL archiving contínuo do Postgres.
- RTO (Recovery Time Objective): até 2h para restaurar o serviço a
partir de um backup, em uma VM nova (tempo dominado por: provisionar a
VM,
git clone/copiar o projeto,./deploy/instalar-docker.sh,./deploy/subir-app.sh,./deploy/restaurar.sh <dump>).
Estas metas assumem volume de dados de um hospital (não terabytes) — um
pg_dump completo deve levar segundos a poucos minutos.
O que é coberto
- Todo o banco
chamados_unimed_nf: quartos, usuários, dispositivos, chamados e a trilha de auditoria completa (EventoAuditoria). - Não coberto por este backup: configuração do servidor (
.env, certificados HTTPS do Caddy) — manter uma cópia segura separada dessas configurações (ex.: gerenciador de segredos da TI), já que elas contêm credenciais.
Rotina de backup
./deploy/backup.sh
Gera um dump comprimido (pg_dump -Fc) em ./backups/, com nome
chamados_unimed_nf_<data>.dump. Mantém automaticamente só os últimos 14
arquivos locais (ver o próprio script).
Agendar via cron (na VM de produção), por exemplo diariamente às 3h:
0 3 * * * /caminho/completo/Projeto_Chamados_Hospital/deploy/backup.sh >> /var/log/chamados-backup.log 2>&1
Cópia fora do servidor (obrigatório em produção)
Um backup que só existe no mesmo disco/servidor do banco não protege
contra falha de disco, do servidor inteiro, ou de um incidente de
segurança que comprometa a VM inteira. Depois de deploy/backup.sh
gerar o arquivo, copie-o para um destino fora desta máquina — a escolha
concreta (S3/object storage, outro datacenter, backup gerenciado pela TI
central da Unimed) fica a critério da infraestrutura do hospital; este
projeto não prescreve um provedor específico. Um exemplo simples de
segunda etapa no cron, depois do backup local:
rclone copy ./backups/ remoto:chamados-backups/ --max-age 25h
(usando rclone configurado para o destino escolhido — S3, outro servidor via SFTP, etc.)
Restauração
./deploy/restaurar.sh ./backups/chamados_unimed_nf_2026-01-01_030000.dump
Destrutivo: apaga o banco atual antes de restaurar. Pede confirmação
explícita (SIM) antes de prosseguir. Depois de restaurar:
docker compose restart app
Teste de restauração (drill)
Um plano de backup só vale se a restauração já foi testada. Recomendado: a cada trimestre, restaurar o backup mais recente em uma VM separada (não a de produção) e confirmar:
docker compose exec app npx prisma migrate deployroda sem erro (schema restaurado é compatível com o código atual).- Login com um usuário real funciona.
- Os relatórios (
/dashboard/supervisor/relatorios) mostram números condizentes com o esperado para a data do backup. - Uma consulta manual em
EventoAuditoriaconfirma que o histórico de auditoria foi preservado (SELECT count(*) FROM "EventoAuditoria";antes e depois deve bater).
Documentar a data e o resultado de cada drill (mesmo que informalmente, ex. em uma planilha da TI) — isso é parte do que auditores/compliance tipicamente pedem como evidência de que o plano de backup funciona de verdade, não só existe no papel.
Cenários de desastre
| Cenário | Ação |
|---|---|
| Corrupção/perda do banco, VM continua íntegra | ./deploy/restaurar.sh <último backup> |
| Perda total da VM | Provisionar VM nova (deploy/instalar-docker.sh → deploy/subir-app.sh → deploy/restaurar.sh) |
| Certificado HTTPS expirado/perdido | Caddy renova automaticamente via Let's Encrypt enquanto o domínio apontar para a VM; se precisar recriar do zero, basta reiniciar o container caddy com o domínio configurado |
| Credenciais comprometidas | Trocar AUTH_SECRET, senhas das roles do Postgres e chaves VAPID no .env; isso invalida todas as sessões ativas, forçando novo login |