Openclaw Install

Category: DevOps & Infrastructure | Read: 10 min | v1.0.0

OpenClaw Installation & Configuration

OpenClaw is an open-source AI agent platform (github.com/openclaw/openclaw, 373k+ GitHub stars). It is NOT the same as Hermes WebUI (nesquena/hermes-webui) — they are completely different products. OpenClaw uses Docker, Node.js/TypeScript, and its own skill system (ClawHub).

⚠️ Critical Distinction: OpenClaw ≠ Hermes WebUI

  • OpenClaw (github.com/openclaw/openclaw) — AI agent platform with Docker gateway, browser automation, multi-provider LLM support, ClawHub skills marketplace
  • Hermes WebUI (github.com/nesquena/hermes-webui) — Web frontend for Hermes Agent, Python-based, uses bootstrap.py
  • Both can coexist on the same server but serve different purposes. Do NOT confuse them.

    Quick Deploy (Docker)

    1. Pull the Docker image

    docker pull ghcr.io/openclaw/openclaw:latest
    

    2. Create config directory structure

    mkdir -p /root/.openclaw/workspace /root/.openclaw-auth-profile-secrets
    chmod -R 777 /root/.openclaw /root/.openclaw-auth-profile-secrets
    

    Container runs as UID 1000 (node user) — needs write access

    3. Run initial setup (generates default config)

    docker run --rm \
      -v /root/.openclaw:/home/node/.openclaw \
      -v /root/.openclaw/workspace:/home/node/.openclaw/workspace \
      ghcr.io/openclaw/openclaw:latest \
      node dist/index.js setup --non-interactive --accept-risk
    

    This creates /root/.openclaw/openclaw.json with default configuration.

    4. Configure providers (API keys)

    Edit /root/.openclaw/openclaw.json — add env block with API keys:

    {
      "defaultProvider": "chutes",
      "defaultModel": "zai-org/GLM-5-Turbo",
      "env": {
        "OPENCLAW_API_KEY_CHUTES": "sk-your-chutes-key",
        "OPENCLAW_API_KEY_GROQ": "gsk_your-groq-key",
        "OPENCLAW_API_KEY_OPENROUTER": "sk-or-your-key"
      },
      "gateway": {
        "controlUi": {
          "allowedOrigins": ["https://your-domain.example.com"]
        }
      }
    }
    

    Provider name mapping — OpenClaw uses lowercase provider names as env var suffixes:

  • OPENCLAW_API_KEY_CHUTES → Chutes provider

  • OPENCLAW_API_KEY_GROQ → Groq

  • OPENCLAW_API_KEY_OPENROUTER → OpenRouter

  • etc.
  • Important: Use a working free provider (e.g., Chutes) as the default. Avoid providers that require special env vars (like opencode-go which needs a separate API key env var) unless that env var is also set.

    5. Create Docker Compose

    # /opt/openclaw/docker-compose.yml
    version: "3.8"
    services:
      gateway:
        image: ghcr.io/openclaw/openclaw:latest
        ports:
          - "18789:8080"
        volumes:
          - /root/.openclaw:/home/node/.openclaw
          - /root/.openclaw/workspace:/home/node/.openclaw/workspace
          - /root/.openclaw-auth-profile-secrets:/home/node/.openclaw-auth-profile-secrets
          - /etc/localtime:/etc/localtime:ro
        environment:
          - OPENCLAW_AUTH_PASSWORD=munaf
        restart: unless-stopped
    

    6. Start the gateway

    cd /opt/openclaw && docker compose up -d
    

    7. Verify

    curl -s http://localhost:18789/healthz
    

    {"ok":true,"status":"live"}

    docker logs openclaw-openclaw-gateway-1 --tail 10

    Should show: [gateway] ready, [browser/server] Browser control listening


    8. Install skills from ClawHub

    # List available skills
    docker exec openclaw-openclaw-gateway-1 node dist/index.js skills list
    

    Search for skills

    docker exec openclaw-openclaw-gateway-1 node dist/index.js skills search "browser"

    Install skills

    docker exec openclaw-openclaw-gateway-1 node dist/index.js skills install bsession docker exec openclaw-openclaw-gateway-1 node dist/index.js skills install github docker exec openclaw-openclaw-gateway-1 node dist/index.js skills install research-agent docker exec openclaw-openclaw-gateway-1 node dist/index.js skills install web-search

    ... etc

    Skills install to /home/node/.openclaw/workspace/skills/ (mapped to /root/.openclaw/workspace/skills/ on host).

    9. Restart after config changes

    cd /opt/openclaw && docker compose restart
    

    Nginx + SSL (External Access)

    # /etc/nginx/sites-available/openclaw
    server {
        server_name oc.example.com;
    

    location / {
    proxy_pass http://127.0.0.1:18789;
    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 86400;
    proxy_send_timeout 86400;
    proxy_buffering off;
    }
    }

    ln -sf /etc/nginx/sites-available/openclaw /etc/nginx/sites-enabled/
    nginx -t && systemctl reload nginx
    certbot --nginx -d oc.example.com
    

    Do NOT add nginx auth_basic — OpenClaw has built-in password auth (OPENCLAW_AUTH_PASSWORD env var). Adding nginx auth creates a double-login.

    Browser Plugin (CamoFox)

    OpenClaw auto-detects a running CamoFox browser server. If CamoFox is on localhost:9377, the gateway log will show:

    [browser/server] Browser control listening on http://127.0.0.1:18791/ (auth=password)
    

    And the browser plugin appears in the gateway startup line.

    To point OpenClaw at a remote CamoFox fleet, add browser config to openclaw.json:

    {
      "browser": {
        "endpoints": [
          {"url": "http://localhost:9377", "label": "US"},
          {"url": "http://103.171.122.216:9377", "label": "PK"},
          {"url": "http://103.171.122.217:9377", "label": "PK-2"}
        ]
      }
    }
    

    Password Auth

    Set OPENCLAW_AUTH_PASSWORD in the Docker Compose environment:

    environment:
      - OPENCLAW_AUTH_PASSWORD=munaf
    

    Copying Config from Another Hermes Setup

    When migrating API keys from a Hermes Agent config:

  • config.yamlopenclaw.json: Extract api_key fields from each provider and create OPENCLAW_API_KEY_{PROVIDER} env vars
  • Skills: OpenClaw uses ClawHub (its own marketplace), NOT Hermes skill files. Install equivalent skills via skills install.
  • System prompt: Edit openclaw.json's systemPrompt field or use the web UI settings
  • Important: Hermes .env values like OPENCODE_GO_API_KEY=* are MASKED — the real keys are in config.yaml under each provider's api_key: field. Always copy from config.yaml, not .env.

    Also important: PyYAML's dump() mangles config files. Never round-trip a YAML config through yaml.safe_load()yaml.dump(). Use scp for raw file transfer, then sed or Python string replacement for targeted edits.

    Config Directory Layout

    /root/.openclaw/
    ├── openclaw.json          # Main config (providers, model, system prompt)
    ├── workspace/
    │   └── skills/            # Installed ClawHub skills
    │       ├── bsession/
    │       ├── github/
    │       ├── research-agent/
    │       └── ...
    └── auth-profile-secrets/
    

    /opt/openclaw/
    ├── docker-compose.yml
    └── .env # OPENCLAW_API_KEY_* vars (alternative to openclaw.json env)

    Pitfalls

  • "OpenClaw" ≠ "Hermes WebUI" — they are completely different products. OpenClaw is from openclaw.ai, Hermes WebUI is from github.com/nesquena/hermes-webui. Do NOT install Hermes WebUI when the user asks for OpenClaw.
  • Container runs as UID 1000 (node)/root/.openclaw needs chmod 777 or the container can't write to it. Without write access, openclaw setup and skill installs fail silently.
  • openclaw onboard fails in Docker — requires TTY. Use setup --non-interactive --accept-risk instead.
  • Browser plugin auto-detects — if CamoFox is running on localhost:9377, OpenClaw finds it automatically. No extra config needed for local browser.
  • Default model after setup is openai/gpt-5.5 — this will fail without an OpenAI API key. Change defaultModel and defaultProvider in openclaw.json to a working free provider (e.g., chutes / zai-org/GLM-5-Turbo).
  • Restart required after config editsdocker compose restart needed for changes to openclaw.json or .env to take effect.
  • Skills are ClawHub-based — OpenClaw has its own skill system (52+ built-in skills, installable via skills install). Hermes skill files (SKILL.md) are NOT compatible with OpenClaw skills.
  • skills install 404s for some names — not all skill names from skills list exist on ClawHub. Use skills search to find the correct installable name.
  • CamoFox GTK dependencies — on fresh Ubuntu servers, CamoFox needs GTK3 and other libraries: apt-get install -y libgtk-3-0 libdbus-glib-1-2 libxt6 libasound2t64 libatk1.0-0 libatk-bridge2.0-0 libcups2 libxdamage1 libxrandr2 libxcomposite1 libxfixes3 libx11-xcb1 libxcb1 libxcursor1 libxi6 libpango-1.0-0 libpangocairo-1.0-0 libcairo2 libcairo-gobject2 libgdk-pixbuf-2.0-0 libfreetype6 libfontconfig1 libatk-adaptor libatspi2.0-0 xvfb. The /health endpoint works without these, but tab creation returns 500.
  • CamoFox sessionKey required for tab creationPOST /tabs returns {"error":"userId and sessionKey required"} if sessionKey is missing. Always include both: {"userId":"user1","sessionKey":"default"}.
  • Nginx auth double-login — do NOT add auth_basic in nginx if OpenClaw already has built-in auth (OPENCLAW_AUTH_PASSWORD). Use one or the other.
  • WebSocket proxy headers requiredproxy_set_header Upgrade and proxy_read_timeout 86400 are essential for the OpenClaw gateway's real-time features to work through nginx.
  • Config file format is JSON — OpenClaw uses openclaw.json (JSON), not YAML like Hermes Agent. Edit with jq or Python json module, not yaml.
  • Device pairing required for every new browser — Each browser that connects to the OpenClaw dashboard needs one-time approval. The dashboard shows: openclaw devices approve . Run this inside the container: docker exec openclaw-openclaw-gateway-1 node dist/index.js devices approve . Without this, the browser sees "Device pairing required" and cannot connect. See references/device-pairing.md for full workflow.
  • Gateway bind must be lan for external/nginx access — if set to loopback (the default from setup), only localhost connections work. Set "bind": "lan" in openclaw.json gateway section for public access behind nginx.
  • controlUi.allowedOrigins must include the external domain — After setup, the gateway only allows localhost origins. Add your domain to gateway.controlUi.allowedOrigins or the dashboard JS will be blocked: "allowedOrigins": ["https://oc.example.com", "http://localhost:18789"].
  • Password auth in config vs env var — Both work, but openclaw.json "auth": {"mode": "password", "password": "munaf"} persists across container recreates. The OPENCLAW_AUTH_PASSWORD env var also works but is only in docker-compose.yml. Prefer the JSON config approach for persistence.
  • setup command workeddocker run --rm -v ... ghcr.io/openclaw/openclaw:latest node dist/index.js setup --non-interactive --accept-risk generates the config. The onboard command requires TTY and fails in Docker even without -it.
  • Files

  • /root/.openclaw/openclaw.json — Main config
  • /opt/openclaw/docker-compose.yml — Docker Compose for gateway
  • /opt/openclaw/.env — Environment vars (API keys)
  • /root/.openclaw/workspace/skills/ — Installed ClawHub skills
  • Advanced Techniques (2025-2026)

    Docker healthcheck with restart policies

    Add a healthcheck to your Compose service so Docker can detect gateway hangs and auto-restart:

    services:
      gateway:
        # ... existing config ...
        healthcheck:
          test: ["CMD", "curl", "-sf", "http://localhost:8080/healthz"]
          interval: 30s
          timeout: 5s
          retries: 3
          start_period: 15s
        restart: unless-stopped
    

    Without a healthcheck, Docker only restarts on process exit — not on deadlocks or silent hangs. The /healthz endpoint returns {"ok":true} when the gateway is live.

    Compose Watch zero-downtime config reload (v2.22+)

    Use Docker Compose Watch to hot-reload openclaw.json changes without restarting the container:

    services:
      gateway:
        # ... existing config ...
        develop:
          watch:
            - path: /root/.openclaw/openclaw.json
              action: sync
              target: /home/node/.openclaw/openclaw.json
    

    This is especially useful for iterative provider/model tuning — changes propagate in seconds instead of requiring docker compose restart.

    Fix UID mismatch with chown instead of chmod 777

    The container runs as UID 1000 (node). chmod 777 works but is sloppy. Prefer targeted ownership:

    # Instead of: chmod -R 777 /root/.openclaw
    chown -R 1000:1000 /root/.openclaw /root/.openclaw-auth-profile-secrets
    

    This grants the node user write access without making directories world-writable.

    jq for JSON config editing

    Since openclaw.json is JSON (not YAML), jq is the right tool for scripted edits:

    # Change default provider
    jq '.defaultProvider = "chutes"' /root/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json /root/.openclaw/openclaw.json
    

    Add an API key

    jq '.env.OPENCLAW_API_KEY_CHUTES = "sk-xxx"' /root/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json /root/.openclaw/openclaw.json

    Set gateway bind to lan

    jq '.gateway.bind = "lan"' /root/.openclaw/openclaw.json > /tmp/oc.json && mv /tmp/oc.json /root/.openclaw/openclaw.json

    Edge Cases / Pitfalls

  • UID 1000 silent write failures — If directories are owned by root with mode 755, the node user (UID 1000) can read but not write. setup and skills install will fail silently — no error, just no output. Always verify ownership with ls -la /root/.openclaw/.
  • env_file vs environment precedence — In Docker Compose, environment: entries override env_file: entries when the same variable name appears in both. If you set OPENCLAW_AUTH_PASSWORD in both environment: and an .env file referenced by env_file:, the environment: value wins. This can be surprising when debugging auth issues — check which source actually provides the value.
  • OpenClaw 2025 Updates

    Skill Marketplace Growth (ClawHub 200+)

    ClawHub has expanded from ~52 built-in skills to 200+ community and official skills. New categories include data-pipeline, devops-automate, ai-redteam, and browser-agent clusters. Search and install:

    # Browse by category
    docker exec openclaw-openclaw-gateway-1 node dist/index.js skills search "category:data-pipeline"
    

    Install popular new skills

    docker exec openclaw-openclaw-gateway-1 node dist/index.js skills install browser-agent docker exec openclaw-openclaw-gateway-1 node dist/index.js skills install ai-redteam docker exec openclaw-openclaw-gateway-1 node dist/index.js skills install devops-automate

    The marketplace now supports skill dependencies — installing a skill auto-installs its prerequisites. Check for skill updates with skills update .

    Browser Plugin Improvements (CamoFox v2+)

    CamoFox integration improvements in 2025:

  • Multi-tab session managementPOST /tabs now supports sessionKey isolation per tab, enabling parallel browser sessions without state leakage

  • Stealth fingerprint rotation — CamoFox v2 rotates Canvas/WebGL fingerprints per session. Set "fingerprintRotation": true in browser config

  • WebSocket health/health endpoint now returns browser engine version and active tab count ({"ok":true,"engine":"122.0","tabs":3})

  • Session persistence — Sessions survive gateway restarts when sessionPersistence: true is set in browser config
  • {
      "browser": {
        "endpoints": [
          {"url": "http://localhost:9377", "label": "local", "fingerprintRotation": true}
        ],
        "sessionPersistence": true
      }
    }
    

    Docker Compose v2 Healthcheck + Watch

    The develop.watch section and healthchecks documented earlier are now the recommended deployment pattern. One addition: use depends_on with health conditions for startup ordering:

    services:
      gateway:
        # ... existing config ...
        depends_on:
          redis:
            condition: service_healthy
      redis:
        image: redis:7-alpine
        healthcheck:
          test: ["CMD", "redis-cli", "ping"]
          interval: 5s
          retries: 5
    

    This ensures the gateway doesn't start accepting connections until Redis is ready.

    References

  • references/device-pairing.md — Full workflow for approving new browsers that connect to the OpenClaw dashboard (required on first connection)
  • Templates

  • templates/docker-compose.yml — Ready-to-use Docker Compose with correct volume mounts and env vars
  • Scripts

  • scripts/openclaw-healthcheck.sh — One-command deployment health check (container status, gateway health, model, skills, errors, pending device pairings)