Include full contents of all nested repositories

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 16:25:02 +01:00
parent 14ff8fd54c
commit 2401ed446f
7271 changed files with 1310112 additions and 6 deletions

View File

@@ -0,0 +1,208 @@
---
summary: "Automated, hardened OpenClaw installation with Ansible, Tailscale VPN, and firewall isolation"
read_when:
- You want automated server deployment with security hardening
- You need firewall-isolated setup with VPN access
- You're deploying to remote Debian/Ubuntu servers
title: "Ansible"
---
# Ansible Installation
The recommended way to deploy OpenClaw to production servers is via **[openclaw-ansible](https://github.com/openclaw/openclaw-ansible)** — an automated installer with security-first architecture.
## Quick Start
One-command install:
```bash
curl -fsSL https://raw.githubusercontent.com/openclaw/openclaw-ansible/main/install.sh | bash
```
> **📦 Full guide: [github.com/openclaw/openclaw-ansible](https://github.com/openclaw/openclaw-ansible)**
>
> The openclaw-ansible repo is the source of truth for Ansible deployment. This page is a quick overview.
## What You Get
- 🔒 **Firewall-first security**: UFW + Docker isolation (only SSH + Tailscale accessible)
- 🔐 **Tailscale VPN**: Secure remote access without exposing services publicly
- 🐳 **Docker**: Isolated sandbox containers, localhost-only bindings
- 🛡️ **Defense in depth**: 4-layer security architecture
- 🚀 **One-command setup**: Complete deployment in minutes
- 🔧 **Systemd integration**: Auto-start on boot with hardening
## Requirements
- **OS**: Debian 11+ or Ubuntu 20.04+
- **Access**: Root or sudo privileges
- **Network**: Internet connection for package installation
- **Ansible**: 2.14+ (installed automatically by quick-start script)
## What Gets Installed
The Ansible playbook installs and configures:
1. **Tailscale** (mesh VPN for secure remote access)
2. **UFW firewall** (SSH + Tailscale ports only)
3. **Docker CE + Compose V2** (for agent sandboxes)
4. **Node.js 22.x + pnpm** (runtime dependencies)
5. **OpenClaw** (host-based, not containerized)
6. **Systemd service** (auto-start with security hardening)
Note: The gateway runs **directly on the host** (not in Docker), but agent sandboxes use Docker for isolation. See [Sandboxing](/gateway/sandboxing) for details.
## Post-Install Setup
After installation completes, switch to the openclaw user:
```bash
sudo -i -u openclaw
```
The post-install script will guide you through:
1. **Onboarding wizard**: Configure OpenClaw settings
2. **Provider login**: Connect WhatsApp/Telegram/Discord/Signal
3. **Gateway testing**: Verify the installation
4. **Tailscale setup**: Connect to your VPN mesh
### Quick commands
```bash
# Check service status
sudo systemctl status openclaw
# View live logs
sudo journalctl -u openclaw -f
# Restart gateway
sudo systemctl restart openclaw
# Provider login (run as openclaw user)
sudo -i -u openclaw
openclaw channels login
```
## Security Architecture
### 4-Layer Defense
1. **Firewall (UFW)**: Only SSH (22) + Tailscale (41641/udp) exposed publicly
2. **VPN (Tailscale)**: Gateway accessible only via VPN mesh
3. **Docker Isolation**: DOCKER-USER iptables chain prevents external port exposure
4. **Systemd Hardening**: NoNewPrivileges, PrivateTmp, unprivileged user
### Verification
Test external attack surface:
```bash
nmap -p- YOUR_SERVER_IP
```
Should show **only port 22** (SSH) open. All other services (gateway, Docker) are locked down.
### Docker Availability
Docker is installed for **agent sandboxes** (isolated tool execution), not for running the gateway itself. The gateway binds to localhost only and is accessible via Tailscale VPN.
See [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) for sandbox configuration.
## Manual Installation
If you prefer manual control over the automation:
```bash
# 1. Install prerequisites
sudo apt update && sudo apt install -y ansible git
# 2. Clone repository
git clone https://github.com/openclaw/openclaw-ansible.git
cd openclaw-ansible
# 3. Install Ansible collections
ansible-galaxy collection install -r requirements.yml
# 4. Run playbook
./run-playbook.sh
# Or run directly (then manually execute /tmp/openclaw-setup.sh after)
# ansible-playbook playbook.yml --ask-become-pass
```
## Updating OpenClaw
The Ansible installer sets up OpenClaw for manual updates. See [Updating](/install/updating) for the standard update flow.
To re-run the Ansible playbook (e.g., for configuration changes):
```bash
cd openclaw-ansible
./run-playbook.sh
```
Note: This is idempotent and safe to run multiple times.
## Troubleshooting
### Firewall blocks my connection
If you're locked out:
- Ensure you can access via Tailscale VPN first
- SSH access (port 22) is always allowed
- The gateway is **only** accessible via Tailscale by design
### Service won't start
```bash
# Check logs
sudo journalctl -u openclaw -n 100
# Verify permissions
sudo ls -la /opt/openclaw
# Test manual start
sudo -i -u openclaw
cd ~/openclaw
pnpm start
```
### Docker sandbox issues
```bash
# Verify Docker is running
sudo systemctl status docker
# Check sandbox image
sudo docker images | grep openclaw-sandbox
# Build sandbox image if missing
cd /opt/openclaw/openclaw
sudo -u openclaw ./scripts/sandbox-setup.sh
```
### Provider login fails
Make sure you're running as the `openclaw` user:
```bash
sudo -i -u openclaw
openclaw channels login
```
## Advanced Configuration
For detailed security architecture and troubleshooting:
- [Security Architecture](https://github.com/openclaw/openclaw-ansible/blob/main/docs/security.md)
- [Technical Details](https://github.com/openclaw/openclaw-ansible/blob/main/docs/architecture.md)
- [Troubleshooting Guide](https://github.com/openclaw/openclaw-ansible/blob/main/docs/troubleshooting.md)
## Related
- [openclaw-ansible](https://github.com/openclaw/openclaw-ansible) — full deployment guide
- [Docker](/install/docker) — containerized gateway setup
- [Sandboxing](/gateway/sandboxing) — agent sandbox configuration
- [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) — per-agent isolation

View File

@@ -0,0 +1,59 @@
---
summary: "Bun workflow (experimental): installs and gotchas vs pnpm"
read_when:
- You want the fastest local dev loop (bun + watch)
- You hit Bun install/patch/lifecycle script issues
title: "Bun (Experimental)"
---
# Bun (experimental)
Goal: run this repo with **Bun** (optional, not recommended for WhatsApp/Telegram)
without diverging from pnpm workflows.
⚠️ **Not recommended for Gateway runtime** (WhatsApp/Telegram bugs). Use Node for production.
## Status
- Bun is an optional local runtime for running TypeScript directly (`bun run …`, `bun --watch …`).
- `pnpm` is the default for builds and remains fully supported (and used by some docs tooling).
- Bun cannot use `pnpm-lock.yaml` and will ignore it.
## Install
Default:
```sh
bun install
```
Note: `bun.lock`/`bun.lockb` are gitignored, so theres no repo churn either way. If you want _no lockfile writes_:
```sh
bun install --no-save
```
## Build / Test (Bun)
```sh
bun run build
bun run vitest run
```
## Bun lifecycle scripts (blocked by default)
Bun may block dependency lifecycle scripts unless explicitly trusted (`bun pm untrusted` / `bun pm trust`).
For this repo, the commonly blocked scripts are not required:
- `@whiskeysockets/baileys` `preinstall`: checks Node major >= 20 (we run Node 22+).
- `protobufjs` `postinstall`: emits warnings about incompatible version schemes (no build artifacts).
If you hit a real runtime issue that requires these scripts, trust them explicitly:
```sh
bun pm trust @whiskeysockets/baileys protobufjs
```
## Caveats
- Some scripts still hardcode pnpm (e.g. `docs:build`, `ui:*`, `protocol:check`). Run those via pnpm for now.

View File

@@ -0,0 +1,77 @@
---
summary: "Stable, beta, and dev channels: semantics, switching, and tagging"
read_when:
- You want to switch between stable/beta/dev
- You are tagging or publishing prereleases
title: "Development Channels"
---
# Development channels
Last updated: 2026-01-21
OpenClaw ships three update channels:
- **stable**: npm dist-tag `latest`.
- **beta**: npm dist-tag `beta` (builds under test).
- **dev**: moving head of `main` (git). npm dist-tag: `dev` (when published).
We ship builds to **beta**, test them, then **promote a vetted build to `latest`**
without changing the version number — dist-tags are the source of truth for npm installs.
## Switching channels
Git checkout:
```bash
openclaw update --channel stable
openclaw update --channel beta
openclaw update --channel dev
```
- `stable`/`beta` check out the latest matching tag (often the same tag).
- `dev` switches to `main` and rebases on the upstream.
npm/pnpm global install:
```bash
openclaw update --channel stable
openclaw update --channel beta
openclaw update --channel dev
```
This updates via the corresponding npm dist-tag (`latest`, `beta`, `dev`).
When you **explicitly** switch channels with `--channel`, OpenClaw also aligns
the install method:
- `dev` ensures a git checkout (default `~/openclaw`, override with `OPENCLAW_GIT_DIR`),
updates it, and installs the global CLI from that checkout.
- `stable`/`beta` installs from npm using the matching dist-tag.
Tip: if you want stable + dev in parallel, keep two clones and point your gateway at the stable one.
## Plugins and channels
When you switch channels with `openclaw update`, OpenClaw also syncs plugin sources:
- `dev` prefers bundled plugins from the git checkout.
- `stable` and `beta` restore npm-installed plugin packages.
## Tagging best practices
- Tag releases you want git checkouts to land on (`vYYYY.M.D` for stable, `vYYYY.M.D-beta.N` for beta).
- `vYYYY.M.D.beta.N` is also recognized for compatibility, but prefer `-beta.N`.
- Legacy `vYYYY.M.D-<patch>` tags are still recognized as stable (non-beta).
- Keep tags immutable: never move or reuse a tag.
- npm dist-tags remain the source of truth for npm installs:
- `latest` → stable
- `beta` → candidate build
- `dev` → main snapshot (optional)
## macOS app availability
Beta and dev builds may **not** include a macOS app release. Thats OK:
- The git tag and npm dist-tag can still be published.
- Call out “no macOS build for this beta” in release notes or changelog.

View File

@@ -0,0 +1,597 @@
---
summary: "Optional Docker-based setup and onboarding for OpenClaw"
read_when:
- You want a containerized gateway instead of local installs
- You are validating the Docker flow
title: "Docker"
---
# Docker (optional)
Docker is **optional**. Use it only if you want a containerized gateway or to validate the Docker flow.
## Is Docker right for me?
- **Yes**: you want an isolated, throwaway gateway environment or to run OpenClaw on a host without local installs.
- **No**: youre running on your own machine and just want the fastest dev loop. Use the normal install flow instead.
- **Sandboxing note**: agent sandboxing uses Docker too, but it does **not** require the full gateway to run in Docker. See [Sandboxing](/gateway/sandboxing).
This guide covers:
- Containerized Gateway (full OpenClaw in Docker)
- Per-session Agent Sandbox (host gateway + Docker-isolated agent tools)
Sandboxing details: [Sandboxing](/gateway/sandboxing)
## Requirements
- Docker Desktop (or Docker Engine) + Docker Compose v2
- At least 2 GB RAM for image build (`pnpm install` may be OOM-killed on 1 GB hosts with exit 137)
- Enough disk for images + logs
## Containerized Gateway (Docker Compose)
### Quick start (recommended)
From repo root:
```bash
./docker-setup.sh
```
This script:
- builds the gateway image
- runs the onboarding wizard
- prints optional provider setup hints
- starts the gateway via Docker Compose
- generates a gateway token and writes it to `.env`
Optional env vars:
- `OPENCLAW_DOCKER_APT_PACKAGES` — install extra apt packages during build
- `OPENCLAW_EXTRA_MOUNTS` — add extra host bind mounts
- `OPENCLAW_HOME_VOLUME` — persist `/home/node` in a named volume
After it finishes:
- Open `http://127.0.0.1:18789/` in your browser.
- Paste the token into the Control UI (Settings → token).
- Need the URL again? Run `docker compose run --rm openclaw-cli dashboard --no-open`.
It writes config/workspace on the host:
- `~/.openclaw/`
- `~/.openclaw/workspace`
Running on a VPS? See [Hetzner (Docker VPS)](/install/hetzner).
### Shell Helpers (optional)
For easier day-to-day Docker management, install `ClawDock`:
```bash
mkdir -p ~/.clawdock && curl -sL https://raw.githubusercontent.com/openclaw/openclaw/main/scripts/shell-helpers/clawdock-helpers.sh -o ~/.clawdock/clawdock-helpers.sh
```
**Add to your shell config (zsh):**
```bash
echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc && source ~/.zshrc
```
Then use `clawdock-start`, `clawdock-stop`, `clawdock-dashboard`, etc. Run `clawdock-help` for all commands.
See [`ClawDock` Helper README](https://github.com/openclaw/openclaw/blob/main/scripts/shell-helpers/README.md) for details.
### Manual flow (compose)
```bash
docker build -t openclaw:local -f Dockerfile .
docker compose run --rm openclaw-cli onboard
docker compose up -d openclaw-gateway
```
Note: run `docker compose ...` from the repo root. If you enabled
`OPENCLAW_EXTRA_MOUNTS` or `OPENCLAW_HOME_VOLUME`, the setup script writes
`docker-compose.extra.yml`; include it when running Compose elsewhere:
```bash
docker compose -f docker-compose.yml -f docker-compose.extra.yml <command>
```
### Control UI token + pairing (Docker)
If you see “unauthorized” or “disconnected (1008): pairing required”, fetch a
fresh dashboard link and approve the browser device:
```bash
docker compose run --rm openclaw-cli dashboard --no-open
docker compose run --rm openclaw-cli devices list
docker compose run --rm openclaw-cli devices approve <requestId>
```
More detail: [Dashboard](/web/dashboard), [Devices](/cli/devices).
### Extra mounts (optional)
If you want to mount additional host directories into the containers, set
`OPENCLAW_EXTRA_MOUNTS` before running `docker-setup.sh`. This accepts a
comma-separated list of Docker bind mounts and applies them to both
`openclaw-gateway` and `openclaw-cli` by generating `docker-compose.extra.yml`.
Example:
```bash
export OPENCLAW_EXTRA_MOUNTS="$HOME/.codex:/home/node/.codex:ro,$HOME/github:/home/node/github:rw"
./docker-setup.sh
```
Notes:
- Paths must be shared with Docker Desktop on macOS/Windows.
- Each entry must be `source:target[:options]` with no spaces, tabs, or newlines.
- If you edit `OPENCLAW_EXTRA_MOUNTS`, rerun `docker-setup.sh` to regenerate the
extra compose file.
- `docker-compose.extra.yml` is generated. Dont hand-edit it.
### Persist the entire container home (optional)
If you want `/home/node` to persist across container recreation, set a named
volume via `OPENCLAW_HOME_VOLUME`. This creates a Docker volume and mounts it at
`/home/node`, while keeping the standard config/workspace bind mounts. Use a
named volume here (not a bind path); for bind mounts, use
`OPENCLAW_EXTRA_MOUNTS`.
Example:
```bash
export OPENCLAW_HOME_VOLUME="openclaw_home"
./docker-setup.sh
```
You can combine this with extra mounts:
```bash
export OPENCLAW_HOME_VOLUME="openclaw_home"
export OPENCLAW_EXTRA_MOUNTS="$HOME/.codex:/home/node/.codex:ro,$HOME/github:/home/node/github:rw"
./docker-setup.sh
```
Notes:
- Named volumes must match `^[A-Za-z0-9][A-Za-z0-9_.-]*$`.
- If you change `OPENCLAW_HOME_VOLUME`, rerun `docker-setup.sh` to regenerate the
extra compose file.
- The named volume persists until removed with `docker volume rm <name>`.
### Install extra apt packages (optional)
If you need system packages inside the image (for example, build tools or media
libraries), set `OPENCLAW_DOCKER_APT_PACKAGES` before running `docker-setup.sh`.
This installs the packages during the image build, so they persist even if the
container is deleted.
Example:
```bash
export OPENCLAW_DOCKER_APT_PACKAGES="ffmpeg build-essential"
./docker-setup.sh
```
Notes:
- This accepts a space-separated list of apt package names.
- If you change `OPENCLAW_DOCKER_APT_PACKAGES`, rerun `docker-setup.sh` to rebuild
the image.
### Power-user / full-featured container (opt-in)
The default Docker image is **security-first** and runs as the non-root `node`
user. This keeps the attack surface small, but it means:
- no system package installs at runtime
- no Homebrew by default
- no bundled Chromium/Playwright browsers
If you want a more full-featured container, use these opt-in knobs:
1. **Persist `/home/node`** so browser downloads and tool caches survive:
```bash
export OPENCLAW_HOME_VOLUME="openclaw_home"
./docker-setup.sh
```
2. **Bake system deps into the image** (repeatable + persistent):
```bash
export OPENCLAW_DOCKER_APT_PACKAGES="git curl jq"
./docker-setup.sh
```
3. **Install Playwright browsers without `npx`** (avoids npm override conflicts):
```bash
docker compose run --rm openclaw-cli \
node /app/node_modules/playwright-core/cli.js install chromium
```
If you need Playwright to install system deps, rebuild the image with
`OPENCLAW_DOCKER_APT_PACKAGES` instead of using `--with-deps` at runtime.
4. **Persist Playwright browser downloads**:
- Set `PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright` in
`docker-compose.yml`.
- Ensure `/home/node` persists via `OPENCLAW_HOME_VOLUME`, or mount
`/home/node/.cache/ms-playwright` via `OPENCLAW_EXTRA_MOUNTS`.
### Permissions + EACCES
The image runs as `node` (uid 1000). If you see permission errors on
`/home/node/.openclaw`, make sure your host bind mounts are owned by uid 1000.
Example (Linux host):
```bash
sudo chown -R 1000:1000 /path/to/openclaw-config /path/to/openclaw-workspace
```
If you choose to run as root for convenience, you accept the security tradeoff.
### Faster rebuilds (recommended)
To speed up rebuilds, order your Dockerfile so dependency layers are cached.
This avoids re-running `pnpm install` unless lockfiles change:
```dockerfile
FROM node:22-bookworm
# Install Bun (required for build scripts)
RUN curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:${PATH}"
RUN corepack enable
WORKDIR /app
# Cache dependencies unless package metadata changes
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY scripts ./scripts
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
RUN pnpm ui:install
RUN pnpm ui:build
ENV NODE_ENV=production
CMD ["node","dist/index.js"]
```
### Channel setup (optional)
Use the CLI container to configure channels, then restart the gateway if needed.
WhatsApp (QR):
```bash
docker compose run --rm openclaw-cli channels login
```
Telegram (bot token):
```bash
docker compose run --rm openclaw-cli channels add --channel telegram --token "<token>"
```
Discord (bot token):
```bash
docker compose run --rm openclaw-cli channels add --channel discord --token "<token>"
```
Docs: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord](/channels/discord)
### OpenAI Codex OAuth (headless Docker)
If you pick OpenAI Codex OAuth in the wizard, it opens a browser URL and tries
to capture a callback on `http://127.0.0.1:1455/auth/callback`. In Docker or
headless setups that callback can show a browser error. Copy the full redirect
URL you land on and paste it back into the wizard to finish auth.
### Health check
```bash
docker compose exec openclaw-gateway node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN"
```
### E2E smoke test (Docker)
```bash
scripts/e2e/onboard-docker.sh
```
### QR import smoke test (Docker)
```bash
pnpm test:docker:qr
```
### Notes
- Gateway bind defaults to `lan` for container use.
- Dockerfile CMD uses `--allow-unconfigured`; mounted config with `gateway.mode` not `local` will still start. Override CMD to enforce the guard.
- The gateway container is the source of truth for sessions (`~/.openclaw/agents/<agentId>/sessions/`).
## Agent Sandbox (host gateway + Docker tools)
Deep dive: [Sandboxing](/gateway/sandboxing)
### What it does
When `agents.defaults.sandbox` is enabled, **non-main sessions** run tools inside a Docker
container. The gateway stays on your host, but the tool execution is isolated:
- scope: `"agent"` by default (one container + workspace per agent)
- scope: `"session"` for per-session isolation
- per-scope workspace folder mounted at `/workspace`
- optional agent workspace access (`agents.defaults.sandbox.workspaceAccess`)
- allow/deny tool policy (deny wins)
- inbound media is copied into the active sandbox workspace (`media/inbound/*`) so tools can read it (with `workspaceAccess: "rw"`, this lands in the agent workspace)
Warning: `scope: "shared"` disables cross-session isolation. All sessions share
one container and one workspace.
### Per-agent sandbox profiles (multi-agent)
If you use multi-agent routing, each agent can override sandbox + tool settings:
`agents.list[].sandbox` and `agents.list[].tools` (plus `agents.list[].tools.sandbox.tools`). This lets you run
mixed access levels in one gateway:
- Full access (personal agent)
- Read-only tools + read-only workspace (family/work agent)
- No filesystem/shell tools (public agent)
See [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) for examples,
precedence, and troubleshooting.
### Default behavior
- Image: `openclaw-sandbox:bookworm-slim`
- One container per agent
- Agent workspace access: `workspaceAccess: "none"` (default) uses `~/.openclaw/sandboxes`
- `"ro"` keeps the sandbox workspace at `/workspace` and mounts the agent workspace read-only at `/agent` (disables `write`/`edit`/`apply_patch`)
- `"rw"` mounts the agent workspace read/write at `/workspace`
- Auto-prune: idle > 24h OR age > 7d
- Network: `none` by default (explicitly opt-in if you need egress)
- `host` is blocked.
- `container:<id>` is blocked by default (namespace-join risk).
- Default allow: `exec`, `process`, `read`, `write`, `edit`, `sessions_list`, `sessions_history`, `sessions_send`, `sessions_spawn`, `session_status`
- Default deny: `browser`, `canvas`, `nodes`, `cron`, `discord`, `gateway`
### Enable sandboxing
If you plan to install packages in `setupCommand`, note:
- Default `docker.network` is `"none"` (no egress).
- `docker.network: "host"` is blocked.
- `docker.network: "container:<id>"` is blocked by default.
- Break-glass override: `agents.defaults.sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true`.
- `readOnlyRoot: true` blocks package installs.
- `user` must be root for `apt-get` (omit `user` or set `user: "0:0"`).
OpenClaw auto-recreates containers when `setupCommand` (or docker config) changes
unless the container was **recently used** (within ~5 minutes). Hot containers
log a warning with the exact `openclaw sandbox recreate ...` command.
```json5
{
agents: {
defaults: {
sandbox: {
mode: "non-main", // off | non-main | all
scope: "agent", // session | agent | shared (agent is default)
workspaceAccess: "none", // none | ro | rw
workspaceRoot: "~/.openclaw/sandboxes",
docker: {
image: "openclaw-sandbox:bookworm-slim",
workdir: "/workspace",
readOnlyRoot: true,
tmpfs: ["/tmp", "/var/tmp", "/run"],
network: "none",
user: "1000:1000",
capDrop: ["ALL"],
env: { LANG: "C.UTF-8" },
setupCommand: "apt-get update && apt-get install -y git curl jq",
pidsLimit: 256,
memory: "1g",
memorySwap: "2g",
cpus: 1,
ulimits: {
nofile: { soft: 1024, hard: 2048 },
nproc: 256,
},
seccompProfile: "/path/to/seccomp.json",
apparmorProfile: "openclaw-sandbox",
dns: ["1.1.1.1", "8.8.8.8"],
extraHosts: ["internal.service:10.0.0.5"],
},
prune: {
idleHours: 24, // 0 disables idle pruning
maxAgeDays: 7, // 0 disables max-age pruning
},
},
},
},
tools: {
sandbox: {
tools: {
allow: [
"exec",
"process",
"read",
"write",
"edit",
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"session_status",
],
deny: ["browser", "canvas", "nodes", "cron", "discord", "gateway"],
},
},
},
}
```
Hardening knobs live under `agents.defaults.sandbox.docker`:
`network`, `user`, `pidsLimit`, `memory`, `memorySwap`, `cpus`, `ulimits`,
`seccompProfile`, `apparmorProfile`, `dns`, `extraHosts`,
`dangerouslyAllowContainerNamespaceJoin` (break-glass only).
Multi-agent: override `agents.defaults.sandbox.{docker,browser,prune}.*` per agent via `agents.list[].sandbox.{docker,browser,prune}.*`
(ignored when `agents.defaults.sandbox.scope` / `agents.list[].sandbox.scope` is `"shared"`).
### Build the default sandbox image
```bash
scripts/sandbox-setup.sh
```
This builds `openclaw-sandbox:bookworm-slim` using `Dockerfile.sandbox`.
### Sandbox common image (optional)
If you want a sandbox image with common build tooling (Node, Go, Rust, etc.), build the common image:
```bash
scripts/sandbox-common-setup.sh
```
This builds `openclaw-sandbox-common:bookworm-slim`. To use it:
```json5
{
agents: {
defaults: {
sandbox: { docker: { image: "openclaw-sandbox-common:bookworm-slim" } },
},
},
}
```
### Sandbox browser image
To run the browser tool inside the sandbox, build the browser image:
```bash
scripts/sandbox-browser-setup.sh
```
This builds `openclaw-sandbox-browser:bookworm-slim` using
`Dockerfile.sandbox-browser`. The container runs Chromium with CDP enabled and
an optional noVNC observer (headful via Xvfb).
Notes:
- Headful (Xvfb) reduces bot blocking vs headless.
- Headless can still be used by setting `agents.defaults.sandbox.browser.headless=true`.
- No full desktop environment (GNOME) is needed; Xvfb provides the display.
- Browser containers default to a dedicated Docker network (`openclaw-sandbox-browser`) instead of global `bridge`.
- Optional `agents.defaults.sandbox.browser.cdpSourceRange` restricts container-edge CDP ingress by CIDR (for example `172.21.0.1/32`).
- noVNC observer access is password-protected by default; OpenClaw provides a short-lived observer token URL instead of sharing the raw password in the URL.
Use config:
```json5
{
agents: {
defaults: {
sandbox: {
browser: { enabled: true },
},
},
},
}
```
Custom browser image:
```json5
{
agents: {
defaults: {
sandbox: { browser: { image: "my-openclaw-browser" } },
},
},
}
```
When enabled, the agent receives:
- a sandbox browser control URL (for the `browser` tool)
- a noVNC URL (if enabled and headless=false)
Remember: if you use an allowlist for tools, add `browser` (and remove it from
deny) or the tool remains blocked.
Prune rules (`agents.defaults.sandbox.prune`) apply to browser containers too.
### Custom sandbox image
Build your own image and point config to it:
```bash
docker build -t my-openclaw-sbx -f Dockerfile.sandbox .
```
```json5
{
agents: {
defaults: {
sandbox: { docker: { image: "my-openclaw-sbx" } },
},
},
}
```
### Tool policy (allow/deny)
- `deny` wins over `allow`.
- If `allow` is empty: all tools (except deny) are available.
- If `allow` is non-empty: only tools in `allow` are available (minus deny).
### Pruning strategy
Two knobs:
- `prune.idleHours`: remove containers not used in X hours (0 = disable)
- `prune.maxAgeDays`: remove containers older than X days (0 = disable)
Example:
- Keep busy sessions but cap lifetime:
`idleHours: 24`, `maxAgeDays: 7`
- Never prune:
`idleHours: 0`, `maxAgeDays: 0`
### Security notes
- Hard wall only applies to **tools** (exec/read/write/edit/apply_patch).
- Host-only tools like browser/camera/canvas are blocked by default.
- Allowing `browser` in sandbox **breaks isolation** (browser runs on host).
## Troubleshooting
- Image missing: build with [`scripts/sandbox-setup.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/sandbox-setup.sh) or set `agents.defaults.sandbox.docker.image`.
- Container not running: it will auto-create per session on demand.
- Permission errors in sandbox: set `docker.user` to a UID:GID that matches your
mounted workspace ownership (or chown the workspace folder).
- Custom tools not found: OpenClaw runs commands with `sh -lc` (login shell), which
sources `/etc/profile` and may reset PATH. Set `docker.env.PATH` to prepend your
custom tool paths (e.g., `/custom/bin:/usr/local/share/npm-global/bin`), or add
a script under `/etc/profile.d/` in your Dockerfile.

View File

@@ -0,0 +1,126 @@
---
summary: "Run OpenClaw Gateway on exe.dev (VM + HTTPS proxy) for remote access"
read_when:
- You want a cheap always-on Linux host for the Gateway
- You want remote Control UI access without running your own VPS
title: "exe.dev"
---
# exe.dev
Goal: OpenClaw Gateway running on an exe.dev VM, reachable from your laptop via: `https://<vm-name>.exe.xyz`
This page assumes exe.dev's default **exeuntu** image. If you picked a different distro, map packages accordingly.
## Beginner quick path
1. [https://exe.new/openclaw](https://exe.new/openclaw)
2. Fill in your auth key/token as needed
3. Click on "Agent" next to your VM, and wait...
4. ???
5. Profit
## What you need
- exe.dev account
- `ssh exe.dev` access to [exe.dev](https://exe.dev) virtual machines (optional)
## Automated Install with Shelley
Shelley, [exe.dev](https://exe.dev)'s agent, can install OpenClaw instantly with our
prompt. The prompt used is as below:
```
Set up OpenClaw (https://docs.openclaw.ai/install) on this VM. Use the non-interactive and accept-risk flags for openclaw onboarding. Add the supplied auth or token as needed. Configure nginx to forward from the default port 18789 to the root location on the default enabled site config, making sure to enable Websocket support. Pairing is done by "openclaw devices list" and "openclaw devices approve <request id>". Make sure the dashboard shows that OpenClaw's health is OK. exe.dev handles forwarding from port 8000 to port 80/443 and HTTPS for us, so the final "reachable" should be <vm-name>.exe.xyz, without port specification.
```
## Manual installation
## 1) Create the VM
From your device:
```bash
ssh exe.dev new
```
Then connect:
```bash
ssh <vm-name>.exe.xyz
```
Tip: keep this VM **stateful**. OpenClaw stores state under `~/.openclaw/` and `~/.openclaw/workspace/`.
## 2) Install prerequisites (on the VM)
```bash
sudo apt-get update
sudo apt-get install -y git curl jq ca-certificates openssl
```
## 3) Install OpenClaw
Run the OpenClaw install script:
```bash
curl -fsSL https://openclaw.ai/install.sh | bash
```
## 4) Setup nginx to proxy OpenClaw to port 8000
Edit `/etc/nginx/sites-enabled/default` with
```
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 8000;
listen [::]:8000;
server_name _;
location / {
proxy_pass http://127.0.0.1:18789;
proxy_http_version 1.1;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Standard proxy headers
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;
# Timeout settings for long-lived connections
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
}
```
## 5) Access OpenClaw and grant privileges
Access `https://<vm-name>.exe.xyz/` (see the Control UI output from onboarding). If it prompts for auth, paste the
token from `gateway.auth.token` on the VM (retrieve with `openclaw config get gateway.auth.token`, or generate one
with `openclaw doctor --generate-gateway-token`). Approve devices with `openclaw devices list` and
`openclaw devices approve <requestId>`. When in doubt, use Shelley from your browser!
## Remote Access
Remote access is handled by [exe.dev](https://exe.dev)'s authentication. By
default, HTTP traffic from port 8000 is forwarded to `https://<vm-name>.exe.xyz`
with email auth.
## Updating
```bash
npm i -g openclaw@latest
openclaw doctor
openclaw gateway restart
openclaw health
```
Guide: [Updating](/install/updating)

View File

@@ -0,0 +1,490 @@
---
title: Fly.io
description: Deploy OpenClaw on Fly.io
summary: "Step-by-step Fly.io deployment for OpenClaw with persistent storage and HTTPS"
read_when:
- Deploying OpenClaw on Fly.io
- Setting up Fly volumes, secrets, and first-run config
---
# Fly.io Deployment
**Goal:** OpenClaw Gateway running on a [Fly.io](https://fly.io) machine with persistent storage, automatic HTTPS, and Discord/channel access.
## What you need
- [flyctl CLI](https://fly.io/docs/hands-on/install-flyctl/) installed
- Fly.io account (free tier works)
- Model auth: Anthropic API key (or other provider keys)
- Channel credentials: Discord bot token, Telegram token, etc.
## Beginner quick path
1. Clone repo → customize `fly.toml`
2. Create app + volume → set secrets
3. Deploy with `fly deploy`
4. SSH in to create config or use Control UI
## 1) Create the Fly app
```bash
# Clone the repo
git clone https://github.com/openclaw/openclaw.git
cd openclaw
# Create a new Fly app (pick your own name)
fly apps create my-openclaw
# Create a persistent volume (1GB is usually enough)
fly volumes create openclaw_data --size 1 --region iad
```
**Tip:** Choose a region close to you. Common options: `lhr` (London), `iad` (Virginia), `sjc` (San Jose).
## 2) Configure fly.toml
Edit `fly.toml` to match your app name and requirements.
**Security note:** The default config exposes a public URL. For a hardened deployment with no public IP, see [Private Deployment](#private-deployment-hardened) or use `fly.private.toml`.
```toml
app = "my-openclaw" # Your app name
primary_region = "iad"
[build]
dockerfile = "Dockerfile"
[env]
NODE_ENV = "production"
OPENCLAW_PREFER_PNPM = "1"
OPENCLAW_STATE_DIR = "/data"
NODE_OPTIONS = "--max-old-space-size=1536"
[processes]
app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan"
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1
processes = ["app"]
[[vm]]
size = "shared-cpu-2x"
memory = "2048mb"
[mounts]
source = "openclaw_data"
destination = "/data"
```
**Key settings:**
| Setting | Why |
| ------------------------------ | --------------------------------------------------------------------------- |
| `--bind lan` | Binds to `0.0.0.0` so Fly's proxy can reach the gateway |
| `--allow-unconfigured` | Starts without a config file (you'll create one after) |
| `internal_port = 3000` | Must match `--port 3000` (or `OPENCLAW_GATEWAY_PORT`) for Fly health checks |
| `memory = "2048mb"` | 512MB is too small; 2GB recommended |
| `OPENCLAW_STATE_DIR = "/data"` | Persists state on the volume |
## 3) Set secrets
```bash
# Required: Gateway token (for non-loopback binding)
fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)
# Model provider API keys
fly secrets set ANTHROPIC_API_KEY=sk-ant-...
# Optional: Other providers
fly secrets set OPENAI_API_KEY=sk-...
fly secrets set GOOGLE_API_KEY=...
# Channel tokens
fly secrets set DISCORD_BOT_TOKEN=MTQ...
```
**Notes:**
- Non-loopback binds (`--bind lan`) require `OPENCLAW_GATEWAY_TOKEN` for security.
- Treat these tokens like passwords.
- **Prefer env vars over config file** for all API keys and tokens. This keeps secrets out of `openclaw.json` where they could be accidentally exposed or logged.
## 4) Deploy
```bash
fly deploy
```
First deploy builds the Docker image (~2-3 minutes). Subsequent deploys are faster.
After deployment, verify:
```bash
fly status
fly logs
```
You should see:
```
[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
[discord] logged in to discord as xxx
```
## 5) Create config file
SSH into the machine to create a proper config:
```bash
fly ssh console
```
Create the config directory and file:
```bash
mkdir -p /data
cat > /data/openclaw.json << 'EOF'
{
"agents": {
"defaults": {
"model": {
"primary": "anthropic/claude-opus-4-6",
"fallbacks": ["anthropic/claude-sonnet-4-5", "openai/gpt-4o"]
},
"maxConcurrent": 4
},
"list": [
{
"id": "main",
"default": true
}
]
},
"auth": {
"profiles": {
"anthropic:default": { "mode": "token", "provider": "anthropic" },
"openai:default": { "mode": "token", "provider": "openai" }
}
},
"bindings": [
{
"agentId": "main",
"match": { "channel": "discord" }
}
],
"channels": {
"discord": {
"enabled": true,
"groupPolicy": "allowlist",
"guilds": {
"YOUR_GUILD_ID": {
"channels": { "general": { "allow": true } },
"requireMention": false
}
}
}
},
"gateway": {
"mode": "local",
"bind": "auto"
},
"meta": {
"lastTouchedVersion": "2026.1.29"
}
}
EOF
```
**Note:** With `OPENCLAW_STATE_DIR=/data`, the config path is `/data/openclaw.json`.
**Note:** The Discord token can come from either:
- Environment variable: `DISCORD_BOT_TOKEN` (recommended for secrets)
- Config file: `channels.discord.token`
If using env var, no need to add token to config. The gateway reads `DISCORD_BOT_TOKEN` automatically.
Restart to apply:
```bash
exit
fly machine restart <machine-id>
```
## 6) Access the Gateway
### Control UI
Open in browser:
```bash
fly open
```
Or visit `https://my-openclaw.fly.dev/`
Paste your gateway token (the one from `OPENCLAW_GATEWAY_TOKEN`) to authenticate.
### Logs
```bash
fly logs # Live logs
fly logs --no-tail # Recent logs
```
### SSH Console
```bash
fly ssh console
```
## Troubleshooting
### "App is not listening on expected address"
The gateway is binding to `127.0.0.1` instead of `0.0.0.0`.
**Fix:** Add `--bind lan` to your process command in `fly.toml`.
### Health checks failing / connection refused
Fly can't reach the gateway on the configured port.
**Fix:** Ensure `internal_port` matches the gateway port (set `--port 3000` or `OPENCLAW_GATEWAY_PORT=3000`).
### OOM / Memory Issues
Container keeps restarting or getting killed. Signs: `SIGABRT`, `v8::internal::Runtime_AllocateInYoungGeneration`, or silent restarts.
**Fix:** Increase memory in `fly.toml`:
```toml
[[vm]]
memory = "2048mb"
```
Or update an existing machine:
```bash
fly machine update <machine-id> --vm-memory 2048 -y
```
**Note:** 512MB is too small. 1GB may work but can OOM under load or with verbose logging. **2GB is recommended.**
### Gateway Lock Issues
Gateway refuses to start with "already running" errors.
This happens when the container restarts but the PID lock file persists on the volume.
**Fix:** Delete the lock file:
```bash
fly ssh console --command "rm -f /data/gateway.*.lock"
fly machine restart <machine-id>
```
The lock file is at `/data/gateway.*.lock` (not in a subdirectory).
### Config Not Being Read
If using `--allow-unconfigured`, the gateway creates a minimal config. Your custom config at `/data/openclaw.json` should be read on restart.
Verify the config exists:
```bash
fly ssh console --command "cat /data/openclaw.json"
```
### Writing Config via SSH
The `fly ssh console -C` command doesn't support shell redirection. To write a config file:
```bash
# Use echo + tee (pipe from local to remote)
echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json"
# Or use sftp
fly sftp shell
> put /local/path/config.json /data/openclaw.json
```
**Note:** `fly sftp` may fail if the file already exists. Delete first:
```bash
fly ssh console --command "rm /data/openclaw.json"
```
### State Not Persisting
If you lose credentials or sessions after a restart, the state dir is writing to the container filesystem.
**Fix:** Ensure `OPENCLAW_STATE_DIR=/data` is set in `fly.toml` and redeploy.
## Updates
```bash
# Pull latest changes
git pull
# Redeploy
fly deploy
# Check health
fly status
fly logs
```
### Updating Machine Command
If you need to change the startup command without a full redeploy:
```bash
# Get machine ID
fly machines list
# Update command
fly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y
# Or with memory increase
fly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -y
```
**Note:** After `fly deploy`, the machine command may reset to what's in `fly.toml`. If you made manual changes, re-apply them after deploy.
## Private Deployment (Hardened)
By default, Fly allocates public IPs, making your gateway accessible at `https://your-app.fly.dev`. This is convenient but means your deployment is discoverable by internet scanners (Shodan, Censys, etc.).
For a hardened deployment with **no public exposure**, use the private template.
### When to use private deployment
- You only make **outbound** calls/messages (no inbound webhooks)
- You use **ngrok or Tailscale** tunnels for any webhook callbacks
- You access the gateway via **SSH, proxy, or WireGuard** instead of browser
- You want the deployment **hidden from internet scanners**
### Setup
Use `fly.private.toml` instead of the standard config:
```bash
# Deploy with private config
fly deploy -c fly.private.toml
```
Or convert an existing deployment:
```bash
# List current IPs
fly ips list -a my-openclaw
# Release public IPs
fly ips release <public-ipv4> -a my-openclaw
fly ips release <public-ipv6> -a my-openclaw
# Switch to private config so future deploys don't re-allocate public IPs
# (remove [http_service] or deploy with the private template)
fly deploy -c fly.private.toml
# Allocate private-only IPv6
fly ips allocate-v6 --private -a my-openclaw
```
After this, `fly ips list` should show only a `private` type IP:
```
VERSION IP TYPE REGION
v6 fdaa:x:x:x:x::x private global
```
### Accessing a private deployment
Since there's no public URL, use one of these methods:
**Option 1: Local proxy (simplest)**
```bash
# Forward local port 3000 to the app
fly proxy 3000:3000 -a my-openclaw
# Then open http://localhost:3000 in browser
```
**Option 2: WireGuard VPN**
```bash
# Create WireGuard config (one-time)
fly wireguard create
# Import to WireGuard client, then access via internal IPv6
# Example: http://[fdaa:x:x:x:x::x]:3000
```
**Option 3: SSH only**
```bash
fly ssh console -a my-openclaw
```
### Webhooks with private deployment
If you need webhook callbacks (Twilio, Telnyx, etc.) without public exposure:
1. **ngrok tunnel** - Run ngrok inside the container or as a sidecar
2. **Tailscale Funnel** - Expose specific paths via Tailscale
3. **Outbound-only** - Some providers (Twilio) work fine for outbound calls without webhooks
Example voice-call config with ngrok:
```json
{
"plugins": {
"entries": {
"voice-call": {
"enabled": true,
"config": {
"provider": "twilio",
"tunnel": { "provider": "ngrok" },
"webhookSecurity": {
"allowedHosts": ["example.ngrok.app"]
}
}
}
}
}
}
```
The ngrok tunnel runs inside the container and provides a public webhook URL without exposing the Fly app itself. Set `webhookSecurity.allowedHosts` to the public tunnel hostname so forwarded host headers are accepted.
### Security benefits
| Aspect | Public | Private |
| ----------------- | ------------ | ---------- |
| Internet scanners | Discoverable | Hidden |
| Direct attacks | Possible | Blocked |
| Control UI access | Browser | Proxy/VPN |
| Webhook delivery | Direct | Via tunnel |
## Notes
- Fly.io uses **x86 architecture** (not ARM)
- The Dockerfile is compatible with both architectures
- For WhatsApp/Telegram onboarding, use `fly ssh console`
- Persistent data lives on the volume at `/data`
- Signal requires Java + signal-cli; use a custom image and keep memory at 2GB+.
## Cost
With the recommended config (`shared-cpu-2x`, 2GB RAM):
- ~$10-15/month depending on usage
- Free tier includes some allowance
See [Fly.io pricing](https://fly.io/docs/about/pricing/) for details.

View File

@@ -0,0 +1,524 @@
---
summary: "Run OpenClaw Gateway 24/7 on a GCP Compute Engine VM (Docker) with durable state"
read_when:
- You want OpenClaw running 24/7 on GCP
- You want a production-grade, always-on Gateway on your own VM
- You want full control over persistence, binaries, and restart behavior
title: "GCP"
---
# OpenClaw on GCP Compute Engine (Docker, Production VPS Guide)
## Goal
Run a persistent OpenClaw Gateway on a GCP Compute Engine VM using Docker, with durable state, baked-in binaries, and safe restart behavior.
If you want "OpenClaw 24/7 for ~$5-12/mo", this is a reliable setup on Google Cloud.
Pricing varies by machine type and region; pick the smallest VM that fits your workload and scale up if you hit OOMs.
## What are we doing (simple terms)?
- Create a GCP project and enable billing
- Create a Compute Engine VM
- Install Docker (isolated app runtime)
- Start the OpenClaw Gateway in Docker
- Persist `~/.openclaw` + `~/.openclaw/workspace` on the host (survives restarts/rebuilds)
- Access the Control UI from your laptop via an SSH tunnel
The Gateway can be accessed via:
- SSH port forwarding from your laptop
- Direct port exposure if you manage firewalling and tokens yourself
This guide uses Debian on GCP Compute Engine.
Ubuntu also works; map packages accordingly.
For the generic Docker flow, see [Docker](/install/docker).
---
## Quick path (experienced operators)
1. Create GCP project + enable Compute Engine API
2. Create Compute Engine VM (e2-small, Debian 12, 20GB)
3. SSH into the VM
4. Install Docker
5. Clone OpenClaw repository
6. Create persistent host directories
7. Configure `.env` and `docker-compose.yml`
8. Bake required binaries, build, and launch
---
## What you need
- GCP account (free tier eligible for e2-micro)
- gcloud CLI installed (or use Cloud Console)
- SSH access from your laptop
- Basic comfort with SSH + copy/paste
- ~20-30 minutes
- Docker and Docker Compose
- Model auth credentials
- Optional provider credentials
- WhatsApp QR
- Telegram bot token
- Gmail OAuth
---
## 1) Install gcloud CLI (or use Console)
**Option A: gcloud CLI** (recommended for automation)
Install from [https://cloud.google.com/sdk/docs/install](https://cloud.google.com/sdk/docs/install)
Initialize and authenticate:
```bash
gcloud init
gcloud auth login
```
**Option B: Cloud Console**
All steps can be done via the web UI at [https://console.cloud.google.com](https://console.cloud.google.com)
---
## 2) Create a GCP project
**CLI:**
```bash
gcloud projects create my-openclaw-project --name="OpenClaw Gateway"
gcloud config set project my-openclaw-project
```
Enable billing at [https://console.cloud.google.com/billing](https://console.cloud.google.com/billing) (required for Compute Engine).
Enable the Compute Engine API:
```bash
gcloud services enable compute.googleapis.com
```
**Console:**
1. Go to IAM & Admin > Create Project
2. Name it and create
3. Enable billing for the project
4. Navigate to APIs & Services > Enable APIs > search "Compute Engine API" > Enable
---
## 3) Create the VM
**Machine types:**
| Type | Specs | Cost | Notes |
| --------- | ------------------------ | ------------------ | -------------------------------------------- |
| e2-medium | 2 vCPU, 4GB RAM | ~$25/mo | Most reliable for local Docker builds |
| e2-small | 2 vCPU, 2GB RAM | ~$12/mo | Minimum recommended for Docker build |
| e2-micro | 2 vCPU (shared), 1GB RAM | Free tier eligible | Often fails with Docker build OOM (exit 137) |
**CLI:**
```bash
gcloud compute instances create openclaw-gateway \
--zone=us-central1-a \
--machine-type=e2-small \
--boot-disk-size=20GB \
--image-family=debian-12 \
--image-project=debian-cloud
```
**Console:**
1. Go to Compute Engine > VM instances > Create instance
2. Name: `openclaw-gateway`
3. Region: `us-central1`, Zone: `us-central1-a`
4. Machine type: `e2-small`
5. Boot disk: Debian 12, 20GB
6. Create
---
## 4) SSH into the VM
**CLI:**
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a
```
**Console:**
Click the "SSH" button next to your VM in the Compute Engine dashboard.
Note: SSH key propagation can take 1-2 minutes after VM creation. If connection is refused, wait and retry.
---
## 5) Install Docker (on the VM)
```bash
sudo apt-get update
sudo apt-get install -y git curl ca-certificates
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
```
Log out and back in for the group change to take effect:
```bash
exit
```
Then SSH back in:
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a
```
Verify:
```bash
docker --version
docker compose version
```
---
## 6) Clone the OpenClaw repository
```bash
git clone https://github.com/openclaw/openclaw.git
cd openclaw
```
This guide assumes you will build a custom image to guarantee binary persistence.
---
## 7) Create persistent host directories
Docker containers are ephemeral.
All long-lived state must live on the host.
```bash
mkdir -p ~/.openclaw
mkdir -p ~/.openclaw/workspace
```
---
## 8) Configure environment variables
Create `.env` in the repository root.
```bash
OPENCLAW_IMAGE=openclaw:latest
OPENCLAW_GATEWAY_TOKEN=change-me-now
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_CONFIG_DIR=/home/$USER/.openclaw
OPENCLAW_WORKSPACE_DIR=/home/$USER/.openclaw/workspace
GOG_KEYRING_PASSWORD=change-me-now
XDG_CONFIG_HOME=/home/node/.openclaw
```
Generate strong secrets:
```bash
openssl rand -hex 32
```
**Do not commit this file.**
---
## 9) Docker Compose configuration
Create or update `docker-compose.yml`.
```yaml
services:
openclaw-gateway:
image: ${OPENCLAW_IMAGE}
build: .
restart: unless-stopped
env_file:
- .env
environment:
- HOME=/home/node
- NODE_ENV=production
- TERM=xterm-256color
- OPENCLAW_GATEWAY_BIND=${OPENCLAW_GATEWAY_BIND}
- OPENCLAW_GATEWAY_PORT=${OPENCLAW_GATEWAY_PORT}
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
- GOG_KEYRING_PASSWORD=${GOG_KEYRING_PASSWORD}
- XDG_CONFIG_HOME=${XDG_CONFIG_HOME}
- PATH=/home/linuxbrew/.linuxbrew/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
ports:
# Recommended: keep the Gateway loopback-only on the VM; access via SSH tunnel.
# To expose it publicly, remove the `127.0.0.1:` prefix and firewall accordingly.
- "127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789"
command:
[
"node",
"dist/index.js",
"gateway",
"--bind",
"${OPENCLAW_GATEWAY_BIND}",
"--port",
"${OPENCLAW_GATEWAY_PORT}",
]
```
---
## 10) Bake required binaries into the image (critical)
Installing binaries inside a running container is a trap.
Anything installed at runtime will be lost on restart.
All external binaries required by skills must be installed at image build time.
The examples below show three common binaries only:
- `gog` for Gmail access
- `goplaces` for Google Places
- `wacli` for WhatsApp
These are examples, not a complete list.
You may install as many binaries as needed using the same pattern.
If you add new skills later that depend on additional binaries, you must:
1. Update the Dockerfile
2. Rebuild the image
3. Restart the containers
**Example Dockerfile**
```dockerfile
FROM node:22-bookworm
RUN apt-get update && apt-get install -y socat && rm -rf /var/lib/apt/lists/*
# Example binary 1: Gmail CLI
RUN curl -L https://github.com/steipete/gog/releases/latest/download/gog_Linux_x86_64.tar.gz \
| tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/gog
# Example binary 2: Google Places CLI
RUN curl -L https://github.com/steipete/goplaces/releases/latest/download/goplaces_Linux_x86_64.tar.gz \
| tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/goplaces
# Example binary 3: WhatsApp CLI
RUN curl -L https://github.com/steipete/wacli/releases/latest/download/wacli_Linux_x86_64.tar.gz \
| tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/wacli
# Add more binaries below using the same pattern
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY scripts ./scripts
RUN corepack enable
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
RUN pnpm ui:install
RUN pnpm ui:build
ENV NODE_ENV=production
CMD ["node","dist/index.js"]
```
---
## 11) Build and launch
```bash
docker compose build
docker compose up -d openclaw-gateway
```
If build fails with `Killed` / `exit code 137` during `pnpm install --frozen-lockfile`, the VM is out of memory. Use `e2-small` minimum, or `e2-medium` for more reliable first builds.
When binding to LAN (`OPENCLAW_GATEWAY_BIND=lan`), configure a trusted browser origin before continuing:
```bash
docker compose run --rm openclaw-cli config set gateway.controlUi.allowedOrigins '["http://127.0.0.1:18789"]' --strict-json
```
If you changed the gateway port, replace `18789` with your configured port.
Verify binaries:
```bash
docker compose exec openclaw-gateway which gog
docker compose exec openclaw-gateway which goplaces
docker compose exec openclaw-gateway which wacli
```
Expected output:
```
/usr/local/bin/gog
/usr/local/bin/goplaces
/usr/local/bin/wacli
```
---
## 12) Verify Gateway
```bash
docker compose logs -f openclaw-gateway
```
Success:
```
[gateway] listening on ws://0.0.0.0:18789
```
---
## 13) Access from your laptop
Create an SSH tunnel to forward the Gateway port:
```bash
gcloud compute ssh openclaw-gateway --zone=us-central1-a -- -L 18789:127.0.0.1:18789
```
Open in your browser:
`http://127.0.0.1:18789/`
Fetch a fresh tokenized dashboard link:
```bash
docker compose run --rm openclaw-cli dashboard --no-open
```
Paste the token from that URL.
If Control UI shows `unauthorized` or `disconnected (1008): pairing required`, approve the browser device:
```bash
docker compose run --rm openclaw-cli devices list
docker compose run --rm openclaw-cli devices approve <requestId>
```
---
## What persists where (source of truth)
OpenClaw runs in Docker, but Docker is not the source of truth.
All long-lived state must survive restarts, rebuilds, and reboots.
| Component | Location | Persistence mechanism | Notes |
| ------------------- | --------------------------------- | ---------------------- | -------------------------------- |
| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens |
| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys |
| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state |
| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts |
| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login |
| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` |
| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time |
| Node runtime | Container filesystem | Docker image | Rebuilt every image build |
| OS packages | Container filesystem | Docker image | Do not install at runtime |
| Docker container | Ephemeral | Restartable | Safe to destroy |
---
## Updates
To update OpenClaw on the VM:
```bash
cd ~/openclaw
git pull
docker compose build
docker compose up -d
```
---
## Troubleshooting
**SSH connection refused**
SSH key propagation can take 1-2 minutes after VM creation. Wait and retry.
**OS Login issues**
Check your OS Login profile:
```bash
gcloud compute os-login describe-profile
```
Ensure your account has the required IAM permissions (Compute OS Login or Compute OS Admin Login).
**Out of memory (OOM)**
If Docker build fails with `Killed` and `exit code 137`, the VM was OOM-killed. Upgrade to e2-small (minimum) or e2-medium (recommended for reliable local builds):
```bash
# Stop the VM first
gcloud compute instances stop openclaw-gateway --zone=us-central1-a
# Change machine type
gcloud compute instances set-machine-type openclaw-gateway \
--zone=us-central1-a \
--machine-type=e2-small
# Start the VM
gcloud compute instances start openclaw-gateway --zone=us-central1-a
```
---
## Service accounts (security best practice)
For personal use, your default user account works fine.
For automation or CI/CD pipelines, create a dedicated service account with minimal permissions:
1. Create a service account:
```bash
gcloud iam service-accounts create openclaw-deploy \
--display-name="OpenClaw Deployment"
```
2. Grant Compute Instance Admin role (or narrower custom role):
```bash
gcloud projects add-iam-policy-binding my-openclaw-project \
--member="serviceAccount:openclaw-deploy@my-openclaw-project.iam.gserviceaccount.com" \
--role="roles/compute.instanceAdmin.v1"
```
Avoid using the Owner role for automation. Use the principle of least privilege.
See [https://cloud.google.com/iam/docs/understanding-roles](https://cloud.google.com/iam/docs/understanding-roles) for IAM role details.
---
## Next steps
- Set up messaging channels: [Channels](/channels)
- Pair local devices as nodes: [Nodes](/nodes)
- Configure the Gateway: [Gateway configuration](/gateway/configuration)

View File

@@ -0,0 +1,356 @@
---
summary: "Run OpenClaw Gateway 24/7 on a cheap Hetzner VPS (Docker) with durable state and baked-in binaries"
read_when:
- You want OpenClaw running 24/7 on a cloud VPS (not your laptop)
- You want a production-grade, always-on Gateway on your own VPS
- You want full control over persistence, binaries, and restart behavior
- You are running OpenClaw in Docker on Hetzner or a similar provider
title: "Hetzner"
---
# OpenClaw on Hetzner (Docker, Production VPS Guide)
## Goal
Run a persistent OpenClaw Gateway on a Hetzner VPS using Docker, with durable state, baked-in binaries, and safe restart behavior.
If you want “OpenClaw 24/7 for ~$5”, this is the simplest reliable setup.
Hetzner pricing changes; pick the smallest Debian/Ubuntu VPS and scale up if you hit OOMs.
Security model reminder:
- Company-shared agents are fine when everyone is in the same trust boundary and the runtime is business-only.
- Keep strict separation: dedicated VPS/runtime + dedicated accounts; no personal Apple/Google/browser/password-manager profiles on that host.
- If users are adversarial to each other, split by gateway/host/OS user.
See [Security](/gateway/security) and [VPS hosting](/vps).
## What are we doing (simple terms)?
- Rent a small Linux server (Hetzner VPS)
- Install Docker (isolated app runtime)
- Start the OpenClaw Gateway in Docker
- Persist `~/.openclaw` + `~/.openclaw/workspace` on the host (survives restarts/rebuilds)
- Access the Control UI from your laptop via an SSH tunnel
The Gateway can be accessed via:
- SSH port forwarding from your laptop
- Direct port exposure if you manage firewalling and tokens yourself
This guide assumes Ubuntu or Debian on Hetzner.
If you are on another Linux VPS, map packages accordingly.
For the generic Docker flow, see [Docker](/install/docker).
---
## Quick path (experienced operators)
1. Provision Hetzner VPS
2. Install Docker
3. Clone OpenClaw repository
4. Create persistent host directories
5. Configure `.env` and `docker-compose.yml`
6. Bake required binaries into the image
7. `docker compose up -d`
8. Verify persistence and Gateway access
---
## What you need
- Hetzner VPS with root access
- SSH access from your laptop
- Basic comfort with SSH + copy/paste
- ~20 minutes
- Docker and Docker Compose
- Model auth credentials
- Optional provider credentials
- WhatsApp QR
- Telegram bot token
- Gmail OAuth
---
## 1) Provision the VPS
Create an Ubuntu or Debian VPS in Hetzner.
Connect as root:
```bash
ssh root@YOUR_VPS_IP
```
This guide assumes the VPS is stateful.
Do not treat it as disposable infrastructure.
---
## 2) Install Docker (on the VPS)
```bash
apt-get update
apt-get install -y git curl ca-certificates
curl -fsSL https://get.docker.com | sh
```
Verify:
```bash
docker --version
docker compose version
```
---
## 3) Clone the OpenClaw repository
```bash
git clone https://github.com/openclaw/openclaw.git
cd openclaw
```
This guide assumes you will build a custom image to guarantee binary persistence.
---
## 4) Create persistent host directories
Docker containers are ephemeral.
All long-lived state must live on the host.
```bash
mkdir -p /root/.openclaw/workspace
# Set ownership to the container user (uid 1000):
chown -R 1000:1000 /root/.openclaw
```
---
## 5) Configure environment variables
Create `.env` in the repository root.
```bash
OPENCLAW_IMAGE=openclaw:latest
OPENCLAW_GATEWAY_TOKEN=change-me-now
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_CONFIG_DIR=/root/.openclaw
OPENCLAW_WORKSPACE_DIR=/root/.openclaw/workspace
GOG_KEYRING_PASSWORD=change-me-now
XDG_CONFIG_HOME=/home/node/.openclaw
```
Generate strong secrets:
```bash
openssl rand -hex 32
```
**Do not commit this file.**
---
## 6) Docker Compose configuration
Create or update `docker-compose.yml`.
```yaml
services:
openclaw-gateway:
image: ${OPENCLAW_IMAGE}
build: .
restart: unless-stopped
env_file:
- .env
environment:
- HOME=/home/node
- NODE_ENV=production
- TERM=xterm-256color
- OPENCLAW_GATEWAY_BIND=${OPENCLAW_GATEWAY_BIND}
- OPENCLAW_GATEWAY_PORT=${OPENCLAW_GATEWAY_PORT}
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
- GOG_KEYRING_PASSWORD=${GOG_KEYRING_PASSWORD}
- XDG_CONFIG_HOME=${XDG_CONFIG_HOME}
- PATH=/home/linuxbrew/.linuxbrew/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
ports:
# Recommended: keep the Gateway loopback-only on the VPS; access via SSH tunnel.
# To expose it publicly, remove the `127.0.0.1:` prefix and firewall accordingly.
- "127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789"
command:
[
"node",
"dist/index.js",
"gateway",
"--bind",
"${OPENCLAW_GATEWAY_BIND}",
"--port",
"${OPENCLAW_GATEWAY_PORT}",
"--allow-unconfigured",
]
```
`--allow-unconfigured` is only for bootstrap convenience, it is not a replacement for a proper gateway configuration. Still set auth (`gateway.auth.token` or password) and use safe bind settings for your deployment.
---
## 7) Bake required binaries into the image (critical)
Installing binaries inside a running container is a trap.
Anything installed at runtime will be lost on restart.
All external binaries required by skills must be installed at image build time.
The examples below show three common binaries only:
- `gog` for Gmail access
- `goplaces` for Google Places
- `wacli` for WhatsApp
These are examples, not a complete list.
You may install as many binaries as needed using the same pattern.
If you add new skills later that depend on additional binaries, you must:
1. Update the Dockerfile
2. Rebuild the image
3. Restart the containers
**Example Dockerfile**
```dockerfile
FROM node:22-bookworm
RUN apt-get update && apt-get install -y socat && rm -rf /var/lib/apt/lists/*
# Example binary 1: Gmail CLI
RUN curl -L https://github.com/steipete/gog/releases/latest/download/gog_Linux_x86_64.tar.gz \
| tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/gog
# Example binary 2: Google Places CLI
RUN curl -L https://github.com/steipete/goplaces/releases/latest/download/goplaces_Linux_x86_64.tar.gz \
| tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/goplaces
# Example binary 3: WhatsApp CLI
RUN curl -L https://github.com/steipete/wacli/releases/latest/download/wacli_Linux_x86_64.tar.gz \
| tar -xz -C /usr/local/bin && chmod +x /usr/local/bin/wacli
# Add more binaries below using the same pattern
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY scripts ./scripts
RUN corepack enable
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
RUN pnpm ui:install
RUN pnpm ui:build
ENV NODE_ENV=production
CMD ["node","dist/index.js"]
```
---
## 8) Build and launch
```bash
docker compose build
docker compose up -d openclaw-gateway
```
Verify binaries:
```bash
docker compose exec openclaw-gateway which gog
docker compose exec openclaw-gateway which goplaces
docker compose exec openclaw-gateway which wacli
```
Expected output:
```
/usr/local/bin/gog
/usr/local/bin/goplaces
/usr/local/bin/wacli
```
---
## 9) Verify Gateway
```bash
docker compose logs -f openclaw-gateway
```
Success:
```
[gateway] listening on ws://0.0.0.0:18789
```
From your laptop:
```bash
ssh -N -L 18789:127.0.0.1:18789 root@YOUR_VPS_IP
```
Open:
`http://127.0.0.1:18789/`
Paste your gateway token.
---
## What persists where (source of truth)
OpenClaw runs in Docker, but Docker is not the source of truth.
All long-lived state must survive restarts, rebuilds, and reboots.
| Component | Location | Persistence mechanism | Notes |
| ------------------- | --------------------------------- | ---------------------- | -------------------------------- |
| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens |
| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys |
| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state |
| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts |
| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login |
| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` |
| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time |
| Node runtime | Container filesystem | Docker image | Rebuilt every image build |
| OS packages | Container filesystem | Docker image | Do not install at runtime |
| Docker container | Ephemeral | Restartable | Safe to destroy |
---
## Infrastructure as Code (Terraform)
For teams preferring infrastructure-as-code workflows, a community-maintained Terraform setup provides:
- Modular Terraform configuration with remote state management
- Automated provisioning via cloud-init
- Deployment scripts (bootstrap, deploy, backup/restore)
- Security hardening (firewall, UFW, SSH-only access)
- SSH tunnel configuration for gateway access
**Repositories:**
- Infrastructure: [openclaw-terraform-hetzner](https://github.com/andreesg/openclaw-terraform-hetzner)
- Docker config: [openclaw-docker-config](https://github.com/andreesg/openclaw-docker-config)
This approach complements the Docker setup above with reproducible deployments, version-controlled infrastructure, and automated disaster recovery.
> **Note:** Community-maintained. For issues or contributions, see the repository links above.

View File

@@ -0,0 +1,218 @@
---
summary: "Install OpenClaw — installer script, npm/pnpm, from source, Docker, and more"
read_when:
- You need an install method other than the Getting Started quickstart
- You want to deploy to a cloud platform
- You need to update, migrate, or uninstall
title: "Install"
---
# Install
Already followed [Getting Started](/start/getting-started)? You're all set — this page is for alternative install methods, platform-specific instructions, and maintenance.
## System requirements
- **[Node 22+](/install/node)** (the [installer script](#install-methods) will install it if missing)
- macOS, Linux, or Windows
- `pnpm` only if you build from source
<Note>
On Windows, we strongly recommend running OpenClaw under [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install).
</Note>
## Install methods
<Tip>
The **installer script** is the recommended way to install OpenClaw. It handles Node detection, installation, and onboarding in one step.
</Tip>
<Warning>
For VPS/cloud hosts, avoid third-party "1-click" marketplace images when possible. Prefer a clean base OS image (for example Ubuntu LTS), then install OpenClaw yourself with the installer script.
</Warning>
<AccordionGroup>
<Accordion title="Installer script" icon="rocket" defaultOpen>
Downloads the CLI, installs it globally via npm, and launches the onboarding wizard.
<Tabs>
<Tab title="macOS / Linux / WSL2">
```bash
curl -fsSL https://openclaw.ai/install.sh | bash
```
</Tab>
<Tab title="Windows (PowerShell)">
```powershell
iwr -useb https://openclaw.ai/install.ps1 | iex
```
</Tab>
</Tabs>
That's it — the script handles Node detection, installation, and onboarding.
To skip onboarding and just install the binary:
<Tabs>
<Tab title="macOS / Linux / WSL2">
```bash
curl -fsSL https://openclaw.ai/install.sh | bash -s -- --no-onboard
```
</Tab>
<Tab title="Windows (PowerShell)">
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -NoOnboard
```
</Tab>
</Tabs>
For all flags, env vars, and CI/automation options, see [Installer internals](/install/installer).
</Accordion>
<Accordion title="npm / pnpm" icon="package">
If you already have Node 22+ and prefer to manage the install yourself:
<Tabs>
<Tab title="npm">
```bash
npm install -g openclaw@latest
openclaw onboard --install-daemon
```
<Accordion title="sharp build errors?">
If you have libvips installed globally (common on macOS via Homebrew) and `sharp` fails, force prebuilt binaries:
```bash
SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install -g openclaw@latest
```
If you see `sharp: Please add node-gyp to your dependencies`, either install build tooling (macOS: Xcode CLT + `npm install -g node-gyp`) or use the env var above.
</Accordion>
</Tab>
<Tab title="pnpm">
```bash
pnpm add -g openclaw@latest
pnpm approve-builds -g # approve openclaw, node-llama-cpp, sharp, etc.
openclaw onboard --install-daemon
```
<Note>
pnpm requires explicit approval for packages with build scripts. After the first install shows the "Ignored build scripts" warning, run `pnpm approve-builds -g` and select the listed packages.
</Note>
</Tab>
</Tabs>
</Accordion>
<Accordion title="From source" icon="github">
For contributors or anyone who wants to run from a local checkout.
<Steps>
<Step title="Clone and build">
Clone the [OpenClaw repo](https://github.com/openclaw/openclaw) and build:
```bash
git clone https://github.com/openclaw/openclaw.git
cd openclaw
pnpm install
pnpm ui:build
pnpm build
```
</Step>
<Step title="Link the CLI">
Make the `openclaw` command available globally:
```bash
pnpm link --global
```
Alternatively, skip the link and run commands via `pnpm openclaw ...` from inside the repo.
</Step>
<Step title="Run onboarding">
```bash
openclaw onboard --install-daemon
```
</Step>
</Steps>
For deeper development workflows, see [Setup](/start/setup).
</Accordion>
</AccordionGroup>
## Other install methods
<CardGroup cols={2}>
<Card title="Docker" href="/install/docker" icon="container">
Containerized or headless deployments.
</Card>
<Card title="Podman" href="/install/podman" icon="container">
Rootless container: run `setup-podman.sh` once, then the launch script.
</Card>
<Card title="Nix" href="/install/nix" icon="snowflake">
Declarative install via Nix.
</Card>
<Card title="Ansible" href="/install/ansible" icon="server">
Automated fleet provisioning.
</Card>
<Card title="Bun" href="/install/bun" icon="zap">
CLI-only usage via the Bun runtime.
</Card>
</CardGroup>
## After install
Verify everything is working:
```bash
openclaw doctor # check for config issues
openclaw status # gateway status
openclaw dashboard # open the browser UI
```
If you need custom runtime paths, use:
- `OPENCLAW_HOME` for home-directory based internal paths
- `OPENCLAW_STATE_DIR` for mutable state location
- `OPENCLAW_CONFIG_PATH` for config file location
See [Environment vars](/help/environment) for precedence and full details.
## Troubleshooting: `openclaw` not found
<Accordion title="PATH diagnosis and fix">
Quick diagnosis:
```bash
node -v
npm -v
npm prefix -g
echo "$PATH"
```
If `$(npm prefix -g)/bin` (macOS/Linux) or `$(npm prefix -g)` (Windows) is **not** in your `$PATH`, your shell can't find global npm binaries (including `openclaw`).
Fix — add it to your shell startup file (`~/.zshrc` or `~/.bashrc`):
```bash
export PATH="$(npm prefix -g)/bin:$PATH"
```
On Windows, add the output of `npm prefix -g` to your PATH.
Then open a new terminal (or `rehash` in zsh / `hash -r` in bash).
</Accordion>
## Update / uninstall
<CardGroup cols={3}>
<Card title="Updating" href="/install/updating" icon="refresh-cw">
Keep OpenClaw up to date.
</Card>
<Card title="Migrating" href="/install/migrating" icon="arrow-right">
Move to a new machine.
</Card>
<Card title="Uninstall" href="/install/uninstall" icon="trash-2">
Remove OpenClaw completely.
</Card>
</CardGroup>

View File

@@ -0,0 +1,405 @@
---
summary: "How the installer scripts work (install.sh, install-cli.sh, install.ps1), flags, and automation"
read_when:
- You want to understand `openclaw.ai/install.sh`
- You want to automate installs (CI / headless)
- You want to install from a GitHub checkout
title: "Installer Internals"
---
# Installer internals
OpenClaw ships three installer scripts, served from `openclaw.ai`.
| Script | Platform | What it does |
| ---------------------------------- | -------------------- | -------------------------------------------------------------------------------------------- |
| [`install.sh`](#installsh) | macOS / Linux / WSL | Installs Node if needed, installs OpenClaw via npm (default) or git, and can run onboarding. |
| [`install-cli.sh`](#install-clish) | macOS / Linux / WSL | Installs Node + OpenClaw into a local prefix (`~/.openclaw`). No root required. |
| [`install.ps1`](#installps1) | Windows (PowerShell) | Installs Node if needed, installs OpenClaw via npm (default) or git, and can run onboarding. |
## Quick commands
<Tabs>
<Tab title="install.sh">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash
```
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --help
```
</Tab>
<Tab title="install-cli.sh">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash
```
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --help
```
</Tab>
<Tab title="install.ps1">
```powershell
iwr -useb https://openclaw.ai/install.ps1 | iex
```
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -Tag beta -NoOnboard -DryRun
```
</Tab>
</Tabs>
<Note>
If install succeeds but `openclaw` is not found in a new terminal, see [Node.js troubleshooting](/install/node#troubleshooting).
</Note>
---
## install.sh
<Tip>
Recommended for most interactive installs on macOS/Linux/WSL.
</Tip>
### Flow (install.sh)
<Steps>
<Step title="Detect OS">
Supports macOS and Linux (including WSL). If macOS is detected, installs Homebrew if missing.
</Step>
<Step title="Ensure Node.js 22+">
Checks Node version and installs Node 22 if needed (Homebrew on macOS, NodeSource setup scripts on Linux apt/dnf/yum).
</Step>
<Step title="Ensure Git">
Installs Git if missing.
</Step>
<Step title="Install OpenClaw">
- `npm` method (default): global npm install
- `git` method: clone/update repo, install deps with pnpm, build, then install wrapper at `~/.local/bin/openclaw`
</Step>
<Step title="Post-install tasks">
- Runs `openclaw doctor --non-interactive` on upgrades and git installs (best effort)
- Attempts onboarding when appropriate (TTY available, onboarding not disabled, and bootstrap/config checks pass)
- Defaults `SHARP_IGNORE_GLOBAL_LIBVIPS=1`
</Step>
</Steps>
### Source checkout detection
If run inside an OpenClaw checkout (`package.json` + `pnpm-workspace.yaml`), the script offers:
- use checkout (`git`), or
- use global install (`npm`)
If no TTY is available and no install method is set, it defaults to `npm` and warns.
The script exits with code `2` for invalid method selection or invalid `--install-method` values.
### Examples (install.sh)
<Tabs>
<Tab title="Default">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash
```
</Tab>
<Tab title="Skip onboarding">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --no-onboard
```
</Tab>
<Tab title="Git install">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --install-method git
```
</Tab>
<Tab title="Dry run">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --dry-run
```
</Tab>
</Tabs>
<AccordionGroup>
<Accordion title="Flags reference">
| Flag | Description |
| ------------------------------- | ---------------------------------------------------------- |
| `--install-method npm\|git` | Choose install method (default: `npm`). Alias: `--method` |
| `--npm` | Shortcut for npm method |
| `--git` | Shortcut for git method. Alias: `--github` |
| `--version <version\|dist-tag>` | npm version or dist-tag (default: `latest`) |
| `--beta` | Use beta dist-tag if available, else fallback to `latest` |
| `--git-dir <path>` | Checkout directory (default: `~/openclaw`). Alias: `--dir` |
| `--no-git-update` | Skip `git pull` for existing checkout |
| `--no-prompt` | Disable prompts |
| `--no-onboard` | Skip onboarding |
| `--onboard` | Enable onboarding |
| `--dry-run` | Print actions without applying changes |
| `--verbose` | Enable debug output (`set -x`, npm notice-level logs) |
| `--help` | Show usage (`-h`) |
</Accordion>
<Accordion title="Environment variables reference">
| Variable | Description |
| ------------------------------------------- | --------------------------------------------- |
| `OPENCLAW_INSTALL_METHOD=git\|npm` | Install method |
| `OPENCLAW_VERSION=latest\|next\|<semver>` | npm version or dist-tag |
| `OPENCLAW_BETA=0\|1` | Use beta if available |
| `OPENCLAW_GIT_DIR=<path>` | Checkout directory |
| `OPENCLAW_GIT_UPDATE=0\|1` | Toggle git updates |
| `OPENCLAW_NO_PROMPT=1` | Disable prompts |
| `OPENCLAW_NO_ONBOARD=1` | Skip onboarding |
| `OPENCLAW_DRY_RUN=1` | Dry run mode |
| `OPENCLAW_VERBOSE=1` | Debug mode |
| `OPENCLAW_NPM_LOGLEVEL=error\|warn\|notice` | npm log level |
| `SHARP_IGNORE_GLOBAL_LIBVIPS=0\|1` | Control sharp/libvips behavior (default: `1`) |
</Accordion>
</AccordionGroup>
---
## install-cli.sh
<Info>
Designed for environments where you want everything under a local prefix (default `~/.openclaw`) and no system Node dependency.
</Info>
### Flow (install-cli.sh)
<Steps>
<Step title="Install local Node runtime">
Downloads Node tarball (default `22.22.0`) to `<prefix>/tools/node-v<version>` and verifies SHA-256.
</Step>
<Step title="Ensure Git">
If Git is missing, attempts install via apt/dnf/yum on Linux or Homebrew on macOS.
</Step>
<Step title="Install OpenClaw under prefix">
Installs with npm using `--prefix <prefix>`, then writes wrapper to `<prefix>/bin/openclaw`.
</Step>
</Steps>
### Examples (install-cli.sh)
<Tabs>
<Tab title="Default">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash
```
</Tab>
<Tab title="Custom prefix + version">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --prefix /opt/openclaw --version latest
```
</Tab>
<Tab title="Automation JSON output">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --json --prefix /opt/openclaw
```
</Tab>
<Tab title="Run onboarding">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --onboard
```
</Tab>
</Tabs>
<AccordionGroup>
<Accordion title="Flags reference">
| Flag | Description |
| ---------------------- | ------------------------------------------------------------------------------- |
| `--prefix <path>` | Install prefix (default: `~/.openclaw`) |
| `--version <ver>` | OpenClaw version or dist-tag (default: `latest`) |
| `--node-version <ver>` | Node version (default: `22.22.0`) |
| `--json` | Emit NDJSON events |
| `--onboard` | Run `openclaw onboard` after install |
| `--no-onboard` | Skip onboarding (default) |
| `--set-npm-prefix` | On Linux, force npm prefix to `~/.npm-global` if current prefix is not writable |
| `--help` | Show usage (`-h`) |
</Accordion>
<Accordion title="Environment variables reference">
| Variable | Description |
| ------------------------------------------- | --------------------------------------------------------------------------------- |
| `OPENCLAW_PREFIX=<path>` | Install prefix |
| `OPENCLAW_VERSION=<ver>` | OpenClaw version or dist-tag |
| `OPENCLAW_NODE_VERSION=<ver>` | Node version |
| `OPENCLAW_NO_ONBOARD=1` | Skip onboarding |
| `OPENCLAW_NPM_LOGLEVEL=error\|warn\|notice` | npm log level |
| `OPENCLAW_GIT_DIR=<path>` | Legacy cleanup lookup path (used when removing old `Peekaboo` submodule checkout) |
| `SHARP_IGNORE_GLOBAL_LIBVIPS=0\|1` | Control sharp/libvips behavior (default: `1`) |
</Accordion>
</AccordionGroup>
---
## install.ps1
### Flow (install.ps1)
<Steps>
<Step title="Ensure PowerShell + Windows environment">
Requires PowerShell 5+.
</Step>
<Step title="Ensure Node.js 22+">
If missing, attempts install via winget, then Chocolatey, then Scoop.
</Step>
<Step title="Install OpenClaw">
- `npm` method (default): global npm install using selected `-Tag`
- `git` method: clone/update repo, install/build with pnpm, and install wrapper at `%USERPROFILE%\.local\bin\openclaw.cmd`
</Step>
<Step title="Post-install tasks">
Adds needed bin directory to user PATH when possible, then runs `openclaw doctor --non-interactive` on upgrades and git installs (best effort).
</Step>
</Steps>
### Examples (install.ps1)
<Tabs>
<Tab title="Default">
```powershell
iwr -useb https://openclaw.ai/install.ps1 | iex
```
</Tab>
<Tab title="Git install">
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -InstallMethod git
```
</Tab>
<Tab title="Custom git directory">
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -InstallMethod git -GitDir "C:\openclaw"
```
</Tab>
<Tab title="Dry run">
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -DryRun
```
</Tab>
<Tab title="Debug trace">
```powershell
# install.ps1 has no dedicated -Verbose flag yet.
Set-PSDebug -Trace 1
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -NoOnboard
Set-PSDebug -Trace 0
```
</Tab>
</Tabs>
<AccordionGroup>
<Accordion title="Flags reference">
| Flag | Description |
| ------------------------- | ------------------------------------------------------ |
| `-InstallMethod npm\|git` | Install method (default: `npm`) |
| `-Tag <tag>` | npm dist-tag (default: `latest`) |
| `-GitDir <path>` | Checkout directory (default: `%USERPROFILE%\openclaw`) |
| `-NoOnboard` | Skip onboarding |
| `-NoGitUpdate` | Skip `git pull` |
| `-DryRun` | Print actions only |
</Accordion>
<Accordion title="Environment variables reference">
| Variable | Description |
| ---------------------------------- | ------------------ |
| `OPENCLAW_INSTALL_METHOD=git\|npm` | Install method |
| `OPENCLAW_GIT_DIR=<path>` | Checkout directory |
| `OPENCLAW_NO_ONBOARD=1` | Skip onboarding |
| `OPENCLAW_GIT_UPDATE=0` | Disable git pull |
| `OPENCLAW_DRY_RUN=1` | Dry run mode |
</Accordion>
</AccordionGroup>
<Note>
If `-InstallMethod git` is used and Git is missing, the script exits and prints the Git for Windows link.
</Note>
---
## CI and automation
Use non-interactive flags/env vars for predictable runs.
<Tabs>
<Tab title="install.sh (non-interactive npm)">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash -s -- --no-prompt --no-onboard
```
</Tab>
<Tab title="install.sh (non-interactive git)">
```bash
OPENCLAW_INSTALL_METHOD=git OPENCLAW_NO_PROMPT=1 \
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash
```
</Tab>
<Tab title="install-cli.sh (JSON)">
```bash
curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install-cli.sh | bash -s -- --json --prefix /opt/openclaw
```
</Tab>
<Tab title="install.ps1 (skip onboarding)">
```powershell
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -NoOnboard
```
</Tab>
</Tabs>
---
## Troubleshooting
<AccordionGroup>
<Accordion title="Why is Git required?">
Git is required for `git` install method. For `npm` installs, Git is still checked/installed to avoid `spawn git ENOENT` failures when dependencies use git URLs.
</Accordion>
<Accordion title="Why does npm hit EACCES on Linux?">
Some Linux setups point npm global prefix to root-owned paths. `install.sh` can switch prefix to `~/.npm-global` and append PATH exports to shell rc files (when those files exist).
</Accordion>
<Accordion title="sharp/libvips issues">
The scripts default `SHARP_IGNORE_GLOBAL_LIBVIPS=1` to avoid sharp building against system libvips. To override:
```bash
SHARP_IGNORE_GLOBAL_LIBVIPS=0 curl -fsSL --proto '=https' --tlsv1.2 https://openclaw.ai/install.sh | bash
```
</Accordion>
<Accordion title='Windows: "npm error spawn git / ENOENT"'>
Install Git for Windows, reopen PowerShell, rerun installer.
</Accordion>
<Accordion title='Windows: "openclaw is not recognized"'>
Run `npm config get prefix`, append `\bin`, add that directory to user PATH, then reopen PowerShell.
</Accordion>
<Accordion title="Windows: how to get verbose installer output">
`install.ps1` does not currently expose a `-Verbose` switch.
Use PowerShell tracing for script-level diagnostics:
```powershell
Set-PSDebug -Trace 1
& ([scriptblock]::Create((iwr -useb https://openclaw.ai/install.ps1))) -NoOnboard
Set-PSDebug -Trace 0
```
</Accordion>
<Accordion title="openclaw not found after install">
Usually a PATH issue. See [Node.js troubleshooting](/install/node#troubleshooting).
</Accordion>
</AccordionGroup>

View File

@@ -0,0 +1,281 @@
---
summary: "Run OpenClaw in a sandboxed macOS VM (local or hosted) when you need isolation or iMessage"
read_when:
- You want OpenClaw isolated from your main macOS environment
- You want iMessage integration (BlueBubbles) in a sandbox
- You want a resettable macOS environment you can clone
- You want to compare local vs hosted macOS VM options
title: "macOS VMs"
---
# OpenClaw on macOS VMs (Sandboxing)
## Recommended default (most users)
- **Small Linux VPS** for an always-on Gateway and low cost. See [VPS hosting](/vps).
- **Dedicated hardware** (Mac mini or Linux box) if you want full control and a **residential IP** for browser automation. Many sites block data center IPs, so local browsing often works better.
- **Hybrid:** keep the Gateway on a cheap VPS, and connect your Mac as a **node** when you need browser/UI automation. See [Nodes](/nodes) and [Gateway remote](/gateway/remote).
Use a macOS VM when you specifically need macOS-only capabilities (iMessage/BlueBubbles) or want strict isolation from your daily Mac.
## macOS VM options
### Local VM on your Apple Silicon Mac (Lume)
Run OpenClaw in a sandboxed macOS VM on your existing Apple Silicon Mac using [Lume](https://cua.ai/docs/lume).
This gives you:
- Full macOS environment in isolation (your host stays clean)
- iMessage support via BlueBubbles (impossible on Linux/Windows)
- Instant reset by cloning VMs
- No extra hardware or cloud costs
### Hosted Mac providers (cloud)
If you want macOS in the cloud, hosted Mac providers work too:
- [MacStadium](https://www.macstadium.com/) (hosted Macs)
- Other hosted Mac vendors also work; follow their VM + SSH docs
Once you have SSH access to a macOS VM, continue at step 6 below.
---
## Quick path (Lume, experienced users)
1. Install Lume
2. `lume create openclaw --os macos --ipsw latest`
3. Complete Setup Assistant, enable Remote Login (SSH)
4. `lume run openclaw --no-display`
5. SSH in, install OpenClaw, configure channels
6. Done
---
## What you need (Lume)
- Apple Silicon Mac (M1/M2/M3/M4)
- macOS Sequoia or later on the host
- ~60 GB free disk space per VM
- ~20 minutes
---
## 1) Install Lume
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/lume/scripts/install.sh)"
```
If `~/.local/bin` isn't in your PATH:
```bash
echo 'export PATH="$PATH:$HOME/.local/bin"' >> ~/.zshrc && source ~/.zshrc
```
Verify:
```bash
lume --version
```
Docs: [Lume Installation](https://cua.ai/docs/lume/guide/getting-started/installation)
---
## 2) Create the macOS VM
```bash
lume create openclaw --os macos --ipsw latest
```
This downloads macOS and creates the VM. A VNC window opens automatically.
Note: The download can take a while depending on your connection.
---
## 3) Complete Setup Assistant
In the VNC window:
1. Select language and region
2. Skip Apple ID (or sign in if you want iMessage later)
3. Create a user account (remember the username and password)
4. Skip all optional features
After setup completes, enable SSH:
1. Open System Settings → General → Sharing
2. Enable "Remote Login"
---
## 4) Get the VM's IP address
```bash
lume get openclaw
```
Look for the IP address (usually `192.168.64.x`).
---
## 5) SSH into the VM
```bash
ssh youruser@192.168.64.X
```
Replace `youruser` with the account you created, and the IP with your VM's IP.
---
## 6) Install OpenClaw
Inside the VM:
```bash
npm install -g openclaw@latest
openclaw onboard --install-daemon
```
Follow the onboarding prompts to set up your model provider (Anthropic, OpenAI, etc.).
---
## 7) Configure channels
Edit the config file:
```bash
nano ~/.openclaw/openclaw.json
```
Add your channels:
```json
{
"channels": {
"whatsapp": {
"dmPolicy": "allowlist",
"allowFrom": ["+15551234567"]
},
"telegram": {
"botToken": "YOUR_BOT_TOKEN"
}
}
}
```
Then login to WhatsApp (scan QR):
```bash
openclaw channels login
```
---
## 8) Run the VM headlessly
Stop the VM and restart without display:
```bash
lume stop openclaw
lume run openclaw --no-display
```
The VM runs in the background. OpenClaw's daemon keeps the gateway running.
To check status:
```bash
ssh youruser@192.168.64.X "openclaw status"
```
---
## Bonus: iMessage integration
This is the killer feature of running on macOS. Use [BlueBubbles](https://bluebubbles.app) to add iMessage to OpenClaw.
Inside the VM:
1. Download BlueBubbles from bluebubbles.app
2. Sign in with your Apple ID
3. Enable the Web API and set a password
4. Point BlueBubbles webhooks at your gateway (example: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)
Add to your OpenClaw config:
```json
{
"channels": {
"bluebubbles": {
"serverUrl": "http://localhost:1234",
"password": "your-api-password",
"webhookPath": "/bluebubbles-webhook"
}
}
}
```
Restart the gateway. Now your agent can send and receive iMessages.
Full setup details: [BlueBubbles channel](/channels/bluebubbles)
---
## Save a golden image
Before customizing further, snapshot your clean state:
```bash
lume stop openclaw
lume clone openclaw openclaw-golden
```
Reset anytime:
```bash
lume stop openclaw && lume delete openclaw
lume clone openclaw-golden openclaw
lume run openclaw --no-display
```
---
## Running 24/7
Keep the VM running by:
- Keeping your Mac plugged in
- Disabling sleep in System Settings → Energy Saver
- Using `caffeinate` if needed
For true always-on, consider a dedicated Mac mini or a small VPS. See [VPS hosting](/vps).
---
## Troubleshooting
| Problem | Solution |
| ------------------------ | ---------------------------------------------------------------------------------- |
| Can't SSH into VM | Check "Remote Login" is enabled in VM's System Settings |
| VM IP not showing | Wait for VM to fully boot, run `lume get openclaw` again |
| Lume command not found | Add `~/.local/bin` to your PATH |
| WhatsApp QR not scanning | Ensure you're logged into the VM (not host) when running `openclaw channels login` |
---
## Related docs
- [VPS hosting](/vps)
- [Nodes](/nodes)
- [Gateway remote](/gateway/remote)
- [BlueBubbles channel](/channels/bluebubbles)
- [Lume Quickstart](https://cua.ai/docs/lume/guide/getting-started/quickstart)
- [Lume CLI Reference](https://cua.ai/docs/lume/reference/cli-reference)
- [Unattended VM Setup](https://cua.ai/docs/lume/guide/fundamentals/unattended-setup) (advanced)
- [Docker Sandboxing](/install/docker) (alternative isolation approach)

View File

@@ -0,0 +1,192 @@
---
summary: "Move (migrate) a OpenClaw install from one machine to another"
read_when:
- You are moving OpenClaw to a new laptop/server
- You want to preserve sessions, auth, and channel logins (WhatsApp, etc.)
title: "Migration Guide"
---
# Migrating OpenClaw to a new machine
This guide migrates a OpenClaw Gateway from one machine to another **without redoing onboarding**.
The migration is simple conceptually:
- Copy the **state directory** (`$OPENCLAW_STATE_DIR`, default: `~/.openclaw/`) — this includes config, auth, sessions, and channel state.
- Copy your **workspace** (`~/.openclaw/workspace/` by default) — this includes your agent files (memory, prompts, etc.).
But there are common footguns around **profiles**, **permissions**, and **partial copies**.
## Before you start (what you are migrating)
### 1) Identify your state directory
Most installs use the default:
- **State dir:** `~/.openclaw/`
But it may be different if you use:
- `--profile <name>` (often becomes `~/.openclaw-<profile>/`)
- `OPENCLAW_STATE_DIR=/some/path`
If youre not sure, run on the **old** machine:
```bash
openclaw status
```
Look for mentions of `OPENCLAW_STATE_DIR` / profile in the output. If you run multiple gateways, repeat for each profile.
### 2) Identify your workspace
Common defaults:
- `~/.openclaw/workspace/` (recommended workspace)
- a custom folder you created
Your workspace is where files like `MEMORY.md`, `USER.md`, and `memory/*.md` live.
### 3) Understand what you will preserve
If you copy **both** the state dir and workspace, you keep:
- Gateway configuration (`openclaw.json`)
- Auth profiles / API keys / OAuth tokens
- Session history + agent state
- Channel state (e.g. WhatsApp login/session)
- Your workspace files (memory, skills notes, etc.)
If you copy **only** the workspace (e.g., via Git), you do **not** preserve:
- sessions
- credentials
- channel logins
Those live under `$OPENCLAW_STATE_DIR`.
## Migration steps (recommended)
### Step 0 — Make a backup (old machine)
On the **old** machine, stop the gateway first so files arent changing mid-copy:
```bash
openclaw gateway stop
```
(Optional but recommended) archive the state dir and workspace:
```bash
# Adjust paths if you use a profile or custom locations
cd ~
tar -czf openclaw-state.tgz .openclaw
tar -czf openclaw-workspace.tgz .openclaw/workspace
```
If you have multiple profiles/state dirs (e.g. `~/.openclaw-main`, `~/.openclaw-work`), archive each.
### Step 1 — Install OpenClaw on the new machine
On the **new** machine, install the CLI (and Node if needed):
- See: [Install](/install)
At this stage, its OK if onboarding creates a fresh `~/.openclaw/` — you will overwrite it in the next step.
### Step 2 — Copy the state dir + workspace to the new machine
Copy **both**:
- `$OPENCLAW_STATE_DIR` (default `~/.openclaw/`)
- your workspace (default `~/.openclaw/workspace/`)
Common approaches:
- `scp` the tarballs and extract
- `rsync -a` over SSH
- external drive
After copying, ensure:
- Hidden directories were included (e.g. `.openclaw/`)
- File ownership is correct for the user running the gateway
### Step 3 — Run Doctor (migrations + service repair)
On the **new** machine:
```bash
openclaw doctor
```
Doctor is the “safe boring” command. It repairs services, applies config migrations, and warns about mismatches.
Then:
```bash
openclaw gateway restart
openclaw status
```
## Common footguns (and how to avoid them)
### Footgun: profile / state-dir mismatch
If you ran the old gateway with a profile (or `OPENCLAW_STATE_DIR`), and the new gateway uses a different one, youll see symptoms like:
- config changes not taking effect
- channels missing / logged out
- empty session history
Fix: run the gateway/service using the **same** profile/state dir you migrated, then rerun:
```bash
openclaw doctor
```
### Footgun: copying only `openclaw.json`
`openclaw.json` is not enough. Many providers store state under:
- `$OPENCLAW_STATE_DIR/credentials/`
- `$OPENCLAW_STATE_DIR/agents/<agentId>/...`
Always migrate the entire `$OPENCLAW_STATE_DIR` folder.
### Footgun: permissions / ownership
If you copied as root or changed users, the gateway may fail to read credentials/sessions.
Fix: ensure the state dir + workspace are owned by the user running the gateway.
### Footgun: migrating between remote/local modes
- If your UI (WebUI/TUI) points at a **remote** gateway, the remote host owns the session store + workspace.
- Migrating your laptop wont move the remote gateways state.
If youre in remote mode, migrate the **gateway host**.
### Footgun: secrets in backups
`$OPENCLAW_STATE_DIR` contains secrets (API keys, OAuth tokens, WhatsApp creds). Treat backups like production secrets:
- store encrypted
- avoid sharing over insecure channels
- rotate keys if you suspect exposure
## Verification checklist
On the new machine, confirm:
- `openclaw status` shows the gateway running
- Your channels are still connected (e.g. WhatsApp doesnt require re-pair)
- The dashboard opens and shows existing sessions
- Your workspace files (memory, configs) are present
## Related
- [Doctor](/gateway/doctor)
- [Gateway troubleshooting](/gateway/troubleshooting)
- [Where does OpenClaw store its data?](/help/faq#where-does-openclaw-store-its-data)

View File

@@ -0,0 +1,98 @@
---
summary: "Install OpenClaw declaratively with Nix"
read_when:
- You want reproducible, rollback-able installs
- You're already using Nix/NixOS/Home Manager
- You want everything pinned and managed declaratively
title: "Nix"
---
# Nix Installation
The recommended way to run OpenClaw with Nix is via **[nix-openclaw](https://github.com/openclaw/nix-openclaw)** — a batteries-included Home Manager module.
## Quick Start
Paste this to your AI agent (Claude, Cursor, etc.):
```text
I want to set up nix-openclaw on my Mac.
Repository: github:openclaw/nix-openclaw
What I need you to do:
1. Check if Determinate Nix is installed (if not, install it)
2. Create a local flake at ~/code/openclaw-local using templates/agent-first/flake.nix
3. Help me create a Telegram bot (@BotFather) and get my chat ID (@userinfobot)
4. Set up secrets (bot token, Anthropic key) - plain files at ~/.secrets/ is fine
5. Fill in the template placeholders and run home-manager switch
6. Verify: launchd running, bot responds to messages
Reference the nix-openclaw README for module options.
```
> **📦 Full guide: [github.com/openclaw/nix-openclaw](https://github.com/openclaw/nix-openclaw)**
>
> The nix-openclaw repo is the source of truth for Nix installation. This page is just a quick overview.
## What you get
- Gateway + macOS app + tools (whisper, spotify, cameras) — all pinned
- Launchd service that survives reboots
- Plugin system with declarative config
- Instant rollback: `home-manager switch --rollback`
---
## Nix Mode Runtime Behavior
When `OPENCLAW_NIX_MODE=1` is set (automatic with nix-openclaw):
OpenClaw supports a **Nix mode** that makes configuration deterministic and disables auto-install flows.
Enable it by exporting:
```bash
OPENCLAW_NIX_MODE=1
```
On macOS, the GUI app does not automatically inherit shell env vars. You can
also enable Nix mode via defaults:
```bash
defaults write ai.openclaw.mac openclaw.nixMode -bool true
```
### Config + state paths
OpenClaw reads JSON5 config from `OPENCLAW_CONFIG_PATH` and stores mutable data in `OPENCLAW_STATE_DIR`.
When needed, you can also set `OPENCLAW_HOME` to control the base home directory used for internal path resolution.
- `OPENCLAW_HOME` (default precedence: `HOME` / `USERPROFILE` / `os.homedir()`)
- `OPENCLAW_STATE_DIR` (default: `~/.openclaw`)
- `OPENCLAW_CONFIG_PATH` (default: `$OPENCLAW_STATE_DIR/openclaw.json`)
When running under Nix, set these explicitly to Nix-managed locations so runtime state and config
stay out of the immutable store.
### Runtime behavior in Nix mode
- Auto-install and self-mutation flows are disabled
- Missing dependencies surface Nix-specific remediation messages
- UI surfaces a read-only Nix mode banner when present
## Packaging note (macOS)
The macOS packaging flow expects a stable Info.plist template at:
```
apps/macos/Sources/OpenClaw/Resources/Info.plist
```
[`scripts/package-mac-app.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/package-mac-app.sh) copies this template into the app bundle and patches dynamic fields
(bundle ID, version/build, Git SHA, Sparkle keys). This keeps the plist deterministic for SwiftPM
packaging and Nix builds (which do not rely on a full Xcode toolchain).
## Related
- [nix-openclaw](https://github.com/openclaw/nix-openclaw) — full setup guide
- [Wizard](/start/wizard) — non-Nix CLI setup
- [Docker](/install/docker) — containerized setup

View File

@@ -0,0 +1,138 @@
---
title: "Node.js"
summary: "Install and configure Node.js for OpenClaw — version requirements, install options, and PATH troubleshooting"
read_when:
- "You need to install Node.js before installing OpenClaw"
- "You installed OpenClaw but `openclaw` is command not found"
- "npm install -g fails with permissions or PATH issues"
---
# Node.js
OpenClaw requires **Node 22 or newer**. The [installer script](/install#install-methods) will detect and install Node automatically — this page is for when you want to set up Node yourself and make sure everything is wired up correctly (versions, PATH, global installs).
## Check your version
```bash
node -v
```
If this prints `v22.x.x` or higher, you're good. If Node isn't installed or the version is too old, pick an install method below.
## Install Node
<Tabs>
<Tab title="macOS">
**Homebrew** (recommended):
```bash
brew install node
```
Or download the macOS installer from [nodejs.org](https://nodejs.org/).
</Tab>
<Tab title="Linux">
**Ubuntu / Debian:**
```bash
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
```
**Fedora / RHEL:**
```bash
sudo dnf install nodejs
```
Or use a version manager (see below).
</Tab>
<Tab title="Windows">
**winget** (recommended):
```powershell
winget install OpenJS.NodeJS.LTS
```
**Chocolatey:**
```powershell
choco install nodejs-lts
```
Or download the Windows installer from [nodejs.org](https://nodejs.org/).
</Tab>
</Tabs>
<Accordion title="Using a version manager (nvm, fnm, mise, asdf)">
Version managers let you switch between Node versions easily. Popular options:
- [**fnm**](https://github.com/Schniz/fnm) — fast, cross-platform
- [**nvm**](https://github.com/nvm-sh/nvm) — widely used on macOS/Linux
- [**mise**](https://mise.jdx.dev/) — polyglot (Node, Python, Ruby, etc.)
Example with fnm:
```bash
fnm install 22
fnm use 22
```
<Warning>
Make sure your version manager is initialized in your shell startup file (`~/.zshrc` or `~/.bashrc`). If it isn't, `openclaw` may not be found in new terminal sessions because the PATH won't include Node's bin directory.
</Warning>
</Accordion>
## Troubleshooting
### `openclaw: command not found`
This almost always means npm's global bin directory isn't on your PATH.
<Steps>
<Step title="Find your global npm prefix">
```bash
npm prefix -g
```
</Step>
<Step title="Check if it's on your PATH">
```bash
echo "$PATH"
```
Look for `<npm-prefix>/bin` (macOS/Linux) or `<npm-prefix>` (Windows) in the output.
</Step>
<Step title="Add it to your shell startup file">
<Tabs>
<Tab title="macOS / Linux">
Add to `~/.zshrc` or `~/.bashrc`:
```bash
export PATH="$(npm prefix -g)/bin:$PATH"
```
Then open a new terminal (or run `rehash` in zsh / `hash -r` in bash).
</Tab>
<Tab title="Windows">
Add the output of `npm prefix -g` to your system PATH via Settings → System → Environment Variables.
</Tab>
</Tabs>
</Step>
</Steps>
### Permission errors on `npm install -g` (Linux)
If you see `EACCES` errors, switch npm's global prefix to a user-writable directory:
```bash
mkdir -p "$HOME/.npm-global"
npm config set prefix "$HOME/.npm-global"
export PATH="$HOME/.npm-global/bin:$PATH"
```
Add the `export PATH=...` line to your `~/.bashrc` or `~/.zshrc` to make it permanent.

View File

@@ -0,0 +1,53 @@
---
title: Deploy on Northflank
---
Deploy OpenClaw on Northflank with a one-click template and finish setup in your browser.
This is the easiest “no terminal on the server” path: Northflank runs the Gateway for you,
and you configure everything via the `/setup` web wizard.
## How to get started
1. Click [Deploy OpenClaw](https://northflank.com/stacks/deploy-openclaw) to open the template.
2. Create an [account on Northflank](https://app.northflank.com/signup) if you dont already have one.
3. Click **Deploy OpenClaw now**.
4. Set the required environment variable: `SETUP_PASSWORD`.
5. Click **Deploy stack** to build and run the OpenClaw template.
6. Wait for the deployment to complete, then click **View resources**.
7. Open the OpenClaw service.
8. Open the public OpenClaw URL and complete setup at `/setup`.
9. Open the Control UI at `/openclaw`.
## What you get
- Hosted OpenClaw Gateway + Control UI
- Web setup wizard at `/setup` (no terminal commands)
- Persistent storage via Northflank Volume (`/data`) so config/credentials/workspace survive redeploys
## Setup flow
1. Visit `https://<your-northflank-domain>/setup` and enter your `SETUP_PASSWORD`.
2. Choose a model/auth provider and paste your key.
3. (Optional) Add Telegram/Discord/Slack tokens.
4. Click **Run setup**.
5. Open the Control UI at `https://<your-northflank-domain>/openclaw`
If Telegram DMs are set to pairing, the setup wizard can approve the pairing code.
## Getting chat tokens
### Telegram bot token
1. Message `@BotFather` in Telegram
2. Run `/newbot`
3. Copy the token (looks like `123456789:AA...`)
4. Paste it into `/setup`
### Discord bot token
1. Go to [https://discord.com/developers/applications](https://discord.com/developers/applications)
2. **New Application** → choose a name
3. **Bot** → **Add Bot**
4. **Enable MESSAGE CONTENT INTENT** under Bot → Privileged Gateway Intents (required or the bot will crash on startup)
5. Copy the **Bot Token** and paste into `/setup`
6. Invite the bot to your server (OAuth2 URL Generator; scopes: `bot`, `applications.commands`)

View File

@@ -0,0 +1,109 @@
---
summary: "Run OpenClaw in a rootless Podman container"
read_when:
- You want a containerized gateway with Podman instead of Docker
title: "Podman"
---
# Podman
Run the OpenClaw gateway in a **rootless** Podman container. Uses the same image as Docker (build from the repo [Dockerfile](https://github.com/openclaw/openclaw/blob/main/Dockerfile)).
## Requirements
- Podman (rootless)
- Sudo for one-time setup (create user, build image)
## Quick start
**1. One-time setup** (from repo root; creates user, builds image, installs launch script):
```bash
./setup-podman.sh
```
This also creates a minimal `~openclaw/.openclaw/openclaw.json` (sets `gateway.mode="local"`) so the gateway can start without running the wizard.
By default the container is **not** installed as a systemd service, you start it manually (see below). For a production-style setup with auto-start and restarts, install it as a systemd Quadlet user service instead:
```bash
./setup-podman.sh --quadlet
```
(Or set `OPENCLAW_PODMAN_QUADLET=1`; use `--container` to install only the container and launch script.)
**2. Start gateway** (manual, for quick smoke testing):
```bash
./scripts/run-openclaw-podman.sh launch
```
**3. Onboarding wizard** (e.g. to add channels or providers):
```bash
./scripts/run-openclaw-podman.sh launch setup
```
Then open `http://127.0.0.1:18789/` and use the token from `~openclaw/.openclaw/.env` (or the value printed by setup).
## Systemd (Quadlet, optional)
If you ran `./setup-podman.sh --quadlet` (or `OPENCLAW_PODMAN_QUADLET=1`), a [Podman Quadlet](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html) unit is installed so the gateway runs as a systemd user service for the openclaw user. The service is enabled and started at the end of setup.
- **Start:** `sudo systemctl --machine openclaw@ --user start openclaw.service`
- **Stop:** `sudo systemctl --machine openclaw@ --user stop openclaw.service`
- **Status:** `sudo systemctl --machine openclaw@ --user status openclaw.service`
- **Logs:** `sudo journalctl --machine openclaw@ --user -u openclaw.service -f`
The quadlet file lives at `~openclaw/.config/containers/systemd/openclaw.container`. To change ports or env, edit that file (or the `.env` it sources), then `sudo systemctl --machine openclaw@ --user daemon-reload` and restart the service. On boot, the service starts automatically if lingering is enabled for openclaw (setup does this when loginctl is available).
To add quadlet **after** an initial setup that did not use it, re-run: `./setup-podman.sh --quadlet`.
## The openclaw user (non-login)
`setup-podman.sh` creates a dedicated system user `openclaw`:
- **Shell:** `nologin` — no interactive login; reduces attack surface.
- **Home:** e.g. `/home/openclaw` — holds `~/.openclaw` (config, workspace) and the launch script `run-openclaw-podman.sh`.
- **Rootless Podman:** The user must have a **subuid** and **subgid** range. Many distros assign these automatically when the user is created. If setup prints a warning, add lines to `/etc/subuid` and `/etc/subgid`:
```text
openclaw:100000:65536
```
Then start the gateway as that user (e.g. from cron or systemd):
```bash
sudo -u openclaw /home/openclaw/run-openclaw-podman.sh
sudo -u openclaw /home/openclaw/run-openclaw-podman.sh setup
```
- **Config:** Only `openclaw` and root can access `/home/openclaw/.openclaw`. To edit config: use the Control UI once the gateway is running, or `sudo -u openclaw $EDITOR /home/openclaw/.openclaw/openclaw.json`.
## Environment and config
- **Token:** Stored in `~openclaw/.openclaw/.env` as `OPENCLAW_GATEWAY_TOKEN`. `setup-podman.sh` and `run-openclaw-podman.sh` generate it if missing (uses `openssl`, `python3`, or `od`).
- **Optional:** In that `.env` you can set provider keys (e.g. `GROQ_API_KEY`, `OLLAMA_API_KEY`) and other OpenClaw env vars.
- **Host ports:** By default the script maps `18789` (gateway) and `18790` (bridge). Override the **host** port mapping with `OPENCLAW_PODMAN_GATEWAY_HOST_PORT` and `OPENCLAW_PODMAN_BRIDGE_HOST_PORT` when launching.
- **Gateway bind:** By default, `run-openclaw-podman.sh` starts the gateway with `--bind loopback` for safe local access. To expose on LAN, set `OPENCLAW_GATEWAY_BIND=lan` and configure `gateway.controlUi.allowedOrigins` (or explicitly enable host-header fallback) in `openclaw.json`.
- **Paths:** Host config and workspace default to `~openclaw/.openclaw` and `~openclaw/.openclaw/workspace`. Override the host paths used by the launch script with `OPENCLAW_CONFIG_DIR` and `OPENCLAW_WORKSPACE_DIR`.
## Useful commands
- **Logs:** With quadlet: `sudo journalctl --machine openclaw@ --user -u openclaw.service -f`. With script: `sudo -u openclaw podman logs -f openclaw`
- **Stop:** With quadlet: `sudo systemctl --machine openclaw@ --user stop openclaw.service`. With script: `sudo -u openclaw podman stop openclaw`
- **Start again:** With quadlet: `sudo systemctl --machine openclaw@ --user start openclaw.service`. With script: re-run the launch script or `podman start openclaw`
- **Remove container:** `sudo -u openclaw podman rm -f openclaw` — config and workspace on the host are kept
## Troubleshooting
- **Permission denied (EACCES) on config or auth-profiles:** The container defaults to `--userns=keep-id` and runs as the same uid/gid as the host user running the script. Ensure your host `OPENCLAW_CONFIG_DIR` and `OPENCLAW_WORKSPACE_DIR` are owned by that user.
- **Gateway start blocked (missing `gateway.mode=local`):** Ensure `~openclaw/.openclaw/openclaw.json` exists and sets `gateway.mode="local"`. `setup-podman.sh` creates this file if missing.
- **Rootless Podman fails for user openclaw:** Check `/etc/subuid` and `/etc/subgid` contain a line for `openclaw` (e.g. `openclaw:100000:65536`). Add it if missing and restart.
- **Container name in use:** The launch script uses `podman run --replace`, so the existing container is replaced when you start again. To clean up manually: `podman rm -f openclaw`.
- **Script not found when running as openclaw:** Ensure `setup-podman.sh` was run so that `run-openclaw-podman.sh` is copied to openclaws home (e.g. `/home/openclaw/run-openclaw-podman.sh`).
- **Quadlet service not found or fails to start:** Run `sudo systemctl --machine openclaw@ --user daemon-reload` after editing the `.container` file. Quadlet requires cgroups v2: `podman info --format '{{.Host.CgroupsVersion}}'` should show `2`.
## Optional: run as your own user
To run the gateway as your normal user (no dedicated openclaw user): build the image, create `~/.openclaw/.env` with `OPENCLAW_GATEWAY_TOKEN`, and run the container with `--userns=keep-id` and mounts to your `~/.openclaw`. The launch script is designed for the openclaw-user flow; for a single-user setup you can instead run the `podman run` command from the script manually, pointing config and workspace to your home. Recommended for most users: use `setup-podman.sh` and run as the openclaw user so config and process are isolated.

View File

@@ -0,0 +1,99 @@
---
title: Deploy on Railway
---
Deploy OpenClaw on Railway with a one-click template and finish setup in your browser.
This is the easiest “no terminal on the server” path: Railway runs the Gateway for you,
and you configure everything via the `/setup` web wizard.
## Quick checklist (new users)
1. Click **Deploy on Railway** (below).
2. Add a **Volume** mounted at `/data`.
3. Set the required **Variables** (at least `SETUP_PASSWORD`).
4. Enable **HTTP Proxy** on port `8080`.
5. Open `https://<your-railway-domain>/setup` and finish the wizard.
## One-click deploy
<a href="https://railway.com/deploy/clawdbot-railway-template" target="_blank" rel="noreferrer">
Deploy on Railway
</a>
After deploy, find your public URL in **Railway → your service → Settings → Domains**.
Railway will either:
- give you a generated domain (often `https://<something>.up.railway.app`), or
- use your custom domain if you attached one.
Then open:
- `https://<your-railway-domain>/setup` — setup wizard (password protected)
- `https://<your-railway-domain>/openclaw` — Control UI
## What you get
- Hosted OpenClaw Gateway + Control UI
- Web setup wizard at `/setup` (no terminal commands)
- Persistent storage via Railway Volume (`/data`) so config/credentials/workspace survive redeploys
- Backup export at `/setup/export` to migrate off Railway later
## Required Railway settings
### Public Networking
Enable **HTTP Proxy** for the service.
- Port: `8080`
### Volume (required)
Attach a volume mounted at:
- `/data`
### Variables
Set these variables on the service:
- `SETUP_PASSWORD` (required)
- `PORT=8080` (required — must match the port in Public Networking)
- `OPENCLAW_STATE_DIR=/data/.openclaw` (recommended)
- `OPENCLAW_WORKSPACE_DIR=/data/workspace` (recommended)
- `OPENCLAW_GATEWAY_TOKEN` (recommended; treat as an admin secret)
## Setup flow
1. Visit `https://<your-railway-domain>/setup` and enter your `SETUP_PASSWORD`.
2. Choose a model/auth provider and paste your key.
3. (Optional) Add Telegram/Discord/Slack tokens.
4. Click **Run setup**.
If Telegram DMs are set to pairing, the setup wizard can approve the pairing code.
## Getting chat tokens
### Telegram bot token
1. Message `@BotFather` in Telegram
2. Run `/newbot`
3. Copy the token (looks like `123456789:AA...`)
4. Paste it into `/setup`
### Discord bot token
1. Go to [https://discord.com/developers/applications](https://discord.com/developers/applications)
2. **New Application** → choose a name
3. **Bot** → **Add Bot**
4. **Enable MESSAGE CONTENT INTENT** under Bot → Privileged Gateway Intents (required or the bot will crash on startup)
5. Copy the **Bot Token** and paste into `/setup`
6. Invite the bot to your server (OAuth2 URL Generator; scopes: `bot`, `applications.commands`)
## Backups & migration
Download a backup at:
- `https://<your-railway-domain>/setup/export`
This exports your OpenClaw state + workspace so you can migrate to another host without losing config or memory.

View File

@@ -0,0 +1,159 @@
---
title: Deploy on Render
---
Deploy OpenClaw on Render using Infrastructure as Code. The included `render.yaml` Blueprint defines your entire stack declaratively, service, disk, environment variables, so you can deploy with a single click and version your infrastructure alongside your code.
## Prerequisites
- A [Render account](https://render.com) (free tier available)
- An API key from your preferred [model provider](/providers)
## Deploy with a Render Blueprint
[Deploy to Render](https://render.com/deploy?repo=https://github.com/openclaw/openclaw)
Clicking this link will:
1. Create a new Render service from the `render.yaml` Blueprint at the root of this repo.
2. Prompt you to set `SETUP_PASSWORD`
3. Build the Docker image and deploy
Once deployed, your service URL follows the pattern `https://<service-name>.onrender.com`.
## Understanding the Blueprint
Render Blueprints are YAML files that define your infrastructure. The `render.yaml` in this
repository configures everything needed to run OpenClaw:
```yaml
services:
- type: web
name: openclaw
runtime: docker
plan: starter
healthCheckPath: /health
envVars:
- key: PORT
value: "8080"
- key: SETUP_PASSWORD
sync: false # prompts during deploy
- key: OPENCLAW_STATE_DIR
value: /data/.openclaw
- key: OPENCLAW_WORKSPACE_DIR
value: /data/workspace
- key: OPENCLAW_GATEWAY_TOKEN
generateValue: true # auto-generates a secure token
disk:
name: openclaw-data
mountPath: /data
sizeGB: 1
```
Key Blueprint features used:
| Feature | Purpose |
| --------------------- | ---------------------------------------------------------- |
| `runtime: docker` | Builds from the repo's Dockerfile |
| `healthCheckPath` | Render monitors `/health` and restarts unhealthy instances |
| `sync: false` | Prompts for value during deploy (secrets) |
| `generateValue: true` | Auto-generates a cryptographically secure value |
| `disk` | Persistent storage that survives redeploys |
## Choosing a plan
| Plan | Spin-down | Disk | Best for |
| --------- | ----------------- | ------------- | ----------------------------- |
| Free | After 15 min idle | Not available | Testing, demos |
| Starter | Never | 1GB+ | Personal use, small teams |
| Standard+ | Never | 1GB+ | Production, multiple channels |
The Blueprint defaults to `starter`. To use free tier, change `plan: free` in your fork's
`render.yaml` (but note: no persistent disk means config resets on each deploy).
## After deployment
### Complete the setup wizard
1. Navigate to `https://<your-service>.onrender.com/setup`
2. Enter your `SETUP_PASSWORD`
3. Select a model provider and paste your API key
4. Optionally configure messaging channels (Telegram, Discord, Slack)
5. Click **Run setup**
### Access the Control UI
The web dashboard is available at `https://<your-service>.onrender.com/openclaw`.
## Render Dashboard features
### Logs
View real-time logs in **Dashboard → your service → Logs**. Filter by:
- Build logs (Docker image creation)
- Deploy logs (service startup)
- Runtime logs (application output)
### Shell access
For debugging, open a shell session via **Dashboard → your service → Shell**. The persistent disk is mounted at `/data`.
### Environment variables
Modify variables in **Dashboard → your service → Environment**. Changes trigger an automatic redeploy.
### Auto-deploy
If you use the original OpenClaw repository, Render will not auto-deploy your OpenClaw. To update it, run a manual Blueprint sync from the dashboard.
## Custom domain
1. Go to **Dashboard → your service → Settings → Custom Domains**
2. Add your domain
3. Configure DNS as instructed (CNAME to `*.onrender.com`)
4. Render provisions a TLS certificate automatically
## Scaling
Render supports horizontal and vertical scaling:
- **Vertical**: Change the plan to get more CPU/RAM
- **Horizontal**: Increase instance count (Standard plan and above)
For OpenClaw, vertical scaling is usually sufficient. Horizontal scaling requires sticky sessions or external state management.
## Backups and migration
Export your configuration and workspace at any time:
```
https://<your-service>.onrender.com/setup/export
```
This downloads a portable backup you can restore on any OpenClaw host.
## Troubleshooting
### Service won't start
Check the deploy logs in the Render Dashboard. Common issues:
- Missing `SETUP_PASSWORD` — the Blueprint prompts for this, but verify it's set
- Port mismatch — ensure `PORT=8080` matches the Dockerfile's exposed port
### Slow cold starts (free tier)
Free tier services spin down after 15 minutes of inactivity. The first request after spin-down takes a few seconds while the container starts. Upgrade to Starter plan for always-on.
### Data loss after redeploy
This happens on free tier (no persistent disk). Upgrade to a paid plan, or
regularly export your config via `/setup/export`.
### Health check failures
Render expects a 200 response from `/health` within 30 seconds. If builds succeed but deploys fail, the service may be taking too long to start. Check:
- Build logs for errors
- Whether the container runs locally with `docker build && docker run`

View File

@@ -0,0 +1,128 @@
---
summary: "Uninstall OpenClaw completely (CLI, service, state, workspace)"
read_when:
- You want to remove OpenClaw from a machine
- The gateway service is still running after uninstall
title: "Uninstall"
---
# Uninstall
Two paths:
- **Easy path** if `openclaw` is still installed.
- **Manual service removal** if the CLI is gone but the service is still running.
## Easy path (CLI still installed)
Recommended: use the built-in uninstaller:
```bash
openclaw uninstall
```
Non-interactive (automation / npx):
```bash
openclaw uninstall --all --yes --non-interactive
npx -y openclaw uninstall --all --yes --non-interactive
```
Manual steps (same result):
1. Stop the gateway service:
```bash
openclaw gateway stop
```
2. Uninstall the gateway service (launchd/systemd/schtasks):
```bash
openclaw gateway uninstall
```
3. Delete state + config:
```bash
rm -rf "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
```
If you set `OPENCLAW_CONFIG_PATH` to a custom location outside the state dir, delete that file too.
4. Delete your workspace (optional, removes agent files):
```bash
rm -rf ~/.openclaw/workspace
```
5. Remove the CLI install (pick the one you used):
```bash
npm rm -g openclaw
pnpm remove -g openclaw
bun remove -g openclaw
```
6. If you installed the macOS app:
```bash
rm -rf /Applications/OpenClaw.app
```
Notes:
- If you used profiles (`--profile` / `OPENCLAW_PROFILE`), repeat step 3 for each state dir (defaults are `~/.openclaw-<profile>`).
- In remote mode, the state dir lives on the **gateway host**, so run steps 1-4 there too.
## Manual service removal (CLI not installed)
Use this if the gateway service keeps running but `openclaw` is missing.
### macOS (launchd)
Default label is `ai.openclaw.gateway` (or `ai.openclaw.<profile>`; legacy `com.openclaw.*` may still exist):
```bash
launchctl bootout gui/$UID/ai.openclaw.gateway
rm -f ~/Library/LaunchAgents/ai.openclaw.gateway.plist
```
If you used a profile, replace the label and plist name with `ai.openclaw.<profile>`. Remove any legacy `com.openclaw.*` plists if present.
### Linux (systemd user unit)
Default unit name is `openclaw-gateway.service` (or `openclaw-gateway-<profile>.service`):
```bash
systemctl --user disable --now openclaw-gateway.service
rm -f ~/.config/systemd/user/openclaw-gateway.service
systemctl --user daemon-reload
```
### Windows (Scheduled Task)
Default task name is `OpenClaw Gateway` (or `OpenClaw Gateway (<profile>)`).
The task script lives under your state dir.
```powershell
schtasks /Delete /F /TN "OpenClaw Gateway"
Remove-Item -Force "$env:USERPROFILE\.openclaw\gateway.cmd"
```
If you used a profile, delete the matching task name and `~\.openclaw-<profile>\gateway.cmd`.
## Normal install vs source checkout
### Normal install (install.sh / npm / pnpm / bun)
If you used `https://openclaw.ai/install.sh` or `install.ps1`, the CLI was installed with `npm install -g openclaw@latest`.
Remove it with `npm rm -g openclaw` (or `pnpm remove -g` / `bun remove -g` if you installed that way).
### Source checkout (git clone)
If you run from a repo checkout (`git clone` + `openclaw ...` / `bun run openclaw ...`):
1. Uninstall the gateway service **before** deleting the repo (use the easy path above or manual service removal).
2. Delete the repo directory.
3. Remove state + workspace as shown above.

View File

@@ -0,0 +1,257 @@
---
summary: "Updating OpenClaw safely (global install or source), plus rollback strategy"
read_when:
- Updating OpenClaw
- Something breaks after an update
title: "Updating"
---
# Updating
OpenClaw is moving fast (pre “1.0”). Treat updates like shipping infra: update → run checks → restart (or use `openclaw update`, which restarts) → verify.
## Recommended: re-run the website installer (upgrade in place)
The **preferred** update path is to re-run the installer from the website. It
detects existing installs, upgrades in place, and runs `openclaw doctor` when
needed.
```bash
curl -fsSL https://openclaw.ai/install.sh | bash
```
Notes:
- Add `--no-onboard` if you dont want the onboarding wizard to run again.
- For **source installs**, use:
```bash
curl -fsSL https://openclaw.ai/install.sh | bash -s -- --install-method git --no-onboard
```
The installer will `git pull --rebase` **only** if the repo is clean.
- For **global installs**, the script uses `npm install -g openclaw@latest` under the hood.
- Legacy note: `clawdbot` remains available as a compatibility shim.
## Before you update
- Know how you installed: **global** (npm/pnpm) vs **from source** (git clone).
- Know how your Gateway is running: **foreground terminal** vs **supervised service** (launchd/systemd).
- Snapshot your tailoring:
- Config: `~/.openclaw/openclaw.json`
- Credentials: `~/.openclaw/credentials/`
- Workspace: `~/.openclaw/workspace`
## Update (global install)
Global install (pick one):
```bash
npm i -g openclaw@latest
```
```bash
pnpm add -g openclaw@latest
```
We do **not** recommend Bun for the Gateway runtime (WhatsApp/Telegram bugs).
To switch update channels (git + npm installs):
```bash
openclaw update --channel beta
openclaw update --channel dev
openclaw update --channel stable
```
Use `--tag <dist-tag|version>` for a one-off install tag/version.
See [Development channels](/install/development-channels) for channel semantics and release notes.
Note: on npm installs, the gateway logs an update hint on startup (checks the current channel tag). Disable via `update.checkOnStart: false`.
### Core auto-updater (optional)
Auto-updater is **off by default** and is a core Gateway feature (not a plugin).
```json
{
"update": {
"channel": "stable",
"auto": {
"enabled": true,
"stableDelayHours": 6,
"stableJitterHours": 12,
"betaCheckIntervalHours": 1
}
}
}
```
Behavior:
- `stable`: when a new version is seen, OpenClaw waits `stableDelayHours` and then applies a deterministic per-install jitter in `stableJitterHours` (spread rollout).
- `beta`: checks on `betaCheckIntervalHours` cadence (default: hourly) and applies when an update is available.
- `dev`: no automatic apply; use manual `openclaw update`.
Use `openclaw update --dry-run` to preview update actions before enabling automation.
Then:
```bash
openclaw doctor
openclaw gateway restart
openclaw health
```
Notes:
- If your Gateway runs as a service, `openclaw gateway restart` is preferred over killing PIDs.
- If youre pinned to a specific version, see “Rollback / pinning” below.
## Update (`openclaw update`)
For **source installs** (git checkout), prefer:
```bash
openclaw update
```
It runs a safe-ish update flow:
- Requires a clean worktree.
- Switches to the selected channel (tag or branch).
- Fetches + rebases against the configured upstream (dev channel).
- Installs deps, builds, builds the Control UI, and runs `openclaw doctor`.
- Restarts the gateway by default (use `--no-restart` to skip).
If you installed via **npm/pnpm** (no git metadata), `openclaw update` will try to update via your package manager. If it cant detect the install, use “Update (global install)” instead.
## Update (Control UI / RPC)
The Control UI has **Update & Restart** (RPC: `update.run`). It:
1. Runs the same source-update flow as `openclaw update` (git checkout only).
2. Writes a restart sentinel with a structured report (stdout/stderr tail).
3. Restarts the gateway and pings the last active session with the report.
If the rebase fails, the gateway aborts and restarts without applying the update.
## Update (from source)
From the repo checkout:
Preferred:
```bash
openclaw update
```
Manual (equivalent-ish):
```bash
git pull
pnpm install
pnpm build
pnpm ui:build # auto-installs UI deps on first run
openclaw doctor
openclaw health
```
Notes:
- `pnpm build` matters when you run the packaged `openclaw` binary ([`openclaw.mjs`](https://github.com/openclaw/openclaw/blob/main/openclaw.mjs)) or use Node to run `dist/`.
- If you run from a repo checkout without a global install, use `pnpm openclaw ...` for CLI commands.
- If you run directly from TypeScript (`pnpm openclaw ...`), a rebuild is usually unnecessary, but **config migrations still apply** → run doctor.
- Switching between global and git installs is easy: install the other flavor, then run `openclaw doctor` so the gateway service entrypoint is rewritten to the current install.
## Always Run: `openclaw doctor`
Doctor is the “safe update” command. Its intentionally boring: repair + migrate + warn.
Note: if youre on a **source install** (git checkout), `openclaw doctor` will offer to run `openclaw update` first.
Typical things it does:
- Migrate deprecated config keys / legacy config file locations.
- Audit DM policies and warn on risky “open” settings.
- Check Gateway health and can offer to restart.
- Detect and migrate older gateway services (launchd/systemd; legacy schtasks) to current OpenClaw services.
- On Linux, ensure systemd user lingering (so the Gateway survives logout).
Details: [Doctor](/gateway/doctor)
## Start / stop / restart the Gateway
CLI (works regardless of OS):
```bash
openclaw gateway status
openclaw gateway stop
openclaw gateway restart
openclaw gateway --port 18789
openclaw logs --follow
```
If youre supervised:
- macOS launchd (app-bundled LaunchAgent): `launchctl kickstart -k gui/$UID/ai.openclaw.gateway` (use `ai.openclaw.<profile>`; legacy `com.openclaw.*` still works)
- Linux systemd user service: `systemctl --user restart openclaw-gateway[-<profile>].service`
- Windows (WSL2): `systemctl --user restart openclaw-gateway[-<profile>].service`
- `launchctl`/`systemctl` only work if the service is installed; otherwise run `openclaw gateway install`.
Runbook + exact service labels: [Gateway runbook](/gateway)
## Rollback / pinning (when something breaks)
### Pin (global install)
Install a known-good version (replace `<version>` with the last working one):
```bash
npm i -g openclaw@<version>
```
```bash
pnpm add -g openclaw@<version>
```
Tip: to see the current published version, run `npm view openclaw version`.
Then restart + re-run doctor:
```bash
openclaw doctor
openclaw gateway restart
```
### Pin (source) by date
Pick a commit from a date (example: “state of main as of 2026-01-01”):
```bash
git fetch origin
git checkout "$(git rev-list -n 1 --before=\"2026-01-01\" origin/main)"
```
Then reinstall deps + restart:
```bash
pnpm install
pnpm build
openclaw gateway restart
```
If you want to go back to latest later:
```bash
git checkout main
git pull
```
## If youre stuck
- Run `openclaw doctor` again and read the output carefully (it often tells you the fix).
- Check: [Troubleshooting](/gateway/troubleshooting)
- Ask in Discord: [https://discord.gg/clawd](https://discord.gg/clawd)