O Capivara que não cai — espelho no Douglas e o failover que funcionou sozinho
🐷 Capivara·

O Capivara que não cai — espelho no Douglas e o failover que funcionou sozinho

📖 5 min de leitura← Voltar para timeline

⚡ O hub pessoal que não pode cair

O Capivara é o painel de comando do meu ecossistema: dashboard, health checks dos serviços, Umami, admin de tudo, Segundo Cérebro. Se ele cai, tudo parece morto — mesmo que os outros projetos estejam de pé.

Em agosto de 2026, ele tava devolvendo 502 intermitente no tunnel. Não era um crash — era pior: um downtime invisível, que aparecia e sumia. A resposta foi o princípio arquitetural que vale pra todo o ecossistema: Douglas = espelho + fallback. E pra provar que funcionava, a gente fez o teste mais honesto que existe: derrubou o serviço principal de propósito.

🧠 Contexto — o 502 que ia e voltava

O Capivara roda no Samuel: FastAPI na porta 8001, Cloudflare Tunnel expondo capivara.seu.pet. O Douglas é o PC espelho/fallback do ecossistema — o mesmo papel que já cumpre pro Arachne e pro Dogwalk.

O problema: o tunnel respondia 200/502 alternando. Um healthcheck de passagem pegava 200, outro pegava 502. Pro usuário (eu), era “às vezes funciona”. Pro sistema, era um ponto único de falha sem cobertura.

A regra do ecossistema: se Samuel OU Douglas cair, o site continua de pé. O Capivara ainda não seguia essa regra.

🔧 A luta — montando o espelho

A implementação (Opção A — espelho completo, decidida em 03/08/2026) foi cirúrgica:

  1. Backend copiado pro Douglas — mesmo path, venv Python 3.13.5 + deps extras (httpx, psutil, pyotp, qrcode, pywebpush, chromadb). O requirements.txt tava desatualizado — a cópia forçou a lista real (commit 9477700)
  2. frontend/dist copiado — o SPA inteiro
  3. Serviço idênticocapivara-backend.service (127.0.0.1:8001, EnvironmentFile .env, JWT secret IGUAL — os dois lados aceitam os mesmos tokens)
  4. Tunnel do Douglascapivara.seu.pet → 127.0.0.1:8001 no cloudflared dele
  5. Sync do banco one-way (Samuel → Douglas), via script dedicado:
# capivara-db-sync-douglas.sh — snapshot consistente mesmo com o app rodando
sqlite3 capivara.db ".backup /tmp/capivara_sync.db"   # snapshot
scp /tmp/capivara_sync.db [email protected]:C:/Temp/  # transfere
# no Douglas: para o serviço, troca o db, sobe de novo
  1. Healthcheck — timer de 5min no Douglas pra garantir que o serviço tá vivo

O sync usa SQLite mode delete (sem WAL) — snapshot via .backup é consistente mesmo com o app escrevendo. Um detalhe que evita corromper o banco no meio da cópia.

Depois de montado, o teste imediato: /health 10/10 = 200 via tunnel com o Douglas ativo (antes: 200/502 alternando).

💡 Resolução — o failover que funcionou sozinho

A prova final foi o teste de failover real: o cloudflared do Samuel foi parado por ~40 segundos. Sem tocar em nada no Douglas.

Resultado:

capivara.seu.pet → 5/5 = 200  (Douglas assumiu SOZINHO)
dogwalk uptime: 61024 → 61104  (prova de que a origem mudou pro Douglas)
religou o cloudflared do Samuel → 5/5 = 200

O detalhe mais bonito: a prova não veio de um log do Capivara — veio do uptime do Dogwalk, que conta de onde a resposta veio. O contador pulou pro Douglas no momento exato do failover e voltou quando o Samuel religou. High availability validada de verdade, não na teoria.

📊 Métricas

Métrica Antes Depois
Tunnel 200/502 alternando 5/5 = 200 estável
Failover não existia automático (Douglas assume em ~40s)
Origem da resposta Samuel (única) Samuel + Douglas (espelho)
Sync DB não existia one-way Samuel → Douglas (cron 1h)
Healthcheck timer 5min no Douglas
Uptime Dogwalk origem única 61024→61104 (prova de troca)

🎯 Aprendizados

  1. Disponibilidade se PROVA, não se promete — o teste de failover real (derrubar o principal e ver o espelho assumir) vale mais que qualquer arquitetura documentada.
  2. O espelho precisa ser idêntico até no secret — JWT secret igual nos dois lados significa que os tokens do usuário sobrevivem ao failover sem re-login.
  3. Sync one-way com snapshot consistentesqlite3 .backup + swap evita banco corrompido. SQLite mode delete (sem WAL) simplifica o sync.
  4. A prova pode estar no vizinho — o uptime do Dogwalk provou o failover do Capivara. Observabilidade cruzada entre serviços é um superpoder.
~/lifelog — bash
$cat about.txt
╔══════════════════════════════════════╗
║  Samuel Medeiros                    ║
║  Senior Software Engineer           ║
║  Stack: Python · TypeScript · Rust  ║
║  Projetos: Arachne, Dogwalk,        ║
║            Capivara, TatuEngine      ║
╚══════════════════════════════════════╝
      
$