Skip to content

OpenClaw: Getting Started

TL;DR / when to use this: OpenClaw is the self-hosted agent gateway. Two install paths — direct (docs install, run in a VM) or Docker compose (build the image yourself). Both need gateway config for LAN access and a model provider (Ollama works fine with a placeholder key).

Direct install

Follow docs.openclaw.ai/install. Run it in a VM so the agent can orchestrate containers without polluting the host. Gateway config for LAN access:

"gateway": {
  "port": 18789,
  "mode": "local",
  "bind": "lan",
  "auth": { "mode": "token", "token": "[redacted]" },
  "trustedProxies": ["192.168.5.8"],
  "controlUi": { "allowedOrigins": ["https://claw.domain.com"] },
  "tailscale": { "mode": "off", "resetOnExit": false },
  "nodes": {
    "denyCommands": [
      "camera.snap", "camera.clip", "screen.record",
      "contacts.add", "calendar.add", "reminders.add", "sms.send"
    ]
  }
}

The denyCommands list is the privacy guard — a personal agent shouldn't be able to snap the camera or send SMS without an explicit allow.

Docker install

Clone openclaw/openclaw and build the image. Two gotchas:

  • docker-setup.sh overwrites any .env you create — preconfigure variables inside the script itself (that's where OPENCLAW_CONFIG_DIR and OPENCLAW_WORKSPACE_DIR are defined).
  • First browser access requires authenticating the browser: run the commands to see and authorize requests. Bash into the container with docker exec -it openclaw-gateway bash (assuming container_name: openclaw-gateway).

Models (Ollama)

Configure under Config → Models. Ollama needs no real key, but OpenClaw won't use a provider without one — give it a nonsense key. Raw config example:

"models": {
  "providers": {
    "ollama": {
      "baseUrl": "http://192.168.4.45:7869",
      "apiKey": "__OPENCLAW_REDACTED__",
      "api": "ollama",
      "injectNumCtxForOpenAICompat": false,
      "models": [
        {
          "id": "qwen3:8b",
          "name": "qwen3:8b",
          "api": "ollama",
          "reasoning": false,
          "input": ["text"],
          "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
          "contextWindow": 16000,
          "maxTokens": 8192
        }
      ]
    }
  }
}

See also