Openclaw Automated Build

March 29, 2026 · View on GitHub

Quick Start

Minimal (docker run)

docker run -d \
  --name openclaw \
  -p 8080:8080 \
  -e ANTHROPIC_API_KEY=sk-ant-... \
  -e AUTH_PASSWORD=changeme \
  -e OPENCLAW_GATEWAY_TOKEN=my-secret-token \
  -e OPENCLAW_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000 \
  -v openclaw-data:/data \
  coollabsio/openclaw:latest
  • ANTHROPIC_API_KEY — any supported provider key works (OpenAI, Gemini, etc.)
  • AUTH_PASSWORD — protects the web UI with HTTP basic auth (user defaults to admin, override with AUTH_USERNAME)
  • OPENCLAW_GATEWAY_TOKEN — internal API token; auto-generated if omitted, but set it explicitly for stable API access
  • OPENCLAW_ALLOWED_ORIGINS(Required) Set to http://localhost:5173 or your frontend origin to enable CORS for the Control UI
  • /data — persists state, config, and workspace across restarts

Full Setup (docker-compose)

Includes persistent storage, browser sidecar (CDP + VNC), and webhook hooks. See docker-compose.yml.

docker compose up -d

After starting:

  1. Openclaw UIhttp://localhost:8080 (login: your AUTH_USERNAME / AUTH_PASSWORD)
  2. Browser desktophttp://localhost:8080/browser/ (login: your AUTH_USERNAME / browser PASSWORD) — use this to log into sites that need auth (OAuth, 2FA, captchas). Openclaw reuses the session via CDP.

Architecture

┌─────────────────────────────────────────────┐
│  Docker container (coollabsio/openclaw)     │
│                                             │
│  Baked in: Linuxbrew, Go, uv, build-essential│
│  Persistent volume: /data                   │
│    ├── .openclaw/      (state & config)     │
│    └── workspace/      (user projects)      │
│                                             │
│  ┌──────────┐  :8080   ┌────────────────┐  │
│  │  nginx    │ ──────→  │  openclaw      │  │
│  │  (basic   │  proxy   │  gateway       │  │
│  │   auth)   │  :18789  │  :18789        │  │
│  └──────────┘          └────────────────┘  │
│                                             │
│  entrypoint.sh                              │
│    1. run custom init script (optional)     │
│    2. configure.js (env vars → json)        │
│    3. nginx (background)                    │
│    4. exec openclaw gateway                 │
└─────────────────────────────────────────────┘

Two-layer Docker build:

  1. Base image (Dockerfile.base) — builds openclaw from source. Tagged coollabsio/openclaw-base:<version>.
  2. Final image (Dockerfile) — FROM base, adds nginx + env-to-config scripts. Tagged coollabsio/openclaw:<version>.

Files

.github/workflows/auto-update.yml   — cron every 6h, check openclaw releases, build+push
.github/workflows/build.yml         — CI on push/PR (build only, no push)
Dockerfile.base                     — multi-stage: build openclaw from source → slim runtime
Dockerfile                          — FROM base, add nginx + config scripts + entrypoint
scripts/configure.js                — reads env vars, writes/patches openclaw.json
scripts/entrypoint.sh               — container entrypoint: configure → nginx → gateway
scripts/smoke.js                    — smoke test (openclaw --version)
nginx/default.conf                  — reverse proxy :8080 → :18789, optional basic auth
.dockerignore                       — standard ignores
.env.example                        — env var reference

auto-update.yml workflow

Jobs:
1. check-release        — fetch latest openclaw/openclaw release, skip if image exists
2. build-base           — matrix amd64/arm64, build Dockerfile.base, push per-arch
3. merge-base-manifest  — merge into coollabsio/openclaw-base:<ver> + :latest
4. build-final          — matrix amd64/arm64, build Dockerfile, push per-arch
5. merge-final-manifest — merge into coollabsio/openclaw:<ver> + :latest

Triggers: schedule: '0 */6 * * *' + workflow_dispatch (version, force_rebuild, skip_latest_tag).

Secrets needed (repo settings)

  • DOCKERHUB_USERNAME — Docker Hub username
  • DOCKERHUB_TOKEN — Docker Hub access token
  • GITHUB_TOKEN — auto-provided by GitHub Actions

