H-03 — Backup Postgres: Preview O que precisa ser feito: Cri...
👤 User
H-03 — Backup Postgres: Preview
O que precisa ser feito: Criar um script de backup agendado do banco kodama_hub (container kodama-hub-postgres, imagem pgvector/pgvector:pg16, porta interna 5432, dados em ./api/pgdata/).
O que backup
Container DB: kodama-hub-postgres, banco kodama_hub, user kodama.
Volume: ./api/pgdata — mas NUNCA backup de volume cru sem parar o container (corrompe). Usar pg_dump.
Credenciais: POSTGRES_PASSWORD via .env no VPS (gitignored).
Como fazer (melhor abordagem)
Dois arquivos no repo, no diretório scripts/:
scripts/backup.sh — script executado dentro do container:
#!/bin/bash
BACKUPDIR="/home/kodama-hub/backups"
TIMESTAMP=$(date +"%Y%m%d%H%M%S")
mkdir -p "$BACKUP_DIR"
docker exec kodama-hub-postgres pg_dump
-U kodama -d kodama_hub
--no-owner --no-acl -Fc
"$BACKUPDIR/kodama-hub${TIMESTAMP}.dump"
Limpa backups com mais de 7 dias
find "$BACKUPDIR" -name "kodama-hub.dump" -mtime +7 -delete
echo "[$(date)] Backup OK: kodama-hub_${TIMESTAMP}.dump"
infra/cron/kodama-hub-backup — crontab (no VPS):
0 3 * * /home/kodama-hub/scripts/backup.sh >> /var/log/kodama-hub-backup.log 2>&1
Restore testado
Script de restore (ou checklist):
Restaurar (dry-run primeiro):
docker exec -i kodama-hub-postgres pg_restore
-U kodama -d kodama_hub
--clean --if-exists
< /home/kodama-hub/backups/kodama-hub_20260620_030000.dump
Health check pós-restore
docker exec kodama-hub-postgres psql -U kodama -d kodama_hub -c "SELECT count(*) FROM information_schema.tables WHERE table_schema='public';"
Resumo do que criar/modificar
Arquivo Ação
scripts/backup.sh Criar — script de dump + retenção 7d
infra/cron/kodama-hub-backup Criar — entry pro crontab
scripts/restore-test.sh Criar (opcional) — docs de restore
README.md ou infra/README.md Atualizar — instrução de setup do cron
VPS /etc/crontab ou crontab -e Manual — adicionar entry
Bônus: envio pro MinIO/S3
Se quiser resiliência extra (VPS pegar fogo), o backup pode ser enviado pro bucket MinIO do vault:
após pg_dump, enviar pro MinIO:
curl -X PUT -T "$BACKUPDIR/kodama-hub${TIMESTAMP}.dump"
"https://mimic-cdn.kodama.solutions/kodama-hub/backups/kodama-hub_$%7BTIMESTAMP%7D.dump"
Pronto quando
Cron de dump rodando → backup na pasta /home/kodama-hub/backups/ com data
Retenção 7 dias → backups antigos somem
Restore validado → rodou pg_restore contra cópia sem erro
🤖 Assistant
Vou analisar o contexto do kodama-hub pra criar os scripts. Primeiro, vou verificar os arquivos relevantes no repo.
[tool: mcp_github__get_file_contents({"owner":"kodama1","repo":"kodama-hub","path":"infra/docker-compose.yml"})]
[tool: mcp_github__get_file_contents({"owner":"kodama1","repo":"kodama-hub","path":"scripts"})]
👤 User
[tool_result: {"error":"MCP error -32603: Not Found: Resource not found: Not Found"}]
[tool_result: {"error":"MCP error -32603: Not Found: Resource not found: Not Found"}]
[tool: mcp_github__get_file_contents({"owner":"kodama1","repo":"kodama-hub","path":"docker-compose.yml"})]
[tool: mcp_github__get_file_contents({"owner":"kodama1","repo":"kodama-hub","path":"."})]
👤 User
[tool_result: {"success":true,"text":"{\n "name": "docker-compose.yml",\n "path": "docker-compose.yml",]
[tool_result: {"success":true,"text":"[\n {\n "type": "dir",\n "size": 0,\n "name": ".claude",]
🤖 Assistant
Agora vou verificar se já existe infra/ e scripts/ pra entender onde colocar os arquivos:
[tool: mcp_github__get_file_contents({"owner":"kodama1","repo":"kodama-hub","path":"infra"})]
[tool: mcp_github__get_file_contents({"owner":"kodama1","repo":"kodama-hub","path":".gitignore"})]
👤 User
[tool_result: {"success":true,"text":"[\n {\n "type": "file",\n "size": 2256,\n "name": "nginx-]
[tool_result: {"success":true,"text":"{\n "name": ".gitignore",\n "path": ".gitignore",\n "sha": "75]
🤖 Assistant
Ok, tenho o contexto completo. Repo já tem infra/ com nginx configs, sem scripts/ e sem backups/. Vou criar os 3 arquivos agora.
Detalhes confirmados do compose:
- Container:
kodama-hub-postgres - User:
kodama, DB:kodama_hub - Dados em
./api/pgdata(volume) - Porta interna 5432, mapeada pra
127.0.0.1:5435 .envna raiz temPOSTGRES_PASSWORD
[tool: mcp_github__create_or_update_file({"owner":"kodama1","repo":"kodama-hub","path":"scripts/backup.sh","message":"feat(scripts): backup.sh — pg_dump agendado)]
👤 User
[tool_result: {"success":true,"text":"{\n "content": {\n "name": "backup.sh",\n "path": "scripts/b]
🤖 Assistant
Agora o arquivo de cron e o script de restore:
[tool: mcp_github__create_or_update_file({"owner":"kodama1","repo":"kodama-hub","path":"infra/cron/kodama-hub-backup","message":"feat(cron): entry crontab para b)]
👤 User
[tool_result: {"success":true,"text":"{\n "content": {\n "name": "kodama-hub-backup",\n "path": "i]
[tool: mcp_github__create_or_update_file({"owner":"kodama1","repo":"kodama-hub","path":"scripts/restore.sh","message":"feat(scripts): restore.sh — instruções de )]
👤 User
[tool_result: {"success":true,"text":"{\n "content": {\n "name": "restore.sh",\n "path": "scripts/]
🤖 Assistant
Agora vou atualizar o DEPLOY.md com a seção de backup:
[tool: mcp_github__get_file_contents({"owner":"kodama1","repo":"kodama-hub","path":"DEPLOY.md"})]
👤 User
[tool_result: {"success":true,"text":"{\n "name": "DEPLOY.md",\n "path": "DEPLOY.md",\n "sha": "a104]
[tool: mcp_github__create_or_update_file({"owner":"kodama1","repo":"kodama-hub","path":"DEPLOY.md","message":"docs(deploy): adiciona seção de backup — pg_dump + )]
👤 User
[tool_result: {"success":true,"text":"{\n "content": {\n "name": "DEPLOY.md",\n "path": "DEPLOY.md]