🦞OpenClaw Guide
Installation

Running OpenClaw in Docker — Setup & Troubleshooting

Complete guide to running OpenClaw in Docker containers, including setup on Synology NAS, fixing permission errors, resolving pairing/1008 errors, and configuring volumes for persistent skills.

⚠️ The Problem

Users encounter various issues when running OpenClaw in Docker containers: Permission denied errors (common on Synology): `` Error: EACCES: permission denied, mkdir '/home/node/.clawdbot/agents/main/agent' **1008 pairing errors when accessing Control UI remotely:** gateway closed (1008): unauthorized: pairing required **Token mismatch errors:** gateway connect failed: Error: unauthorized: gateway token mismatch (set gateway.remote.token to match gateway.auth.token) **Skills/CLI tools not available inside container:** Enter passphrase to unlock "/home/node/.config/gogcli/keyring": **Missing workspace template:** Missing workspace template: AGENTS.md **Signal linking issues in Docker:** link request error: connection closed

🔍 Why This Happens

These issues stem from several Docker-specific challenges: 1. Permission mismatches: Docker containers run with different UID/GID than host filesystems, especially on Synology NAS where volume mounts don't map cleanly. 2. Remote pairing requirements: The Control UI is treated as a "device" that requires one-time pairing approval when accessed remotely (LAN/Tailscale). Local 127.0.0.1 connections auto-approve, but remote connections need explicit approval. 3. Network mode conflicts: Using network_mode: host affects how ports and localhost are handled. 4. Volume persistence: Skills, CLI tools (Homebrew packages), and auth credentials need proper volume mounts to persist. 5. Environment variables not passed: Credentials and keyring passwords must be explicitly passed to the container, not just set on the host. 6. Docker image missing template files: The workspace template files aren't copied to the dist/ folder during build.

The Fix

## Basic Docker Setup

Clone the repository and use the provided docker-compose:

bash
git clone https://github.com/openclaw/openclaw.gitcd openclawdocker compose up -d

## Fix Permission Denied Errors (Synology/NAS)

The container runs as a different user than your host. Fix by specifying user ID:

Option 1: Check your user ID first:

bash
id $(whoami)# Output: uid=1000(youruser) gid=1000(yourgroup) ...

Option 2: Add user specification to docker-compose.yml:

yaml
services:  openclaw-gateway:    user: "1000:1000"  # Replace with your actual UID:GID    volumes:      - ~/clawd:/home/node/clawd      - ~/.openclaw:/home/node/.openclaw

Option 3: Fix host folder permissions:

bash
sudo chown -R 1000:1000 ~/.openclaw ~/clawd

## Fix 1008 Pairing Errors (Remote Access)

When accessing the Control UI remotely (via Tailscale, LAN IP, etc.), the browser needs device pairing approval:

Step 1: List pending pairing requests:

bash
docker compose run --rm openclaw-cli devices list

Step 2: Approve the pending device:

bash
docker compose run --rm openclaw-cli devices approve <DEVICE_ID>

Step 3: If CLI can't connect, start dashboard with no-open flag:

bash
docker compose run --rm openclaw-cli dashboard --no-open

Note: Each browser profile has its own device ID — clearing site data or switching browsers requires re-pairing.

## Fix Token Mismatch Errors

The gateway remote token must match the auth token exactly:

Step 1: Check your config file:

bash
cat ~/.openclaw/openclaw.json | grep -A 10 gateway

Step 2: Ensure tokens match:

