shivao-projeto/DEPLOY.md
PontualTech / Karlão 5b02feae50 chore: initial commit + security hardening (4 runs squad shivao-melhoria)
Importação inicial do projeto Shivão (Diário de Bordo do veleiro) em estado
pronto pra produção, já incluindo as 5 mudanças de hardening implementadas
pela squad shivao-melhoria em 2026-04-27.

Mudanças de hardening (HANDOFF.md seção " Pronto"):

1. **Rate limiting nos 3 endpoints públicos de share**
   - express-rate-limit ^8.4.1, 60 req/min/IP
   - server/src/index.js linhas 38, 262, 271, 279

2. **Tamanho de upload reduzido pra 50MB** (era 200MB)
   - multer linha 84

3. **Validação Zod nos endpoints autenticados** (POST /api/data e /zones)
   - novo arquivo server/src/schemas/index.js
   - middleware validate() retorna 400 com top 5 issues

4. **Audit log de ações sensíveis**
   - nova tabela audit_log + funções db.audit() e db.recentAudit()
   - 6 endpoints instrumentados (state_set, media_insert/delete, share_create/revoke/zones_update)
   - novo endpoint GET /api/audit (autenticado)

5. **Catch silencioso de webhook em zona PROIBIDA tratado**
   - app/diario-bordo.html + server/public/index.html linha 3280
   - agora loga erro + exibe toast ao usuário

Status final do HANDOFF:
- 🔴 Críticos restantes: 1 (CORS — decisão consciente single-tenant, não-acionável)
- 🟡 Importantes: 4 itens (testes, vigia reconnect, refator frontend, demais catches)
- 🟢 Bom-ter: 5 itens

Stack: Node 20 ESM + Express + better-sqlite3 + Docker (Coolify)
Single-tenant pessoal · single-file frontend HTML · offline-first

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 13:24:08 -03:00

230 lines
6.2 KiB
Markdown