Environment variables

AI Providers (at least one required)

VariableDescription
ANTHROPIC_API_KEYAnthropic API key. Configures Claude models (Opus 4.5, Sonnet 4.5, Haiku 4.5). Set as primary when present.
OPENAI_API_KEYOpenAI API key. Configures GPT models (5.2, 5, 4.5-preview). Primary if no Anthropic key.
OPENROUTER_API_KEYOpenRouter API key. Primary if no Anthropic/OpenAI key.
GEMINI_API_KEYGoogle Gemini API key. Primary if no other provider key set.
XAI_API_KEYxAI API key. Configures Grok models.
GROQ_API_KEYGroq API key. Configures Llama models on Groq hardware.
MISTRAL_API_KEYMistral API key. Configures Mistral Large and other models.
CEREBRAS_API_KEYCerebras API key. Configures Llama models on Cerebras hardware.
VENICE_API_KEYVenice AI API key (OpenAI-compatible). Configures Llama 3.3 70B.
MOONSHOT_API_KEYMoonshot API key (OpenAI-compatible). Configures Kimi K2.5.
KIMI_API_KEYKimi Coding API key (Anthropic-compatible). Configures K2P5.
MINIMAX_API_KEYMiniMax API key (Anthropic-compatible). Configures MiniMax M2.1.
ZAI_API_KEYZAI API key. Configures GLM models.
AI_GATEWAY_API_KEYVercel AI Gateway API key.
OPENCODE_API_KEYOpenCode API key. Also accepted as OPENCODE_ZEN_API_KEY.
SYNTHETIC_API_KEYSynthetic API key (Anthropic-compatible).
COPILOT_GITHUB_TOKENGitHub Copilot token. Configures Claude models via GitHub.
XIAOMI_API_KEYXiaomi MiMo API key (Anthropic-compatible). Configures MiMo v2 Flash.

Multiple providers can be set simultaneously. Priority for primary model: Anthropic > OpenAI > OpenRouter > Gemini > OpenCode > GitHub Copilot > xAI > Groq > Mistral > Cerebras > Venice > Moonshot > Kimi > MiniMax > Synthetic > ZAI > AI Gateway > Xiaomi > Bedrock > Ollama.

If a provider env var is removed, that provider section is cleaned from openclaw.json on next start.

Deepgram (audio transcription, optional)

VariableDescription
DEEPGRAM_API_KEYDeepgram API key. Enables audio transcription via Nova 3 model.

Amazon Bedrock (uses AWS credential chain)

VariableDefaultDescription
AWS_ACCESS_KEY_IDAWS access key. Both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY required.
AWS_SECRET_ACCESS_KEYAWS secret key.
AWS_REGIONus-east-1AWS region for Bedrock runtime endpoint.
AWS_SESSION_TOKENOptional session token for temporary credentials.
BEDROCK_PROVIDER_FILTER["anthropic"]Filter Bedrock model discovery by provider (JSON array or comma-separated string).

Ollama (local models, no API key needed)

