refactor: switch openclaw and hermes to their official images

This commit is contained in:
tiennm99 committed 2026-10-05 13:22:01 +07:00
1 parent 8d4c3d14a4
commit 0d0a48221b
10 files changed
+174 -184

No files matched your search

+2 -2
View File
@@ -82,10 +82,10 @@ Each links to its own README for variables, ports, and storage.
| [diun](diun/README.md) | Image-update notifier, reading the Docker API through a read-only proxy |
| [gitea-mirror](gitea-mirror/README.md) | Gitea + PostgreSQL + gitea-mirror, mirroring GitHub repos |
| [goclaw](goclaw/README.md) | Multi-tenant AI agent gateway, with pgvector PostgreSQL |
| [hermes](hermes/README.md) | Hermes Agent with its web chat UI |
| [hermes](hermes/README.md) | Hermes Agent with its built-in web dashboard |
| [litellm](litellm/README.md) | LiteLLM proxy in front of many LLM providers, with PostgreSQL and Redis |
| [open-webui](open-webui/README.md) | Open WebUI chat interface for OpenAI-compatible and Ollama providers |
| [openclaw](openclaw/README.md) | OpenClaw AI agent gateway, with a CDP browser |
| [openclaw](openclaw/README.md) | OpenClaw AI agent gateway, with built-in browser automation |
| [opencode](opencode/README.md) | opencode coding agent, served as a browser UI |
| [owncloud](owncloud/README.md) | ownCloud file sync and share, with MariaDB and Redis |
| [paseo](paseo/README.md) | Paseo coding-agent daemon and web UI |
+8 -3
View File
@@ -2,9 +2,14 @@
#
# cp .env.example .env
# Web UI login password.
# Generate one with: openssl rand -base64 24
HERMES_WEBUI_PASSWORD=
# Full public URL of the dashboard, e.g. https://hermes.example.com.
HERMES_DASHBOARD_PUBLIC_URL=https://hermes.example.com
# Dashboard login. Generate the password with: openssl rand -base64 24
HERMES_DASHBOARD_USERNAME=hermes
HERMES_DASHBOARD_PASSWORD=
# Signs dashboard sessions; keep it stable. Generate with: openssl rand -hex 32
HERMES_DASHBOARD_SECRET=
# Model provider for the agent.
OPENROUTER_API_KEY=
+4
View File
@@ -0,0 +1,4 @@
FROM nousresearch/hermes-agent:latest
# Workspace directory owned by the hermes user (HERMES_UID/HERMES_GID 1000).
RUN mkdir -p /workspace && chown 1000:1000 /workspace
+47 -27
View File
@@ -1,52 +1,72 @@
# hermes
[Hermes Agent](https://github.com/NousResearch/hermes-agent), an autonomous AI
agent with persistent memory and scheduling, behind
[Hermes WebUI](https://github.com/nesquena/hermes-webui), a self-hosted web
chat for it.
[Hermes Agent](https://github.com/NousResearch/hermes-agent): an autonomous AI
agent with persistent memory, scheduling and chat-platform gateways, from Nous
Research's official image, with its built-in web dashboard.
Two containers: `hermes-agent` runs the agent gateway, and `hermes-webui`
serves the chat on port `8787`.
One container. `gateway run` starts the agent gateway, and the image's s6
supervisor also starts the dashboard on port `9119`: chat (the Hermes
terminal UI in the browser), sessions, config, cron, skills and logs.
## Setup
1. Set `HERMES_WEBUI_PASSWORD` and `OPENROUTER_API_KEY`.
2. Map the domain to the `hermes-webui` container on port `8787` and deploy.
3. Open the domain and log in with `HERMES_WEBUI_PASSWORD`.
1. Set `HERMES_DASHBOARD_PUBLIC_URL`, `HERMES_DASHBOARD_PASSWORD`,
`HERMES_DASHBOARD_SECRET` and `OPENROUTER_API_KEY`.
2. Map the domain to port `9119` and deploy.
3. Open the domain and log in with `HERMES_DASHBOARD_USERNAME` /
`HERMES_DASHBOARD_PASSWORD`.
Health check: `GET /health` on the web UI, also its compose healthcheck.
Health check: `GET /api/status`, also the compose healthcheck.
## Environment
| Variable | Default | Purpose |
| --- | --- | --- |
| `HERMES_WEBUI_PASSWORD` | — | Web UI login |
| `HERMES_DASHBOARD_PUBLIC_URL` | — | Full public URL, e.g. `https://hermes.example.com` |
| `HERMES_DASHBOARD_USERNAME` / `HERMES_DASHBOARD_PASSWORD` | `hermes` / — | Dashboard login |
| `HERMES_DASHBOARD_SECRET` | — | Signs dashboard sessions |
| `OPENROUTER_API_KEY` | empty | Model provider |
| `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_API_KEY` | optional | Other model providers |
`HERMES_WEBUI_PASSWORD` is required: without it the chat, and the agent
behind it, are open to anyone who reaches the domain.
`HERMES_DASHBOARD=1` turns the dashboard on. Bound to `0.0.0.0`, it refuses to
start without an auth provider, so the password is required. The image's
username/password provider is the one that needs no outside identity service;
upstream describes it as meant for trusted networks and recommends OAuth (Nous
Portal) or self-hosted OIDC for a public domain.
The uid/gid pairs are pinned to `1000` in `compose.yml`. Both containers write
the shared `hermes-home` volume, so both must run as the same user.
`HERMES_DASHBOARD_PUBLIC_URL` adds the domain to the dashboard's Host and
WebSocket Origin guard, which rejects requests for any other host.
`HERMES_DASHBOARD_SECRET` keeps sessions valid across restarts; without it
each restart signs with a new random key and logs everyone out.
The uid/gid are pinned to `1000` in `compose.yml`; the `Dockerfile` depends on
that (see Storage).
## Storage
| Volume | Mount | Holds |
| --- | --- | --- |
| `hermes-home` | `/home/hermes/.hermes` (agent), `/home/hermeswebui/.hermes` (web UI) | Agent config, memory, skills and sessions; web UI state in `webui/` |
| `hermes-agent-src` | `/opt/hermes` (agent), `.hermes/hermes-agent`, read-only (web UI) | The agent's source code, which the web UI imports |
| `hermes-workspace` | `/workspace` (web UI) | Files the agent works on |
| `hermes-data` | `/opt/data` | `HERMES_HOME`: config, `.env`, sessions, memory, skills, logs |
| `hermes-workspace` | `/workspace` | Files the agent works on |
### Updating the agent
The image hard-blocks the agent's file tools from writing outside
`HERMES_WRITE_SAFE_ROOT`, which it sets to `/opt/data` alone, so
`compose.yml` adds `/workspace` to it. `TERMINAL_CWD` starts gateway and cron
terminal sessions in `/workspace`. Upstream marks that variable deprecated in
favour of `terminal.cwd` in `config.yaml`; it is used here so the setting stays
in the compose file rather than on the volume.
`hermes-agent-src` is filled from the agent image only when the volume is
first created. A newer `latest` image therefore keeps running the old source
until the volume is removed, which upstream documents as the upgrade step:
stop the app, delete the `hermes-agent-src` volume, and deploy again. Nothing
else lives in that volume.
The `Dockerfile` exists only to make `/workspace` writable. The image does not
ship that directory and its init chowns only `/opt/data`, so a named volume on
`/workspace` would come up `root:root`. Creating the directory in the image,
owned by `1000:1000`, fixes that: Docker seeds an empty named volume from the
image directory, ownership included.
## Images
## Image
Both images use `latest`. Upstream recommends moving the two together, since
the web UI imports the agent's source and is built against matching versions.
`nousresearch/hermes-agent:latest` moves only on stable releases, roughly
weekly; upstream publishes no major tag. The agent's code lives in the image,
not a volume, so a new release takes effect on the next pull and recreate. The
first start after an upgrade migrates `config.yaml`, keeping a timestamped
backup.
+13 -30
View File
@@ -1,49 +1,32 @@
services:
hermes-agent:
image: nousresearch/hermes-agent:latest
hermes:
build: .
restart: unless-stopped
command: gateway run
environment:
- HERMES_HOME=/home/hermes/.hermes
- HERMES_DASHBOARD=1
- HERMES_DASHBOARD_PUBLIC_URL=${HERMES_DASHBOARD_PUBLIC_URL:?required}
- HERMES_DASHBOARD_BASIC_AUTH_USERNAME=${HERMES_DASHBOARD_USERNAME:-hermes}
- HERMES_DASHBOARD_BASIC_AUTH_PASSWORD=${HERMES_DASHBOARD_PASSWORD:?required}
- HERMES_DASHBOARD_BASIC_AUTH_SECRET=${HERMES_DASHBOARD_SECRET:?required}
- HERMES_UID=1000
- HERMES_GID=1000
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
- HERMES_WRITE_SAFE_ROOT=/opt/data:/workspace
- TERMINAL_CWD=/workspace
# - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
# - OPENAI_API_KEY=${OPENAI_API_KEY:-}
# - GOOGLE_API_KEY=${GOOGLE_API_KEY:-}
volumes:
- hermes-home:/home/hermes/.hermes
- hermes-agent-src:/opt/hermes
healthcheck:
test: ["CMD-SHELL", "test -d /home/hermes/.hermes || exit 1"]
interval: 10s
timeout: 5s
retries: 5
# Web chat UI, sharing the agent's home and source.
hermes-webui:
image: ghcr.io/nesquena/hermes-webui:latest
restart: unless-stopped
depends_on:
- hermes-agent
environment:
- HERMES_WEBUI_PASSWORD=${HERMES_WEBUI_PASSWORD:?required}
- WANTED_UID=1000
- WANTED_GID=1000
- HERMES_WEBUI_HOST=0.0.0.0
- HERMES_WEBUI_PORT=8787
- HERMES_WEBUI_STATE_DIR=/home/hermeswebui/.hermes/webui
volumes:
- hermes-home:/home/hermeswebui/.hermes
- hermes-agent-src:/home/hermeswebui/.hermes/hermes-agent:ro
- hermes-data:/opt/data
- hermes-workspace:/workspace
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:8787/health"]
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:9119/api/status"]
interval: 30s
timeout: 5s
retries: 3
start_period: 60s
volumes:
hermes-home:
hermes-agent-src:
hermes-data:
hermes-workspace:
+11 -29
View File
@@ -2,19 +2,20 @@
#
# cp .env.example .env
# Web UI login.
# Generate a password with: openssl rand -base64 24
AUTH_USERNAME=admin
AUTH_PASSWORD=
# Token for the agent gateway. Generate one with: openssl rand -hex 32
# Gateway token: the Control UI login and the key for every API and WebSocket call.
# Generate one with: openssl rand -hex 32
OPENCLAW_GATEWAY_TOKEN=
# At least one provider key is required; OpenRouter is the active one.
# Public origin of the Control UI, scheme included, no trailing slash.
OPENCLAW_PUBLIC_ORIGIN=https://openclaw.example.com
# Address range the reverse proxy connects from, in CIDR form.
OPENCLAW_TRUSTED_PROXIES=10.0.0.0/16
# At least one model provider; OpenRouter is the active one.
OPENROUTER_API_KEY=
# Default model, e.g. openrouter/anthropic/claude-sonnet-4.5.
# OPENCLAW_PRIMARY_MODEL=
TZ=Asia/Ho_Chi_Minh
# Other providers. Uncomment here and in compose.yml to enable one.
# ANTHROPIC_API_KEY=
@@ -26,9 +27,7 @@ OPENROUTER_API_KEY=
# CEREBRAS_API_KEY=
# VENICE_API_KEY=
# MOONSHOT_API_KEY=
# MOONSHOT_BASE_URL=https://api.moonshot.ai/v1
# KIMI_API_KEY=
# KIMI_BASE_URL=https://api.moonshot.ai/anthropic
# MINIMAX_API_KEY=
# ZAI_API_KEY=
# AI_GATEWAY_API_KEY=
@@ -36,6 +35,7 @@ OPENROUTER_API_KEY=
# SYNTHETIC_API_KEY=
# COPILOT_GITHUB_TOKEN=
# XIAOMI_API_KEY=
# OLLAMA_API_KEY=
# Speech to text.
# DEEPGRAM_API_KEY=
# AWS Bedrock.
@@ -43,27 +43,9 @@ OPENROUTER_API_KEY=
# AWS_SECRET_ACCESS_KEY=
# AWS_SESSION_TOKEN=
# AWS_REGION=us-east-1
# BEDROCK_PROVIDER_FILTER=anthropic
# OLLAMA_BASE_URL=
# Chat channels.
# TELEGRAM_BOT_TOKEN=
# DISCORD_BOT_TOKEN=
# SLACK_BOT_TOKEN=
# SLACK_APP_TOKEN=
# WHATSAPP_ENABLED=
# Gateway, browser and hook tuning.
# Origins allowed to open the control UI, comma separated, e.g. https://openclaw.example.com.
# OPENCLAW_ALLOWED_ORIGINS=
# OPENCLAW_GATEWAY_BIND=loopback
# BROWSER_DEFAULT_PROFILE=openclaw
# BROWSER_EVALUATE_ENABLED=true
# BROWSER_SNAPSHOT_MODE=efficient
# BROWSER_REMOTE_TIMEOUT_MS=1500
# BROWSER_REMOTE_HANDSHAKE_TIMEOUT_MS=3000
# HOOKS_ENABLED=false
# HOOKS_PATH=/hooks
# Extra apt packages installed into the container at start, space separated.
# OPENCLAW_DOCKER_APT_PACKAGES=
+4
View File
@@ -0,0 +1,4 @@
FROM ghcr.io/openclaw/openclaw:latest-browser
# Gateway config seeded into the state volume on first start.
COPY --chown=node:node openclaw.json /home/node/.openclaw/openclaw.json
+60 -39
View File
@@ -1,65 +1,86 @@
# openclaw
[OpenClaw](https://docs.openclaw.ai): a personal AI agent gateway with a web
UI, chat-channel bots and browser automation. Runs Coolify's
`coollabsio/openclaw` image, which wraps OpenClaw with nginx basic auth and
env-driven configuration.
Control UI, chat-channel bots and browser automation. Runs the project's
official image, in its `-browser` variant with Chromium built in.
Two containers: `openclaw`, and `browser`, a Chromium the agent drives over
the Chrome DevTools Protocol.
One container, serving the gateway and the Control UI on port `18789`.
## Setup
1. Set `AUTH_PASSWORD`, `OPENCLAW_GATEWAY_TOKEN` and `OPENROUTER_API_KEY`.
2. Map the domain to port `8080` and deploy.
3. Open the domain and log in with `AUTH_USERNAME` / `AUTH_PASSWORD`.
1. Set `OPENCLAW_GATEWAY_TOKEN`, `OPENCLAW_PUBLIC_ORIGIN` and
`OPENROUTER_API_KEY`.
2. Map the domain to port `18789` and deploy.
3. Open the domain and connect with the gateway token. Each new browser is
then approved once from inside the container:
`node openclaw.mjs devices approve`.
4. Pick a default model in the Control UI. The image's default is an OpenAI
model, which needs `OPENAI_API_KEY`.
Health check: `GET /healthz`, also the compose healthcheck.
Health check: the image's own, which calls `/healthz`.
## Environment
| Variable | Default | Purpose |
| --- | --- | --- |
| `AUTH_USERNAME` / `AUTH_PASSWORD` | `admin` / — | Basic-auth login in front of the web UI |
| `OPENCLAW_GATEWAY_TOKEN` | — | Token the web UI and clients use to reach the gateway |
| `OPENCLAW_GATEWAY_TOKEN` | — | Control UI login and API/WebSocket key |
| `OPENCLAW_PUBLIC_ORIGIN` | — | Public origin, e.g. `https://openclaw.example.com` |
| `OPENCLAW_TRUSTED_PROXIES` | `10.0.0.0/16` | Range the reverse proxy connects from |
| `OPENROUTER_API_KEY` | empty | Model provider |
| `OPENCLAW_PRIMARY_MODEL` | optional | Default model |
| Other provider keys, `AWS_*`, `OLLAMA_BASE_URL` | optional | Additional model providers |
| `TELEGRAM_BOT_TOKEN`, `DISCORD_BOT_TOKEN`, `SLACK_*`, `WHATSAPP_ENABLED` | optional | Chat channels |
| `OPENCLAW_ALLOWED_ORIGINS` | optional | Origins allowed to open the control UI |
| `BROWSER_*`, `HOOKS_*`, `OPENCLAW_GATEWAY_BIND` | optional | Tuning, defaults shown in `compose.yml` |
| `OPENCLAW_DOCKER_APT_PACKAGES` | optional | Extra apt packages installed at start |
| `TZ` | `Asia/Ho_Chi_Minh` | Timezone for logs and schedules |
| Other provider keys, `AWS_*` | optional | Additional model providers |
| `TELEGRAM_BOT_TOKEN`, `DISCORD_BOT_TOKEN`, `SLACK_*` | optional | Chat channels |
`AUTH_PASSWORD` is required: without it nginx serves the UI with no login.
The entrypoint itself refuses to start without `OPENCLAW_GATEWAY_TOKEN` or
without at least one provider key.
`OPENCLAW_GATEWAY_TOKEN` is required: the gateway binds to all interfaces, and
the token is what keeps the Control UI and API closed. Provider and channel
keys are read from the environment, so the provider set is changed by
uncommenting lines.
OpenRouter stays active as the one provider every deployment needs; any
other provider is enabled by uncommenting its line. Each provider key is read
from the environment on every start, never stored in the config.
`OPENCLAW_TRUSTED_PROXIES` must cover the address Coolify's Traefik connects
from. Traefik joins each app's network with an address from the Docker
address pool, which on this host is `10.0.0.0/16` in `/24` slices; the gateway
answers every proxied request from an untrusted address with 403
`proxy_attribution_required`.
`PORT`, the gateway port, the state and workspace directories and
`BROWSER_CDP_URL` are fixed in `compose.yml`, as properties of this layout.
## Config
`OPENCLAW_CONFIG_JSON` sets `gateway.trustedProxies` to `127.0.0.1`. The
image's own nginx sits in front of the gateway on loopback, and current
OpenClaw (tested on 2026.9.8) rejects every proxied request with 403
`proxy_attribution_required` unless that proxy is trusted. The wrapper merges
this JSON into `openclaw.json` on every start.
The rest of OpenClaw's settings live in `openclaw.json` on the state volume
and are edited in the Control UI or with `node openclaw.mjs config set`.
The wrapper adds the deployment's domain to the control UI's allowed origins
from the `COOLIFY_URL` and `COOLIFY_FQDN` Coolify injects.
`OPENCLAW_ALLOWED_ORIGINS` is for any other origin, and for a deployment
Coolify does not inject that into.
The `Dockerfile` copies `openclaw.json` into the image's state directory, and
Docker seeds an empty named volume from it on first start. It holds only what
this deployment needs before anyone can log in: local gateway mode, a bind to
all interfaces, the port, and the public origin and trusted proxy range as
`${VAR}` references that OpenClaw resolves from the environment at load. The
image's own start-up `doctor --fix` keeps those references when it rewrites
the file. Without `gateway.mode` a fresh volume crash-loops.
The seed applies only to a fresh volume. Editing `openclaw.json` in the
repository later changes nothing for an existing deployment; change the live
config instead.
## Storage
| Volume | Mount | Holds |
| --- | --- | --- |
| `openclaw-data` | `/data` | Config and sessions in `.openclaw`, the agent workspace in `workspace` |
| `browser-data` | `/config` | Chromium profile: cookies and logins of sites the agent uses |
| `openclaw-state` | `/home/node/.openclaw` | `openclaw.json`, sessions, credentials, agent state |
| `openclaw-workspace` | `/home/node/.openclaw/workspace` | Files the agent works on |
| `openclaw-secrets` | `/home/node/.config/openclaw` | Auth-profile secrets |
## Images
The three mounts follow upstream's own compose. `/home/node` as a whole is not
mounted: the bundled Chromium lives in `/home/node/.cache`, and a volume there
would freeze it at the first image's version.
Both images use `latest`. `coollabsio/openclaw` publishes no major tag, only
dated releases, so `latest` is the moving one.
`cap_drop` and `no-new-privileges` are also upstream's; the image runs as the
non-root `node` user.
## Image
`ghcr.io/openclaw/openclaw:latest-browser` is the latest stable release with
Playwright Chromium built in, published by the project's release automation.
Upstream publishes no major tag.
On ARM64, release 2026.9.8 cannot find its bundled Chromium ("No supported
browser found"); the fix is merged upstream but not yet released. Everything
except browser automation works meanwhile, and the browser starts working on
the first pull after a release that contains the fix, with no change here.
+16 -54
View File
@@ -1,19 +1,13 @@
services:
openclaw:
image: coollabsio/openclaw:latest
build: .
restart: unless-stopped
environment:
- AUTH_USERNAME=${AUTH_USERNAME:-admin}
- AUTH_PASSWORD=${AUTH_PASSWORD:?required}
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN:?required}
- OPENCLAW_PUBLIC_ORIGIN=${OPENCLAW_PUBLIC_ORIGIN:?required}
- OPENCLAW_TRUSTED_PROXIES=${OPENCLAW_TRUSTED_PROXIES:-10.0.0.0/16}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
- PORT=8080
- OPENCLAW_GATEWAY_PORT=18789
- OPENCLAW_STATE_DIR=/data/.openclaw
- OPENCLAW_WORKSPACE_DIR=/data/workspace
- BROWSER_CDP_URL=http://browser:9223
- 'OPENCLAW_CONFIG_JSON={"gateway":{"trustedProxies":["127.0.0.1"]}}'
# - OPENCLAW_PRIMARY_MODEL=${OPENCLAW_PRIMARY_MODEL:-}
- TZ=${TZ:-Asia/Ho_Chi_Minh}
# - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
# - OPENAI_API_KEY=${OPENAI_API_KEY:-}
# - GEMINI_API_KEY=${GEMINI_API_KEY:-}
@@ -23,9 +17,7 @@ services:
# - CEREBRAS_API_KEY=${CEREBRAS_API_KEY:-}
# - VENICE_API_KEY=${VENICE_API_KEY:-}
# - MOONSHOT_API_KEY=${MOONSHOT_API_KEY:-}
# - MOONSHOT_BASE_URL=${MOONSHOT_BASE_URL:-https://api.moonshot.ai/v1}
# - KIMI_API_KEY=${KIMI_API_KEY:-}
# - KIMI_BASE_URL=${KIMI_BASE_URL:-https://api.moonshot.ai/anthropic}
# - MINIMAX_API_KEY=${MINIMAX_API_KEY:-}
# - ZAI_API_KEY=${ZAI_API_KEY:-}
# - AI_GATEWAY_API_KEY=${AI_GATEWAY_API_KEY:-}
@@ -33,57 +25,27 @@ services:
# - SYNTHETIC_API_KEY=${SYNTHETIC_API_KEY:-}
# - COPILOT_GITHUB_TOKEN=${COPILOT_GITHUB_TOKEN:-}
# - XIAOMI_API_KEY=${XIAOMI_API_KEY:-}
# - OLLAMA_API_KEY=${OLLAMA_API_KEY:-}
# - DEEPGRAM_API_KEY=${DEEPGRAM_API_KEY:-}
# - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-}
# - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-}
# - AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN:-}
# - AWS_REGION=${AWS_REGION:-us-east-1}
# - BEDROCK_PROVIDER_FILTER=${BEDROCK_PROVIDER_FILTER:-anthropic}
# - OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-}
# - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
# - DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN:-}
# - SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN:-}
# - SLACK_APP_TOKEN=${SLACK_APP_TOKEN:-}
# - WHATSAPP_ENABLED=${WHATSAPP_ENABLED:-}
# - OPENCLAW_ALLOWED_ORIGINS=${OPENCLAW_ALLOWED_ORIGINS:-}
# - OPENCLAW_GATEWAY_BIND=${OPENCLAW_GATEWAY_BIND:-loopback}
# - BROWSER_DEFAULT_PROFILE=${BROWSER_DEFAULT_PROFILE:-openclaw}
# - BROWSER_EVALUATE_ENABLED=${BROWSER_EVALUATE_ENABLED:-true}
# - BROWSER_SNAPSHOT_MODE=${BROWSER_SNAPSHOT_MODE:-efficient}
# - BROWSER_REMOTE_TIMEOUT_MS=${BROWSER_REMOTE_TIMEOUT_MS:-1500}
# - BROWSER_REMOTE_HANDSHAKE_TIMEOUT_MS=${BROWSER_REMOTE_HANDSHAKE_TIMEOUT_MS:-3000}
# - HOOKS_ENABLED=${HOOKS_ENABLED:-false}
# - HOOKS_PATH=${HOOKS_PATH:-/hooks}
# - OPENCLAW_DOCKER_APT_PACKAGES=${OPENCLAW_DOCKER_APT_PACKAGES:-}
volumes:
- openclaw-data:/data
depends_on:
browser:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-sf", "http://127.0.0.1:8080/healthz"]
interval: 10s
timeout: 10s
retries: 5
# Chromium the agent drives over CDP.
browser:
image: coollabsio/openclaw-browser:latest
restart: unless-stopped
shm_size: 2g
environment:
- PUID=1000
- PGID=1000
- CHROME_CLI=--remote-debugging-port=9222
- TZ=Etc/UTC
volumes:
- browser-data:/config
healthcheck:
test: ["CMD-SHELL", "bash -c ':> /dev/tcp/127.0.0.1/9222' || exit 1"]
interval: 5s
timeout: 5s
retries: 10
- openclaw-state:/home/node/.openclaw
- openclaw-workspace:/home/node/.openclaw/workspace
- openclaw-secrets:/home/node/.config/openclaw
cap_drop:
- NET_RAW
- NET_ADMIN
security_opt:
- no-new-privileges:true
volumes:
openclaw-data:
browser-data:
openclaw-state:
openclaw-workspace:
openclaw-secrets:
+9
View File
@@ -0,0 +1,9 @@
{
"gateway": {
"mode": "local",
"bind": "lan",
"port": 18789,
"publicOrigin": "${OPENCLAW_PUBLIC_ORIGIN}",
"trustedProxies": ["${OPENCLAW_TRUSTED_PROXIES}"]
}
}