# DEPLOY — Coolify (Hetzner VPS)
Guia passo-a-passo para colocar o **shivao-cloud** em produção no Coolify.
## Pré-requisitos
- VPS Hetzner com **Coolify** instalado e acessível
- Domínio (ou subdomínio) apontando para o IP do servidor
- Ex: `shivao.exemplo.com` → IP da VPS
- DNS propagado (verifique com `dig shivao.exemplo.com`)
## Passo 1 — Subir o código para Git
Recomendado: criar repo privado no GitHub/GitLab.
```bash
cd shivao-projeto/server
git init
git add .
git commit -m "Initial commit"
git remote add origin git@github.com:OWNER/shivao-cloud.git
git push -u origin main
```
> Alternativa: usar a opção "Deploy from Docker Image" do Coolify e fazer
> build local + push para um registry. Mas Git é mais simples.
## Passo 2 — No Coolify
### 2.1. Criar a aplicação
1. **+ New Resource** → **Application**
2. Selecione **Public/Private Repository (with GitHub App)** ou **Public/Private Repository**
3. Cole a URL do repo
4. Branch: `main`
5. **Build Pack**: `Dockerfile`
6. **Base Directory**: deixe em branco (o Dockerfile está na raiz)
7. **Dockerfile location**: `/Dockerfile`
8. **Port**: `3000`
9. Salvar
### 2.2. Configurar domínio
1. Aba **Domains**
2. Adicione: `https://shivao.exemplo.com`
3. **Generate Let's Encrypt** (automático)
4. Salvar
### 2.3. Variáveis de ambiente
Aba **Environment Variables** → adicionar:
#### Mínimo obrigatório
```
BOAT_TOKEN=<gere com: openssl rand -hex 32>
```
#### Pelo menos um canal de notificação
**Telegram** (recomendado, grátis):
```
TELEGRAM_BOT_TOKEN=<token do BotFather>
TELEGRAM_CHAT_IDS=<seus chat IDs separados por vírgula>
```
**E-mail** (Gmail com app password):
```
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=seu-email@gmail.com
SMTP_PASS=<senha de app de 16 chars>
SMTP_FROM=Shivao <seu-email@gmail.com>
SMTP_TO=destinatario@exemplo.com,outro@exemplo.com
```
**ntfy.sh** (push grátis sem cadastro):
```
NTFY_TOPIC=<algo aleatório, ex: shivao-alertas-x7k9p2>
```
Veja **server/.env.example** para todas as opções (Twilio, webhook, etc).
#### Opcionais
```
HEARTBEAT_TIMEOUT_SEC=300 # 5 min — tempo até dead-man disparar
NODE_ENV=production
```
### 2.4. Volume persistente
**Crítico** — sem isso, ao reiniciar o container você perde tudo.
1. Aba **Storages**
2. **+ Add**
3. Tipo: **Persistent Storage** ou **Volume**
4. Name: `shivao-data`
5. Mount Path: `/data`
6. Salvar
### 2.5. Deploy
1. Aba principal da aplicação
2. **Deploy** (canto superior direito)
3. Acompanhar logs do build (~2-3 minutos primeira vez)
Se tudo der certo, ao final:
```
Shivao Cloud rodando em :3000
Canais configurados: telegram, email, ...
Dead-man switch: 300s
```
## Passo 3 — Verificar
### 3.1. Health check público
```bash
curl https://shivao.exemplo.com/api/health
# {"ok":true,"ts":1730000000000}
```
### 3.2. Auth funcionando
```bash
curl -H "Authorization: Bearer SEU_TOKEN" https://shivao.exemplo.com/api/info
# {"channels":["telegram","email"],"heartbeatTimeoutSec":300,"version":"1.0"}
```
### 3.3. Acessar o app
Abra `https://shivao.exemplo.com/` no navegador. O frontend deve carregar.
### 3.4. Testar notificação
No app: **Arquivo** → preencha servidor + token → **Disparar mensagem de teste**
Você deve receber a mensagem em todos os canais configurados.
## Passo 4 — Configurar Telegram (5 minutos)
Se ainda não fez:
1. No Telegram, fale com [@BotFather](https://t.me/BotFather)
2. `/newbot` → escolha nome e username → ele dá um **token**
3. Copie o token (tipo `123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11`)
4. Inicie conversa com o bot recém-criado (envie qualquer coisa)
5. Acesse `https://api.telegram.org/bot<SEU_TOKEN>/getUpdates`
6. No JSON retornado, procure `"chat":{"id":123456789,...}` → esse é seu `CHAT_ID`
7. Cole `TELEGRAM_BOT_TOKEN` e `TELEGRAM_CHAT_IDS` no Coolify
8. Redeploy
9. Teste no app
Para grupo: adicione o bot ao grupo, mande uma mensagem lá, repita o passo 5
(o `chat_id` do grupo é negativo).
## Passo 5 — Conectar o app ao servidor
No celular:
1. Abrir `https://shivao.exemplo.com/` no Chrome
2. Menu (⋮) → **Adicionar à tela inicial** (vira "app")
3. Abrir o app, ir em **Arquivo**
4. Seção **☁️ Sincronização na nuvem**:
- Servidor: `https://shivao.exemplo.com`
- Token: o `BOAT_TOKEN` definido no Coolify
5. **Testar conexão** → deve receber notificação de teste
6. **↑ Enviar tudo para nuvem** (primeira vez)
A partir daí, o app sincroniza automaticamente. Se trocar de celular,
basta colar a URL + token e tocar em **↓ Baixar da nuvem**.
## Atualizando o código
Sempre que houver mudanças:
```bash
git push origin main
```
No Coolify:
- **Deploy** → ele puxa, builda, e troca o container
- A migração de schema do SQLite é automática (CREATE TABLE IF NOT EXISTS)
## Backup
O volume `/data` contém:
- `shivao.db` (SQLite com todos os dados)
- `media/` (fotos, áudios, vídeos)
**Recomendado**: configurar backup periódico do volume no Coolify ou
sincronizar `/data` para um S3 com `restic` ou `borgbackup` via cronjob.
## Troubleshooting
### "BOAT_TOKEN não configurado"
Variável de ambiente faltando ou < 16 chars. Veja Passo 2.3.
### "Failed to fetch" no app
- DNS não propagou ainda
- Token errado
- Coolify não está expondo SSL (verificar Domains)
### "Webhooks falham mas Telegram funciona"
Discord/genérico podem ter rate limits. O servidor faz fan-out independente,
então um falhar não afeta os outros.
### "GPS não funciona no app"
Geolocation API funciona em HTTPS. Coolify configura HTTPS
automaticamente mas verifique se está acessando `https://...` e não `http://`.
### "Dead-man switch não dispara"
- Verificar logs do servidor: `docker logs <container>`
- Dead-man dispara se houve `/api/anchor/start` antes
- Default é 5 min sem heartbeat pode ajustar em `HEARTBEAT_TIMEOUT_SEC`
### Container reinicia em loop
Verificar logs. Causa comum: `BOAT_TOKEN` muito curto (mínimo 16 chars).
## Custos esperados
- Hetzner CX22 (2 vCPU, 4 GB RAM): ~6€/mês sobra recurso
- Domínio: ~10€/ano
- Telegram, ntfy, Open-Meteo: grátis
- Twilio (se ativar SMS): ~$1/mês + ~$0.05 por SMS no Brasil
- Windy Point Forecast: o dono tem premium pessoal
Total mínimo: ~7€/mês.