Plano de Backup — CAIXA1¶
Doc canônico do sistema de backup diário automatizado que a CAIXA1 (VPS Local Windows) executa. Baseia decisões nos dados coletados em DEV-1727 (inventario-vps-2026-08.md).
1. Princípios¶
- Backup só é backup se restore funciona — F6 valida restore em ≥3 tipos de fonte antes de fechar o projeto.
- Snapshot-style, deduplicado e encriptado —
resticé o motor central (equivalente ao snapshot da Hostinger). Primeiro backup ~100 GB, incrementais diários em MB. - Falha ruidosa — qualquer job que falha dispara notificação WhatsApp via Evo comercial. Silêncio ≠ sucesso.
- Um comando de restore de emergência documentado por cenário — quem restaurar não deve precisar reconstruir o raciocínio.
- Retention determinística —
--keep-daily 30 --keep-weekly 12 --keep-monthly 12em todas as fontes. Retention consistente vale mais que retention perfeita por fonte.
2. Storage layout no HD F: (PD-Backup)¶
F:\
├── restic-repo\ ← repo restic encriptado (todas fontes filesystem)
│ ├── config
│ ├── data\
│ ├── index\
│ ├── keys\
│ └── snapshots\
├── Backups\
│ ├── VPS-Dev\
│ │ ├── db-dumps\
│ │ │ ├── lara-postgres-<YYYYMMDD>.sql.gz
│ │ │ ├── cadencia-agenda-mysql-<YYYYMMDD>.sql.gz
│ │ │ └── crontabs-<YYYYMMDD>.txt
│ │ └── (fs vai direto pro restic-repo)
│ ├── VPS-Master\
│ │ ├── coolify-dump\
│ │ │ └── coolify-<YYYYMMDD>.tar.gz
│ │ ├── db-dumps\
│ │ │ ├── evolution-<YYYYMMDD>.sql.gz
│ │ │ ├── lara-legada-<YYYYMMDD>.sql.gz
│ │ │ ├── ecuro-<YYYYMMDD>.sql.gz
│ │ │ ├── confirmation-queue-<YYYYMMDD>.sql.gz
│ │ │ ├── cadencia-agenda-master-<YYYYMMDD>.sql.gz
│ │ │ └── crontabs-<YYYYMMDD>.txt
│ │ └── (fs + docker volumes vão direto pro restic-repo)
│ ├── Supabase\
│ │ ├── cadencia-<YYYYMMDD>.sql.gz
│ │ ├── hubpd-<YYYYMMDD>.sql.gz
│ │ └── outros-<YYYYMMDD>.sql.gz
│ ├── Vercel\
│ │ └── <project>-envs-<YYYYMMDD>.txt.gpg
│ ├── GitHub\
│ │ └── <org>\<repo>.git\ ← mirror clones (git fetch --all diário)
│ ├── 1P\
│ │ └── 1p-export-<YYYYMMDD>.zip.gpg
│ ├── Linear\
│ │ └── linear-<YYYYMMDD>.json.gz ← semanal
│ ├── Cloudflare\
│ │ └── cf-<YYYYMMDD>.json ← semanal
│ └── Resend\
│ └── events-<YYYYMMDD>.json.gz ← semanal
└── Logs\
└── backup\
└── run-<YYYYMMDD>.log ← rotativo 30 dias
Nota: dumps em Backups\ são inputs pro restic-repo\ (o repo dedupa entre versões). Manter arquivos crus em paralelo agiliza restore de casos triviais sem precisar restic restore.
3. Fontes e estratégia por fonte¶
3.1 VPS Dev (ssh vps-dev)¶
| O quê | Como | Frequência |
|---|---|---|
/home/felipe, /home/luiz, /opt | restic backup via SSH | diário |
DB Lara nova (lara-postgres container) | docker exec lara-postgres pg_dump -U <user> <db> → .sql.gz → restic | diário |
MySQL EasyAppointments (cadencia-agenda-mysql) | docker exec cadencia-agenda-mysql mysqldump ... → .sql.gz → restic | diário |
Redis Lara (lara-redis) | ❌ NÃO backupar — é cache reconstrível | — |
| Docker volumes não-DB | restic /var/lib/docker/volumes/ (só volumes que NÃO são de DB) | diário |
| Crontabs (felipe + root via sudo) | crontab -l; sudo crontab -l → crontabs-<data>.txt → restic | diário |
3.2 VPS Master (ssh -i ~/.ssh/hostinger_prod_master master@72.60.4.71)¶
| O quê | Como | Frequência |
|---|---|---|
| Coolify metadata (banco interno) | Backup nativo Coolify — dashboard config'do pra dump diário em local mount → copiado pra F: via SCP. Fallback manual: docker exec coolify-db pg_dump -U postgres coolify | diário |
| DBs dos apps gerenciados (Evolution, Lara legada, Ecuro, Confirmation-queue, EasyAppointments Master) | docker exec <container> pg_dump/mysqldump por container identificado | diário |
/data/coolify | restic backup via SSH (contém app configs, deploys) | diário |
/var/lib/docker/volumes — volumes NÃO de DB | restic backup via SSH | diário |
/opt, /etc, /root/scripts | restic backup via SSH | diário |
| Crontabs (master + root) | idem VPS Dev | diário |
3.3 Supabase¶
| O quê | Como | Frequência |
|---|---|---|
| Cadencia project | pg_dump via connection string (1P: Supabase - Cadencia [ClaudeCode]) | diário |
| Hub PD project | idem (1P: Supabase - HubPD - [ClaudeCode]) | diário |
| Outros projects | idem — descobertos via npx supabase projects list | diário |
Dumps .sql.gz vão pra F:\Backups\Supabase\ e são consumidos pelo restic (dedupe entre versões).
3.4 Vercel¶
| O quê | Como | Frequência |
|---|---|---|
| Env vars de todos os projects | vercel env pull por project → encriptar com GPG (chave dedicada, senha 1P) → F: | diário |
| Código | ❌ NÃO — GitHub é fonte de verdade | |
| Deploys / builds | ❌ NÃO — rollback nativo Vercel funciona |
3.5 GitHub¶
| O quê | Como | Frequência |
|---|---|---|
| Repos privados da conta felipeluissalgueiro | gh repo list --limit 1000 --json name,url + git clone --mirror (ou git fetch --all se já existir) | diário |
| Repos da org Posicionamento-Digital | idem, gh repo list Posicionamento-Digital --limit 1000 | diário |
| Issues / PRs / Wiki | fora de escopo por ora (baixa prioridade) | — |
3.6 1Password¶
| O quê | Como | Frequência |
|---|---|---|
| Export completo | op export → zip encriptado com GPG (senha 1P separada, guardar impressa) → F: | diário |
Cuidado: export do 1P sai em plaintext antes de encriptar. Encriptação com GPG é obrigatória; deletar plaintext imediatamente. Senha GPG guardada em Hosts no 1P + cópia impressa/física.
3.7 Notebook (via Tailscale)¶
| O quê | Como | Frequência |
|---|---|---|
C:\dev\pd-framework | restic backup do CAIXA1 puxando via \\notebook.tailscale-mesh\C$\dev\pd-framework OU push direto do notebook | diário |
C:\Users\felip\Obsidian_Vaults_* | idem | diário |
C:\Users\felip\.claude | idem (exclui .claude/projects/*.jsonl — transcripts recuperáveis) | diário |
C:\Users\felip\OneDrive\Documentos | idem — cobre Hub Projetos, Customer Success, Credenciais | diário |
Nota: OneDrive já tem versionamento nativo, mas backup local dá restore instantâneo sem depender de conta MS.
3.8 Semanal¶
| Fonte | O quê | Como |
|---|---|---|
| Linear | issues + projects + docs export | API linear.app → JSON gzip → F: |
| Cloudflare | DNS records + tunnels + workers configs | API por zone → JSON → F: |
| Resend | events (delivered/bounced/complained) últimos 7 dias | API events → JSON gzip → F: |
4. Retention¶
Aplicada via restic forget --keep-daily 30 --keep-weekly 12 --keep-monthly 12 --prune após cada backup.
- 30 dias diários — restore pontual de última semana/mês
- 12 semanas — cobre trimestre
- 12 meses — cobre 1 ano (redundância anti-catástrofe)
Total esperado no F: (596 GB): primeiro backup ~100 GB, delta médio ~2 GB/dia. Depois de 1 ano: ~300 GB dedupados. Folga confortável.
5. Restore procedure — cenários¶
5.1 "Perdi arquivo do notebook"¶
# Lista snapshots do notebook
restic -r F:\restic-repo snapshots --tag notebook
# Restaura arquivo específico do snapshot de N dias atrás
restic -r F:\restic-repo restore <snapshot-id> --target C:\restore\ --include "C:\dev\pd-framework\times\infra\<arquivo>"
Tempo estimado: < 5 min.
5.2 "Supabase apagou tabela"¶
# Restaura dump do último dia
gunzip -c F:\Backups\Supabase\cadencia-20260808.sql.gz > cadencia-20260808.sql
# Sobe Postgres temp local
docker run -d --name pg-restore -p 55432:5432 -e POSTGRES_PASSWORD=temp postgres:15
psql -h localhost -p 55432 -U postgres -f cadencia-20260808.sql
# Extrai só a tabela e re-injeta na produção
pg_dump -h localhost -p 55432 -U postgres -t <tabela> > tabela.sql
psql "postgresql://<supabase-connection>" -f tabela.sql
Tempo estimado: 15-30 min.
5.3 "VPS Master crashou total"¶
Sequência: 1. Provisionar nova VM Hostinger 2. Instalar Docker + Coolify 3. Restaurar /data/coolify do restic-repo → montar em /data/coolify da nova VM 4. Restaurar coolify-db dump em Postgres novo (Coolify vai reconectar) 5. Restaurar docker volumes de DBs por app (docker volume create + restic restore + subir container) 6. Ajustar DNS Cloudflare pro novo IP
Tempo estimado: 3-6 horas dependendo do tamanho dos volumes.
5.4 "GitHub bloqueou conta"¶
# Cada mirror clone em F:\Backups\GitHub\<org>\<repo>.git é um repo bare completo
cd F:\Backups\GitHub\felipeluissalgueiro\cadencia-app.git
git worktree add /tmp/restore main
# Ou push pra novo remoto (GitLab, Bitbucket, self-hosted)
git remote add new-remote git@gitlab.com:...
git push new-remote --all --tags
Tempo estimado: 1-2 horas pra restaurar acesso operacional.
5.5 "1P bloqueou conta"¶
# Export mais recente encriptado
gpg --decrypt F:\Backups\1P\1p-export-20260808.zip.gpg > 1p-export.zip
# Descompactar e importar em cliente 1P novo, Bitwarden, ou Vaultwarden self-hosted
Tempo estimado: 30 min-1h.
5.0 Comando de restore de emergência (setup-free)¶
Se você precisa restaurar algo agora, sem ler nada além disto:
# Na CAIXA1 (via SSH ou local):
$env:RESTIC_PASSWORD = cmd /c "op item get `"restic - CAIXA1 backup repo`" --vault Databases --fields password --reveal < NUL"
$env:RESTIC_REPOSITORY = "F:\restic-repo"
# Lista todos os snapshots
C:\Tools\restic\restic.exe snapshots
# Restaura último snapshot completo pra C:\restore\
C:\Tools\restic\restic.exe restore latest --target C:\restore\
# Restaura arquivo específico
C:\Tools\restic\restic.exe restore <snapshot-id> --target C:\restore\ --include "/path/no/backup"
Se op não estiver disponível, a senha está no 1P vault Databases, item restic - CAIXA1 backup repo (ID: tfso2ux7uajctdq4nbawainkn4).
5.6 "Restic repo corrompeu"¶
# Check integridade (roda semanal automático)
restic -r F:\restic-repo check --read-data
# Se corrompido: fallback pros dumps crus em F:\Backups\ (sem incrementalidade mas dados presentes)
Última linha de defesa: os dumps crus em F:\Backups\<fonte>\ não dependem de restic. Se restic morrer, ainda temos o essencial.
6. Monitoramento¶
6.1 Log local¶
Todo script escreve em F:\Logs\backup\run-<YYYYMMDD>.log (formato: timestamp | fonte | ação | status | tamanho | duração). Rotação: 30 dias.
6.2 Notificação de falha¶
Wrapper run-all-backups.ps1 captura exit code de cada script. Qualquer falha → mensagem WhatsApp via evo_client.py pro número comercial de Felipe:
[BACKUP CAIXA1] ❌ FALHA <fonte> em <data> <hora>
Erro: <primeira linha do stderr>
Log completo: F:\Logs\backup\run-<data>.log
Sucesso silencioso — sem notificação diária de sucesso (evita ruído). Digest semanal (domingo 10h) com resumo dos 7 dias: quantos backups OK, tamanhos, retention aplicada.
6.3 Deadman¶
Se nenhum backup rodar por 48h, cron separado na CAIXA1 dispara alerta ("último snapshot restic tem mais de 48h — CAIXA1 sem backup"). Detecta cenário onde CAIXA1 desligou/travou e ninguém notou.
7. Riscos e mitigações¶
| Risco | Mitigação |
|---|---|
| Dump Postgres inconsistente (transações em vôo) | pg_dump usa snapshot transacional consistente — seguro em produção |
| Docker volume DB "quente" copiado pelo restic gera dump corrompido | Excluir docker/volumes/*postgres-data* do restic; DBs vão só via pg_dump |
| HD F: falha | Off-site futuro (Cloudflare R2 ou Backblaze B2) — fora de escopo dessa fase |
| Senha restic perdida | Guardada em 1P vault Hosts + cópia impressa/física em envelope selado |
| Senha GPG (Vercel envs, 1P export) perdida | Idem — 1P + cópia impressa |
| CAIXA1 rouba/incendeia | Off-site futuro (fase 2) — hoje risco aceito |
| Backup rodando durante uso pesado da VPS Master | Agendado 03h00 (madrugada); pg_dump usa --jobs=1 pra minimizar contenção |
8. Dependências¶
- Restic instalado no CAIXA1 (F3 — DEV-1730)
- Senha restic no 1P (F3)
- HDs renomeados (F2 — DEV-1729)
- Chaves SSH CAIXA1 → VPS Dev + Master já validadas (session 08/08 01:02)
opservice account rodando no CAIXA1 (validado)evo_client.pyacessível do CAIXA1 (validar em F4)
9. Referências¶
- Inventário fonte:
inventario-vps-2026-08.md— F0/DEV-1727 - Skills:
/vps-local,/vps-local-acesso-remoto - Doc VPS Local:
Obsidian_Vaults_Pessoal/Infra/2026-08-08 VPS Local CAIXA1 (Windows).md - Restic docs: https://restic.readthedocs.io/
- Coolify backup: https://coolify.io/docs/knowledge-base/backup