Skip to content

Deploy OpenClaw na Oracle Cloud com Nginx e Telegram

Guia de instalação do OpenClaw em uma VM Oracle Cloud (4 oCPU Ampere, 24 GB RAM, 150 GB storage) com Nginx como proxy reverso, SSL via Certbot, Telegram como canal de comunicação, integração com Google Workspace via gog e modelo MiniMax M2.5 via OpenRouter.

Pré-requisitos

  • VM Oracle Cloud provisionada e acessível via SSH
  • Docker e Docker Compose instalados
  • Entrada DNS tipo A apontando o subdomínio para o IP público da VM
  • Portas 80 e 443 liberadas no Security List da Oracle Cloud e no firewall do SO
  • Conta no OpenRouter com créditos ($5 mínimo)

Estrutura do Projeto

openclaw-docker/
├── docker-compose.yml
├── .env
├── nginx/
│   └── openclaw.conf
├── config/
│   └── openclaw.json
├── data/
│   ├── state/
│   └── gogcli/
└── workspace/
    ├── AGENTS.md
    ├── SOUL.md
    └── memory/

Crie a estrutura:

mkdir -p openclaw-docker/{nginx,config,data/state,data/gogcli,workspace/memory}
cd openclaw-docker

Arquivos de Configuração

docker-compose.yml

services:
  openclaw:
    image: node:22-slim
    container_name: openclaw-gateway
    restart: unless-stopped
    working_dir: /app/workspace
    command: >
      sh -c "
        apt-get update -qq &&
        apt-get install -y -qq git curl &&
        rm -rf /usr/local/lib/node_modules/openclaw &&
        npm install -g openclaw@latest &&
        curl -L https://github.com/steipete/gogcli/releases/download/v0.12.0/gogcli_0.12.0_linux_arm64.tar.gz -o /tmp/gogcli.tar.gz &&
        cd /tmp && tar -xzf gogcli.tar.gz &&
        mv /tmp/gog /usr/local/bin/gog &&
        chmod +x /usr/local/bin/gog &&
        openclaw gateway --port 3000
      "
    env_file:
      - .env
    environment:
      - NODE_ENV=production
      - OPENCLAW_STATE_DIR=/app/state
      - OPENCLAW_CONFIG=/app/config/openclaw.json
      - GOG_KEYRING_PASSWORD=sua-senha-do-keyring
      - GOG_KEYRING_BACKEND=file
      - GOG_ACCOUNT=${GOG_ACCOUNT}
    volumes:
      - ./config:/app/config:ro
      - ./data/state:/app/state
      - ./workspace:/app/workspace
      - ./data/gogcli:/root/.config/gogcli
    expose:
      - "3000"
    ports:
      - "4000:4000"
    networks:
      - openclaw-internal
    healthcheck:
      test: ["CMD-SHELL", "node -e \"const http = require('http'); http.get('http://localhost:3000/health', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))\""]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    deploy:
      resources:
        limits:
          memory: 2G
        reservations:
          memory: 512M

  nginx:
    image: nginx:alpine
    container_name: openclaw-nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/openclaw.conf:/etc/nginx/conf.d/openclaw.conf:ro
      - /etc/letsencrypt:/etc/letsencrypt:ro
      - /var/www/certbot:/var/www/certbot:ro
    networks:
      - openclaw-internal
    depends_on:
      - openclaw

networks:
  openclaw-internal:
    driver: bridge

Nota: O gog é instalado automaticamente a cada inicialização do container. As credenciais OAuth ficam persistidas em ./data/gogcli, mapeado como volume.


.env

# NUNCA commite este arquivo!

# OpenRouter (modelo principal)
OPENROUTER_API_KEY=sua-chave-openrouter

# Canal Telegram
TELEGRAM_BOT_TOKEN=token-do-seu-bot-telegram

# Token do OpenClaw (gerado automaticamente pelo setup — veja seção Acesso ao Control UI)
OPENCLAW_TOKEN=seu-openclaw-token

# Google Workspace (gog)
GOG_KEYRING_PASSWORD=sua-senha-do-keyring
GOG_KEYRING_BACKEND=file
GOG_ACCOUNT=seu-email@gmail.com

