Projeto para operar um gateway OpenClaw em VM/host dedicado com Docker Compose, mantendo OPENAI_API_KEY e GEMINI_API_KEY fora do compose.yaml e oferecendo dois caminhos oficiais: local-first conservador e WhatsApp dedicado + browser.
Este repositorio oferece um scaffold local para:
- buildar uma imagem OpenClaw a partir de
vendor/openclaw; - opcionalmente embutir browser local gerenciado na imagem do gateway/CLI;
- opcionalmente buildar uma imagem de sandbox separada para execucao isolada de tools;
- subir o gateway com Docker Compose;
- persistir configuracao e workspace localmente;
- injetar chaves de provider em runtime via Docker secret;
- operar o runtime via CLI, TUI e dashboard;
- manter Telegram como integracao opcional;
- promover um perfil oficial de WhatsApp dedicado + browser com baseline conservador.
As chaves de provider nao ficam inline em environment:. O projeto usa:
secrets/openai_api_key.txtsecrets/gemini_api_key.txt
Esses arquivos sao disponibilizados em runtime como Docker secrets:
/run/secrets/openai_api_key/run/secrets/gemini_api_key
Observacao pratica:
openai_api_key.txtcontinua sendo o secret base para o provider principal;gemini_api_key.txte opcional e so entra no compose quando o arquivo local existe.
O OpenClaw armazena estado, sessoes e configuracoes em ~/.openclaw. Neste projeto, esses dados sao persistidos em:
runtime/configruntime/workspace
Isso permite reiniciar containers sem perder o estado operacional.
Quando o sandbox esta habilitado, o projeto continua usando openclaw:local como imagem principal do gateway.
O que muda e apenas o ambiente de execucao de tools:
openclaw:localcontinua sendo o runtime principal;openclaw-sandbox:bookworm-slimvira a imagem isolada para tools sandboxadas;- o gateway precisa ser buildado com Docker CLI para conseguir orquestrar os containers de sandbox.
O repositorio nao versiona configuracoes estaticas de Telegram ou WhatsApp. A configuracao de canais deve ser criada pelo onboarding ou pela CLI da versao instalada e persistida em runtime/config.
- local-first conservador: subir o gateway, operar via TUI/dashboard/CLI e adicionar Telegram depois, se fizer sentido;
- WhatsApp dedicado + browser: usar numero separado, browser gerenciado pelo OpenClaw,
web_searchcom Gemini,web_fetchhabilitado, grupos allowlisted e baseline conservador semexec/elevated.
.
├── .env.example
├── compose.sandbox.yaml
├── compose.whatsapp-browser.yaml
├── compose.yaml
├── docs/
├── runtime/
│ ├── config/
│ └── workspace/
├── scripts/
│ ├── _load-runtime-secrets.sh
│ ├── _load-openai-secret.sh
│ ├── build.sh
│ ├── build-sandbox.sh
│ ├── cli-entrypoint.sh
│ ├── compose.sh
│ ├── dashboard.sh
│ ├── docker-logs.sh
│ ├── down.sh
│ ├── gateway-entrypoint.sh
│ ├── health.sh
│ ├── logs.sh
│ ├── onboard-runtime.sh
│ ├── whatsapp-configure.sh
│ ├── onboard-whatsapp.sh
│ ├── onboard-telegram.sh
│ ├── ps.sh
│ ├── sandbox-enable.sh
│ ├── sandbox-explain.sh
│ ├── status.sh
│ ├── tui.sh
│ ├── up.sh
│ └── whatsapp-browser-enable.sh
├── secrets/
│ └── README.md
└── vendor/
└── openclaw/
cp .env.example .env.localRevise pelo menos:
OPENCLAW_IMAGEOPENCLAW_INSTALL_BROWSEROPENCLAW_INSTALL_DOCKER_CLIOPENCLAW_SANDBOX_ENABLEOPENCLAW_SANDBOX_IMAGEOPENCLAW_HOST_PORTOPENCLAW_GATEWAY_PORTOPENCLAW_BRIDGE_HOST_PORTOPENCLAW_GATEWAY_BINDOPENCLAW_LOG_LEVEL
Crie:
secrets/openai_api_key.txt
secrets/gemini_api_key.txt
Formato esperado:
openai_api_key.txt: obrigatorio para o provider principal;gemini_api_key.txt: opcional no caminho local-first, recomendado no perfil WhatsApp dedicado + browser paraweb_search.
Cada arquivo deve conter apenas a chave, em uma unica linha.
O projeto assume que o repositorio oficial do OpenClaw esta disponivel em:
vendor/openclaw
O build Docker usa esse diretorio como contexto.
./scripts/build.shCom a configuracao atual de .env.local, esse build inclui Docker CLI dentro de openclaw:local, o que e necessario para o gateway criar sandboxes Docker.
Se voce for seguir o perfil WhatsApp dedicado + browser, ajuste antes:
OPENCLAW_INSTALL_BROWSER=1Esse toggle instrui o Dockerfile do vendor a embutir Chromium/Xvfb na imagem para evitar bootstrap ad-hoc do browser em runtime.
./scripts/build-sandbox.shEsse passo builda localmente a imagem openclaw-sandbox:bookworm-slim a partir do vendor do OpenClaw. Ela nao substitui openclaw:local; ela existe para executar tools em ambiente isolado.
./scripts/sandbox-enable.shEsse wrapper aplica o baseline recomendado para este projeto:
agents.defaults.sandbox.mode = "all"agents.defaults.sandbox.scope = "agent"agents.defaults.sandbox.workspaceAccess = "rw"agents.defaults.sandbox.docker.image = "openclaw-sandbox:bookworm-slim"gateway.controlUi.allowedOrigins = ["http://127.0.0.1:${OPENCLAW_HOST_PORT}"]tools.deny = ["exec"]tools.elevated.enabled = false
Se voce ja tiver uma policy propria em tools.deny, ajuste esse ponto manualmente depois do bootstrap de sandbox.
Decisao atual deste scaffold:
- manter o baseline conservador acima;
- tratar este runtime primeiro como um agente pessoal focado em contexto, memoria e workspace;
- nao liberar
execnemelevatedpor padrao antes de sentir falta real dessa automacao.
Depois disso, o gateway precisa ser reiniciado para carregar a configuracao nova.
Observacao importante:
- o wrapper
./scripts/sandbox-enable.shpode subir temporariamente o gateway se ele ainda nao estiver em execucao, porque a CLI precisa falar com um gateway ativo para aplicar a configuracao; - isso nao substitui o restart final quando voce quiser garantir que o processo do gateway recarregou a configuracao persistida.
- Local-first conservador:
- rode
./scripts/onboard-runtime.shpara configurar provider, modelo e auth do gateway; - siga operando localmente por TUI/dashboard/CLI;
- quando quiser Telegram, rode
./scripts/onboard-telegram.sh; - guia dedicado: docs/telegram-onboarding.md
- rode
- WhatsApp dedicado + browser:
- preencha
secrets/gemini_api_key.txt; - rode
./scripts/onboard-runtime.shpara configurar provider, modelo e auth do gateway; - aplique
./scripts/whatsapp-browser-enable.sh; - preencha allowlists e grupos com
./scripts/whatsapp-configure.sh; - faca login do canal com
./scripts/onboard-whatsapp.sh; - guia dedicado: docs/whatsapp-dedicado-browser.md
- preencha
./scripts/up.sh./scripts/sandbox-explain.shUse esse comando para confirmar se a sessao esta realmente sandboxed, qual imagem esta em uso e como elevated esta sendo aplicado.
Para confirmar especificamente tools.deny = ["exec"], prefira inspecionar a config persistida:
./scripts/compose.sh run --rm openclaw-cli config get tools --json./scripts/docker-logs.shO runtime pode ser entendido em tres camadas:
- Infra Docker
- sobe e mantem o servico
openclaw-gateway; - persiste estado em
runtime/configeruntime/workspace.
- sobe e mantem o servico
- Gateway OpenClaw
- expoe a porta
18789; - serve a UI web;
- recebe comandos do CLI e da TUI;
- quando sandbox esta habilitado, coordena containers de sandbox via Docker socket;
- pode integrar canais externos apos o onboarding.
- expoe a porta
- Sandbox de tools
- executa tools em
openclaw-sandbox:bookworm-slim; - isola execucao do host principal;
- herda acesso ao workspace de acordo com
workspaceAccess.
- executa tools em
- Clientes locais
- terminal local via
openclaw-cli; - navegador local via dashboard/control UI;
- canais externos como Telegram ou WhatsApp dedicado, quando configurados.
- terminal local via
- subir o gateway;
- checar saude e status;
- operar localmente via TUI, dashboard ou CLI;
- escolher se Telegram ou WhatsApp dedicado entram no fluxo operacional.
./scripts/up.sh./scripts/ps.sh./scripts/down.shCamada mais baixa de observabilidade, util para startup, restart loop e erros de infraestrutura.
./scripts/docker-logs.shCheck rapido para verificar se o gateway esta respondendo.
./scripts/health.sh
./scripts/health.sh --jsonResumo operacional do runtime.
./scripts/status.sh
./scripts/status.sh --all
./scripts/status.sh --usageUse status --usage para um snapshot mais orientado a consumo e uso.
Depois que o gateway estiver rodando, os logs tambem podem ser acompanhados via RPC.
./scripts/logs.sh
./scripts/logs.sh --jsonO projeto oferece tres formas principais de operacao local.
Antes de usar TUI/dashboard/CLI de forma real, faca o onboarding base do runtime:
./scripts/onboard-runtime.shAbre uma interface de terminal conectada ao gateway.
./scripts/tui.shExemplo com mensagem inicial:
./scripts/tui.sh --message "oi"Existe suporte a --deliver para cenarios com canal externo, mas isso nao e necessario para a operacao local inicial.
O gateway serve a interface web na porta 18789.
Depois que o gateway estiver de pe, abra:
http://127.0.0.1:18789/
Como a publicacao de porta ocorre apenas em loopback, o acesso fica restrito ao host local.
Observacoes importantes:
- conexoes locais em
127.0.0.1sao auto-aprovadas; - se o onboarding configurar token para o gateway, a UI pode pedir esse token na primeira conexao;
- o comando abaixo ajuda a abrir ou imprimir a URL da dashboard com o auth atual:
./scripts/dashboard.shPara diagnostico e operacao:
./scripts/status.sh
./scripts/health.sh
./scripts/logs.shPara help e descoberta:
./scripts/compose.sh run --rm openclaw-cli --help
./scripts/tui.sh --help
./scripts/dashboard.sh --helpEsse caminho sobe o mesmo runtime, mas com um baseline operacional explicito para automacao mais seria:
- numero de WhatsApp separado do pessoal;
- browser local gerenciado pelo OpenClaw com perfil
openclaw; web_searchcom Gemini eweb_fetchmantido ligado;- grupos fechados por allowlist e configurados manualmente;
tools.deny = ["exec"]etools.elevated.enabled = false.
Antes do login do canal, faca o onboarding base do runtime para provider/modelo/auth:
./scripts/onboard-runtime.shWrapper de baseline:
./scripts/whatsapp-browser-enable.shWrapper guiado para allowlists e grupos:
./scripts/whatsapp-configure.shLogin do canal:
./scripts/onboard-whatsapp.shRunbook completo:
Os wrappers em scripts/ funcionam como a interface principal do projeto.
./scripts/build.sh./scripts/build-sandbox.sh./scripts/up.sh./scripts/down.sh./scripts/ps.sh./scripts/docker-logs.sh
./scripts/health.sh./scripts/status.sh./scripts/logs.sh./scripts/sandbox-enable.sh./scripts/sandbox-explain.sh./scripts/tui.sh./scripts/dashboard.sh./scripts/onboard-runtime.sh./scripts/whatsapp-browser-enable.sh./scripts/whatsapp-configure.sh./scripts/onboard-whatsapp.sh./scripts/onboard-telegram.sh
export OPENCLAW_HOME="$HOME/Development/openclaw-personal-gateway"
alias oc-build='$OPENCLAW_HOME/scripts/build.sh'
alias oc-build-sandbox='$OPENCLAW_HOME/scripts/build-sandbox.sh'
alias oc-up='$OPENCLAW_HOME/scripts/up.sh'
alias oc-down='$OPENCLAW_HOME/scripts/down.sh'
alias oc-ps='$OPENCLAW_HOME/scripts/ps.sh'
alias oc-dlogs='$OPENCLAW_HOME/scripts/docker-logs.sh'
alias oc-health='$OPENCLAW_HOME/scripts/health.sh'
alias oc-status='$OPENCLAW_HOME/scripts/status.sh'
alias oc-logs='$OPENCLAW_HOME/scripts/logs.sh'
alias oc-sandbox-enable='$OPENCLAW_HOME/scripts/sandbox-enable.sh'
alias oc-sandbox-explain='$OPENCLAW_HOME/scripts/sandbox-explain.sh'
alias oc-tui='$OPENCLAW_HOME/scripts/tui.sh'
alias oc-dash='$OPENCLAW_HOME/scripts/dashboard.sh'
alias oc-onboard='$OPENCLAW_HOME/scripts/onboard-runtime.sh'
alias oc-wa-enable='$OPENCLAW_HOME/scripts/whatsapp-browser-enable.sh'
alias oc-wa-config='$OPENCLAW_HOME/scripts/whatsapp-configure.sh'
alias oc-wa-login='$OPENCLAW_HOME/scripts/onboard-whatsapp.sh'
alias oc-onboard-tg='$OPENCLAW_HOME/scripts/onboard-telegram.sh'Fluxo tipico com aliases:
oc-up
oc-status --all
oc-health --json
oc-sandbox-explain
oc-tui
oc-dash
oc-dlogsEsse perfil nao substitui a operacao local pelo PC. Ele adiciona um caminho oficial para ter:
- um numero dedicado de WhatsApp como superficie remota;
- um browser separado da sua sessao pessoal;
- Google/Gemini apenas na superficie do agente;
- grupos sempre fechados por allowlist explicita.
O fluxo recomendado e:
OPENCLAW_INSTALL_BROWSER=1em.env.local;- preencher
secrets/openai_api_key.txtesecrets/gemini_api_key.txt; - rebuildar com
./scripts/build.sh; - rodar
./scripts/onboard-runtime.shpara configurar provider, modelo e auth do gateway; - aplicar
./scripts/whatsapp-browser-enable.sh; - preencher
allowFrom/groupAllowFrom/groupscom./scripts/whatsapp-configure.sh; - logar o numero dedicado com
./scripts/onboard-whatsapp.sh.
Detalhes e exemplos concretos:
Telegram nao substitui a operacao local pelo PC. Quando habilitado, ele passa a funcionar como mais um canal de entrada e saida para o mesmo runtime.
Na pratica:
- TUI e dashboard continuam funcionando normalmente;
- Telegram adiciona uma interface remota para o mesmo gateway;
- monitoramento e operacao seguem concentrados em
status,health,logse dashboard.
Consulte docs/telegram-onboarding.md para o fluxo dedicado de onboarding.
./scripts/up.sh./scripts/down.sh./scripts/build.sh --no-cache./scripts/compose.sh run --rm openclaw-cli --help./scripts/tui.sh./scripts/dashboard.shDepois abra:
http://127.0.0.1:18789/
./scripts/status.sh --all./scripts/health.sh --json./scripts/logs.shMinimos recomendados para operacao local:
- usar uma Project API key separada para este ambiente;
- usar uma chave Gemini separada se for habilitar
web_searchvia Gemini; - manter spend limit baixo;
- nao colocar segredos diretamente em
compose.yamlou em conversas desnecessarias; - tratar
runtime/configcomo sensivel; - tratar
runtime/workspacecomo memoria privada do agente; - preferir VM ou host dedicado;
- publicar portas apenas em
127.0.0.1; - manter
tools.elevated.enabled = falsepara este perfil; - negar
execpor default quando o sandbox estiver ativo; - tratar Telegram como etapa opcional, nao como requisito de bootstrap;
- usar numero de WhatsApp dedicado, nao o pessoal, se escolher esse canal;
- usar conta Google dedicada dentro do browser
openclaw, com permissoes minimas.
openclaw:localcontinua sendo a imagem principal do sistema.openclaw-sandbox:bookworm-slimnao substitui o gateway; ela so executa tools isoladas.- sem sandbox, tools rodam no ambiente principal do gateway;
- com sandbox, tools rodam em um container separado, enquanto memoria, sessoes e bootstrap continuam no mesmo runtime OpenClaw.
O projeto segue um baseline deliberadamente conservador:
tools.deny = ["exec"]tools.elevated.enabled = false
Isso significa:
- o agente continua podendo trabalhar com memoria, sessoes e arquivos do workspace;
- o agente nao pode executar shell arbitrario por default;
- qualquer necessidade futura de automacao shell deve ser uma decisao explicita, nao um comportamento implicito.
Se o agente nao conseguir executar algo por policy muito restritiva, o fluxo recomendado de debug e:
- reproduzir a tentativa;
- inspecionar a policy efetiva:
./scripts/sandbox-explain.sh- olhar os logs do gateway:
./scripts/docker-logs.sh- se precisar inspecionar a config persistida:
./scripts/compose.sh run --rm openclaw-cli config get tools --json
./scripts/compose.sh run --rm openclaw-cli config get agents.defaults.sandbox --jsonHeuristicas uteis:
- se o pedido exigia shell, a primeira suspeita e
tools.deny = ["exec"]; - se o pedido exigia sair do sandbox e tocar host diretamente, a primeira suspeita e
tools.elevated.enabled = false; ./scripts/sandbox-explain.she a fonte mais direta para entender sandbox, imagem efetiva e gates deelevated;./scripts/compose.sh run --rm openclaw-cli config get tools --jsone a fonte mais confiavel para confirmartools.deny = ["exec"].
- buildar a imagem local;
- buildar a imagem base de sandbox;
- aplicar a configuracao com
./scripts/sandbox-enable.sh; - validar
./scripts/sandbox-explain.sh; - escolher entre local-first conservador ou WhatsApp dedicado + browser;
- concluir o onboarding do provider e, se desejado, do Telegram ou do WhatsApp dedicado;
- testar uma conversa ponta a ponta no fluxo escolhido.