VariableDescription
OLLAMA_BASE_URLOllama server URL (e.g. http://host.docker.internal:11434). Enables Ollama provider when set.

Model selection

VariableDescription
OPENCLAW_PRIMARY_MODELOverride auto-selected primary model. Format: provider/model-id (e.g. anthropic/claude-sonnet-4-5-20250929).
VariableDefaultDescription
AUTH_PASSWORD(none)If set, nginx enforces HTTP basic auth on all routes except /healthz and the hooks path (when hooks are enabled). If unset, no auth — gateway is open.
AUTH_USERNAMEadminUsername for basic auth.

Gateway

VariableDefaultDescription
OPENCLAW_GATEWAY_TOKEN(auto-generated)Bearer token for gateway auth. Auto-generated and persisted to <STATE_DIR>/gateway.token if not set.
OPENCLAW_GATEWAY_PORT18789Internal port the gateway binds to.
OPENCLAW_GATEWAY_BINDloopbackGateway bind mode. loopback = 127.0.0.1 only (nginx proxies LAN traffic). lan = 0.0.0.0 (direct access, bypasses nginx auth). Also: tailnet, auto, custom.
OPENCLAW_STATE_DIR/data/.openclawPersistent state directory. Mount a volume here.
OPENCLAW_WORKSPACE_DIR/data/workspaceWorkspace directory for openclaw projects.
OPENCLAW_CONFIG_PATH<STATE_DIR>/openclaw.jsonOverride path to the config file.
OPENCLAW_CUSTOM_CONFIG/app/config/openclaw.jsonPath to a user-provided custom JSON config. Env vars override on top.

CORS / Allowed Origins (optional)

Configure Cross-Origin Resource Sharing for the Control UI. Required when accessing the gateway from a different origin (e.g., a custom web app or local dev server).

VariableDescription
OPENCLAW_ALLOWED_ORIGINSComma-separated list or JSON array of allowed origins. Example: http://localhost:5173,https://app.example.com or ["http://localhost:5173"].
# Allow specific origins
OPENCLAW_ALLOWED_ORIGINS=http://localhost:5173,https://app.example.com

# Or as JSON array
OPENCLAW_ALLOWED_ORIGINS='["http://localhost:5173","https://app.example.com"]'

Hooks (webhook automation, optional)

VariableDefaultDescription
HOOKS_ENABLEDSet to true to enable the webhook hooks endpoint.
HOOKS_TOKENShared secret for hook request auth. Required by openclaw when hooks are enabled.
HOOKS_PATH/hooksPath prefix for hook endpoints (/hooks/wake, /hooks/agent, etc.).

When hooks are enabled and AUTH_PASSWORD is set, the hooks path automatically bypasses HTTP basic auth. Openclaw validates requests using the hook token instead. Docs: https://docs.openclaw.ai/automation/webhook

Browser tool (remote CDP sidecar, optional)

VariableDefaultDescription
BROWSER_CDP_URLRemote CDP URL pointing to a browser sidecar (e.g. http://browser:9222). Required to activate browser tool.
BROWSER_EVALUATE_ENABLEDfalseAllow JavaScript evaluation in page context via browser actions.
BROWSER_SNAPSHOT_MODEDefault snapshot mode (e.g. efficient).
BROWSER_REMOTE_TIMEOUT_MS1500HTTP timeout in ms for remote CDP connection.
BROWSER_REMOTE_HANDSHAKE_TIMEOUT_MS3000WebSocket handshake timeout in ms for remote CDP.
BROWSER_DEFAULT_PROFILEOverride the default browser profile name.

Requires a separate browser container connected via Docker networking. Recommended: kasmweb/chrome (full Chrome desktop via noVNC on :6901, CDP on :9222). Docs: https://docs.openclaw.ai/tools/browser

Browser login (VNC sidecar)

For sites requiring authentication, use kasmweb/chrome so you can log in manually via a web-based desktop. Openclaw reuses the authenticated session via CDP.

  1. Open https://<host>:6901 — full Chrome desktop via noVNC
  2. Navigate to the target site, log in manually (handles captchas, 2FA, OAuth)
  3. Sessions persist in a mounted volume across restarts
  4. Set BROWSER_CDP_URL=http://browser:9222 — openclaw connects via CDP

Mount a persistent volume at the sidecar's profile directory (/home/kasm-user) so cookies and sessions survive container restarts. The sidecar may need CHROME_ARGS=--remote-debugging-port=9222 --remote-debugging-address=0.0.0.0 to expose CDP. Docs: https://docs.openclaw.ai/tools/browser-login

Channels (optional)

Note: Use these dedicated env vars for standard channel configuration. For settings not covered here, use Dot-Notation Config as a fallback.

VariableDefaultDescription
TELEGRAM_BOT_TOKENTelegram bot token from BotFather.
TELEGRAM_DM_POLICYpairingDM access policy: pairing, allowlist, open, or disabled.
TELEGRAM_ALLOW_FROMComma-separated allowlist of user IDs/usernames. Required when dmPolicy=allowlist or dmPolicy=open (use *).
TELEGRAM_GROUP_POLICYallowlistGroup access policy: open, allowlist, or disabled.
TELEGRAM_GROUP_ALLOW_FROMComma-separated group sender allowlist (user IDs/usernames).
TELEGRAM_REPLY_TO_MODEfirstReply threading: off, first, or all.
TELEGRAM_CHUNK_MODElengthOutbound split mode: length or newline (paragraph boundaries).
TELEGRAM_TEXT_CHUNK_LIMIT4000Outbound text chunk size (chars).
TELEGRAM_STREAM_MODEpartialDraft streaming: off, partial, or block.
TELEGRAM_LINK_PREVIEWtrueToggle link previews for outbound messages.
TELEGRAM_MEDIA_MAX_MB5Inbound/outbound media cap in MB.
TELEGRAM_REACTION_NOTIFICATIONSownWhich reactions trigger events: off, own, or all.
TELEGRAM_REACTION_LEVELminimalAgent reaction capability: off, ack, minimal, or extensive.
TELEGRAM_INLINE_BUTTONSallowlistInline button capability: off, dm, group, all, or allowlist.
TELEGRAM_ACTIONS_REACTIONStrueGate Telegram tool reactions.
TELEGRAM_ACTIONS_STICKERfalseGate Telegram sticker send/search actions.
TELEGRAM_PROXYProxy URL for Bot API calls (SOCKS/HTTP).
TELEGRAM_WEBHOOK_URLEnable webhook mode with public endpoint URL.
TELEGRAM_WEBHOOK_SECRETWebhook secret (optional).
TELEGRAM_WEBHOOK_PATH/telegram-webhookLocal webhook path for incoming updates.
TELEGRAM_MESSAGE_PREFIXPrefix prepended to inbound messages.
DISCORD_BOT_TOKENDiscord bot token. Enable MESSAGE CONTENT INTENT in Discord Developer Portal.
DISCORD_DM_POLICYpairingDM access policy: pairing, allowlist, open, or disabled.
DISCORD_DM_ALLOW_FROMComma-separated user IDs/names for DM allowlist.
DISCORD_GROUP_POLICYallowlistGuild access policy: open, allowlist, or disabled.
DISCORD_REPLY_TO_MODEoffReply threading: off, first, or all.
DISCORD_CHUNK_MODElengthOutbound split mode: length or newline.
DISCORD_TEXT_CHUNK_LIMIT2000Outbound text chunk size (chars).
DISCORD_MAX_LINES_PER_MESSAGE17Soft line limit per message.
DISCORD_MEDIA_MAX_MB8Inbound media cap in MB.
DISCORD_HISTORY_LIMIT20Recent guild messages for context.
DISCORD_DM_HISTORY_LIMITDM history limit per user.
DISCORD_REACTION_NOTIFICATIONSownWhich reactions trigger events: off, own, all, or allowlist.
DISCORD_ALLOW_BOTSfalseProcess messages from other bots.
DISCORD_MESSAGE_PREFIXPrefix prepended to inbound messages.
DISCORD_ACTIONS_REACTIONStrueGate reaction actions.
DISCORD_ACTIONS_STICKERStrueGate sticker send.
DISCORD_ACTIONS_EMOJI_UPLOADStrueGate emoji uploads.
DISCORD_ACTIONS_STICKER_UPLOADStrueGate sticker uploads.
DISCORD_ACTIONS_POLLStrueGate poll creation.
DISCORD_ACTIONS_PERMISSIONStrueGate channel permission edits.
DISCORD_ACTIONS_MESSAGEStrueGate message read/send/edit/delete.
DISCORD_ACTIONS_THREADStrueGate thread operations.
DISCORD_ACTIONS_PINStrueGate pin/unpin operations.
DISCORD_ACTIONS_SEARCHtrueGate message search.
DISCORD_ACTIONS_MEMBER_INFOtrueGate member lookup.
DISCORD_ACTIONS_ROLE_INFOtrueGate role list.
DISCORD_ACTIONS_CHANNEL_INFOtrueGate channel info.
DISCORD_ACTIONS_CHANNELStrueGate channel management.
DISCORD_ACTIONS_VOICE_STATUStrueGate voice state.
DISCORD_ACTIONS_EVENTStrueGate event management.
DISCORD_ACTIONS_ROLESfalseGate role add/remove.
DISCORD_ACTIONS_MODERATIONfalseGate timeout/kick/ban.
SLACK_BOT_TOKENSlack bot token (xoxb-...). Both bot + app token required for Slack.
SLACK_APP_TOKENSlack app token (xapp-...).
SLACK_USER_TOKENSlack user token (xoxp-...). Optional, for user-level API calls.
SLACK_SIGNING_SECRETSigning secret for HTTP mode verification.
SLACK_MODEsocketConnection mode: socket or http.
SLACK_WEBHOOK_PATH/slack/eventsWebhook path for HTTP mode.
SLACK_DM_POLICYpairingDM access policy: pairing or open.
SLACK_DM_ALLOW_FROMComma-separated user IDs/handles for DM allowlist.
SLACK_GROUP_POLICYopenChannel access policy: open, allowlist, or disabled.
SLACK_REPLY_TO_MODEoffReply threading: off, first, or all.
SLACK_REACTION_NOTIFICATIONSownWhich reactions trigger events: off, own, or all.
SLACK_CHUNK_MODEnewlineOutbound split mode.
SLACK_TEXT_CHUNK_LIMIT4000Outbound text chunk size (chars).
SLACK_MEDIA_MAX_MB20Inbound media cap in MB.
SLACK_HISTORY_LIMIT50Recent channel messages for context.
SLACK_ALLOW_BOTSfalseProcess messages from other bots.
SLACK_MESSAGE_PREFIXPrefix prepended to inbound messages.
SLACK_ACTIONS_REACTIONStrueGate reaction actions.
SLACK_ACTIONS_MESSAGEStrueGate message read/send/edit/delete.
SLACK_ACTIONS_PINStrueGate pin/unpin operations.
SLACK_ACTIONS_MEMBER_INFOtrueGate member lookup.
SLACK_ACTIONS_EMOJI_LISTtrueGate emoji list retrieval.
WHATSAPP_ENABLEDSet to true to enable WhatsApp channel. Uses QR/pairing code auth at runtime.
WHATSAPP_DM_POLICYpairingDM access policy: pairing, allowlist, open, or disabled.
WHATSAPP_ALLOW_FROMComma-separated E.164 phone numbers for DM allowlist.
WHATSAPP_SELF_CHAT_MODEfalseEnable when running on your personal WhatsApp number.
WHATSAPP_GROUP_POLICYallowlistGroup access policy: open, disabled, or allowlist.
WHATSAPP_GROUP_ALLOW_FROMComma-separated E.164 phone numbers for group sender allowlist.
WHATSAPP_MEDIA_MAX_MB50Inbound media save cap in MB.
WHATSAPP_HISTORY_LIMIT50Recent unprocessed messages inserted for group context.
WHATSAPP_DM_HISTORY_LIMITDM history limit in user turns.
WHATSAPP_SEND_READ_RECEIPTStrueSend read receipts (blue ticks) on message receipt.
WHATSAPP_ACK_REACTION_EMOJIEmoji sent on message receipt (e.g. 👀). Omit to disable.
WHATSAPP_ACK_REACTION_DIRECTtrueSend ack reactions in DM chats.
WHATSAPP_ACK_REACTION_GROUPmentionsGroup reaction behavior: always, mentions, or never.
WHATSAPP_MESSAGE_PREFIXInbound message prefix.
WHATSAPP_ACTIONS_REACTIONStrueEnable WhatsApp tool reactions.

If a channel env var is removed, that channel is cleaned from config on next start. WhatsApp env vars fully overwrite any existing WhatsApp config (no merge with custom JSON).

Provider overrides (optional)

VariableDescription
AI_GATEWAY_BASE_URLCustom base URL for AI gateway (e.g. Cloudflare AI Gateway). Applied to the matching provider based on URL suffix.
ANTHROPIC_BASE_URLOverride Anthropic API base URL specifically.
MOONSHOT_BASE_URLOverride Moonshot API base URL. Default: https://api.moonshot.ai/v1.
KIMI_BASE_URLOverride Kimi Coding API base URL. Default: https://api.moonshot.ai/anthropic.

Extra system packages (optional)

VariableDescription
OPENCLAW_DOCKER_APT_PACKAGESSpace-separated list of apt packages to install at container startup (e.g. ffmpeg build-essential). Packages are installed before openclaw starts. Reinstalled on each container restart.

Linuxbrew (baked into image)

The base image includes common skill dependencies baked in:

  • Linuxbrew/home/linuxbrew/.linuxbrew — skills that need brew work out of the box
  • Go/usr/local/go — for Go-based skills and tools
  • uv — fast Python package manager for Python-based skills
  • build-essential, git, curl — common build dependencies

Note: packages installed at runtime (e.g. via brew install) are part of the container filesystem and do not persist across container rebuilds. To permanently add packages, customize Dockerfile.base or use OPENCLAW_DOCKER_APT_PACKAGES for apt-available equivalents.

Custom init script (optional)

VariableDefaultDescription
OPENCLAW_DOCKER_INIT_SCRIPT(none)Script that runs on every container start before openclaw starts. Must be executable and idempotent.

Port

VariableDefaultDescription
PORT8080External port nginx listens on.

Dot-Notation Config (OPENCLAW__*) — Fallback for Customization

Recommended: Use the dedicated env vars (e.g., TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN) for standard configuration. Use dot-notation (OPENCLAW__*) only when you need to customize settings not covered by the dedicated vars or for quick one-off changes.

VariableDescription
OPENCLAW__<path>__<to>__<key>Set any config value using dot notation. Use [] suffix for arrays.
# Use dedicated env vars for standard config:
TELEGRAM_BOT_TOKEN=your-token
TELEGRAM_TEXT_CHUNK_LIMIT=4000

# Use dot-notation ONLY for small customizations not covered above:
OPENCLAW__channels__telegram__customSetting=value
OPENCLAW__channels__discord__customSetting=value

Auto-typing: true/false → boolean, integers → number, floats → number, otherwise string. Use [] suffix for arrays (comma-separated).

Precedence (highest wins): OPENCLAW_CONFIG_JSON > OPENCLAW__* dot-notation > dedicated env vars (e.g. TELEGRAM_BOT_TOKEN) > custom JSON mount > persisted config. If both a dedicated env var and a dot-notation var set the same key, the dot-notation value wins.

JSON Config via Env Var (OPENCLAW_CONFIG_JSON)

Pass partial or full config as a JSON string. This is parsed after dot-notation vars, so it can override them. Invalid JSON will cause the container to exit with an error.

VariableDescription
OPENCLAW_CONFIG_JSONJSON object merged into config. Must be valid JSON.
# Partial config override
OPENCLAW_CONFIG_JSON='{"gateway":{"port":8080},"channels":{"telegram":{"enabled":true}}}'

# In docker-compose (use quotes carefully)
environment:
  OPENCLAW_CONFIG_JSON: '{"gateway":{"port":8080}}'

Validation: If JSON is invalid, the container exits with error before starting. Use docker logs to see the parse error.

Coolify-specific (auto-set by Coolify)

VariableDescription
COOLIFY_FQDNPublic FQDN assigned by Coolify.
COOLIFY_URLCoolify dashboard URL.
COOLIFY_BRANCHGit branch deployed.

Custom JSON config (Docker mount)

For settings too complex for flat env vars (e.g. channels.*.groups, agent defaults, plugin config), mount a custom JSON file into the container:

docker run -v ./my-openclaw.json:/app/config/openclaw.json ...

Override the mount path with OPENCLAW_CUSTOM_CONFIG env var if needed.

3-tier merge order (configure.js):

  1. Custom JSON (/app/config/openclaw.json) — base layer
  2. Persisted state (<STATE_DIR>/openclaw.json) — preserves runtime changes from previous runs
  3. Env vars — applied on top, always win

Arrays are replaced, not concatenated. Provider API keys are always read from env vars, never from JSON.

Note: WhatsApp is a special case — when WHATSAPP_ENABLED=true, env vars fully overwrite the WhatsApp config block (custom JSON whatsapp keys are discarded). For all other channels, custom JSON keys are preserved and env vars merge on top.

Notes

  • Openclaw uses CalVer: v2026.1.29 (roughly daily releases). Detected via GitHub Releases API.
  • Using native ubuntu-24.04-arm runners for arm64 builds (same pattern as coollabsio/pocketbase).
  • Config is environment-driven: set env vars → restart container → config updates automatically.