# Otimizações para container/VPS
NODE_COMPILE_CACHE=/var/tmp/openclaw-compile-cache
OPENCLAW_NO_RESPAWN=1

# Configurações do gateway
OPENCLAW_LOG_LEVEL=info
OPENCLAW_HOST=0.0.0.0
OPENCLAW_PORT=3000

Proteja o arquivo:

echo ".env" >> .gitignore
chmod 600 .env

⚠️ Importante: docker compose restart não relê o .env. Para que alterações em variáveis de ambiente surtam efeito, sempre use docker compose down && docker compose up -d.


config/openclaw.json

Este arquivo é usado como referência inicial, mas o OpenClaw persiste sua configuração ativa em /app/state/openclaw.json.

{
  "models": {
    "default": "openrouter/minimax/minimax-m2.5",
    "providers": {
      "openrouter": {
        "apiKey": "${OPENROUTER_API_KEY}"
      }
    }
  },
  "gateway": {
    "host": "0.0.0.0",
    "port": 3000
  },
  "channels": {
    "telegram": {
      "enabled": true,
      "token": "${TELEGRAM_BOT_TOKEN}",
      "dmPolicy": "open",
      "allowFrom": ["*"],
      "groupPolicy": "open"
    }
  },
  "workspace": {
    "path": "/app/workspace"
  },
  "memory": {
    "enabled": true,
    "path": "/app/state/memory"
  },
  "logging": {
    "level": "info",
    "file": "/app/state/logs/gateway.log"
  }
}

workspace/SOUL.md

# SOUL.md
Você é um assistente pessoal operando via Telegram.

## Ferramentas Google Workspace
- Você tem acesso COMPLETO ao Google Workspace via ferramenta `exec` usando o comando `gog`
- O binário `gog` está disponível em `/usr/local/bin/gog`
- As variáveis `GOG_KEYRING_PASSWORD` e `GOG_ACCOUNT` já estão configuradas — nunca peça senha ou conta
- Serviços disponíveis: Gmail, Calendar, Drive, Docs, Sheets, Slides, Contacts, Tasks, Chat, Classroom, Forms, AppScript
- Exemplos de uso:
  - `gog calendar list` — listar calendários
  - `gog calendar events primary --from <iso> --to <iso>` — listar eventos
  - `gog gmail search "<query>"` — buscar emails
  - `gog gmail send --to <email> --subject "<assunto>" --body "<mensagem>"` — enviar email
  - `gog drive search "<query>"` — buscar arquivos no Drive
  - `gog contacts list` — listar contatos
  - `gog sheets get <sheetId> "Tab!A1:D10"` — ler planilha
- Nunca diga que não tem acesso ao Google Workspace — use sempre o `exec` com `gog`
- Confirme com o usuário antes de enviar emails, criar ou modificar eventos e arquivos

## Restrições absolutas
- NUNCA use ferramentas de browser (`browser`, `open_url`, `navigate`) para nenhuma tarefa
- Para Google Drive: use EXCLUSIVAMENTE `gog drive`
- Para Gmail: use EXCLUSIVAMENTE `gog gmail`
- Para Calendar: use EXCLUSIVAMENTE `gog calendar`
- Se uma tarefa parecer exigir browser, informe o usuário e sugira alternativa via gog

workspace/AGENTS.md

# AGENTS.md
Workspace do OpenClaw em Docker.

## Regras
- Mantenha logs em memory/
- Use paths relativos dentro do workspace

Certificado SSL

Instalar o Certbot

sudo apt update && sudo apt install certbot -y
sudo mkdir -p /var/www/certbot

Configurar o Nginx apenas com HTTP (temporário)

