2026-01-02 20:58:50 +01:00
---
2026-01-31 21:13:13 +09:00
summary: "Optional Docker-based setup and onboarding for OpenClaw"
2026-01-02 20:58:50 +01:00
read_when:
- You want a containerized gateway instead of local installs
- You are validating the Docker flow
2026-01-31 16:04:03 -05:00
title: "Docker"
2026-01-02 20:58:50 +01:00
---
# Docker (optional)
Docker is **optional** . Use it only if you want a containerized gateway or to validate the Docker flow.
2026-01-08 21:56:41 +01:00
## Is Docker right for me?
2026-01-30 03:15:10 +01:00
- **Yes**: you want an isolated, throwaway gateway environment or to run OpenClaw on a host without local installs.
2026-03-19 12:07:37 -07:00
- **No**: you are running on your own machine and just want the fastest dev loop. Use the normal install flow instead.
2026-01-08 21:56:41 +01:00
- **Sandboxing note**: agent sandboxing uses Docker too, but it does **not** require the full gateway to run in Docker. See [Sandboxing ](/gateway/sandboxing ).
2026-03-19 12:07:37 -07:00
## Prerequisites
2026-01-03 21:35:44 +01:00
- Docker Desktop (or Docker Engine) + Docker Compose v2
2026-02-25 08:35:48 +01:00
- At least 2 GB RAM for image build (`pnpm install` may be OOM-killed on 1 GB hosts with exit 137)
2026-03-19 12:07:37 -07:00
- Enough disk for images and logs
2026-03-03 23:28:35 +03:00
- If running on a VPS/public host, review
2026-03-19 10:31:20 -07:00
[Security hardening for network exposure ](/gateway/security#0-4-network-exposure-bind-port-firewall ),
2026-03-03 23:28:35 +03:00
especially Docker `DOCKER-USER` firewall policy.
2026-01-03 21:35:44 +01:00
2026-03-19 12:07:37 -07:00
## Containerized Gateway
2026-01-03 21:35:44 +01:00
2026-03-19 12:07:37 -07:00
< Steps >
< Step title = "Build the image" >
From the repo root, run the setup script:
2026-01-03 21:35:44 +01:00
2026-03-19 12:07:37 -07:00
```bash
2026-03-19 13:40:10 -07:00
./scripts/docker/setup.sh
2026-03-19 12:07:37 -07:00
```
2026-03-02 09:15:27 +05:30
2026-03-19 12:07:37 -07:00
This builds the gateway image locally. To use a pre-built image instead:
2026-01-02 20:58:50 +01:00
2026-03-19 12:07:37 -07:00
```bash
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
2026-03-19 13:40:10 -07:00
./scripts/docker/setup.sh
2026-03-19 12:07:37 -07:00
```
2026-01-02 20:58:50 +01:00
2026-03-19 12:07:37 -07:00
Pre-built images are published at the
[GitHub Container Registry ](https://github.com/openclaw/openclaw/pkgs/container/openclaw ).
Common tags: `main` , `latest` , `<version>` (e.g. `2026.2.26` ).
2026-01-31 18:31:49 +09:00
2026-03-19 12:07:37 -07:00
< / Step >
2026-01-08 21:56:41 +01:00
2026-03-19 12:07:37 -07:00
< Step title = "Complete onboarding" >
The setup script runs onboarding automatically. It will:
- prompt for provider API keys
- generate a gateway token and write it to `.env`
- start the gateway via Docker Compose
2026-01-31 18:31:49 +09:00
2026-03-19 12:07:37 -07:00
< / Step >
2026-01-11 03:27:48 +01:00
2026-03-19 12:07:37 -07:00
< Step title = "Open the Control UI" >
Open `http://127.0.0.1:18789/` in your browser and paste the token into
Settings.
2026-01-31 18:31:49 +09:00
2026-03-19 12:07:37 -07:00
Need the URL again?
2026-01-02 20:58:50 +01:00
2026-03-19 12:07:37 -07:00
```bash
docker compose run --rm openclaw-cli dashboard --no-open
```
feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments
Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).
Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
build sandbox image, configure sandbox defaults, add group_add
All changes are opt-in. Zero impact on existing deployments.
Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh
Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review feedback on sandbox support
- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
by using printf instead of echo with line continuation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove `local` outside function and guard sandbox behind Docker CLI check
- Remove `local` keyword from top-level `sandbox_config_ok` assignment
which caused script exit under `set -euo pipefail` (bash `local`
outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
runs `docker --version` inside the container and skips sandbox setup
with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: defer docker.sock mount until sandbox prerequisites pass
Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host
Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.
Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(docker): fix sandbox docs URL in setup output
* Docker: harden sandbox setup fallback behavior
* Tests: cover docker-setup sandbox edge paths
* Docker: roll back sandbox mode on partial config failure
* Tests: assert sandbox mode rollback on partial setup
* Docs: document Docker sandbox bootstrap env controls
* Changelog: credit Docker sandbox bootstrap hardening
* Update CHANGELOG.md
* Docker: verify Docker apt signing key fingerprint
* Docker: avoid sandbox overlay deps during policy writes
* Tests: assert no-deps sandbox rollback gateway recreate
* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars
---------
Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 08:06:10 +01:00
2026-03-19 12:07:37 -07:00
< / Step >
feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments
Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).
Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
build sandbox image, configure sandbox defaults, add group_add
All changes are opt-in. Zero impact on existing deployments.
Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh
Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review feedback on sandbox support
- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
by using printf instead of echo with line continuation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove `local` outside function and guard sandbox behind Docker CLI check
- Remove `local` keyword from top-level `sandbox_config_ok` assignment
which caused script exit under `set -euo pipefail` (bash `local`
outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
runs `docker --version` inside the container and skips sandbox setup
with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: defer docker.sock mount until sandbox prerequisites pass
Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host
Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.
Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(docker): fix sandbox docs URL in setup output
* Docker: harden sandbox setup fallback behavior
* Tests: cover docker-setup sandbox edge paths
* Docker: roll back sandbox mode on partial config failure
* Tests: assert sandbox mode rollback on partial setup
* Docs: document Docker sandbox bootstrap env controls
* Changelog: credit Docker sandbox bootstrap hardening
* Update CHANGELOG.md
* Docker: verify Docker apt signing key fingerprint
* Docker: avoid sandbox overlay deps during policy writes
* Tests: assert no-deps sandbox rollback gateway recreate
* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars
---------
Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 08:06:10 +01:00
2026-03-19 12:07:37 -07:00
< Step title = "Configure channels (optional)" >
Use the CLI container to add messaging channels:
feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments
Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).
Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
build sandbox image, configure sandbox defaults, add group_add
All changes are opt-in. Zero impact on existing deployments.
Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh
Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review feedback on sandbox support
- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
by using printf instead of echo with line continuation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove `local` outside function and guard sandbox behind Docker CLI check
- Remove `local` keyword from top-level `sandbox_config_ok` assignment
which caused script exit under `set -euo pipefail` (bash `local`
outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
runs `docker --version` inside the container and skips sandbox setup
with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: defer docker.sock mount until sandbox prerequisites pass
Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host
Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.
Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(docker): fix sandbox docs URL in setup output
* Docker: harden sandbox setup fallback behavior
* Tests: cover docker-setup sandbox edge paths
* Docker: roll back sandbox mode on partial config failure
* Tests: assert sandbox mode rollback on partial setup
* Docs: document Docker sandbox bootstrap env controls
* Changelog: credit Docker sandbox bootstrap hardening
* Update CHANGELOG.md
* Docker: verify Docker apt signing key fingerprint
* Docker: avoid sandbox overlay deps during policy writes
* Tests: assert no-deps sandbox rollback gateway recreate
* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars
---------
Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 08:06:10 +01:00
2026-03-19 12:07:37 -07:00
```bash
# WhatsApp (QR)
docker compose run --rm openclaw-cli channels login
feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments
Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).
Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
build sandbox image, configure sandbox defaults, add group_add
All changes are opt-in. Zero impact on existing deployments.
Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh
Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review feedback on sandbox support
- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
by using printf instead of echo with line continuation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove `local` outside function and guard sandbox behind Docker CLI check
- Remove `local` keyword from top-level `sandbox_config_ok` assignment
which caused script exit under `set -euo pipefail` (bash `local`
outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
runs `docker --version` inside the container and skips sandbox setup
with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: defer docker.sock mount until sandbox prerequisites pass
Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host
Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.
Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(docker): fix sandbox docs URL in setup output
* Docker: harden sandbox setup fallback behavior
* Tests: cover docker-setup sandbox edge paths
* Docker: roll back sandbox mode on partial config failure
* Tests: assert sandbox mode rollback on partial setup
* Docs: document Docker sandbox bootstrap env controls
* Changelog: credit Docker sandbox bootstrap hardening
* Update CHANGELOG.md
* Docker: verify Docker apt signing key fingerprint
* Docker: avoid sandbox overlay deps during policy writes
* Tests: assert no-deps sandbox rollback gateway recreate
* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars
---------
Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 08:06:10 +01:00
2026-03-19 12:07:37 -07:00
# Telegram
docker compose run --rm openclaw-cli channels add --channel telegram --token "< token > "
feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments
Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).
Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
build sandbox image, configure sandbox defaults, add group_add
All changes are opt-in. Zero impact on existing deployments.
Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh
Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review feedback on sandbox support
- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
by using printf instead of echo with line continuation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove `local` outside function and guard sandbox behind Docker CLI check
- Remove `local` keyword from top-level `sandbox_config_ok` assignment
which caused script exit under `set -euo pipefail` (bash `local`
outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
runs `docker --version` inside the container and skips sandbox setup
with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: defer docker.sock mount until sandbox prerequisites pass
Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host
Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.
Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(docker): fix sandbox docs URL in setup output
* Docker: harden sandbox setup fallback behavior
* Tests: cover docker-setup sandbox edge paths
* Docker: roll back sandbox mode on partial config failure
* Tests: assert sandbox mode rollback on partial setup
* Docs: document Docker sandbox bootstrap env controls
* Changelog: credit Docker sandbox bootstrap hardening
* Update CHANGELOG.md
* Docker: verify Docker apt signing key fingerprint
* Docker: avoid sandbox overlay deps during policy writes
* Tests: assert no-deps sandbox rollback gateway recreate
* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars
---------
Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 08:06:10 +01:00
2026-03-19 12:07:37 -07:00
# Discord
docker compose run --rm openclaw-cli channels add --channel discord --token "< token > "
```
feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments
Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).
Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
build sandbox image, configure sandbox defaults, add group_add
All changes are opt-in. Zero impact on existing deployments.
Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh
Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review feedback on sandbox support
- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
by using printf instead of echo with line continuation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove `local` outside function and guard sandbox behind Docker CLI check
- Remove `local` keyword from top-level `sandbox_config_ok` assignment
which caused script exit under `set -euo pipefail` (bash `local`
outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
runs `docker --version` inside the container and skips sandbox setup
with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: defer docker.sock mount until sandbox prerequisites pass
Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host
Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.
Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(docker): fix sandbox docs URL in setup output
* Docker: harden sandbox setup fallback behavior
* Tests: cover docker-setup sandbox edge paths
* Docker: roll back sandbox mode on partial config failure
* Tests: assert sandbox mode rollback on partial setup
* Docs: document Docker sandbox bootstrap env controls
* Changelog: credit Docker sandbox bootstrap hardening
* Update CHANGELOG.md
* Docker: verify Docker apt signing key fingerprint
* Docker: avoid sandbox overlay deps during policy writes
* Tests: assert no-deps sandbox rollback gateway recreate
* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars
---------
Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 08:06:10 +01:00
2026-03-19 12:07:37 -07:00
Docs: [WhatsApp ](/channels/whatsapp ), [Telegram ](/channels/telegram ), [Discord ](/channels/discord )
feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments
Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).
Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
build sandbox image, configure sandbox defaults, add group_add
All changes are opt-in. Zero impact on existing deployments.
Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh
Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review feedback on sandbox support
- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
by using printf instead of echo with line continuation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove `local` outside function and guard sandbox behind Docker CLI check
- Remove `local` keyword from top-level `sandbox_config_ok` assignment
which caused script exit under `set -euo pipefail` (bash `local`
outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
runs `docker --version` inside the container and skips sandbox setup
with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: defer docker.sock mount until sandbox prerequisites pass
Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host
Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.
Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(docker): fix sandbox docs URL in setup output
* Docker: harden sandbox setup fallback behavior
* Tests: cover docker-setup sandbox edge paths
* Docker: roll back sandbox mode on partial config failure
* Tests: assert sandbox mode rollback on partial setup
* Docs: document Docker sandbox bootstrap env controls
* Changelog: credit Docker sandbox bootstrap hardening
* Update CHANGELOG.md
* Docker: verify Docker apt signing key fingerprint
* Docker: avoid sandbox overlay deps during policy writes
* Tests: assert no-deps sandbox rollback gateway recreate
* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars
---------
Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 08:06:10 +01:00
2026-03-19 12:07:37 -07:00
< / Step >
< / Steps >
feat(docker): add opt-in sandbox support for Docker deployments (#29974)
* feat(docker): add opt-in sandbox support for Docker deployments
Enable Docker-based sandbox isolation via OPENCLAW_SANDBOX=1 env var
in docker-setup.sh. This is a prerequisite for agents.defaults.sandbox
to function in any Docker deployment (self-hosted, Hostinger, DigitalOcean).
Changes:
- Dockerfile: add OPENCLAW_INSTALL_DOCKER_CLI build arg (~50MB, opt-in)
- docker-compose.yml: add commented-out docker.sock mount with docs
- docker-setup.sh: auto-detect Docker socket, inject mount, detect GID,
build sandbox image, configure sandbox defaults, add group_add
All changes are opt-in. Zero impact on existing deployments.
Usage: OPENCLAW_SANDBOX=1 ./docker-setup.sh
Closes #29933
Related: #7575, #7827, #28401, #10361, #12505, #28326
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address code review feedback on sandbox support
- Persist OPENCLAW_SANDBOX, DOCKER_GID, OPENCLAW_INSTALL_DOCKER_CLI
to .env via upsert_env so group_add survives re-runs
- Show config set errors instead of swallowing them silently;
report partial failure when sandbox config is incomplete
- Warn when Dockerfile.sandbox is missing but sandbox config
is still applied (sandbox image won't exist)
- Fix non-canonical whitespace in apt sources.list entry
by using printf instead of echo with line continuation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: remove `local` outside function and guard sandbox behind Docker CLI check
- Remove `local` keyword from top-level `sandbox_config_ok` assignment
which caused script exit under `set -euo pipefail` (bash `local`
outside a function is an error)
- Add Docker CLI prerequisite check for pre-built (non-local) images:
runs `docker --version` inside the container and skips sandbox setup
with a clear warning if the CLI is missing
- Split sandbox block so config is only applied after prerequisites pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: defer docker.sock mount until sandbox prerequisites pass
Move Docker socket mounting from the early setup phase (before image
build/pull) to a dedicated compose overlay created only after:
1. Docker CLI is verified inside the container image
2. /var/run/docker.sock exists on the host
Previously the socket was mounted optimistically at startup, leaving
the host Docker daemon exposed even when sandbox setup was later
skipped due to missing Docker CLI. Now the gateway starts without
the socket, and a docker-compose.sandbox.yml overlay is generated
only when all prerequisites pass. The gateway restart at the end of
sandbox setup picks up both the socket mount and sandbox config.
Also moves group_add from write_extra_compose() into the sandbox
overlay, keeping all sandbox-specific compose configuration together.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs(docker): fix sandbox docs URL in setup output
* Docker: harden sandbox setup fallback behavior
* Tests: cover docker-setup sandbox edge paths
* Docker: roll back sandbox mode on partial config failure
* Tests: assert sandbox mode rollback on partial setup
* Docs: document Docker sandbox bootstrap env controls
* Changelog: credit Docker sandbox bootstrap hardening
* Update CHANGELOG.md
* Docker: verify Docker apt signing key fingerprint
* Docker: avoid sandbox overlay deps during policy writes
* Tests: assert no-deps sandbox rollback gateway recreate
* Docs: mention OPENCLAW_INSTALL_DOCKER_CLI in Docker env vars
---------
Co-authored-by: Jakub Karwowski <jakubkarwowski@Mac.lan>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-02 08:06:10 +01:00
2026-03-19 12:07:37 -07:00
### Manual flow
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
If you prefer to run each step yourself instead of using the setup script:
2026-03-02 08:28:35 +07:00
```bash
2026-01-30 03:15:10 +01:00
docker build -t openclaw:local -f Dockerfile .
docker compose run --rm openclaw-cli onboard
docker compose up -d openclaw-gateway
2026-03-02 08:28:35 +07:00
```
2026-03-19 12:07:37 -07:00
< 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 with `-f docker-compose.yml -f docker-compose.extra.yml` .
< / Note >
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
### Environment variables
2026-01-31 18:31:49 +09:00
2026-03-19 12:07:37 -07:00
The setup script accepts these optional environment variables:
2026-01-02 20:58:50 +01:00
2026-03-19 16:53:43 -07:00
| Variable | Purpose |
| ------------------------------------ | ---------------------------------------------------------------- |
| `OPENCLAW_IMAGE` | Use a remote image instead of building locally |
| `OPENCLAW_DOCKER_APT_PACKAGES` | Install extra apt packages during build (space-separated) |
| `OPENCLAW_INSTALL_BROWSER` | Install Chromium and Playwright deps during the image build |
| `OPENCLAW_EXTENSIONS` | Pre-install extension deps at build time (space-separated names) |
| `OPENCLAW_EXTRA_MOUNTS` | Extra host bind mounts (comma-separated `source:target[:opts]` ) |
| `OPENCLAW_HOME_VOLUME` | Persist `/home/node` in a named Docker volume |
| `OPENCLAW_SANDBOX` | Opt in to sandbox bootstrap (`1` , `true` , `yes` , `on` ) |
| `OPENCLAW_DOCKER_SOCKET` | Override Docker socket path |
| `OPENCLAW_INSTALL_DOCKER_CLI` | Install Docker CLI in the image (auto-set for sandbox bootstrap) |
| `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS` | Allow trusted private-network `ws://` client targets |
| `OPENCLAW_TZ` | Set container timezone (for example `America/Los_Angeles` ) |
2026-01-09 18:21:28 +01:00
2026-03-01 18:31:20 -08:00
### Use a remote image (skip local build)
Use image name `ghcr.io/openclaw/openclaw` (not similarly named Docker Hub
images).
Common tags:
- `main` — latest build from `main`
2026-03-19 16:53:43 -07:00
- `<version>` — release tag builds (for example `2026.3.12` )
2026-03-01 18:31:20 -08:00
- `latest` — latest stable release tag
```bash
export OPENCLAW_IMAGE="ghcr.io/openclaw/openclaw:latest"
2026-03-19 16:53:43 -07:00
./scripts/docker/setup.sh
2026-02-02 04:25:57 -08:00
```
2026-01-10 20:12:23 +00:00
### Extra mounts (optional)
2026-03-19 16:53:43 -07:00
Set `OPENCLAW_EXTRA_MOUNTS` to add host directories to both containers:
2026-01-10 20:12:23 +00:00
```bash
2026-01-30 03:15:10 +01:00
export OPENCLAW_EXTRA_MOUNTS="$HOME/.codex:/home/node/.codex:ro,$HOME/github:/home/node/github:rw"
2026-03-19 16:53:43 -07:00
./scripts/docker/setup.sh
2026-01-10 20:12:23 +00:00
```
Notes:
2026-01-31 18:31:49 +09:00
2026-01-10 20:12:23 +00:00
- Paths must be shared with Docker Desktop on macOS/Windows.
2026-03-19 16:53:43 -07:00
- Each entry must be `source:target[:options]` with no spaces or control characters.
- Rerun the setup script after changing the value so `docker-compose.extra.yml`
is regenerated.
2026-01-10 20:12:23 +00:00
### Persist the entire container home (optional)
2026-03-19 16:53:43 -07:00
Use `OPENCLAW_HOME_VOLUME` if you want `/home/node` to survive container
recreation:
2026-01-10 20:12:23 +00:00
```bash
2026-01-30 03:15:10 +01:00
export OPENCLAW_HOME_VOLUME="openclaw_home"
2026-03-19 16:53:43 -07:00
./scripts/docker/setup.sh
2026-01-10 20:12:23 +00:00
```
2026-01-11 00:06:19 +00:00
### Install extra apt packages (optional)
2026-03-19 16:53:43 -07:00
`OPENCLAW_DOCKER_APT_PACKAGES` installs additional Debian packages at build time:
2026-01-11 00:06:19 +00:00
```bash
2026-01-30 03:15:10 +01:00
export OPENCLAW_DOCKER_APT_PACKAGES="ffmpeg build-essential"
2026-03-19 16:53:43 -07:00
./scripts/docker/setup.sh
2026-03-06 12:18:42 -05:00
```
2026-03-19 16:53:43 -07:00
The Docker image already includes a baseline for common container workflows:
`cron` , `gosu` , `pnpm` , non-root `npm -g` , `go install` , Linuxbrew, and browser
runtime libraries. Add only the extra packages your environment needs.
2026-03-06 12:18:42 -05:00
2026-03-19 16:53:43 -07:00
### Install browser dependencies at build time (optional)
2026-02-02 02:07:00 -08:00
2026-03-19 16:53:43 -07:00
If you want Chromium baked into the image instead of downloading it later:
2026-02-02 02:07:00 -08:00
```bash
2026-03-19 16:53:43 -07:00
export OPENCLAW_INSTALL_BROWSER=1
./scripts/docker/setup.sh
2026-02-02 02:07:00 -08:00
```
2026-03-19 16:53:43 -07:00
This installs Chromium through Playwright during the image build and stores it
under `/home/node/.cache/ms-playwright` .
2026-02-27 18:06:52 -08:00
2026-03-19 16:53:43 -07:00
### Pre-install extension dependencies (optional)
2026-02-02 02:07:00 -08:00
2026-03-19 16:53:43 -07:00
Extensions with their own `package.json` can be baked into the image:
2026-02-02 02:07:00 -08:00
```bash
2026-03-19 16:53:43 -07:00
export OPENCLAW_EXTENSIONS="diagnostics-otel matrix"
./scripts/docker/setup.sh
2026-01-09 15:23:06 -05:00
```
2026-03-19 16:53:43 -07:00
### Keep macOS awake (optional)
2026-01-08 07:48:23 +00:00
2026-03-19 16:53:43 -07:00
Docker itself does not reliably keep macOS awake. If the gateway must stay
online for Slack, webhooks, or scheduled jobs:
2026-01-31 18:31:49 +09:00
2026-01-08 07:48:23 +00:00
```bash
2026-03-19 16:53:43 -07:00
scripts/openclaw-keepawake.sh on
scripts/openclaw-keepawake.sh status
scripts/openclaw-keepawake.sh off
2026-01-08 07:48:23 +00:00
```
2026-03-19 16:53:43 -07:00
By default this uses `caffeinate -imsu` , which allows the displays to sleep.
Set `OPENCLAW_KEEPAWAKE_FLAGS=-dimsu` if you also want to keep the displays on.
2026-01-31 18:31:49 +09:00
2026-03-19 16:53:43 -07:00
### Base image metadata
2026-01-08 07:48:23 +00:00
2026-03-19 16:53:43 -07:00
The main Docker image uses `node:24-bookworm` and publishes OCI base-image
annotations including:
2026-01-08 07:48:23 +00:00
2026-03-19 16:53:43 -07:00
- `org.opencontainers.image.base.name`
- `org.opencontainers.image.base.digest`
- `org.opencontainers.image.source`
- `org.opencontainers.image.documentation`
2026-02-02 04:25:57 -08:00
2026-03-19 16:53:43 -07:00
Reference: [OCI image annotations ](https://github.com/opencontainers/image-spec/blob/main/annotations.md )
2026-02-02 04:25:57 -08:00
2026-03-01 20:36:58 -08:00
### Health checks
Container probe endpoints (no auth required):
```bash
2026-03-19 12:07:37 -07:00
curl -fsS http://127.0.0.1:18789/healthz # liveness
curl -fsS http://127.0.0.1:18789/readyz # readiness
2026-03-01 20:36:58 -08:00
```
2026-03-19 12:07:37 -07:00
The Docker image includes a built-in `HEALTHCHECK` that pings `/healthz` .
If checks keep failing, Docker marks the container as `unhealthy` and
orchestration systems can restart or replace it.
2026-03-01 20:36:58 -08:00
2026-03-19 12:07:37 -07:00
Authenticated deep health snapshot:
2026-01-03 21:35:44 +01:00
```bash
2026-01-31 18:31:49 +09:00
docker compose exec openclaw-gateway node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN"
2026-01-03 21:35:44 +01:00
```
2026-03-19 12:07:37 -07:00
### LAN vs loopback
2026-01-02 20:58:50 +01:00
2026-03-19 13:40:10 -07:00
`scripts/docker/setup.sh` defaults `OPENCLAW_GATEWAY_BIND=lan` so host access to
2026-03-02 08:28:35 +07:00
`http://127.0.0.1:18789` works with Docker port publishing.
2026-01-02 20:58:50 +01:00
2026-03-19 12:07:37 -07:00
- `lan` (default): host browser and host CLI can reach the published gateway port.
2026-03-02 08:28:35 +07:00
- `loopback` : only processes inside the container network namespace can reach
2026-03-19 12:07:37 -07:00
the gateway directly.
2026-01-06 02:22:20 +01:00
2026-03-19 12:07:37 -07:00
< Note >
Use bind mode values in `gateway.bind` (`lan` / `loopback` / `custom` /
`tailnet` / `auto` ), not host aliases like `0.0.0.0` or `127.0.0.1` .
< / Note >
2026-01-06 02:22:20 +01:00
2026-03-19 12:07:37 -07:00
### Storage and persistence
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
Docker Compose bind-mounts `OPENCLAW_CONFIG_DIR` to `/home/node/.openclaw` and
`OPENCLAW_WORKSPACE_DIR` to `/home/node/.openclaw/workspace` , so those paths
survive container replacement.
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
For full persistence details on VM deployments, see
[Docker VM Runtime - What persists where ](/install/docker-vm-runtime#what-persists-where ).
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
**Disk growth hotspots:** watch `media/` , session JSONL files, `cron/runs/*.jsonl` ,
and rolling file logs under `/tmp/openclaw/` .
2026-03-02 08:28:35 +07:00
2026-03-19 12:07:37 -07:00
### Shell helpers (optional)
2026-03-02 09:15:27 +05:30
2026-03-19 12:07:37 -07:00
For easier day-to-day Docker management, install `ClawDock` :
2026-03-02 08:28:35 +07:00
```bash
2026-03-19 12:07:37 -07:00
mkdir -p ~/.clawdock & & curl -sL https://raw.githubusercontent.com/openclaw/openclaw/main/scripts/shell-helpers/clawdock-helpers.sh -o ~/.clawdock/clawdock-helpers.sh
echo 'source ~/.clawdock/clawdock-helpers.sh' >> ~/.zshrc & & source ~/.zshrc
2026-03-02 08:28:35 +07:00
```
2026-03-19 12:07:37 -07:00
Then use `clawdock-start` , `clawdock-stop` , `clawdock-dashboard` , etc. Run
`clawdock-help` for all commands.
See the [`ClawDock` Helper README ](https://github.com/openclaw/openclaw/blob/main/scripts/shell-helpers/README.md ).
< AccordionGroup >
< Accordion title = "Enable agent sandbox for Docker gateway" >
```bash
export OPENCLAW_SANDBOX=1
2026-03-19 13:40:10 -07:00
./scripts/docker/setup.sh
2026-03-19 12:07:37 -07:00
```
Custom socket path (e.g. rootless Docker):
```bash
export OPENCLAW_SANDBOX=1
export OPENCLAW_DOCKER_SOCKET=/run/user/1000/docker.sock
2026-03-19 13:40:10 -07:00
./scripts/docker/setup.sh
2026-03-19 12:07:37 -07:00
```
The script mounts `docker.sock` only after sandbox prerequisites pass. If
sandbox setup cannot complete, the script resets `agents.defaults.sandbox.mode`
to `off` .
< / Accordion >
< Accordion title = "Automation / CI (non-interactive)" >
Disable Compose pseudo-TTY allocation with `-T` :
```bash
docker compose run -T --rm openclaw-cli gateway probe
docker compose run -T --rm openclaw-cli devices list --json
```
< / Accordion >
< Accordion title = "Shared-network security note" >
`openclaw-cli` uses `network_mode: "service:openclaw-gateway"` so CLI
commands can reach the gateway over `127.0.0.1` . Treat this as a shared
trust boundary. The compose config drops `NET_RAW` /`NET_ADMIN` and enables
`no-new-privileges` on `openclaw-cli` .
< / Accordion >
< Accordion title = "Permissions and 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:
```bash
sudo chown -R 1000:1000 /path/to/openclaw-config /path/to/openclaw-workspace
```
< / Accordion >
< Accordion title = "Faster rebuilds" >
Order your Dockerfile so dependency layers are cached. This avoids re-running
`pnpm install` unless lockfiles change:
```dockerfile
FROM node:24-bookworm
RUN curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:${PATH}"
RUN corepack enable
WORKDIR /app
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"]
```
< / Accordion >
< Accordion title = "Power-user container options" >
The default image is security-first and runs as non-root `node` . For a more
full-featured container:
1. **Persist `/home/node`** : `export OPENCLAW_HOME_VOLUME="openclaw_home"`
2. **Bake system deps** : `export OPENCLAW_DOCKER_APT_PACKAGES="git curl jq"`
3. **Install Playwright browsers** :
```bash
docker compose run --rm openclaw-cli \
node /app/node_modules/playwright-core/cli.js install chromium
```
4. **Persist browser downloads** : set
`PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright` and use
`OPENCLAW_HOME_VOLUME` or `OPENCLAW_EXTRA_MOUNTS` .
< / Accordion >
< Accordion title = "OpenAI Codex OAuth (headless Docker)" >
If you pick OpenAI Codex OAuth in the wizard, it opens a browser URL. In
Docker or headless setups, copy the full redirect URL you land on and paste
it back into the wizard to finish auth.
< / Accordion >
< Accordion title = "Base image metadata" >
The main Docker image uses `node:24-bookworm` and publishes OCI base-image
annotations including `org.opencontainers.image.base.name` ,
`org.opencontainers.image.source` , and others. See
[OCI image annotations ](https://github.com/opencontainers/image-spec/blob/main/annotations.md ).
< / Accordion >
< / AccordionGroup >
2026-03-06 19:55:26 -05:00
2026-02-27 18:18:45 -08:00
## Backup and migration (Intel Mac to Apple Silicon)
2026-03-19 16:53:43 -07:00
For low-disruption host migration, move OpenClaw data and config, then rebuild
the Docker image natively on the new machine.
2026-02-27 18:18:45 -08:00
Use:
2026-03-19 16:53:43 -07:00
- `scripts/migrate/backup-openclaw.sh` on the source host
- `scripts/migrate/restore-openclaw.sh` on the target host
2026-02-27 18:18:45 -08:00
2026-03-19 16:53:43 -07:00
### 1) Create a backup on the source host
2026-02-27 18:18:45 -08:00
2026-03-19 16:53:43 -07:00
From the repo root:
2026-02-27 18:18:45 -08:00
```bash
scripts/migrate/backup-openclaw.sh
```
The archive includes:
- OpenClaw config dir (`OPENCLAW_CONFIG_DIR` or `~/.openclaw` )
- OpenClaw workspace dir (`OPENCLAW_WORKSPACE_DIR` or `~/.openclaw/workspace` )
2026-03-19 16:53:43 -07:00
- `.env` and Docker setup files from the repo root
- metadata and an internal checksum manifest
2026-02-27 18:18:45 -08:00
Output files:
- `backups/openclaw-backup-<timestamp>.tar.gz`
- `backups/openclaw-backup-<timestamp>.tar.gz.sha256`
Optional path overrides:
```bash
scripts/migrate/backup-openclaw.sh \
--config-dir "$HOME/.openclaw" \
--workspace-dir "$HOME/.openclaw/workspace" \
--output-dir "$HOME/openclaw-backups"
```
2026-03-19 16:53:43 -07:00
### 2) Transfer the archive to the target host
2026-02-27 18:18:45 -08:00
2026-03-19 16:53:43 -07:00
Copy the archive and checksum file to the new machine using your normal secure
transfer method.
2026-02-27 18:18:45 -08:00
2026-03-19 16:53:43 -07:00
### 3) Restore on the target host
2026-02-27 18:18:45 -08:00
2026-03-19 16:53:43 -07:00
From the repo root on the target host:
2026-02-27 18:18:45 -08:00
```bash
scripts/migrate/restore-openclaw.sh --archive /path/to/openclaw-backup-< timestamp > .tar.gz
```
Default restore behavior:
- verifies archive checksums
2026-03-19 16:53:43 -07:00
- stops `openclaw-gateway` before restore
- snapshots current config and workspace as `.pre-restore-<timestamp>`
- restores config and workspace from backup
- writes the backup env file as `.env.from-backup` for review
2026-02-27 18:18:45 -08:00
To overwrite `.env` directly:
```bash
scripts/migrate/restore-openclaw.sh \
--archive /path/to/openclaw-backup-< timestamp > .tar.gz \
--apply-env
```
2026-03-19 16:53:43 -07:00
### 4) Rebuild and validate on the target architecture
2026-02-27 18:18:45 -08:00
Always rebuild on Apple Silicon:
```bash
docker compose up -d --build --force-recreate openclaw-gateway
docker compose run --rm openclaw-cli health
docker compose run --rm openclaw-cli channels status --probe
```
### Architecture migration note
Do not carry over architecture-specific binary caches from x86 to arm hosts.
Rebuild containers and reinstall native toolchains on the target host.
2026-03-19 12:07:37 -07:00
### Running on a VPS?
2026-01-03 21:35:44 +01:00
2026-03-19 12:07:37 -07:00
See [Hetzner (Docker VPS) ](/install/hetzner ) and
[Docker VM Runtime ](/install/docker-vm-runtime ) for shared VM deployment steps
including binary baking, persistence, and updates.
2026-01-08 21:49:26 +01:00
2026-03-19 12:07:37 -07:00
## Agent Sandbox
2026-01-03 21:35:44 +01:00
2026-03-19 12:07:37 -07:00
When `agents.defaults.sandbox` is enabled, the gateway runs agent tool execution
(shell, file read/write, etc.) inside isolated Docker containers while the
gateway itself stays on the host. This gives you a hard wall around untrusted or
multi-tenant agent sessions without containerizing the entire gateway.
2026-01-31 18:31:49 +09:00
2026-03-19 12:07:37 -07:00
Sandbox scope can be per-agent (default), per-session, or shared. Each scope
gets its own workspace mounted at `/workspace` . You can also configure
allow/deny tool policies, network isolation, resource limits, and browser
containers.
2026-01-03 21:35:44 +01:00
2026-03-19 12:07:37 -07:00
For full configuration, images, security notes, and multi-agent profiles, see:
2026-01-06 23:22:49 +01:00
2026-03-19 12:07:37 -07:00
- [Sandboxing ](/gateway/sandboxing ) -- complete sandbox reference
- [OpenShell ](/gateway/openshell ) -- interactive shell access to sandbox containers
- [Multi-Agent Sandbox and Tools ](/tools/multi-agent-sandbox-tools ) -- per-agent overrides
2026-01-07 20:31:23 +01:00
2026-03-19 12:07:37 -07:00
### Quick enable
2026-01-19 01:35:17 +00:00
2026-01-03 21:35:44 +01:00
```json5
{
2026-01-09 12:44:23 +00:00
agents: {
defaults: {
sandbox: {
2026-01-31 21:13:13 +09:00
mode: "non-main", // off | non-main | all
2026-03-19 12:07:37 -07:00
scope: "agent", // session | agent | shared
2026-01-31 18:31:49 +09:00
},
},
},
2026-01-03 21:35:44 +01:00
}
```
2026-03-19 12:07:37 -07:00
Build the default sandbox image:
2026-01-03 21:35:44 +01:00
```bash
scripts/sandbox-setup.sh
```
## Troubleshooting
2026-03-19 12:07:37 -07:00
< AccordionGroup >
< Accordion title = "Image missing or sandbox container not starting" >
Build the sandbox image with
[`scripts/sandbox-setup.sh` ](https://github.com/openclaw/openclaw/blob/main/scripts/sandbox-setup.sh )
or set `agents.defaults.sandbox.docker.image` to your custom image.
Containers are auto-created per session on demand.
< / Accordion >
< Accordion title = "Permission errors in sandbox" >
Set `docker.user` to a UID:GID that matches your mounted workspace ownership,
or chown the workspace folder.
< / Accordion >
< Accordion title = "Custom tools not found in sandbox" >
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, or add a script under `/etc/profile.d/` in your Dockerfile.
< / Accordion >
< Accordion title = "OOM-killed during image build (exit 137)" >
The VM needs at least 2 GB RAM. Use a larger machine class and retry.
< / Accordion >
< Accordion title = "Unauthorized or pairing required in Control UI" >
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 ).
< / Accordion >
< Accordion title = "Gateway target shows ws://172.x.x.x or pairing errors from Docker CLI" >
Reset gateway mode and bind:
```bash
docker compose run --rm openclaw-cli config set gateway.mode local
docker compose run --rm openclaw-cli config set gateway.bind lan
docker compose run --rm openclaw-cli devices list --url ws://127.0.0.1:18789
```
< / Accordion >
< / AccordionGroup >