Runbook para IA
Provisionamento via CLI, pra colar numa sessão de Claude Code (ou similar).
Este runbook é pra ser colado numa sessão de IA com acesso a terminal. O objetivo é a IA executar o máximo possível via CLI, parando só nos pontos que exigem uma ação humana (login/2FA, pagamento, propriedade de domínio).
Instrução pra IA que for executar isto
Siga os passos em ordem. Antes de qualquer comando que crie recurso cobrável (instância de VPS, projeto em plano pago) ou seja difícil de reverter, confirme com o humano — não assuma. Depois de cada etapa marcada, mostre o resultado pro humano conferir antes de seguir. Nunca sugira Vercel pra hospedar o app — o motivo está em Deploy do Next.js: o pub/sub de chat/presença é em memória e exige um processo persistente, incompatível com serverless.
Pré-requisitos que só o humano resolve
- Conta Discord Developer Portal
- Conta Railway (login via GitHub)
- Conta Vultr com pagamento configurado — só se for self-host o LiveKit
- Conta Cloudflare — pro R2
- Conta LiveKit Cloud — se não for self-host
- Domínio próprio apontável
- Repositório do OpenCall clonado localmente
1. Discord Application
Não tem CLI oficial — é a única etapa 100% manual mesmo em modo IA (ver Configurar o Discord). Peça ao humano:
DISCORD_CLIENT_ID,DISCORD_CLIENT_SECRET- O Discord user ID dele, pra
BOOTSTRAP_ADMIN_DISCORD_IDS
2. Instalar as CLIs
npm i -g @railway/cli
railway --version
# Só se for self-host o LiveKit:
brew install vultr/vultr-cli/vultr-cli # macOS
vultr-cli version3. Autenticar sem navegador interativo
# Railway: fluxo device-code, mostra link+código pro humano abrir em
# qualquer dispositivo com navegador
railway login --browserless
# Alternativa: token já gerado pelo humano em railway.com/account/tokens
export RAILWAY_API_TOKEN="<token colado pelo humano>"# Vultr: gerar API key em my.vultr.com/settings/#settingsapi (sem
# device-code flow) — peça ao humano pra colar
export VULTR_API_KEY="<colado pelo humano>"4. Projeto Railway + Postgres
railway init --name opencall
railway link # se init não linkar automaticamente
railway add --database postgresConfirme com o humano se o plano é Hobby ou superior — Free/Trial não sustenta um app rodando 24/7 (necessário pro pub/sub em memória, ver aviso no topo).
5. LiveKit
Caminho Cloud — não tem CLI pra criar o projeto (é web-only). Peça ao
humano LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET depois de
criar em cloud.livekit.io.
Caminho self-host (ver LiveKit self-host pro detalhe de cada passo):
vultr-cli plans list --type vhf
vultr-cli regions list
vultr-cli instance create \
--region <region-id> \
--plan <plan-id-high-frequency> \
--os 2284 \
--host opencall-livekit \
--label "OpenCall LiveKit"
vultr-cli instance list # pegar o IPAção humana obrigatória: apontar um registro DNS tipo A do domínio pro IP da VPS. Confirme propagação antes de seguir:
dig +short SEU-SUBDOMINIODepois, instalar o LiveKit via SSH:
ssh root@<ip-da-vps> "curl -sSL https://get.livekit.io | bash -s -- --domain <seu-subdominio>"Esse instalador é interativo por padrão — se travar esperando input, essa é
a etapa mais provável de precisar de um humano completando via SSH manual
(junto com o DNS, são os dois pontos de fricção deste runbook). Capturar do
output: LIVEKIT_API_KEY, LIVEKIT_API_SECRET, LIVEKIT_URL=wss://<seu-subdominio>.
6. R2 (Cloudflare)
Sem automação via CLI que valha a pena pra um bucket único — peça ao humano
pra seguir Armazenamento (R2) e colar:
R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET, URL
pública.
7. Env vars no Railway
railway variables --set "DISCORD_CLIENT_ID=..." \
--set "DISCORD_CLIENT_SECRET=..." \
--set "NEXTAUTH_SECRET=$(openssl rand -base64 32)" \
--set "NEXTAUTH_URL=https://SEU-DOMINIO" \
--set "BOOTSTRAP_ADMIN_DISCORD_IDS=<id-do-humano>" \
--set "LIVEKIT_URL=wss://..." \
--set "LIVEKIT_API_KEY=..." \
--set "LIVEKIT_API_SECRET=..." \
--set "R2_ACCOUNT_ID=..." \
--set "R2_ACCESS_KEY_ID=..." \
--set "R2_SECRET_ACCESS_KEY=..." \
--set "R2_BUCKET=..." \
--set "NEXT_PUBLIC_R2_PUBLIC_BASE_URL=..." \
--set "NEXT_PUBLIC_APP_URL=https://SEU-DOMINIO"(DATABASE_URL não precisa ser setada manualmente se o Postgres foi criado
no mesmo projeto Railway — referenciar ${{Postgres.DATABASE_URL}} já
resolve.)
8. Deploy
railway up
railway domain # gera/mostra o domínio *.up.railway.app
# ou: railway domain add SEU-DOMINIO (ação humana: apontar CNAME depois)Pausa pra ação humana: com o domínio definitivo, voltar no Discord
Developer Portal e completar o Redirect URI
(https://SEU-DOMINIO/api/auth/callback/discord).
9. Criar as tabelas do banco
railway run pnpm prisma db push(o repo ainda não versiona prisma/migrations/, então db push — não
migrate deploy — é o comando que sincroniza o schema; ver nota em Banco
de dados)
10. Validação final
- Abrir
https://SEU-DOMINIO, logar com a conta doBOOTSTRAP_ADMIN_DISCORD_IDS— confirmar acesso a/admin/channels. - Testar uma chamada de voz em
/channels. - Mandar uma mensagem com anexo no chat — confirma R2.
- Se self-host: seguir
infra/vps-metrics/README.mdno repo do app pra instalar os coletores de métrica (passo separado, escrito pra execução manual/cron).
Pontos de checkpoint humano (resumo)
- Criar a Discord Application e colar client id/secret
- Login inicial em cada provedor (mesmo browserless, alguém aprova no navegador)
- Confirmar plano pago antes de provisionar (Railway, Vultr)
- Apontar DNS (A record pra VPS, CNAME pro Railway)
- Completar o Redirect URI no Discord depois que o domínio final existir