server {
    listen 80;
    server_name seu.subdominio.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

Subir o Nginx

docker compose up -d nginx

Emitir o certificado

sudo certbot certonly --webroot \
  -w /var/www/certbot \
  -d seu.subdominio.com \
  --email seu@email.com \
  --agree-tos --non-interactive

Nginx com HTTPS

server {
    listen 80;
    server_name seu.subdominio.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name seu.subdominio.com;

    ssl_certificate     /etc/letsencrypt/live/seu.subdominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/seu.subdominio.com/privkey.pem;

    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    location /oauth2/callback {
        proxy_pass         http://openclaw-gateway:4000;
        proxy_http_version 1.1;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout    60s;
        proxy_connect_timeout 10s;
    }

    location / {
        proxy_pass         http://openclaw-gateway:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout    300s;
        proxy_connect_timeout  10s;
    }
}

Subir o Stack Completo

docker compose down && docker compose up -d

Verifique os logs:

docker compose logs -f openclaw

Teste o health:

curl https://seu.subdominio.com/health
# Esperado: {"ok":true,"status":"live"}

Configuração do State

O OpenClaw gera o arquivo /app/state/openclaw.json automaticamente na primeira execução. Execute o setup inicial:

docker compose exec openclaw openclaw setup
docker compose exec openclaw openclaw doctor --fix

Crie o state no host:

cat > /tmp/state.json << 'EOF'
{
  "meta": {
    "lastTouchedVersion": "2026.3.13",
    "lastTouchedAt": "2026-03-16T00:00:00.000Z"
  },
  "agents": {
    "defaults": {
      "workspace": "/app/workspace",
      "model": "openrouter/minimax/minimax-m2.5",
      "compaction": {
        "mode": "safeguard"
      }
    }
  },
  "commands": {
    "native": "auto",
    "nativeSkills": "auto",
    "restart": true,
    "ownerDisplay": "raw"
  },
  "channels": {
    "telegram": {
      "enabled": true,
      "dmPolicy": "open",
      "allowFrom": ["*"],
      "groupPolicy": "open",
      "streaming": "partial"
    }
  },
  "gateway": {
    "mode": "local",
    "bind": "lan",
    "port": 3000,
    "auth": {
      "mode": "token",
      "token": "seu-token-gerado-pelo-setup"
    },
    "trustedProxies": ["172.18.0.0/16"],
    "controlUi": {
      "allowedOrigins": [
        "https://seu.subdominio.com",
        "https://app.openclaw.ai"
      ]
    }
  }
}
EOF

Copie e reinicie:

docker cp /tmp/state.json openclaw-gateway:/app/state/openclaw.json
docker compose down && docker compose up -d

Verifique o modelo ativo:

docker compose logs openclaw | grep "agent model"
# Esperado: agent model: openrouter/minimax/minimax-m2.5

Modelo: MiniMax M2.5 via OpenRouter

O MiniMax M2.5 é o modelo padrão desta configuração. Principais características:

  • Preço: $0.15/M tokens de entrada, $1.15/M tokens de saída — para uso pessoal (~50 mensagens/dia), os $5 iniciais duram meses
  • Contexto: 196k tokens
  • Tool calling: suportado — obrigatório para o OpenClaw funcionar
  • Foco: produtividade real-world, agentic workflows, office (Drive, Sheets, Docs)

Trocar de modelo

Se necessário, edite diretamente no state:

docker exec -it openclaw-gateway sed -i 's/"model": "openrouter\/minimax\/minimax-m2.5"/"model": "openrouter\/NOVO_MODELO"/' /app/state/openclaw.json
cd /home/ubuntu/openclaw-docker && docker compose down && docker compose up -d

Ou via Telegram/Control UI:

/model openrouter/minimax/minimax-m2.5

Verificar IDs de modelos disponíveis

docker compose exec openclaw openclaw models list 2>&1 | grep openrouter

Acesso ao Control UI

O Control UI fica disponível em https://seu.subdominio.com. O acesso exige um token de sessão gerado dinamicamente — diferente do OPENCLAW_TOKEN no .env.

⚠️ Não cole o OPENCLAW_TOKEN do .env na interface web. Isso resulta em gateway token mismatch e bloqueio temporário por rate limiting.

Fluxo correto de acesso

Passo 1 — Gerar a URL tokenizada

docker compose exec openclaw openclaw dashboard

Passo 2 — Adaptar para o domínio público

Substitua http://127.0.0.1:3000 pelo seu subdomínio:

https://seu.subdominio.com/#token=...

Passo 3 — Aprovar o dispositivo

docker compose exec openclaw openclaw devices list
docker compose exec openclaw openclaw devices approve <requestId>

Recarregue o browser. Acesso permanente neste browser a partir daí.

Gerenciar dispositivos

docker compose exec openclaw openclaw devices list
docker compose exec openclaw openclaw devices revoke <deviceId>
docker compose exec openclaw openclaw devices remove <deviceId>

Integração com Google Workspace (gog)

Pré-requisitos no Google Cloud Console

  1. Crie um projeto em console.cloud.google.com
  2. Ative as APIs: Gmail, Google Calendar, Google Drive
  3. Configure a Tela de Consentimento OAuth (Externo, adicione seu email como usuário de teste)
  4. Crie credenciais: ID do cliente OAuth → Aplicativo da Web
  5. Origens autorizadas: https://seu.subdominio.com
  6. URIs de redirecionamento: https://seu.subdominio.com/oauth2/callback
  7. Baixe o JSON das credenciais

Autenticar

A autenticação OAuth do gog requer acesso a um servidor web temporário na porta 4000. Como a VPS está atrás de um bastion Oracle, o acesso direto à porta 4000 pode ser bloqueado — use um tunnel SSH.

Terminal 1 — tunnel SSH (deixe aberto durante todo o processo):

ssh -i ssh-key.key \
  -o ProxyCommand="ssh -i ssh-key.key -W %h:%p -p 22 <bastion-session>@host.bastion.<region>.oci.oraclecloud.com" \
  -L 4000:localhost:4000 \
  -p 22 ubuntu@<ip-privado-vps>

Terminal 2 — copie as credenciais e inicie o login:

scp /caminho/local/client_secret_*.json ubuntu@sua-vps:/home/ubuntu/
docker cp ~/client_secret_*.json openclaw-gateway:/app/state/google-credentials.json
docker exec -it openclaw-gateway bash -c "gog auth credentials /app/state/google-credentials.json && gog auth login --services=calendar,gmail,drive,contacts,sheets,docs --listen-addr=0.0.0.0:4000 --redirect-host=seu.subdominio.com --force-consent"

Quando aparecer Server listening on [::]:4000, acesse no browser do seu PC:

http://localhost:4000

Autorize todos os serviços solicitados.

⚠️ O URI de redirecionamento no Google Cloud Console deve ser exatamente https://seu.subdominio.com/oauth2/callback. Qualquer diferença causa erro redirect_uri_mismatch.

⚠️ Se aparecer address already in use ao tentar reconectar, reinicie o container antes de tentar novamente: docker compose restart openclaw

Verificar

# Listar autenticações ativas
docker exec -it openclaw-gateway bash -c "gog auth list"

# Testar acesso ao Calendar (especifique a conta explicitamente)
docker exec -it openclaw-gateway bash -c "gog calendar list --account seu-email@gmail.com"

Nota: sempre use --account seu-email@gmail.com nos comandos gog para evitar ambiguidade, especialmente se houver múltiplas contas autenticadas.

Serviços disponíveis

Serviço Exemplo
Calendar gog calendar events primary --from 2026-05-01T00:00:00 --to 2026-05-01T23:59:59
Gmail gog gmail search "is:unread"
Drive gog drive search "relatório"
Contacts gog contacts list
Sheets gog sheets get <sheetId> "Aba!A1:D10"
Docs gog docs cat <docId>

Organizar arquivos no Google Drive via agente

O OpenClaw acessa o Drive exclusivamente via gog drive — sem browser. Para solicitar organização de arquivos, use o seguinte prompt no Telegram:

Quero organizar os arquivos soltos na raiz do meu Google Drive. Siga estas regras:

1. Use `gog drive list` para listar todos os arquivos e pastas na raiz
2. Identifique quais são arquivos soltos (não estão dentro de nenhuma pasta)
3. Para cada arquivo solto, infira o assunto ou projeto pelo nome do arquivo e decida a pasta mais adequada dentre as que já existem na raiz
4. Só crie uma nova pasta se nenhuma existente for adequada para aquele arquivo
5. Antes de mover qualquer coisa, me apresente o plano completo no formato:
   - 📄 nome_do_arquivo → 📁 pasta_destino (existente ou NOVA)
6. Aguarde minha confirmação antes de executar qualquer movimentação
7. NUNCA delete nada — apenas mova
8. NUNCA use browser — use exclusivamente comandos `gog drive`

Renovação Automática do SSL

sudo crontab -e
# Adicione:
0 3 * * * certbot renew --quiet && docker compose -f /home/ubuntu/openclaw-docker/docker-compose.yml restart nginx

Comandos Úteis

# Reiniciar COM releitura do .env (obrigatório para mudanças em variáveis)
docker compose down && docker compose up -d

# Reiniciar SEM releitura do .env (apenas para mudanças no state)
docker compose restart openclaw

# Ver logs em tempo real
docker compose logs -f openclaw

# Verificar modelo ativo
docker compose logs openclaw | grep "agent model"

# Gerar URL tokenizada do dashboard
docker compose exec openclaw openclaw dashboard

# Listar e aprovar dispositivos
docker compose exec openclaw openclaw devices list
docker compose exec openclaw openclaw devices approve <requestId>

# Trocar modelo no state
docker exec -it openclaw-gateway sed -i 's/"model": "modelo-atual"/"model": "novo-modelo"/' /app/state/openclaw.json

# Listar modelos disponíveis
docker compose exec openclaw openclaw models list 2>&1

# Verificar autenticação do gog
docker compose exec openclaw bash -c "gog calendar list"

Solução de Problemas

docker compose restart não aplica mudanças no .env

Causa: restart não relê variáveis de ambiente — apenas reinicia o processo no container existente.

Solução: docker compose down && docker compose up -d


Agente tenta usar browser em vez do gog

Sintoma: [tools] browser failed: No supported browser found

Causa: o agente tentou abrir o Drive/Gmail no browser em vez de usar o gog.

Solução: adicione a seção Restrições absolutas ao SOUL.md (já incluída neste guia). Certifique-se de que o arquivo está salvo e reinicie o container.


Erro redirect_uri_mismatch no OAuth do gog

Causa: a URI de redirecionamento no Google Cloud Console não bate com a usada pelo gog.

Solução: verifique em APIs e Serviços → Credenciais → seu cliente OAuth que a URI https://seu.subdominio.com/oauth2/callback está cadastrada exatamente assim em URIs de redirecionamento autorizados.


Insufficient credits no OpenRouter (erro 402)

Causa: conta OpenRouter sem saldo.

Solução: adicione créditos em openrouter.ai/settings/credits. O mínimo recomendado é $5 — para uso pessoal dura meses com o MiniMax M2.5 ($0.15/M input).


Rate limit temporário no OpenRouter (erro 429)

Causa: pico de demanda no provider upstream.

Solução: aguarde alguns minutos e tente novamente. O OpenClaw reprocessa automaticamente na próxima mensagem.


State com modelo desatualizado após troca

Sintoma: agente reporta modelo diferente do configurado no state.

Causa: o OpenClaw faz cache do modelo em memória — restart simples não é suficiente.

Solução:

# Verificar o que está no state
docker exec -it openclaw-gateway grep '"model"' /app/state/openclaw.json

# Corrigir se necessário
docker exec -it openclaw-gateway sed -i 's/"model": "modelo-errado"/"model": "openrouter\/minimax\/minimax-m2.5"/' /app/state/openclaw.json

# Reiniciar completamente
cd /home/ubuntu/openclaw-docker && docker compose down && docker compose up -d

Fluxo de Funcionamento

Telegram ──► OpenClaw Gateway (porta 3000, rede interna Docker)
Internet ──► :443 ──► Nginx ──► openclaw-gateway:3000
OAuth    ──► :443/oauth2/callback ──► Nginx ──► openclaw-gateway:4000
OpenClaw ──► OpenRouter API ──► MiniMax M2.5

O OpenClaw recebe mensagens do Telegram via polling, processa com o MiniMax M2.5 via OpenRouter e responde diretamente no chat. Para requisições ao Google Workspace, o agente usa o gog via ferramenta exec — sem browser, sem OAuth adicional em runtime.