{"id":50577866,"url":"https://github.com/Made-By-Adem/openClaw-Docker","last_synced_at":"2026-06-21T19:00:25.607Z","repository":{"id":339580940,"uuid":"1157508706","full_name":"Made-By-Adem/openClaw-Docker","owner":"Made-By-Adem","description":"Self-host OpenClaw in Docker — ready-to-use setup with Chromium support.","archived":false,"fork":false,"pushed_at":"2026-05-06T19:59:20.000Z","size":258,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-06T21:42:13.466Z","etag":null,"topics":["ai","ai-agents","ai-assistant","chatbot","chatgpt","claude","clawdbot","docker","linux","moltbot","opencl","telegram","vps"],"latest_commit_sha":null,"homepage":"https://madebyadem.dev","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Made-By-Adem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T22:41:29.000Z","updated_at":"2026-05-06T19:34:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Made-By-Adem/openClaw-Docker","commit_stats":null,"previous_names":["madebyadem/openclaw-docker","made-by-adem/openclaw-docker"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Made-By-Adem/openClaw-Docker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Made-By-Adem%2FopenClaw-Docker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Made-By-Adem%2FopenClaw-Docker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Made-By-Adem%2FopenClaw-Docker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Made-By-Adem%2FopenClaw-Docker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Made-By-Adem","download_url":"https://codeload.github.com/Made-By-Adem/openClaw-Docker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Made-By-Adem%2FopenClaw-Docker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34622271,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-21T02:00:05.568Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","ai-agents","ai-assistant","chatbot","chatgpt","claude","clawdbot","docker","linux","moltbot","opencl","telegram","vps"],"created_at":"2026-06-05T00:00:28.685Z","updated_at":"2026-06-21T19:00:25.579Z","avatar_url":"https://github.com/Made-By-Adem.png","language":"JavaScript","funding_links":[],"categories":["Open Source Projects"],"sub_categories":["Hosting Platforms"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://openclaw.ai/blog/openclaw-logo-text.png\" alt=\"OpenClaw\" width=\"300\" /\u003e\n  \u003cbr /\u003e\n  \u003cimg src=\"https://www.docker.com/wp-content/uploads/2022/03/Moby-logo.png\" alt=\"Docker\" width=\"80\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eopenClaw Docker\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eSelf-host OpenClaw on your own server — hardened, Dockerized, ready to go.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/MadeByAdem/openClaw-Docker/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License\" /\u003e\u003c/a\u003e\n  \u003ca href=\"#security\"\u003e\u003cimg src=\"https://img.shields.io/badge/security-hardened-brightgreen.svg\" alt=\"Security Hardened\" /\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/docker-ready-2496ED.svg?logo=docker\u0026logoColor=white\" alt=\"Docker Ready\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/platform-linux%20%7C%20raspberry%20pi-lightgrey.svg\" alt=\"Platform\" /\u003e\n\u003c/p\u003e\n\n---\n\n\u003e [!CAUTION]\n\u003e **OpenClaw is new and has known security risks.** Independent researchers (Aikido, Microsoft, Cisco) warn about vulnerabilities. This repo includes hardening measures, but a completely secure setup is not currently achievable. Do not run on machines with sensitive data without understanding the risks.\n\u003e See [Security](#-security) and [SECURITY.md](docs/SECURITY.md) for details.\n\n\u003e **What is OpenClaw?** OpenClaw is an open-source AI assistant that connects to messaging platforms like WhatsApp, Telegram and Discord. This repository lets you self-host it in a Docker container on any Linux server — with security hardening built in.\n\n---\n\n## 📋 Table of Contents\n\n- [📦 What\u0026#39;s Included](#-whats-included)\n- [📚 Documentation](#-documentation)\n- [✅ Prerequisites](#-prerequisites)\n- [🚀 Installation](#-installation)\n- [🎨 Personalization](#-personalization)\n- [💬 Connecting Channels](#-connecting-channels)\n- [🖥️ Accessing the Dashboard](#️-accessing-the-dashboard)\n- [⚙️ Managing Your Server](#️-managing-your-server)\n- [🔐 Environment Variables](#-environment-variables)\n- [🔧 Troubleshooting](#-troubleshooting)\n- [🔒 Security](#-security)\n- [🔄 Updating](#-updating)\n- [📦 Migrating to Hardened Setup](#-migrating-to-hardened-setup)\n- [🤖 Choosing a Model](#-choosing-a-model)\n- [🔍 Add-ons](#-add-ons)\n- [📁 File Overview](#-file-overview)\n- [💾 Data \u0026amp; Backups](#-data--backups)\n- [📄 License](#-license)\n\n---\n\n## 📦 What's Included\n\nThis project adds a thin Docker layer on top of the official `alpine/openclaw` image:\n\n- 🌐 **Chromium browser** with all required dependencies for browser automation skills\n- 🐳 A `--no-sandbox` wrapper so Chromium runs correctly inside Docker\n- 🔧 Execute-permission fixes for bundled skill scripts\n- 🔒 **Security hardening** — dropped capabilities, rate limiting, health checks, and documented filesystem tradeoffs for CLI-enabled setups\n- 🎙️ **Voice message support** — local speech-to-text (faster-whisper) and text-to-speech (edge-tts), no external APIs needed\n\nEverything else is standard OpenClaw — no custom code.\n\n---\n\n## 📚 Documentation\n\n| Guide | Description |\n| --- | --- |\n| [Workspace Architecture](docs/WORKSPACE-ARCHITECTURE.md) | How workspace files are structured, what each file does, conventions to follow |\n| [Skill Development](docs/SKILL-DEVELOPMENT.md) | How to create, structure, and maintain custom skills |\n| [Personalization](docs/PERSONALIZATION.md) | Quick reference for the personalization script and workspace files |\n| [Multi-Agent Guide](docs/AGENTS-GUIDE.md) | Give your agent specialized roles — it switches between developer, assistant, marketeer (or custom) based on what you ask |\n| [CLI Setup](docs/AI-CLI-SETUP.md) | Set up Claude CLI, Gemini CLI, and GitHub CLI — authenticate without API keys, push code to GitHub (includes security tradeoffs) |\n| [Security](docs/SECURITY.md) | Security hardening details, container isolation, recommended practices |\n| [SearXNG Setup](docs/SEARXNG-SETUP.md) | Add private self-hosted web search with optional Tor support |\n\n---\n\n## ✅ Prerequisites\n\nBefore you start, make sure you have:\n\n| # | Requirement | Details |\n| - | - | - |\n| 1 | **Linux server** | Ubuntu recommended, Raspberry Pi also works |\n| 2 | **Docker Engine + Compose v2** | [Install Docker](https://docs.docker.com/engine/install/) |\n| 3 | **AI provider API key or CLI** | API key for any provider, or use [Claude CLI / Gemini CLI](docs/AI-CLI-SETUP.md) to authenticate without a key |\n\n\u003cdetails\u003e\n\u003csummary\u003e📥 \u003cstrong\u003eInstalling Docker (if you don't have it yet)\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\n# Install Docker\ncurl -fsSL https://get.docker.com | sudo sh\n\n# Allow your user to run Docker without sudo\nsudo usermod -aG docker $USER\n\n# Log out and back in for the group change to take effect\nexit\n```\n\nAfter logging back in, verify it works:\n\n```bash\ndocker --version\ndocker compose version\n```\n\nBoth commands should print a version number without errors.\n\n\u003c/details\u003e\n\n---\n\n## 🚀 Installation\n\nFollow these steps one by one. Each step includes the exact command to run.\n\n### Step 1 — Clone this repository\n\n```bash\ngit clone https://github.com/MadeByAdem/openClaw-Docker.git\ncd openClaw-Docker\n```\n\n### Step 2 — Run the setup script\n\n```bash\nchmod +x setup.sh\nsudo ./setup.sh\n```\n\nThe setup script will automatically:\n\n1. ✅ Check that Docker and Docker Compose are installed\n2. 📁 Create the required data directories (`./data/config` and `./data/workspace`)\n3. 🔑 Generate a `.env` file with a secure 256-bit gateway token\n4. 🐳 Build the Docker image with security hardening\n5. 🧙 Start the interactive onboarding process\n6. 🔒 Run `doctor --repair` and `security audit`\n\n### Step 3 — Complete the onboarding\n\nThe onboarding wizard will start automatically. It will ask you to:\n\n1. **Enter your AI provider API key** (e.g. OpenAI, Anthropic, Google, Mistral, or any compatible provider)\n2. **Connect your first messaging channel** (WhatsApp, Telegram or Discord)\n\nFollow the prompts on screen. When it's done, your OpenClaw gateway will be running.\n\n### Step 4 — Verify it's running\n\n```bash\ndocker compose logs -f openclaw-gateway\n```\n\nYou should see log output indicating the gateway is active. Press `Ctrl+C` to stop following the logs (the gateway keeps running in the background).\n\n\u003e [!TIP]\n\u003e **Ask the AI itself for help!** Once your bot is running, you can message it directly:\n\u003e\n\u003e - *\"Connect my Telegram bot\"* — walks you through BotFather setup\n\u003e - *\"Switch my model to Claude Sonnet\"* — updates its own config\n\u003e - *\"Why am I getting an error?\"* — paste the error and it suggests a fix\n\u003e - *\"Set up a daily summary cron job\"* — configures scheduled tasks\n\u003e - *\"What skills do you have?\"* — lists available capabilities\n\u003e\n\u003e You don't need to memorize CLI commands. If you're unsure, just ask your bot.\n\n### Step 5 — Personalize your agent (optional)\n\nMake your AI agent yours — give it a name, personality, and context about you:\n\n```bash\nchmod +x personalize.sh\n./personalize.sh\n```\n\nSee [Personalization](#-personalization) for details.\n\n---\n\n## 🎨 Personalization\n\nAfter the initial setup, you can personalize your AI agent by running the personalization script. This creates configuration files in the workspace that define your agent's identity, personality, and behavior.\n\n```bash\n./personalize.sh\n```\n\nThe script walks you through creating these files:\n\n| File | Purpose |\n| --- | --- |\n| `IDENTITY.md` | Your agent's name, roles, language, and how it introduces itself |\n| `SOUL.md` | Core values, communication style, and personality |\n| `USER.md` | About you — name, timezone, preferences, so the agent knows who it's helping |\n| `AGENTS.md` | Behavioral guidelines — memory management, safety rules, group chat behavior |\n| `CONVENTIONS.md` | Coding standards, git workflow, project terminology (for developers) |\n| `TOOLS.md` | Integration notes — scripts, APIs, credentials locations |\n| `HEARTBEAT.md` | Periodic tasks your agent should check on |\n| `MEMORY.md` | Long-term memory (starts empty, your agent fills this over time) |\n\nFor each file, you can:\n\n- **Edit** — open in your text editor to customize\n- **View example** — see a working example before editing\n- **Skip** — use the default template (you can always edit later)\n\nThe script restarts OpenClaw automatically when done. You can also edit these files manually at any time in `./data/workspace/` and restart with `docker compose restart openclaw-gateway`.\n\n\u003e [!TIP]\n\u003e For advanced workspace configuration (skill routing, workspace structure, file separation conventions), see [Workspace Architecture](docs/WORKSPACE-ARCHITECTURE.md). For creating custom skills, see [Skill Development](docs/SKILL-DEVELOPMENT.md).\n\n---\n\n## 💬 Connecting Channels\n\nYou can connect one or more messaging platforms after setup.\n\n### WhatsApp\n\n1. Enable the WhatsApp plugin (skip if you already selected WhatsApp during onboarding):\n\n```bash\ndocker compose exec openclaw-gateway node dist/index.js plugins enable whatsapp\n```\n\n2. Login and scan the QR code:\n\n```bash\ndocker compose exec openclaw-gateway node dist/index.js channels login --channel whatsapp\n```\n\nA QR code will appear in your terminal. Scan it with WhatsApp on your phone (**Settings \u003e Linked Devices \u003e Link a Device**).\n\n### Telegram\n\n1. Enable the Telegram plugin (skip if you already selected Telegram during onboarding):\n\n```bash\ndocker compose exec openclaw-gateway node dist/index.js plugins enable telegram\n```\n\n2. Create a bot via [@BotFather](https://t.me/BotFather) on Telegram and copy the bot token.\n3. Add the bot:\n\n```bash\ndocker compose exec openclaw-gateway node dist/index.js channels add --channel telegram --token \"YOUR_BOT_TOKEN\"\n```\n\n4. Send a message to your bot on Telegram. It will ask you to approve the pairing:\n\n```bash\ndocker compose exec openclaw-gateway node dist/index.js pairing approve telegram CODE\n```\n\nReplace `CODE` with the pairing code shown in the message.\n\n\u003e [!NOTE]\n\u003e **Webhook conflict?** If the bot was previously used in another project, you may need to remove the old webhook first:\n\u003e\n\u003e ```bash\n\u003e curl -s \"https://api.telegram.org/botYOUR_BOT_TOKEN/deleteWebhook\"\n\u003e docker compose restart openclaw-gateway\n\u003e ```\n\u003e\n\u003e Alternatively, create a fresh bot via @BotFather.\n\n### Discord\n\n1. Enable the Discord plugin (skip if you already selected Discord during onboarding):\n\n```bash\ndocker compose exec openclaw-gateway node dist/index.js plugins enable discord\n```\n\n2. Create a bot on the [Discord Developer Portal](https://discord.com/developers/applications) and copy the bot token.\n3. Add the bot:\n\n```bash\ndocker compose exec openclaw-gateway node dist/index.js channels add --channel discord --token \"YOUR_BOT_TOKEN\"\n```\n\n---\n\n## 🖥️ Accessing the Dashboard\n\nOpenClaw includes a web dashboard (Control UI) for managing your instance. The setup script automatically configures it for you.\n\n### Local access\n\nAfter running `setup.sh`, the dashboard URL is printed in the terminal. You can also retrieve it at any time:\n\n```bash\ndocker compose exec openclaw-gateway node dist/index.js dashboard --no-open\n```\n\nOpen the printed URL in your browser. It looks like this:\n\n```\nhttp://127.0.0.1:18789/#token=YOUR_GATEWAY_TOKEN\n```\n\n\u003e [!IMPORTANT]\n\u003e 🔑 The token is passed after the `#` (hash), not as a `?` query parameter. Do not share URLs containing your token.\n\n\u003e [!WARNING]\n\u003e 🚫 **Never expose the dashboard directly to the internet.** The gateway should only be accessible on `127.0.0.1`. Use an SSH tunnel, Tailscale, or a reverse proxy with TLS termination for remote access. Exposed instances have been found in sensitive sectors ([Bitsight](https://www.bitsight.com/blog/openclaw-ai-security-risks-exposed-instances)). See [Security](#-security) for details.\n\n### Remote access (reverse proxy)\n\nIf you access OpenClaw through a reverse proxy (Cloudflare Tunnel, nginx, Caddy, etc.), the setup script already configures the required settings. If you set up a reverse proxy after initial installation, add these settings to `./data/config/openclaw.json`:\n\n```json\n{\n  \"gateway\": {\n    \"bind\": \"lan\",\n    \"trustedProxies\": [\"172.17.0.0/16\"],\n    \"controlUi\": {\n      \"allowInsecureAuth\": true\n    }\n  }\n}\n```\n\n\u003e [!WARNING]\n\u003e Setting `allowInsecureAuth: true` allows token authentication over plain HTTP. **Only enable this if your reverse proxy terminates TLS** — otherwise your gateway token is sent in plaintext. If you used `setup.sh`, this is `false` by default and can be opted in via `OPENCLAW_ALLOW_INSECURE_AUTH=true` in `.env`.\n\nThen restart the gateway:\n\n```bash\ndocker compose restart openclaw-gateway\n```\n\nOpen the dashboard in your browser using your domain:\n\n```\nhttps://your-domain.com/#token=YOUR_GATEWAY_TOKEN\n```\n\nReplace `YOUR_GATEWAY_TOKEN` with the token from your `.env` file.\n\n**What these settings do:**\n\n| Setting                         | Purpose                                                                                   |\n| ------------------------------- | ----------------------------------------------------------------------------------------- |\n| `bind: \"lan\"`                 | Allows connections from Docker's internal network (default `loopback` blocks them)      |\n| `trustedProxies`              | Tells the gateway to trust proxy headers from Docker's bridge network (`172.17.0.0/16`) |\n| `controlUi.allowInsecureAuth` | Allows the dashboard to authenticate over HTTP (only safe behind a TLS-terminating proxy) |\n\n\u003cdetails\u003e\n\u003csummary\u003e🔧 \u003cstrong\u003eTroubleshooting the dashboard\u003c/strong\u003e\u003c/summary\u003e\n\n**\"gateway token mismatch\"** — The token in your browser URL does not match the token in `openclaw.json`. Check that `gateway.auth.token` in `./data/config/openclaw.json` matches the `OPENCLAW_GATEWAY_TOKEN` in your `.env` file. If they differ, update one to match the other and restart.\n\n**\"pairing required\"** — The gateway doesn't trust the proxy connection. Make sure `trustedProxies` and `controlUi.allowInsecureAuth` are set as shown above, then restart the gateway.\n\n**\"Proxy headers detected from untrusted address\"** — Same cause as above. Add `trustedProxies` with the Docker network range to your gateway config.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e☁️ \u003cstrong\u003eCloudflare Tunnel + Access (recommended for remote access)\u003c/strong\u003e\u003c/summary\u003e\n\nCloudflare Tunnel exposes your gateway to the internet **without opening any ports** on your server. Cloudflare Access adds a Zero Trust authentication layer **in front of** the gateway — users must authenticate with Cloudflare before they even reach the OpenClaw dashboard.\n\n**What you get:**\n\n- No open ports on your server\n- TLS handled by Cloudflare (no certificate management)\n- Extra authentication layer before the gateway token\n- Your server's IP address stays hidden\n\n#### Step 1 — Install `cloudflared`\n\n```bash\n# Debian/Ubuntu\ncurl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg \u003e/dev/null\necho \"deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main\" | sudo tee /etc/apt/sources.list.d/cloudflared.list\nsudo apt update \u0026\u0026 sudo apt install -y cloudflared\n```\n\n#### Step 2 — Authenticate and create a tunnel\n\n```bash\n# Login to your Cloudflare account (opens a browser)\ncloudflared tunnel login\n\n# Create a tunnel\ncloudflared tunnel create openclaw\n```\n\nNote the **Tunnel ID** from the output — you'll need it in the next step.\n\n#### Step 3 — Configure the tunnel\n\nCreate the config file at `~/.cloudflared/config.yml`:\n\n```yaml\ntunnel: \u003cYOUR_TUNNEL_ID\u003e\ncredentials-file: /root/.cloudflared/\u003cYOUR_TUNNEL_ID\u003e.json\n\ningress:\n  - hostname: pa.example.com\n    service: http://localhost:18789\n  - service: http_status:404\n```\n\nReplace `pa.example.com` with your actual domain.\n\n#### Step 4 — Create a DNS route\n\n```bash\ncloudflared tunnel route dns openclaw pa.example.com\n```\n\nThis creates a CNAME record pointing your domain to the tunnel.\n\n#### Step 5 — Run as a systemd service\n\n```bash\nsudo cloudflared service install\nsudo systemctl enable cloudflared\nsudo systemctl start cloudflared\n```\n\n#### Step 6 — Set up Cloudflare Access\n\n1. Go to the [Cloudflare Zero Trust dashboard](https://one.dash.cloudflare.com/)\n2. Navigate to **Access** → **Applications** → **Add an application**\n3. Select **Self-hosted** and enter your domain (`pa.example.com`)\n4. Create a policy — for example, allow specific email addresses:\n   - **Policy name:** `OpenClaw admins`\n   - **Action:** Allow\n   - **Include:** Emails — `you@example.com`\n5. Save the application\n\nNow anyone accessing `pa.example.com` must first authenticate through Cloudflare Access before reaching the OpenClaw dashboard.\n\n#### Step 7 — Update `openclaw.json`\n\nAdd your Cloudflare domain to the allowed origins:\n\n```json\n{\n  \"gateway\": {\n    \"controlUi\": {\n      \"allowedOrigins\": [\n        \"http://localhost:18789\",\n        \"http://127.0.0.1:18789\",\n        \"https://pa.example.com\"\n      ],\n      \"allowInsecureAuth\": true\n    }\n  }\n}\n```\n\n\u003e `allowInsecureAuth: true` is safe here because Cloudflare terminates TLS — traffic between `cloudflared` and your local gateway stays on `localhost`.\n\nMake sure `gateway.mode` is set to `\"local\"` — the gateway refuses to start without it:\n\n```json\n{\n  \"gateway\": {\n    \"mode\": \"local\",\n    \"bind\": \"lan\"\n  }\n}\n```\n\nRestart the gateway:\n\n```bash\ndocker compose restart openclaw-gateway\n```\n\n#### Step 8 — Approve the device pairing\n\nWhen you open the dashboard for the first time via Cloudflare, the gateway will show a **pairing request**. Approve it from the server:\n\n```bash\n# List pending pairing requests\ndocker compose exec openclaw-gateway node dist/index.js devices list\n\n# Approve the request\ndocker compose exec openclaw-gateway node dist/index.js devices approve \u003cREQUEST_ID\u003e\n```\n\nReplace `\u003cREQUEST_ID\u003e` with the ID shown in the list.\n\nOpen the dashboard at:\n\n```\nhttps://pa.example.com/#token=YOUR_GATEWAY_TOKEN\n```\n\n#### Troubleshooting Cloudflare setup\n\n**\"Gateway start blocked: set gateway.mode=local\"** — Add `\"mode\": \"local\"` to the `gateway` object in `openclaw.json`.\n\n**Gateway ignores bind setting** — Do not use `--bind` in the docker-compose `command`. Let `openclaw.json` handle it via `\"bind\": \"lan\"`. The `--bind` CLI flag overrides the config file and can cause conflicts.\n\n**Dashboard loads but pairing fails** — Make sure `trustedProxies` includes the Docker bridge subnet (`172.17.0.0/16`) and `allowInsecureAuth` is `true`. Then approve the device pairing as shown in Step 8.\n\n\u003c/details\u003e\n\n---\n\n## ⚙️ Managing Your Server\n\nCommon commands for managing your OpenClaw instance:\n\n| Action                    | Command                                                                            |\n| ------------------------- | ---------------------------------------------------------------------------------- |\n| 📋 View live logs         | `docker compose logs -f openclaw-gateway`                                        |\n| ⏹️ Stop the server      | `docker compose down`                                                            |\n| ▶️ Start the server     | `docker compose up -d`                                                           |\n| 🔄 Restart the server     | `docker compose restart openclaw-gateway`                                        |\n| 💻 Interactive TUI        | `docker compose exec openclaw-gateway node dist/index.js tui`                                       |\n| ⚙️ Change configuration | `docker compose exec openclaw-gateway node dist/index.js configure`                                 |\n| 🔨 Rebuild after updates  | `docker compose down \u0026\u0026 docker compose build --no-cache \u0026\u0026 docker compose up -d` |\n| 🔒 Run a security audit   | `docker compose exec openclaw-gateway node dist/index.js security audit --deep`                     |\n| 🩺 Run doctor check       | `docker compose exec openclaw-gateway node dist/index.js doctor --repair`                           |\n\n---\n\n## 🔐 Environment Variables\n\nYou can use `${VAR_NAME}` references in `openclaw.json` instead of hardcoding secrets like API keys, bot tokens and chat IDs. OpenClaw resolves these references at startup from environment variables.\n\n### Example\n\nInstead of hardcoding your Telegram bot token:\n\n```json\n{\n  \"channels\": {\n    \"telegram\": {\n      \"botToken\": \"123456:ABC-DEF...\"\n    }\n  }\n}\n```\n\nReference an environment variable:\n\n```json\n{\n  \"channels\": {\n    \"telegram\": {\n      \"botToken\": \"${TELEGRAM_BOT_TOKEN}\"\n    }\n  }\n}\n```\n\n### Where to put the `.env` file\n\nThis project uses **two** `.env` files with different purposes:\n\n| File | Read by | Purpose |\n| --- | --- | --- |\n| `./.env` (project root) | Docker Compose | Interpolates `${...}` variables in `docker-compose.yaml` |\n| `./data/config/.env` | OpenClaw | Resolves `${...}` references in `openclaw.json` |\n\nThe **project root** `.env` is created by `setup.sh` and feeds Docker Compose. It does **not** reach OpenClaw inside the container.\n\nTo use `${VAR}` references in `openclaw.json`, create a `.env` file in the **config directory**:\n\n```bash\n# Create the file\ncat \u003e ./data/config/.env \u003c\u003c 'EOF'\nTELEGRAM_BOT_TOKEN=123456:ABC-DEF...\nGATEWAY_TOKEN=your-gateway-token\nOPENAI_API=sk-...\nNOTION_API=secret_...\nEOF\n\n# Set ownership to the container's node user (uid 1000)\nchown 1000:1000 ./data/config/.env\n\n# Restrict permissions\nchmod 600 ./data/config/.env\n```\n\n\u003e [!IMPORTANT]\n\u003e The file **must** be owned by uid `1000:1000` (the `node` user inside the container). If it is owned by `root`, OpenClaw cannot read it and will fail with `MissingEnvVarError`.\n\nThen restart the gateway:\n\n```bash\ndocker compose restart openclaw-gateway\n```\n\n\u003e [!WARNING]\n\u003e **Known issue:** Commands like `doctor --fix`, `configure` and `update` can resolve `${VAR}` references back to **plaintext** and write the actual secrets into `openclaw.json`. After running these commands, check `openclaw.json` and restore any `${...}` references that were overwritten.\n\n---\n\n## 🔧 Troubleshooting\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\"Unknown model\" error\u003c/strong\u003e\u003c/summary\u003e\n\nIf you see `Unknown model: anthropic/claude-sonnet-4`, the configured model name is outdated. Update it:\n\n```bash\ndocker compose exec openclaw-gateway sed -i \\\n  's|anthropic/claude-sonnet-4|anthropic/claude-sonnet-4-5|g' \\\n  /home/node/.openclaw/openclaw.json\ndocker compose restart openclaw-gateway\n```\n\nAvailable Anthropic models:\n\n- `anthropic/claude-opus-4-5`\n- `anthropic/claude-sonnet-4-5`\n- `anthropic/claude-haiku-4-5`\n\n\u003e **Which model should I choose?** See [Choosing a Model](#-choosing-a-model) below for guidance.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eSkill installation fails (EACCES permission error)\u003c/strong\u003e\u003c/summary\u003e\n\nSome skills may fail to install during onboarding due to permissions. Fix it with:\n\n```bash\ndocker compose run --rm --user root openclaw-cli npm install -g clawhub\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\"Gateway start blocked: set gateway.mode=local\"\u003c/strong\u003e\u003c/summary\u003e\n\nThe gateway requires `gateway.mode` to be set in `openclaw.json`. Add it:\n\n```bash\ndocker compose exec openclaw-gateway sed -i \\\n  's|\"gateway\": {|\"gateway\": {\\n    \"mode\": \"local\",|' \\\n  /home/node/.openclaw/openclaw.json\ndocker compose restart openclaw-gateway\n```\n\nOr edit `./data/config/openclaw.json` directly and add `\"mode\": \"local\"` inside the `gateway` object.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eContainer won't start\u003c/strong\u003e\u003c/summary\u003e\n\nCheck if Docker is running:\n\n```bash\nsudo systemctl status docker\n```\n\nIf it's not active, start it:\n\n```bash\nsudo systemctl start docker\n```\n\nThen try again:\n\n```bash\ndocker compose up -d\n```\n\n\u003c/details\u003e\n\n---\n\n## 🔒 Security\n\n\u003e [!CAUTION]\n\u003e ⚠️ **OpenClaw has access to your files, messages and API keys.** Security researchers have identified vulnerabilities including SSRF bugs, path traversal, missing webhook authentication and malicious skills on the ClawHub marketplace. **Take security seriously — review the hardening measures below.**\n\nThis Docker setup includes several hardening measures out of the box:\n\n| Measure                               | What it does                                                                     |\n| ------------------------------------- | -------------------------------------------------------------------------------- |\n| 🔏**Read-only filesystem**      | The container filesystem is immutable — malware cannot modify application files |\n| 🚫**Dropped capabilities**      | All Linux capabilities are removed (`cap_drop: ALL`)                           |\n| ⬆️**No privilege escalation** | `no-new-privileges` prevents processes from gaining additional permissions     |\n| 📊**Resource limits**           | Memory, CPU, and PID limits prevent resource exhaustion and fork-bomb attacks    |\n| 🏠**Localhost binding**         | Ports are bound to `127.0.0.1` — the gateway is not exposed to the internet   |\n| 🔑**Token authentication**      | A 256-bit gateway token is required for all dashboard and API access             |\n| 🛡️**Auth rate limiting**      | Brute-force protection: 10 attempts per minute, 5-minute lockout                 |\n| 💓**Health checks**             | Docker automatically detects and restarts unhealthy containers                   |\n| 🌐**Isolated network**          | Containers run in a dedicated Docker network                                     |\n\n### 🛡️ Application-level hardening\n\nIn addition to Docker container isolation, the setup script applies these **application-level** security settings to `openclaw.json`:\n\n| Setting | Value | What it does |\n| --- | --- | --- |\n| `session.dmScope` | `\"per-channel-peer\"` | Each sender gets an isolated session — prevents cross-user context leakage |\n| `tools.deny` | `[\"sessions_spawn\", \"sessions_send\"]` | Blocks session hijacking tools |\n| `tools.exec.security` | `\"full\"` | Allows command execution (for custom scripts) |\n| `tools.fs.workspaceOnly` | `true` | Restricts file access to the workspace directory only |\n| `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork` | `false` | Blocks browser access to private/internal networks (SSRF protection) |\n| `logging.redactSensitive` | `\"tools\"` | Redacts tokens and secrets from log output |\n| `discovery.mdns.mode` | `\"off\"` | Disables mDNS broadcast (leaks hostname and install path) |\n\n\u003e [!CAUTION]\n\u003e ⚠️ **Command execution is enabled by default** (`tools.exec.security: \"full\"`). This allows the AI to run scripts and commands on your server. The bot **cannot**:\n\u003e\n\u003e - ❌ Spawn or hijack other sessions\n\u003e - ❌ Access files outside the workspace directory\n\u003e - ❌ Access your internal network via browser (SSRF protection)\n\u003e\n\u003e If you don't need command execution, set `tools.exec.security` to `\"deny\"` or use `\"allowlist\"` mode for a safer middle ground. See the [OpenClaw security docs](https://docs.openclaw.ai/gateway/security) for details.\n\n\u003cdetails\u003e\n\u003csummary\u003e🔓 \u003cstrong\u003eRelaxing tool restrictions (at your own risk)\u003c/strong\u003e\u003c/summary\u003e\n\nTo re-enable specific capabilities, edit `./data/config/openclaw.json`:\n\n**Allow browser automation** (needed for web search/scraping skills):\n\n```json\n{\n  \"browser\": {\n    \"ssrfPolicy\": { \"dangerouslyAllowPrivateNetwork\": false }\n  },\n  \"tools\": {\n    \"profile\": \"full\"\n  }\n}\n```\n\n**Allow command execution** (needed for code/shell skills):\n\n```json\n{\n  \"tools\": {\n    \"exec\": {\n      \"security\": \"ask\",\n      \"ask\": \"always\"\n    }\n  }\n}\n```\n\n**Allow filesystem writes** (needed for file management skills):\n\n```json\n{\n  \"tools\": {\n    \"fs\": { \"workspaceOnly\": true }\n  }\n}\n```\n\n**Allow custom scripts** (needed for email, automation or other custom integrations):\n\nIf you want the AI to run your own scripts (e.g. check email, query a database, send notifications), use `allowlist` mode with `safeBins` to restrict execution to trusted commands only.\n\n1. Create a scripts directory:\n\n```bash\nmkdir -p ./data/config/scripts\nchmod +x ./data/config/scripts/*.sh\n```\n\n1. Update `tools` in `./data/config/openclaw.json`:\n\n```json\n{\n  \"tools\": {\n    \"deny\": [\n      \"sessions_spawn\",\n      \"sessions_send\"\n    ],\n    \"exec\": {\n      \"security\": \"allowlist\",\n      \"safeBins\": [\"bash\"],\n      \"safeBinTrustedDirs\": [\"/home/node/.openclaw/scripts\"]\n    },\n    \"fs\": {\n      \"workspaceOnly\": true\n    }\n  }\n}\n```\n\n\u003e **What this does:**\n\u003e\n\u003e | Setting | Effect |\n\u003e | --- | --- |\n\u003e | `security: \"allowlist\"` | Only pre-approved commands can run (instead of everything or nothing) |\n\u003e | `safeBins: [\"bash\"]` | Allows `bash` as an interpreter for your scripts |\n\u003e | `safeBinTrustedDirs` | Only scripts in this directory can be executed |\n\u003e | Removed `group:runtime` from `deny` | Unblocks the exec tool (required for scripts to work) |\n\u003e | Removed `profile: \"messaging\"` | The messaging profile blocks exec entirely — remove it or change to `\"full\"` |\n\u003e\n\u003e **Security notes:**\n\u003e\n\u003e - Only place scripts you trust in the `scripts/` directory — the AI can execute anything in it\n\u003e - Keep `sessions_spawn` and `sessions_send` in the deny list to prevent the AI from creating new sessions\n\u003e - Keep `fs.workspaceOnly: true` to restrict file access\n\u003e - Review your scripts for command injection vulnerabilities (e.g. unsanitized user input passed to shell commands)\n\u003e - Use `security: \"allowlist\"` instead of `\"full\"` — `\"full\"` allows the AI to run **any** command on your server\n\nAfter any change, restart the gateway:\n\n```bash\ndocker compose restart openclaw-gateway\n```\n\n\u003e **Keep `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork: false`** even when relaxing other settings. This prevents the bot's browser from reaching internal services on your network (databases, admin panels, etc.).\n\n\u003c/details\u003e\n\n### 🩺 Run security checks\n\nRun these commands regularly and after every update:\n\n```bash\n# Detect and fix configuration issues\ndocker compose exec openclaw-gateway node dist/index.js doctor --repair\n\n# Deep security audit\ndocker compose exec openclaw-gateway node dist/index.js security audit --deep\n```\n\n### 🔑 Rotate your gateway token\n\nRotate your token periodically and immediately if you suspect it has been compromised:\n\n```bash\n# 1. Generate a new token\nNEW_TOKEN=$(openssl rand -hex 32)\n\n# 2. Update root .env (used by Docker Compose)\nsed -i \"s/^OPENCLAW_GATEWAY_TOKEN=.*/OPENCLAW_GATEWAY_TOKEN=${NEW_TOKEN}/\" .env\n\n# 3. Update data/config/.env (used by OpenClaw for ${GATEWAY_TOKEN} in openclaw.json)\nsed -i \"s/^GATEWAY_TOKEN=.*/GATEWAY_TOKEN=${NEW_TOKEN}/\" ./data/config/.env\n\n# 4. Restart\ndocker compose restart openclaw-gateway\n```\n\n\u003e [!NOTE]\n\u003e If your `openclaw.json` uses `\"${GATEWAY_TOKEN}\"` (recommended), you only need to update the `.env` files — not `openclaw.json` itself. See [Environment Variables](#-environment-variables) for details.\n\n### ⚠️ Skill marketplace safety\n\n\u003e [!WARNING]\n\u003e 🦠 **26% of agent skills** on public marketplaces contain at least one vulnerability. Malicious skills have been used to **exfiltrate data and distribute malware** ([Cisco](https://blogs.cisco.com/ai/personal-ai-agents-like-openclaw-are-a-security-nightmare), [Trend Micro](https://www.trendmicro.com/en_us/research/26/b/openclaw-skills-used-to-distribute-atomic-macos-stealer.html)). Never install skills without reviewing the source code first.\n\n- **Never install skills without reviewing their source code**\n- Only use skills from trusted authors\n- Monitor what skills are installed: check `./data/config/` for unexpected additions\n- Disable skills you don't actively use\n\n### 🌍 Remote access best practices\n\n- **Never bind the gateway to a public IP address** — keep it on `127.0.0.1`\n- Use **SSH tunnels** or **Tailscale** for remote access\n- If using a reverse proxy (Cloudflare Tunnel, nginx, Caddy), always terminate TLS at the proxy\n- See [Accessing the Dashboard](#️-accessing-the-dashboard) for reverse proxy configuration\n\n### 📚 Further reading\n\n| Source                                                                                                                      | Topic                                  |\n| --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |\n| [Aikido](https://www.aikido.dev/blog/why-trying-to-secure-openclaw-is-ridiculous)                                              | Security architecture analysis         |\n| [Microsoft](https://www.microsoft.com/en-us/security/blog/2026/02/19/running-openclaw-safely-identity-isolation-runtime-risk/) | Identity isolation and runtime risk    |\n| [Cisco](https://blogs.cisco.com/ai/personal-ai-agents-like-openclaw-are-a-security-nightmare)                                  | Skill marketplace risks                |\n| [Infosecurity Magazine](https://www.infosecurity-magazine.com/news/researchers-six-new-openclaw/)                              | Endor Labs: 6 new vulnerabilities      |\n| [Bitsight](https://www.bitsight.com/blog/openclaw-ai-security-risks-exposed-instances)                                         | Exposed instances in sensitive sectors |\n| [Trend Micro](https://www.trendmicro.com/en_us/research/26/b/openclaw-skills-used-to-distribute-atomic-macos-stealer.html)     | Atomic macOS Stealer via skills        |\n| [University of Toronto](https://security.utoronto.ca/advisories/openclaw-vulnerability-notification/)                          | CVE-2026-25253 advisory                |\n| [GBHackers](https://gbhackers.com/openclaw-2026-2-12-released/)                                                                | 40+ security fixes in v2026.2.12       |\n| [OpenClaw Docs](https://docs.openclaw.ai/gateway/security)                                                                     | Security configuration reference       |\n| [OpenClaw Docs](https://docs.openclaw.ai/gateway/doctor)                                                                       | Built-in config auditing               |\n| [OpenClaw Docs](https://docs.openclaw.ai/gateway/remote)                                                                       | Secure remote access                   |\n\n---\n\n## 🔄 Updating\n\n\u003e [!IMPORTANT]\n\u003e 🔄 **Keep your OpenClaw instance up to date.** Security patches are released frequently — version 2026.2.12 alone fixed over **40 security issues** ([GBHackers](https://gbhackers.com/openclaw-2026-2-12-released/)).\n\n### Step-by-step update\n\n\u003e **How it works:** The Dockerfile automatically fetches the latest stable OpenClaw release from npm during build (skipping beta/rc versions). A `--no-cache` rebuild is all you need to upgrade.\n\n```bash\n# 1. Back up your data\ncp -r ./data ./data-backup-$(date +%Y%m%d)\n\n# 2. Pull the latest changes to this repo\ngit pull origin main\n\n# 3. Rebuild the Docker image (fetches latest stable OpenClaw + Dockerfile changes)\ndocker compose build --no-cache\n\n# 4. Restart with the new image\ndocker compose down \u0026\u0026 docker compose up -d\n\n# 5. Run security checks\ndocker compose exec openclaw-gateway node dist/index.js doctor --repair\ndocker compose exec openclaw-gateway node dist/index.js security audit --deep\n\n# 6. Verify the gateway is healthy\ndocker compose logs -f openclaw-gateway\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e⚡ \u003cstrong\u003eQuick one-liner\u003c/strong\u003e (for experienced users)\u003c/summary\u003e\n\n```bash\ncp -r ./data ./data-backup-$(date +%Y%m%d) \u0026\u0026 git pull origin main \u0026\u0026 docker compose build --no-cache \u0026\u0026 docker compose down \u0026\u0026 docker compose up -d \u0026\u0026 docker compose exec openclaw-gateway node dist/index.js doctor --repair\n```\n\n\u003c/details\u003e\n\n### 📡 Staying informed\n\n- **Watch this repository** on GitHub to get notified of new releases\n- **Watch the upstream** [OpenClaw repository](https://github.com/openclaw/openclaw) for security advisories\n- Check the [OpenClaw changelog](https://docs.openclaw.ai) after each update\n\n---\n\n## 📦 Migrating to Hardened Setup\n\nIf you installed OpenClaw using an older version of this repository (before the security hardening), follow these steps to apply the new security features to your existing installation. This guide works whether you used `git clone` or manually uploaded the files.\n\n### What changed\n\nThe hardened setup adds:\n\n| Feature                      | Description                                                               |\n| ---------------------------- | ------------------------------------------------------------------------- |\n| 🔏 Read-only filesystem      | Container files cannot be modified at runtime                             |\n| 🚫 Dropped capabilities      | All Linux capabilities removed                                            |\n| ⬆️ No privilege escalation | Processes cannot gain new privileges                                      |\n| 📊 Resource limits           | Memory, CPU, and PID caps                                                 |\n| 💓 Health checks             | Auto-detect and restart unhealthy containers                              |\n| 🌐 Isolated network          | Dedicated Docker bridge network                                           |\n| 🎯 Narrower trusted proxies  | Dynamically detected Docker bridge subnet (defaults to `172.17.0.0/16`) |\n| 🛡️ Auth rate limiting      | Brute-force protection                                                    |\n| 🩺 Auto security auditing    | `doctor` and `audit` run during setup                                 |\n| 👤 Session isolation         | Each sender gets isolated context (`per-channel-peer`)                  |\n| 🔒 Tool restrictions         | Messaging-only profile, exec denied, filesystem restricted                |\n| 🌐 SSRF protection           | Browser blocked from private networks                                     |\n| 📝 Log redaction             | Tokens and secrets hidden from logs                                       |\n| 📡 mDNS disabled             | No network broadcast of hostname/path                                     |\n\n### Files changed\n\nThese files were modified or added in the hardened setup. If you uploaded files manually (without git), you need to update each of these:\n\n| File | Change |\n| --- | --- |\n| `docker-compose.yaml` | Added read-only FS, dropped capabilities, resource limits, healthcheck, isolated network, tmpfs mounts |\n| `Dockerfile` | Added `curl` (required for container health checks) |\n| `.dockerignore` | **New file** — prevents `.env` and `data/` from leaking into the Docker build |\n| `setup.sh` | Added token generation, config patching, security auditing |\n| `.env.example` | Added `OPENCLAW_ALLOW_INSECURE_AUTH` option |\n\n\u003e [!TIP]\n\u003e The easiest way to get all file changes at once — even if you didn't use `git clone` originally — is to initialize git in your existing directory. See step 2 (Option B) below.\n\n### Migration steps\n\n```bash\n# 1. Back up your data first\ncp -r ./data ./data-backup-$(date +%Y%m%d)\n\n# 2. Get the latest files\n#    Option A: If you used git clone\ngit pull origin main\n\n#    Option B: If you uploaded files manually, initialize git first:\n#    git init \u0026\u0026 git remote add origin https://github.com/MadeByAdem/openClaw-Docker.git\n#    git fetch origin\n#    mv Dockerfile docker-compose.yaml setup.sh /tmp/openclaw-backup/\n#    git checkout -b main origin/main\n\n# 3. Restrict .env file permissions\nchmod 600 .env\n\n# 4. (Recommended) Rotate your gateway token\nNEW_TOKEN=$(openssl rand -hex 32)\nsed -i \"s/^OPENCLAW_GATEWAY_TOKEN=.*/OPENCLAW_GATEWAY_TOKEN=${NEW_TOKEN}/\" .env\nDOCKER_SUBNET=$(docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2\u003e/dev/null || echo \"172.17.0.0/16\")\nOC_NEW_TOKEN=\"$NEW_TOKEN\" OC_DOCKER_SUBNET=\"$DOCKER_SUBNET\" python3 -c \"\nimport json, os\ntoken = os.environ['OC_NEW_TOKEN']\ndocker_subnet = os.environ['OC_DOCKER_SUBNET']\nwith open('./data/config/openclaw.json') as f: cfg = json.load(f)\n\n# Gateway auth + networking\ncfg['gateway']['auth']['token'] = token\ncfg['gateway']['auth']['rateLimit'] = {'maxAttempts': 10, 'windowMs': 60000, 'lockoutMs': 300000}\ncfg['gateway']['trustedProxies'] = [docker_subnet]\n\n# Session isolation\ncfg.setdefault('session', {})['dmScope'] = 'per-channel-peer'\n\n# Tool restrictions (messaging-only, no exec, workspace-only fs)\ntools = cfg.setdefault('tools', {})\ntools['profile'] = 'messaging'\ntools['deny'] = ['group:automation', 'group:runtime', 'sessions_spawn', 'sessions_send']\ntools.setdefault('exec', {})['security'] = 'deny'\ntools.setdefault('fs', {})['workspaceOnly'] = True\n\n# SSRF protection + logging + mDNS\ncfg.setdefault('browser', {}).setdefault('ssrfPolicy', {})['dangerouslyAllowPrivateNetwork'] = False\ncfg.setdefault('logging', {})['redactSensitive'] = 'tools'\ncfg.setdefault('discovery', {}).setdefault('mdns', {})['mode'] = 'off'\n\nwith open('./data/config/openclaw.json', 'w') as f: json.dump(cfg, f, indent=2)\n\"\n\n# 5. Rebuild the Docker image\ndocker compose build --no-cache\n\n# 6. Restart with hardened configuration\ndocker compose down \u0026\u0026 docker compose up -d\n\n# 7. Run security checks\ndocker compose exec openclaw-gateway node dist/index.js doctor --repair\ndocker compose exec openclaw-gateway node dist/index.js security audit --deep\n\n# 8. Verify the container is healthy\ndocker inspect --format='{{.State.Health.Status}}' openclaw-gateway\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e⚡ \u003cstrong\u003eMigration one-liner\u003c/strong\u003e\u003c/summary\u003e\n\n```bash\ncp -r ./data ./data-backup-$(date +%Y%m%d) \u0026\u0026 git pull origin main \u0026\u0026 chmod 600 .env \u0026\u0026 docker compose build --no-cache \u0026\u0026 docker compose down \u0026\u0026 docker compose up -d \u0026\u0026 docker compose exec openclaw-gateway node dist/index.js doctor --repair\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e🔧 \u003cstrong\u003eTroubleshooting the migration\u003c/strong\u003e\u003c/summary\u003e\n\n**Container won't start after migration** — The read-only filesystem may conflict with directories that need write access. The `tmpfs` mounts in `docker-compose.yaml` should handle this, but if you see permission errors, check that the `data/` directory is owned by uid 1000:\n\n```bash\nsudo chown -R 1000:1000 ./data\n```\n\n**\"Health check failed\"** — The health check expects the gateway to respond on port 18789. Give it up to 60 seconds after starting (the `start_period`). Check logs with `docker compose logs openclaw-gateway`.\n\n**Skills not working** — Some skills may need write access to directories not covered by `tmpfs`. If a specific skill fails, check its error logs and consider adding the required path as a `tmpfs` mount in `docker-compose.yaml`.\n\n\u003c/details\u003e\n\n---\n\n## 🤖 Choosing a Model\n\nYour choice of AI model has a direct impact on the quality of responses and your API costs.\n\n### Model comparison\n\n| Model                           | Strengths                                   | Cost   |\n| ------------------------------- | ------------------------------------------- | ------ |\n| `anthropic/claude-haiku-4-5`  | ⚡ Fast, lightweight, good for simple tasks | 💰     |\n| `anthropic/claude-sonnet-4-5` | ⚖️ Balanced: capable and cost-effective   | 💰💰   |\n| `anthropic/claude-opus-4-5`   | 🧠 Most capable, best for complex reasoning | 💰💰💰 |\n\n### Recommendations\n\n- **Start with Sonnet.** It offers the best balance between capability and cost for most use cases. This is a solid default for everyday conversations and tasks.\n- **Use Haiku for high-volume, simple tasks.** If your bot handles many short interactions (quick Q\u0026A, simple lookups), Haiku keeps costs low while still delivering good results.\n- **Reserve Opus for complex work.** Opus excels at multi-step reasoning, detailed analysis and creative tasks — but it costs significantly more per message. Only use it when you genuinely need the extra capability.\n\n\u003cdetails\u003e\n\u003csummary\u003e🔀 \u003cstrong\u003eAdvanced: use different models per task type\u003c/strong\u003e\u003c/summary\u003e\n\nYou can significantly reduce costs by routing tasks to the right model automatically. Instead of using a single model for everything, configure your assistant to:\n\n- **Use Haiku for routine tasks** — emails, calendar queries, simple Q\u0026A, summaries and other straightforward interactions.\n- **Use Sonnet for complex tasks** — code generation, debugging, technical analysis and multi-step reasoning.\n\nThis \"model routing\" approach can reduce your per-session costs by **60–70%**, because the majority of everyday interactions don't need the most capable (and most expensive) model.\n\nYou can set this up by defining task categories and model assignments in your OpenClaw configuration or via an `AGENTS.md` file in your workspace.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e💻 \u003cstrong\u003eAdvanced: use Claude Code CLI for code tasks\u003c/strong\u003e\u003c/summary\u003e\n\nIf you frequently ask your assistant to analyze or generate code, consider offloading those tasks to [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (Anthropic's CLI tool). Claude Code is optimized for coding workflows and can be more efficient than running code tasks through the chat interface, because it:\n\n- Sends only the relevant code context instead of the full conversation history\n- Uses targeted file reads instead of loading entire documents\n- Avoids unnecessary overhead from chat-based interaction\n\nYou can configure OpenClaw to prioritize Claude Code CLI for code-related skills.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e🔑 \u003cstrong\u003eAuthenticate via CLI (no API key needed)\u003c/strong\u003e\u003c/summary\u003e\n\nInstead of entering an API key during onboarding, you can authenticate using the **Claude Code CLI** (Anthropic) or **Gemini CLI** (Google). The CLI tools reuse your existing login session — no need to create or manage API keys.\n\n\u003e [!WARNING]\n\u003e The CLI-enabled setup documented here trades away the gateway container's read-only filesystem hardening. If you enable these in-container CLI flows, read the security notes in [CLI Setup](docs/AI-CLI-SETUP.md) first and only run this on a machine you trust for that risk level.\n\n**Supported CLIs:**\n\n| CLI | Provider | Package |\n| --- | --- | --- |\n| Claude Code CLI | Anthropic (Claude models) | `@anthropic-ai/claude-code` |\n| Gemini CLI | Google (Gemini models) | `@google/gemini-cli` |\n\nDuring onboarding, select your provider and choose **\"Reuse a local CLI login\"** as the auth method.\n\n\u003e All CLI tools are included in the Docker image by default. You only need to authenticate once — see [CLI Setup](docs/AI-CLI-SETUP.md) for step-by-step instructions.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e🔓 \u003cstrong\u003eOpenAI OAuth (use your paid subscription instead of API credits)\u003c/strong\u003e\u003c/summary\u003e\n\nIf you have a paid OpenAI account (ChatGPT Plus, Pro, or Team), you can connect via **OAuth** instead of an API key. This means usage is deducted from your subscription allowance rather than billed separately through the API — which can be significantly cheaper or even free depending on your plan.\n\nDuring onboarding, select **OpenAI** as your provider and choose the **OAuth** login method. OpenClaw will open a browser-based login flow. Once authenticated, your OpenAI models (like `gpt-4o`) will use your subscription quota.\n\n\u003e **Note:** OpenAI is currently the only provider tested with OAuth. Other providers use API keys.\n\u003e\n\u003e **Tip:** You can combine providers — for example, use OpenAI OAuth for GPT models and a separate API key for Claude or Gemini models. Configure fallback models in `./data/config/openclaw.json` under `agents.defaults.model`.\n\n\u003c/details\u003e\n\n### 💸 Keeping costs under control\n\n- **Monitor your API usage** through your provider's dashboard (e.g. [OpenAI Platform](https://platform.openai.com/), [Anthropic Console](https://console.anthropic.com/), [Google AI Studio](https://aistudio.google.com/)). Set spending alerts and budget limits before going live.\n- **Set a monthly budget limit** with your API provider to avoid surprises.\n- **Minimize context size.** Only load documents and files when they're actually needed.\n- **Longer conversations cost more.** Each message includes the full history — consider restarting conversations when the topic changes.\n- **Use text-to-speech sparingly.** Audio replies are generated only when the user sends a voice message (see [Voice \u0026 Audio](templates/skills/audio/SKILL.md)).\n- **Skills and tools add cost.** Browser automation and other skills generate extra API calls.\n- **Test in low-traffic environments first.** Test with one or two users before connecting a busy group chat.\n\n### Changing your model\n\n```bash\ndocker compose exec openclaw-gateway node dist/index.js configure\n```\n\nOr edit the configuration file directly at `./data/config/openclaw.json`.\n\n---\n\n## 🔍 Add-ons\n\nOptional guides for extending your OpenClaw instance with additional services:\n\n| Add-on | Description |\n| --- | --- |\n| 🔑 [CLI Setup](docs/AI-CLI-SETUP.md) | Set up Claude CLI, Gemini CLI, and GitHub CLI — authenticate without API keys, push code to GitHub |\n| 🔎 [SearXNG Setup](docs/SEARXNG-SETUP.md) | Add private, self-hosted web search (70+ engines including Google, Bing, DuckDuckGo) with optional darkweb search via Tor |\n| 🎙️ [Voice \u0026 Audio](templates/skills/audio/SKILL.md) | How voice messages work — local STT (faster-whisper) and TTS (edge-tts), voice selection, customization |\n| 🎭 [Multi-Agent Guide](docs/AGENTS-GUIDE.md) | Give your agent specialized roles that activate automatically — better output, consistent behavior, less repetition |\n| 🏗️ [Workspace Architecture](docs/WORKSPACE-ARCHITECTURE.md) | How workspace files are structured, what each file does, conventions to follow |\n| 🔧 [Skill Development](docs/SKILL-DEVELOPMENT.md) | How to create, structure, and maintain custom skills — includes template and checklist |\n\n---\n\n## 📁 File Overview\n\n| File                   | Description                                                                          |\n| ---------------------- | ------------------------------------------------------------------------------------ |\n| `docker-compose.yaml`  | 🐳 Defines the gateway and CLI services with security hardening                      |\n| `Dockerfile`           | 📦 Extends the official OpenClaw image with Chromium, audio tools and browser support |\n| `scripts/`             | 🎙 STT and TTS scripts (baked into the Docker image at build time)                    |\n| `.env.example`         | 🔑 Template for environment variables                                                |\n| `setup.sh`             | 🚀 Automated setup script with security auditing (run once)                          |\n| `personalize.sh`       | 🎨 Agent personalization wizard (run after setup)                                    |\n| `agents.sh`            | 🎭 Agent persona manager (init, list, add, remove personas)                         |\n| `.dockerignore`        | 🚫 Prevents secrets from leaking into the Docker build                               |\n| `templates/agents/`    | 🎭 Agent persona templates (developer, assistant, marketeer, blank)                  |\n| `templates/skills/`    | 🧩 Skill templates and examples (weather, audio, blank template)                     |\n| `docs/`                | 📖 Guides: workspace architecture, skill development, security, personalization, SearXNG |\n\n---\n\n## 💾 Data \u0026 Backups\n\nAll persistent data is stored in the `./data/` directory:\n\n```\ndata/\n├── config/          # OpenClaw configuration, API keys, memory\n├── config-cli/      # Minimal config for the CLI container (auto-created by setup.sh)\n└── workspace/       # Agent workspace\n    ├── skills/      # Custom skills (SKILL.md + scripts per skill)\n    ├── secrets/     # Credentials per skill (.env files, never committed)\n    ├── memory/      # Daily session logs (YYYY-MM-DD.md)\n    ├── files/       # Reference library (PDFs, exports)\n    ├── docs/        # Large docs (loaded on request only)\n    └── tmp/         # Working files, intermediate results\n```\n\n**To back up your instance**, simply copy the entire `data/` directory:\n\n```bash\ncp -r ./data ./data-backup-$(date +%Y%m%d)\n```\n\n**To restore**, stop the server, replace the `data/` directory with your backup, and start again.\n\n---\n\n## 📄 License\n\nThis project is licensed under the [MIT License](LICENSE) — free to use, modify and distribute.\n\n---\n\n\u003cp align=\"center\"\u003e\n  Made with ❤️ by \u003ca href=\"https://github.com/MadeByAdem\"\u003eMadeByAdem\u003c/a\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMade-By-Adem%2FopenClaw-Docker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMade-By-Adem%2FopenClaw-Docker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMade-By-Adem%2FopenClaw-Docker/lists"}