RunClawd is a curated Docker Compose preset repository for OpenClaw, providing an opinionated, production-oriented deployment.
Platform scope (based on the current installer and images):
- Host OS: Linux (multiple distros via
apt/dnf/yum/apk/pacman/zypper) - CPU arch:
amd64/arm64are explicitly handled in the Dockerfile for some bundled tools
- Root access: recommended install runs as root (
sudo bash get-runclawd.sh). - Network access: pulls Docker / container images, and uses Cloudflare Tunnel by default.
curl -fsSL https://get.runclawd.sh -o get-runclawd.sh
sudo bash get-runclawd.shInstaller flags:
sudo bash get-runclawd.sh --buildWhat the installer does (as implemented in get-runclawd.sh):
- Installs dependencies:
curl,git,ssh(via your system package manager:apt/dnf/yum/apk/pacman/zypper). - Installs Docker (if missing): via
https://get.docker.com. - Clones/updates this repo: into
/opt/runclawd. - Starts services: runs
docker compose up -din/opt/runclawd. - Prints access info: waits for logs and prints
Access Token,Basic Auth Password, and a publictrycloudflare.comURL.
If you're developing this repo locally (no cloning into /opt/runclawd, no root-required steps), run:
bash get-runclawd.sh --localTo force rebuilding the runclawd image before starting services:
bash get-runclawd.sh --local --buildBy default, cloudflared runs in quick tunnel mode and prints an ephemeral https://xxxx.trycloudflare.com URL.
If you want to use a named tunnel token, set CF_TUNNEL_TOKEN. The installer will start services using the docker-compose.tunnel.yaml override.
Optional:
SERVICE_FQDN_OPENCLAW: if set, the installer treatshttps://${SERVICE_FQDN_OPENCLAW}as the public URL and generatescloudflared/config.ymlto forward that hostname tohttp://caddy:80.
Example:
export CF_TUNNEL_TOKEN=...
export SERVICE_FQDN_OPENCLAW=openclaw.example.com
sudo --preserve-env=CF_TUNNEL_TOKEN,SERVICE_FQDN_OPENCLAW bash get-runclawd.shThis repo runs the following services (see docker-compose.yaml):
- OpenClaw Gateway:
runclawdcontainer (port18789inside the compose network) - Web terminal:
ttydinsiderunclawd(port7681) - Reverse proxy:
caddyroutes:/->runclawd:18789/term/*->runclawd:7681/openclaw/*->runclawd:7682
- Public access (optional by default):
cloudflaredcreates an ephemeralhttps://xxxx.trycloudflare.comtunnel - Docker API hardening:
docker-proxy(docker-socket-proxy) exposes only a limited set of Docker APIs torunclawd
Data persistence:
- Persistent volume:
openclaw-data:/data(contains OpenClaw state, configs, workspace, shell history, caches, etc.)
After installation, the installer prints URLs derived from the tunnel:
- Onboarding URL:
<tunnel_url>/openclaw/?arg=onboard
- Gateway dashboard:
<tunnel_url>/?token=<access_token>
- Web terminal:
<tunnel_url>/term/
Notes:
- All HTTP endpoints are protected by Caddy HTTP Basic Auth (including onboarding routes), username
runclawd, password printed by the installer.
Local access (from the machine running Docker):
- Gateway:
http://localhost:18789/?token=<token> - Web terminal:
http://localhost:7681/term/
The gateway token is generated on first boot and stored in /data/.openclaw/openclaw.json inside the runclawd container (generated by scripts/bootstrap.sh).
OpenClaw requires devices to be approved before they can access the gateway. The installer provides a link to do this, but you can also do it manually via the CLI or web terminal.
-
List devices to find the pending Request ID (UUID):
openclaw devices list
Output example:
Pending (1) ┌──────────────────────────────────────┬───────────────────────────────────... │ Request │ Device ... ├──────────────────────────────────────┼───────────────────────────────────... │ 62cd8691-b244-4e34-90e1-62b5530ef268 │ 0b874c0cb5c7ea23541cccd1034fc930a1... └──────────────────────────────────────┴───────────────────────────────────... -
Approve the device using the Request ID from the first column:
openclaw devices approve 62cd8691-b244-4e34-90e1-62b5530ef268
Output example:
Approved 0b874c0cb5c7ea23541cccd1034fc930a1dff0895fc42eedb1ab454060a7cff9
This compose preset reads API keys from environment variables (see docker-compose.yaml, e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, etc.).
Docker Compose automatically loads a .env file from the project directory. On the host:
- Path:
/opt/runclawd/.env
Then set the keys you actually use, for example:
OPENAI_API_KEY=...
ANTHROPIC_API_KEY=...
GEMINI_API_KEY=...Restart the stack after editing .env:
cd /opt/runclawd
docker compose up -d-
View logs
cd /opt/runclawd docker compose logs -f runclawd -
Stop / start
cd /opt/runclawd docker compose stop docker compose up -d -
Disable public tunnel (keep local-only access)
cd /opt/runclawd docker compose stop cloudflared -
Upgrade
Re-run the installer (it performs
git pull --rebaseand then starts services):curl -fsSL https://get.runclawd.sh -o get-runclawd.sh sudo bash get-runclawd.sh
-
Uninstall
cd /opt/runclawd docker compose down docker volume rm runclawd_openclaw-data sudo rm -rf /opt/runclawd
- Docker socket is not mounted directly into
runclawd. Instead it talks todocker-proxy(DOCKER_HOST=tcp://docker-proxy:2375), and only a limited set of APIs are enabled. - Caddyfile is mounted read-only:
./Caddyfile:/etc/caddy/Caddyfile:ro. - Access control:
- Gateway UI requires a token (
auth.mode=token, generated on first boot). - All HTTP endpoints (gateway + terminals) are protected by Caddy HTTP Basic Auth (
runclawd:<generated password>).
- Gateway UI requires a token (