Configuração
Duas fontes: o arquivo config.yml (~/.garraia/config.yml, com hot-reload — editar aplica sem reiniciar) e variáveis de ambiente para secrets. Referências canônicas:
docs/configuration.md— referência completa doconfig.yml.env.example— todas as variáveis, comentadas, em 18 seçõesdocs/auth-config.md— matriz de precedência de auth (leia antes de configurar JWT)mcp.json.example— servidores MCP.garraignore— padrões de exclusão de arquivos
Mapa rápido do .env.example
| Quero configurar… | Seção |
|---|---|
| Provedor LLM | LLM Provider API Keys (pelo menos uma) |
| Login/JWT do gateway | Auth (JWT + refresh + mobile) — ver nota abaixo |
| Cofre de credenciais | Vault Encryption (AES-256-GCM) |
| Telegram/Discord/etc. | Channel Tokens |
| Porta/host do gateway | Gateway Configuration |
| Voz (STT/TTS) | Voice |
| Busca na web | Web Search (BRAVE_API_KEY) |
| Postgres multi-tenant | Database + Group Workspace (Fase 3) |
| Uploads/S3 | Object Storage (Fase 3.5) |
| Métricas/tracing | Observabilidade |
| Embeddings/RAG | Embeddings + RAG/Memória de longo prazo |
Notas que evitam dor de cabeça
-
GARRAIA_JWT_SECRETé env-only e fail-closed: sem ele, os endpoints de auth respondem 503 de propósito (nunca há fallback inseguro). -
Precedência de secrets:
GARRAIA_JWT_SECRET>GarraIA_VAULT_PASSPHRASE(grafia mista, deprecated) >GARRAIA_VAULT_PASSPHRASE— as duas grafias da passphrase são aceitas em todos os consumidores (issue #824). -
Valide tudo com
garraia config check(exit 0 ok · 2 warnings em--strict· 65 config inválida). O relatório aponta a fonte efetiva de cada valor e nunca imprime secrets (só*_set: true). Desde a v0.4.5 o mesmo check roda em todogarraia start/restart/start -d(#1247): os achados vão para o log, e só uma lista fechada recusa o boot com exit 78 (hoje, o TLS configurado pela metade); escotilhaGARRAIA_ALLOW_INVALID_CONFIG=1(exatamente1). Um bind exposto semgateway.api_keynemGARRAIA_GATEWAY_API_KEYtambém recusa o boot (#1261). -
agent.sandbox(novo na v0.4.3, defaultoff): envolve as tools que executam processo num backenddocker/podman/ssh. Seção ausente reproduz o comportamento anterior. Desde a v0.4.5, commode: allentrambash,run_tests,git_diff,code_reviewerepo_search(#1225): a imagem precisa da toolchain (git/cargo/rg) ou a tool vai emelevated.sshé execução remota, não sandbox, e é recusado para as tools de diretório. Emexecution.profile: standard, ogarraia mcp-servere o gateway registrambashcom um sandboxdocker/podmanválido ou, desde a v0.4.8, em modo allowlist-only no host viaagent.bash_allowlist(HostComAllowlist, #1272). Referência:docs/security/threat-model.md§5.13, schema emcrates/garraia-config/src/sandbox.rs, exemplo emconfig.hardened.example.yml. -
execution.profile(novo na v0.4.4, ADR 0024, defaultstandard):isolated-poddeclara que o processo roda num pod descartável — poder total dentro do pod (dono do WhatsApp em 1:1 ganha o pisocode; MCPfilesystemna raizexecution.pod_root, senão<data_dir>/workspace, nunca$HOME), nada implícito fora. A envGARRAIA_EXECUTION_PROFILEvence o arquivo e nunca é gravada nele; valor inválido recusa o boot e sai comoErrornoconfig check; seção ausente = comportamento de hoje. Nunca é inferido de/.dockerenvou cgroups.pod_rootprecisa ser absoluto e só vale emisolated-pod(Warningfora dele). Referência:docs/execution-profiles.md·docs/configuration.md. -
channels.whatsapp_linked.access(novo na v0.4.6, ADR 0025): quem fala com o agente e até onde cada um vai, por principal — não por lista única.access:admission: restricted # restricted | opendefault: { level: chat, write: false } # o DESCONHECIDO, so com `open`users:"+5511999998888": { level: read, write: false }"+5511977776666": { role: owner }"+5511955554444": { blocked: true }groups:enabled: falsedefault: { level: read, write: false }"120363@g.us": { level: chat }Três regras que a seção não escolhe. (1) Compatibilidade: sem
access:, o comportamento é o da v0.4.5 —allowsegue valendo (usuário sem teto: o piso de modo decide),ownerssegue valendo (dono) ereply_in_groupssegue ligando os grupos. Nível ewritesó existem onde foram declarados;access.usersvence o legado para a mesma identidade, eaccess.groups.enableddeclarado vence oreply_in_groups(#1501). Quem entrou por código (/pair) é a exceção: credencial fraca, tetoread. (2) Fail-closed: nível desconhecido échat;chatcomwrite: trueéchat;admissiondesconhecida érestricted; odefaultdeopennunca chega afull(#1390). Cada normalização deixa um aviso — sem número — que o boot e oconfig checkmostram. (3) Nível é teto, não piso: o valor compõe por E com o modo da sessão — só tira, nunca põe. Edite pela CLI (garraia whatsapp access|level|write|block|unblock|owner|unowner|remove) ou pela página WhatsApp Access do console, que usam o mesmo motor e deixam rastro no audit; grupos valem na mensagem seguinte, sem restart (#1412). Referência: ADR 0025 ·docs/whatsapp.md. -
Retenção de memória e do ledger de runs (fatia de dados na v0.4.6, #1436): política em
garraia-config::retention(memory.enabled/max_age_days/interval_hourserun_ledger.retention_days), aplicada porgarraia-db::retentione coberta peloconfig check. A página do console e oPATCH /admin/api/retentionficam para o ciclo seguinte. -
hardware.*(mqtt,home_assistant,automations): nada liga sem a seção — o registro de dispositivos nasce vazio (fail-closed). Os adapters Serial/USB e GPIO existem na crate atrás das featureshardware-serial/hardware-gpio, mas ainda sem chave de config nem wiring no boot do gateway (#1130). Referência:docs/hardware.md·docs/hardware-skills.md.