Portainer Templates logo

Portainer Templates

OpenClaw OpenClaw

Stack

AI Agents

OpenClaw, an autonomous AI agent you run yourself: web dashboard, scheduled tasks, plugins, persistent workspace. This template uses the coollabsio all-in-one image (nginx + gateway, env-driven).

Image details

Pulls: 208k
Architecture: amd64, arm64
Image size: 2.0 GB
Latest: 2026.9.6
User: coollabsio
Created: Jan 31, 2026
Updated: 14 hours ago
Status: active

Source details

Stars: 399
Forks: 123
Language: JavaScript
Updated: 14 days ago

Configuration

Type
Compose
Platform
linux
Image
coollabsio/openclaw:2026.7.1
Ports
5000:5000
Volumes
/data : openclawdata
Env vars
PORT=5000ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}AUTH_USERNAME=${AUTH_USERNAME:-admin}AUTH_PASSWORD=${AUTH_PASSWORD}OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}OPENCLAW_ALLOWED_ORIGINS=${OPENCLAW_ALLOWED_ORIGINS:-}
Restart
unless-stopped
Source

Standalone Install

Select an install method, to see config/commands for deploying OpenClaw

Installation method

Install on Portainer

Import all app templates into your Portainer instance, for easy 1-click deploys

  1. Ensure both Docker and Portainer are installed, and up-to-date
  2. Log into your Portainer web UI
  3. Under Settings → App Templates, paste the below URL
  4. Head to Home → App Templates, and the list of apps will show up
  5. Select OpenClaw, fill in any config options, and hit Deploy

Template Import URL

https://raw.githubusercontent.com/Lissy93/portainer-templates/main/templates.json
Show Me demo
Original stackfile

The compose file this template deploys, straight from its repo:

name: openclaw

services:
  openclaw:
    image: coollabsio/openclaw:2026.7.1
    restart: unless-stopped
    environment:
      PORT: "5000"
      ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
      AUTH_USERNAME: ${AUTH_USERNAME:-admin}
      AUTH_PASSWORD: ${AUTH_PASSWORD}
      OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN}
      OPENCLAW_ALLOWED_ORIGINS: ${OPENCLAW_ALLOWED_ORIGINS:-}
    ports:
      - "5000:5000"
    volumes:
      - openclawdata:/data

volumes:
  openclawdata:

Or deploy it directly from the source:

git clone https://github.com/deployable-sh/stacks
cd stacks
docker compose -f openclaw/compose.yaml up -d

More install options in our documentation, or see coollabsio/openclaw for app-specific guidance.

Openclaw Automated Build

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, forcerebuild, skiplatesttag).

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
ANTHROPICAPIKEYAnthropic API key. Configures Claude models (Opus 4.5, Sonnet 4.5, Haiku 4.5). Set as primary when present.
OPENAIAPIKEYOpenAI API key. Configures GPT models (5.2, 5, 4.5-preview). Primary if no Anthropic key.
OPENROUTERAPIKEYOpenRouter API key. Primary if no Anthropic/OpenAI key.
GEMINIAPIKEYGoogle Gemini API key. Primary if no other provider key set.
XAIAPIKEYxAI API key. Configures Grok models.
GROQAPIKEYGroq API key. Configures Llama models on Groq hardware.
MISTRALAPIKEYMistral API key. Configures Mistral Large and other models.
CEREBRASAPIKEYCerebras API key. Configures Llama models on Cerebras hardware.
VENICEAPIKEYVenice AI API key (OpenAI-compatible). Configures Llama 3.3 70B.
MOONSHOTAPIKEYMoonshot API key (OpenAI-compatible). Configures Kimi K2.5.
KIMIAPIKEYKimi Coding API key (Anthropic-compatible). Configures K2P5.
MINIMAXAPIKEYMiniMax API key (Anthropic-compatible). Configures MiniMax M2.1.
ZAIAPIKEYZAI API key. Configures GLM models.
AIGATEWAYAPIKEYVercel AI Gateway API key.
OPENCODEAPIKEYOpenCode API key. Also accepted as OPENCODEZENAPIKEY.
SYNTHETICAPIKEYSynthetic API key (Anthropic-compatible).
COPILOTGITHUBTOKENGitHub Copilot token. Configures Claude models via GitHub.
XIAOMIAPIKEYXiaomi 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
DEEPGRAMAPIKEYDeepgram API key. Enables audio transcription via Nova 3 model.

