← Back
OpenClaw Ops — Deploy OpenClaw with Docker Compose (production)

Deploy OpenClaw with Docker Compose (Production)

A production-grade Docker Compose setup for OpenClaw on a VPS: Caddy reverse proxy + HTTPS, secrets, upgrades, backups, and troubleshooting.

tested-on.txt
info
  • Tested on: Debian/Ubuntu
  • Updated: 2026-02-06
  • Assumption: Caddy is your public entrypoint; OpenClaw is not exposed directly.

Prerequisites

Architecture

The minimum safe shape is: client → reverse proxy (TLS) → OpenClaw Gateway. The proxy is the only public entrypoint.

OpenClaw Ops architecture diagram: client to reverse proxy to OpenClaw Gateway

Directory layout

/opt/openclaw/
  docker-compose.yml
  .env            # chmod 600
  Caddyfile

.env (template)

Keep secrets out of git. On the server: chmod 600 /opt/openclaw/.env.

# OpenClaw
OPENCLAW_BASE_URL=https://openclaw.example.com
# Add other required tokens/keys here.
# NEVER commit this file.

docker-compose.yml (OpenClaw + Caddy)

Notes:

services:
  openclaw:
    image: ghcr.io/openclaw/openclaw:latest
    restart: unless-stopped
    env_file:
      - .env
    expose:
      - "3000"
    volumes:
      - openclaw_data:/var/lib/openclaw

  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - openclaw

volumes:
  openclaw_data:
  caddy_data:
  caddy_config:

Caddyfile

Replace the domain and (optionally) set a real email for ACME.

openclaw.example.com {
  # email you@example.com

  encode zstd gzip

  # Basic security headers (adjust to your app needs)
  header {
    X-Content-Type-Options nosniff
    X-Frame-Options DENY
    Referrer-Policy no-referrer
  }

  reverse_proxy openclaw:3000
}

Start + verify

cd /opt/openclaw

docker compose up -d

docker compose ps
# Expect: openclaw + caddy = Up

docker compose logs -f --tail=200 caddy
# Expect: certificate obtained + no crash loops

Verification checklist:

Firewall hardening (UFW)

# allow ssh first (don’t lock yourself out)
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status verbose

Backups (volume snapshot)

Back up the OpenClaw data volume. Store backups off the host. Test restores.

# Create a timestamped tarball backup
TS=$(date -u +%Y%m%d-%H%M%S)
docker run --rm   -v openclaw-run_openclaw_data:/data:ro   -v /opt/openclaw/backups:/backups   alpine   sh -c "cd /data && tar -czf /backups/openclaw-data-$TS.tgz ."

Upgrades + rollback

# Upgrade
cd /opt/openclaw

docker compose pull
# (Optional) take a backup first

docker compose up -d

docker compose logs -f --tail=200 openclaw

# Rollback idea:
# - set image tag back to previous known-good
# - docker compose up -d

Troubleshooting

FAQ

Q
FAQ

Do I have to use Caddy?

No. This guide uses Caddy because it is the simplest way to get automatic HTTPS. If you already run Nginx/Traefik, keep it — the key rule is: only the proxy is public.

Q
FAQ

Should I expose the OpenClaw port directly?

No. Bind OpenClaw to localhost (127.0.0.1) or a private Docker network and expose it only through the reverse proxy.

Q
FAQ

How do I upgrade safely?

Pin image tags (not :latest), take a backup of volumes, pull the new image, restart, then verify health. Keep the previous tag to rollback.

Q
FAQ

Where should I store secrets?

Use a local .env with strict permissions (chmod 600). Do not commit it. For teams, use a secret manager and inject env at deploy time.

Q
FAQ

What should I back up?

Back up the OpenClaw data volume (state) and any local config you maintain (compose file, Caddyfile). Test restoring on a fresh host.

Production checklist

OpenClaw Ops production checklist before shipping

If you can’t check every line, don’t call it production yet.

Next

Canonical: https://openclaw.run/en/guides/docker-compose-production