json
{  "gateway": {    "auth": {      "mode": "token",      "token": "your-secret-token"    },    "remote": {      "token": "your-secret-token"  // MUST match auth.token    }  }}

Step 3: Restart the gateway:

bash
docker compose restart openclaw-gateway

## Configure Proper Port Binding

For remote access, bind to all interfaces, not just localhost:

yaml
# docker-compose.ymlservices:  openclaw-gateway:    ports:      - "0.0.0.0:18789:18789"  # Correct - allows external access      # NOT "127.0.0.1:18789:18789" - only allows localhost

Verify container is listening correctly:

bash
docker exec -it openclaw-gateway ss -tlnp | grep LISTEN# Should show 0.0.0.0:18789, not 127.0.0.1:18789

## Tailscale + Docker Configuration

When using Tailscale with Docker, use network_mode: host and disable the built-in Tailscale config:

yaml
services:  openclaw-gateway:    network_mode: host    # Do NOT specify tailscale config - use host's Tailscale

Gateway config for Tailscale:

json
{  "gateway": {    "mode": "local",    "tailscale": {      "mode": "off"  // Use host's Tailscale, not container's    }  }}

## Make Skills and Tools Persistent

Skills need Homebrew packages and config directories to persist. Add these volumes:

yaml
services:  openclaw:    volumes:      - ./linuxbrew-home:/home/linuxbrew/.linuxbrew  # Homebrew packages      - ./node-home:/home/node                        # Go binaries, cache      - ~/.config/gogcli:/home/node/.config/gogcli    # Google OAuth credentials

To install additional tools into the container:

bash
# 1. Start a copy of your existing imagedocker run -it --name temp-install openclaw-sandbox:latest /bin/bash# 2. Install what you needapt install xyzbrew install abc# 3. Exit and commitexitdocker commit temp-install openclaw-sandbox:with-tools# 4. Update config to use new image# In openclaw.json:# "docker": { "image": "openclaw-sandbox:with-tools" }# 5. Restart gatewaydocker compose restart

## Fix Keyring Passphrase Prompts (gog/gogcli)

The keyring requires both environment variables set AND passed to the container:

yaml
# docker-compose.override.ymlservices:  openclaw:    environment:      - GOG_KEYRING_BACKEND=file      - GOG_KEYRING_PASSWORD=${GOG_KEYRING_PASSWORD}    volumes:      - gog-config:/home/node/.config/gogcli

Set the keyring backend inside the container:

bash
docker exec -it openclaw gog auth keyring file

Verify it works:

bash
docker exec -e GOG_KEYRING_PASSWORD='your-passphrase' openclaw gog auth status

## Fix Missing Workspace Template Error

The Docker image may be missing template files. Mount the docs folder:

yaml
services:  openclaw:    volumes:      - ./docs:/app/dist/docs:ro

Or copy docs during build:

bash
cp -r docs dist/

## Fix Signal Linking Issues in Docker

Signal CLI needs a clean environment and proper timing:

bash
# Kill any existing signal-cli processespkill -f signal-cli# Fresh link attemptsignal-cli link -n "OpenClaw"

If using daemon mode:

bash
# Start daemon in backgroundsignal-cli daemon --dbus=json-rpc &# Then linksignal-cli link -n "OpenClaw" --dbus=json-rpc

Ensure port 8080 is exposed if using HTTP daemon mode.

## VPS + Docker + Tailscale Checklist

1. Docker port binding: Use 0.0.0.0:port, not 127.0.0.1:port

2. Check container listening address: ``bash docker exec -it <container> ss -tlnp | grep LISTEN

3. Use Tailscale IP directly: http://<tailscale-ip>:18789

4. Windows firewall: Add inbound rule for the port or temporarily disable to test

5. Subnet routing if needed: ``bash sudo tailscale up --advertise-routes=192.168.1.0/24 --accept-routes

🔥 Your AI should run your business, not just answer questions.

We'll show you how.$97/mo (going to $197 soon)

Join Vibe Combinator →

📋 Quick Commands

CommandDescription
docker compose up -dStart OpenClaw containers
docker compose run --rm openclaw-cli devices listList pending device pairing requests
docker compose run --rm openclaw-cli devices approve <ID>Approve a device for remote access
docker exec -it openclaw-gateway ss -tlnpCheck what ports the container is listening on
docker compose restart openclaw-gatewayRestart the gateway container
id $(whoami)Get your user ID and group ID for permission fixes
docker commit <container> <new-image-name>Save container with installed tools as new image

Related Issues

🐙 Your AI should run your business.

Weekly live builds + template vault. We'll show you how to make AI actually work.$97/mo (going to $197 soon)

Join Vibe Combinator →

Still stuck?

Join our Discord community for real-time help.

Join Discord