Amazon Bedrock (uses AWS credential chain)

VariableDefaultDescription
AWSACCESSKEYIDAWS access key. Both AWSACCESSKEYID and AWSSECRETACCESSKEY required.
AWSSECRETACCESSKEYAWS secret key.
AWSREGIONus-east-1AWS region for Bedrock runtime endpoint.
AWSSESSIONTOKENOptional session token for temporary credentials.
BEDROCKPROVIDERFILTER"anthropic"Filter Bedrock model discovery by provider (JSON array or comma-separated string).

Ollama (local models, no API key needed)

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

Model selection

VariableDescription
OPENCLAWPRIMARYMODELOverride auto-selected primary model. Format: provider/model-id (e.g. anthropic/claude-sonnet-4-5-20250929).

HTTP Basic Auth (recommended)

VariableDefaultDescription
AUTHPASSWORD(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.
AUTHUSERNAMEadminUsername for basic auth.

Gateway

VariableDefaultDescription
OPENCLAWGATEWAYTOKEN(auto-generated)Bearer token for gateway auth. Auto-generated and persisted to <STATEDIR>/gateway.token if not set.
OPENCLAWGATEWAYPORT18789Internal port the gateway binds to.
OPENCLAWGATEWAYBINDloopbackGateway 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.
OPENCLAWSTATEDIR/data/.openclawPersistent state directory. Mount a volume here.
OPENCLAWWORKSPACEDIR/data/workspaceWorkspace directory for openclaw projects.
OPENCLAWCONFIGPATH<STATEDIR>/openclaw.jsonOverride path to the config file.
OPENCLAWCUSTOMCONFIG/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
OPENCLAWALLOWEDORIGINSComma-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
HOOKSENABLEDSet to true to enable the webhook hooks endpoint.
HOOKSTOKENShared secret for hook request auth. Required by openclaw when hooks are enabled.
HOOKSPATH/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
BROWSERCDPURLRemote CDP URL pointing to a browser sidecar (e.g. http://browser:9222). Required to activate browser tool.
BROWSEREVALUATEENABLEDfalseAllow JavaScript evaluation in page context via browser actions.
BROWSERSNAPSHOTMODEDefault snapshot mode (e.g. efficient).
BROWSERREMOTETIMEOUTMS1500HTTP timeout in ms for remote CDP connection.
BROWSERREMOTEHANDSHAKETIMEOUTMS3000WebSocket handshake timeout in ms for remote CDP.
BROWSERDEFAULTPROFILEOverride 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
TELEGRAMBOTTOKENTelegram bot token from BotFather.
TELEGRAMDMPOLICYpairingDM access policy: pairing, allowlist, open, or disabled.
TELEGRAMALLOWFROMComma-separated allowlist of user IDs/usernames. Required when dmPolicy=allowlist or dmPolicy=open (use ).
TELEGRAMGROUPPOLICYallowlistGroup access policy: open, allowlist, or disabled.
TELEGRAMGROUPALLOWFROMComma-separated group sender allowlist (user IDs/usernames).
TELEGRAMREPLYTOMODEfirstReply threading: off, first, or all.
TELEGRAMCHUNKMODElengthOutbound split mode: length or newline (paragraph boundaries).
TELEGRAMTEXTCHUNKLIMIT4000Outbound text chunk size (chars).
TELEGRAMSTREAMMODEpartialDraft streaming: off, partial, or block.
TELEGRAMLINKPREVIEWtrueToggle link previews for outbound messages.
TELEGRAMMEDIAMAXMB5Inbound/outbound media cap in MB.
TELEGRAMREACTIONNOTIFICATIONSownWhich reactions trigger events: off, own, or all.
TELEGRAMREACTIONLEVELminimalAgent reaction capability: off, ack, minimal, or extensive.
TELEGRAMINLINEBUTTONSallowlistInline button capability: off, dm, group, all, or allowlist.
TELEGRAMACTIONSREACTIONStrueGate Telegram tool reactions.
TELEGRAMACTIONSSTICKERfalseGate Telegram sticker send/search actions.
TELEGRAMPROXYProxy URL for Bot API calls (SOCKS/HTTP).
TELEGRAMWEBHOOKURLEnable webhook mode with public endpoint URL.
TELEGRAMWEBHOOKSECRETWebhook secret (optional).
TELEGRAMWEBHOOKPATH/telegram-webhookLocal webhook path for incoming updates.
TELEGRAMMESSAGEPREFIXPrefix prepended to inbound messages.
DISCORDBOTTOKENDiscord bot token. Enable MESSAGE CONTENT INTENT in Discord Developer Portal.
DISCORDDMPOLICYpairingDM access policy: pairing, allowlist, open, or disabled.
DISCORDDMALLOWFROMComma-separated user IDs/names for DM allowlist.
DISCORDGROUPPOLICYallowlistGuild access policy: open, allowlist, or disabled.
DISCORDREPLYTOMODEoffReply threading: off, first, or all.
DISCORDCHUNKMODElengthOutbound split mode: length or newline.
DISCORDTEXTCHUNKLIMIT2000Outbound text chunk size (chars).
DISCORDMAXLINESPERMESSAGE17Soft line limit per message.
DISCORDMEDIAMAXMB8Inbound media cap in MB.
DISCORDHISTORYLIMIT20Recent guild messages for context.
DISCORDDMHISTORYLIMITDM history limit per user.
DISCORDREACTIONNOTIFICATIONSownWhich reactions trigger events: off, own, all, or allowlist.
DISCORDALLOWBOTSfalseProcess messages from other bots.
DISCORDMESSAGEPREFIXPrefix prepended to inbound messages.
DISCORDACTIONSREACTIONStrueGate reaction actions.
DISCORDACTIONSSTICKERStrueGate sticker send.
DISCORDACTIONSEMOJIUPLOADStrueGate emoji uploads.
DISCORDACTIONSSTICKERUPLOADStrueGate sticker uploads.
DISCORDACTIONSPOLLStrueGate poll creation.
DISCORDACTIONSPERMISSIONStrueGate channel permission edits.
DISCORDACTIONSMESSAGEStrueGate message read/send/edit/delete.
DISCORDACTIONSTHREADStrueGate thread operations.
DISCORDACTIONSPINStrueGate pin/unpin operations.
DISCORDACTIONSSEARCHtrueGate message search.
DISCORDACTIONSMEMBERINFOtrueGate member lookup.
DISCORDACTIONSROLEINFOtrueGate role list.
DISCORDACTIONSCHANNELINFOtrueGate channel info.
DISCORDACTIONSCHANNELStrueGate channel management.
DISCORDACTIONSVOICESTATUStrueGate voice state.
DISCORDACTIONSEVENTStrueGate event management.
DISCORDACTIONSROLESfalseGate role add/remove.
DISCORDACTIONSMODERATIONfalseGate timeout/kick/ban.
SLACKBOTTOKENSlack bot token (xoxb-...). Both bot + app token required for Slack.
SLACKAPPTOKENSlack app token (xapp-...).
SLACKUSERTOKENSlack user token (xoxp-...). Optional, for user-level API calls.
SLACKSIGNINGSECRETSigning secret for HTTP mode verification.
SLACKMODEsocketConnection mode: socket or http.
SLACKWEBHOOKPATH/slack/eventsWebhook path for HTTP mode.
SLACKDMPOLICYpairingDM access policy: pairing or open.
SLACKDMALLOWFROMComma-separated user IDs/handles for DM allowlist.
SLACKGROUPPOLICYopenChannel access policy: open, allowlist, or disabled.
SLACKREPLYTOMODEoffReply threading: off, first, or all.
SLACKREACTIONNOTIFICATIONSownWhich reactions trigger events: off, own, or all.
SLACKCHUNKMODEnewlineOutbound split mode.
SLACKTEXTCHUNKLIMIT4000Outbound text chunk size (chars).
SLACKMEDIAMAXMB20Inbound media cap in MB.
SLACKHISTORYLIMIT50Recent channel messages for context.
SLACKALLOWBOTSfalseProcess messages from other bots.
SLACKMESSAGEPREFIXPrefix prepended to inbound messages.
SLACKACTIONSREACTIONStrueGate reaction actions.
SLACKACTIONSMESSAGEStrueGate message read/send/edit/delete.
SLACKACTIONSPINStrueGate pin/unpin operations.
SLACKACTIONSMEMBERINFOtrueGate member lookup.
SLACKACTIONSEMOJILISTtrueGate emoji list retrieval.
WHATSAPPENABLEDSet to true to enable WhatsApp channel. Uses QR/pairing code auth at runtime.
WHATSAPPDMPOLICYpairingDM access policy: pairing, allowlist, open, or disabled.
WHATSAPPALLOWFROMComma-separated E.164 phone numbers for DM allowlist.
WHATSAPPSELFCHATMODEfalseEnable when running on your personal WhatsApp number.
WHATSAPPGROUPPOLICYallowlistGroup access policy: open, disabled, or allowlist.
WHATSAPPGROUPALLOWFROMComma-separated E.164 phone numbers for group sender allowlist.
WHATSAPPMEDIAMAXMB50Inbound media save cap in MB.
WHATSAPPHISTORYLIMIT50Recent unprocessed messages inserted for group context.
WHATSAPPDMHISTORYLIMITDM history limit in user turns.
WHATSAPPSENDREADRECEIPTStrueSend read receipts (blue ticks) on message receipt.
WHATSAPPACKREACTIONEMOJIEmoji sent on message receipt (e.g. 👀). Omit to disable.
WHATSAPPACKREACTIONDIRECTtrueSend ack reactions in DM chats.
WHATSAPPACKREACTIONGROUPmentionsGroup reaction behavior: always, mentions, or never.
WHATSAPPMESSAGEPREFIXInbound message prefix.
WHATSAPPACTIONSREACTIONStrueEnable 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
AIGATEWAYBASEURLCustom base URL for AI gateway (e.g. Cloudflare AI Gateway). Applied to the matching provider based on URL suffix.
ANTHROPICBASEURLOverride Anthropic API base URL specifically.
MOONSHOTBASEURLOverride Moonshot API base URL. Default: https://api.moonshot.ai/v1.
KIMIBASEURLOverride Kimi Coding API base URL. Default: https://api.moonshot.ai/anthropic.

Extra system packages (optional)

VariableDescription
OPENCLAWDOCKERAPTPACKAGESSpace-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
OPENCLAWDOCKERINITSCRIPT(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 (OPENCLAWCONFIGJSON)

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
OPENCLAWCONFIGJSONJSON 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
COOLIFYFQDNPublic FQDN assigned by Coolify.
COOLIFYURLCoolify dashboard URL.
COOLIFYBRANCHGit 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.

Serve OpenClaw on your own domain behind Caddy, Nginx or Traefik. Fill in your domain and copy the result. It's a starting point, some apps need their own base URL or extra headers set too.

Proxying openclaw.example.com to http://openclaw:5000

Add this to your Caddyfile

openclaw.example.com {
	reverse_proxy http://openclaw:5000
}

Check the logs first

Nine times out of ten the logs tell you exactly what went wrong.

  • In Portainer, go to Containers, click the container, then Logs. Or run docker logs <container>
  • Exit codes help too: 137 means killed, usually out of memory. 126 or 127 means the command inside the image is broken.

Port already in use

If deployment fails with "Bind for 0.0.0.0:5000 failed: port is already allocated", something else on your server is using that port.

  • Find what's using it: sudo ss -tlnp | grep :5000
  • Stop the other service, or pick a different host port. In 5000:5000 only the left number is yours to change, the right one belongs to the app.

Running but the page won't load

The container is up but nothing appears in your browser.

  • Use your server's real IP: http://your-server-ip:5000. The 0.0.0.0 link Portainer shows isn't a real address.
  • Give it a minute after first deploy, openclaw can take a while to initialise.
  • Make sure your firewall allows the port, e.g. sudo ufw allow 5000

Image won't pull

Test the pull directly on the host: docker pull coollabsio/openclaw:2026.7.1

  • "manifest unknown" means the tag no longer exists.
  • "toomanyrequests" is the Docker Hub rate limit. Log in with docker login to raise it.
  • "no space left on device" means a full disk. Reclaim space with docker system prune

"exec format error"

This means the image was built for a different CPU architecture than your server.

  • This image supports: amd64, arm64
  • Check yours with uname -m: x86_64 is amd64, aarch64 is arm64. Raspberry Pi and other ARM boards are the usual culprits.

Container keeps restarting

The unless-stopped restart policy relaunches the app after every crash, so the real error can scroll past.

  • Check the logs right after a restart, the last few lines before it died are the useful ones.
  • Get the exit code with docker inspect <container> --format '{{.State.ExitCode}}'
  • Still stuck? Redeploy once with the restart policy set to no so the failure stays visible.

Stack won't deploy

Compose stacks fail fast on small mistakes, and Portainer shows the reason just above the editor.

  • YAML only accepts spaces for indentation, a single tab breaks the whole file.

Raise an issue

Found something which isn't working as it should? Here's how to report it.

A Compose stack

OpenClaw is a Compose stack, a set of containers defined in one file and brought up together by Portainer, then started and stopped as a single app.

The app image

An image is the app packed up ready to go, everything OpenClaw needs bundled into one download. This template pulls coollabsio/openclaw:2026.7.1, which Docker fetches once (about 2.0 GB) and then starts your own copy from.

Where the image comes from

Docker pulls its images from registries, public libraries of ready-built apps. OpenClaw's comes from Docker Hub, published by coollabsio.

Version tags

The bit after the colon in the image name is the version tag. This one pins 2026.7.1, so every redeploy gives you that exact build until you bump it yourself.

Which machines it runs on

Every image is built for particular CPU types. This one ships for amd64, arm64, so it runs on both regular x86 servers and ARM boards like a Raspberry Pi.

Ports

A port is the door the app answers on. A mapping like 5000:5000 means it's reachable on port 5000 of your server, where the left number is yours to change and the right one belongs to the app. It opens:

  • 5000:5000

Volumes

A volume is where OpenClaw keeps its files so they survive an update or a restart. Without one, anything it saves would sit inside the container and vanish the moment it's recreated. This template mounts:

  • /data kept in the openclawdata volume Docker manages

Environment variables

Environment variables are the settings you hand over when you deploy, things like a password or a timezone. OpenClaw takes 6 of them, all with defaults you can leave alone or tweak:

  • PORT, defaults to 5000
  • ANTHROPIC_API_KEY, pulled from your own environment
  • AUTH_USERNAME, defaults to admin
  • AUTH_PASSWORD, pulled from your own environment
  • OPENCLAW_GATEWAY_TOKEN, pulled from your own environment
  • OPENCLAW_ALLOWED_ORIGINS, pulled from your own environment. Set to the app's https domain on Miget (after first deploy):

Restart policy

The restart policy here is unless-stopped, so Docker restarts OpenClaw after a crash or reboot, but leaves it off when you stop it on purpose. You can change this on the deploy screen. The choices are no (never restart), on-failure (only after a crash), unless-stopped (restart unless you stop it), and always (bring it back no matter what).

Networking

Nothing custom is set, so OpenClaw sits on Docker's default bridge network: its own private space that reaches the outside world only through the ports it publishes.

Container name

Once it's deployed, Portainer names the container openclaw. That's what you'll spot in the containers list and use in commands like docker logs openclaw.

Platform

The platform is linux, the kind of system the container is built to run on. Docker and Portainer handle this on a normal Linux server.

Portainer app templates

Zooming out, this whole page comes from a Portainer app template: a short recipe telling Portainer how to set OpenClaw up. Add the template list to Portainer once, then deploying OpenClaw is a click rather than a wall of config.