Openclaw · EN · Part 3
Ch 11 Deployment And Operations
11-ch-11-Deployment-and-Operations.md
第11章 Deployment and Operations
"The gap between development and production is where good ideas go to die." This observation holds especially true for AI assistants that must reliably handle twenty messaging channels, maintain state across sessions, and respond within seconds. You've built OpenClaw locally—it works on your machine, passes tests, and handles your Telegram and WhatsApp messages during development. Now you need it to run continuously, survive restarts, and behave predictably when you're not watching over it.
Production deployment isn't just "running it somewhere else." It's about visibility, recoverability, and operational discipline. When the Gateway crashes at 3 AM, you need logs that explain why. When an update introduces a breaking change, you need a rollback path that doesn't require forensic archaeology. When disk space fills up with session history, you need monitoring that alerts you before operations degrade.
OpenClaw supports three primary deployment strategies, each with different trade-offs:
- npm global install: Simplest for single-machine deployments, gives you direct CLI access, but requires manual process management
- Docker containers: Isolated runtime, reproducible builds, easier horizontal scaling, but adds container orchestration complexity
- Building from source: Maximum customization, useful for development and testing, but requires ongoing maintenance
This chapter covers each approach, then dives into monitoring, logging, update management, and Docker-specific operations. We'll focus on what you need to know to keep OpenClaw running reliably in production.
Deployment Strategies
The right deployment strategy depends on your environment, scale requirements, and operational preferences. Let's examine each approach with production considerations.
npm Global Install Deployment
The simplest path to production is installing OpenClaw globally via npm:
# Install the latest published version
npm install -g openclaw@latest
# Or install a specific version for reproducibility
npm install -g [email protected]
This places the openclaw binary in your global npm bin directory (typically ~/Library/pnpm on macOS with pnpm, or /usr/local/bin with npm). The Gateway runs as a background process managed by launchd on macOS or systemd on Linux.
Starting the Gateway:
# Start the gateway in the background
openclaw gateway run --bind lan --port 18789
# Or run in daemon mode with auto-restart
openclaw gateway daemon start
Production considerations for npm deployment:
- Version pinning: Always specify explicit versions in production scripts. Using
@latestcan introduce breaking changes unexpectedly. - Process management: Use
openclaw gateway daemon starton macOS/Linux for automatic restart, or configure systemd/supervisord for more control. - Log rotation: Gateway logs grow indefinitely. Configure logrotate or use the
--log-fileflag with rotation. - User isolation: Run as a non-privileged user. The Gateway doesn't need root access after initial installation.
⚠️ 避坑指南: npm global installs share the same
node_modulestree across all global packages. If another global package installs conflicting dependencies, OpenClaw may fail to start. Version pinning and regular testing of updates in a staging environment first helps avoid this.
Docker Container Deployment
Docker provides isolation and reproducibility at the cost of added complexity. OpenClaw's multi-stage Dockerfile produces a minimal runtime image without build tools or source code.
Building the image:
# Default build (bookworm base)
docker build -t openclaw:local .
# Slim variant (smaller image, fewer preinstalled tools)
docker build --build-arg OPENCLAW_VARIANT=slim -t openclaw:local .
# With optional extensions and system packages
docker build \
--build-arg OPENCLAW_EXTENSIONS="diagnostics-otel" \
--build-arg OPENCLAW_DOCKER_APT_PACKAGES="python3 wget" \
-t openclaw:local .
Running with Docker Compose:
The repository provides a production-ready docker-compose.yml:
services:
openclaw-gateway:
image: ${OPENCLAW_IMAGE:-openclaw:local}
environment:
HOME: /home/node
TERM: xterm-256color
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
OPENCLAW_ALLOW_INSECURE_PRIVATE_WS: ${OPENCLAW_ALLOW_INSECURE_PRIVATE_WS:-}
TZ: ${OPENCLAW_TZ:-UTC}
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
ports:
- "${OPENCLAW_GATEWAY_PORT:-18789}:18789"
- "${OPENCLAW_BRIDGE_PORT:-18790}:18790"
init: true
restart: unless-stopped
command: ["node", "dist/index.js", "gateway", "--bind", "${OPENCLAW_GATEWAY_BIND:-lan}", "--port", "18789"]
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
retries: 5
start_period: 20s
Production considerations for Docker deployment:
- Volume permissions: The container runs as the
nodeuser (uid 1000). Ensure bind-mounted directories are writable by this UID, or use the setup script's permission-fixing step. - Networking: The default Gateway bind is
loopback(127.0.0.1). With Docker bridge networking, this makes the Gateway unreachable from the host. Either use--network hostor overrideOPENCLAW_GATEWAY_BIND=lan. - Resource limits: Set memory and CPU limits in docker-compose to prevent container resource exhaustion from affecting the host.
- Image digest pinning: For reproducible deployments, pin images by SHA256 digest rather than tags.
# Example resource limits
services:
openclaw-gateway:
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
🤿 深入底层: The Dockerfile uses a multi-stage build pattern. The
buildstage includes Bun for compilation, theruntime-assetsstage prunes dev dependencies, and the final runtime stage copies only production artifacts. This reduces the final image size by ~60% compared to a single-stage build.
Building from Source
Building from source gives you maximum control but requires ongoing maintenance:
# Clone and build
git clone https://github.com/openclaw/openclaw.git
cd openclaw
pnpm install
pnpm build
# Run the built output
node dist/index.js gateway run
Production considerations for source builds:
- Reproducibility: Pin exact commit SHAs in your deployment scripts.
mainbranch moves quickly. - Build time: Builds take 3-5 minutes on modern hardware. Factor this into deployment pipelines.
- Dependencies: Source builds require Node.js 22+, pnpm, and platform-specific build tools (Xcode for macOS, various compilers for Linux).
- Testing: Always run
pnpm testafter building before deploying. The codebase has 3,500+ tests for a reason.
Deployment Architecture
Here's how the pieces fit together in a production deployment:
Rendering diagram...
This architecture separates concerns: clients connect via WebSocket, the Gateway manages state, and monitoring runs independently. The health check endpoints (/healthz for liveness, /readyz for readiness) allow orchestrators like Docker or Kubernetes to detect and respond to Gateway failures.
☕ 茶水间时间: The health check uses a Node.js one-liner instead of
curlbecause the base Node image doesn't include curl. This design choice keeps the image smaller (~50MB savings) but requires the healthcheck to usefetch()via Node's built-in HTTP client.
Monitoring and Observability
Production systems require visibility. You can't fix what you can't see, and you can't improve what you don't measure. OpenClaw provides several mechanisms for monitoring Gateway health and behavior.
Health Checks
The Gateway exposes built-in health check endpoints:
# Liveness check: is the gateway process running?
curl http://localhost:18789/healthz
# Readiness check: is the gateway accepting requests?
curl http://localhost:18789/readyz
# With authentication
curl -H "X-Gateway-Token: your-token" http://localhost:18789/healthz
These endpoints return HTTP 200 when healthy and HTTP 503 when unhealthy. They're used by Docker's HEALTHCHECK directive and can be integrated with external monitoring systems.
What they check:
- /healthz: Verifies the Gateway server is responding. Fails if the process is dead or the HTTP server is stuck.
- /readyz: Verifies the Gateway can accept new WebSocket connections. Fails if at capacity or during shutdown.
Custom health checks:
# Check via CLI (respects configured auth)
openclaw health --token your-gateway-token
# Check from within a container
docker compose exec openclaw-gateway node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN"
Metrics Collection
OpenClaw doesn't include a built-in metrics server, but it exposes operational data through several paths:
- Gateway status:
openclaw gateway statusshows running state, uptime, and connection counts - Channel status:
openclaw channels statusshows per-channel connectivity - Session listing:
openclaw sessions listshows active sessions and their states
Example metrics collection script:
#!/bin/bash
# collect-metrics.sh - Gather Gateway metrics for monitoring
GATEWAY_TOKEN="${OPENCLAW_GATEWAY_TOKEN}"
GATEWAY_URL="${OPENCLAW_GATEWAY_URL:-http://localhost:18789}"
# Function to metric-safe output
sanitize_metric_name() {
echo "$1" | tr '[:upper:]' '[:lower:]' | tr -cs '[:alnum:]' '_'
}
# Collect Gateway status
STATUS=$(openclaw gateway status --token "$GATEWAY_TOKEN" 2>/dev/null)
UPTIME=$(echo "$STATUS" | grep "Uptime" | awk '{print $2}')
CONNECTIONS=$(echo "$STATUS" | grep "Connections" | awk '{print $2}')
echo "openclaw_gateway_uptime_seconds $UPTIME"
echo "openclaw_gateway_connections $CONNECTIONS"
# Collect per-channel status
openclaw channels status --token "$GATEWAY_TOKEN" 2>/dev/null | \
while read -r channel status; do
CHANNEL_METRIC=$(sanitize_metric_name "$channel")
STATUS_CODE=0
[[ "$status" == "connected" ]] && STATUS_CODE=1 || STATUS_CODE=0
echo "openclaw_channel_up{channel=\"$CHANNEL_METRIC\"} $STATUS_CODE"
done
This script outputs Prometheus-style metrics that can be scraped by monitoring systems.
Log Aggregation
OpenClaw logs to stdout/stderr by default, making it compatible with container log drivers and log aggregation systems:
Docker log driver configuration:
services:
openclaw-gateway:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Sending logs to external systems:
# Example: Send to syslog
services:
openclaw-gateway:
logging:
driver: "syslog"
options:
syslog-address: "tcp://192.168.0.42:514"
tag: "openclaw"
# Example: Send to Fluentd
services:
openclaw-gateway:
logging:
driver: "fluentd"
options:
fluentd-address: "localhost:24224"
tag: "openclaw.gateway"
macOS Unified Logging
On macOS, OpenClaw integrates with the unified logging system for structured, searchable logs:
# View recent OpenClaw logs
log show --predicate 'subsystem == "ai.openclaw"' --last 5m --info
# Stream logs in real-time
log stream --predicate 'subsystem == "ai.openclaw"' --level info
# Filter by category
log show --predicate 'subsystem == "ai.openclaw" AND category == "gateway"' --last 1h
clawlog.sh Tool
The scripts/clawlog.sh utility simplifies macOS log access:
# Show last 50 lines (default)
./scripts/clawlog.sh
# Follow logs in real-time
./scripts/clawlog.sh -f
# Show only errors
./scripts/clawlog.sh -e
# Show specific category
./scripts/clawlog.sh -c ServerManager
# Search for text
./scripts/clawlog.sh -s "failed to connect"
# Export to file
./scripts/clawlog.sh -l 1h -o /tmp/openclaw-logs.txt
The tool handles Apple's privacy redaction by using sudo to access full log details, which Apple otherwise hides for sensitive subsystems.
⚠️ 避坑指南: macOS unified logging has rate limits and may drop messages under high log volume. For production deployments, consider forwarding critical logs to an external aggregation system (syslog, Fluentd, or a SaaS logging service) to ensure nothing is lost.
Update Management
Software updates are a fact of life. OpenClaw provides several update mechanisms depending on your deployment method. The key principle is safe rollback: never deploy an update without a path back to the previous working state.
macOS Sparkle Update System
The macOS app uses Sparkle for automatic updates:
# Check for updates (via the app)
OpenClaw → Check for Updates...
# Manual update via CLI
openclaw update
Sparkle updates:
- Download the new version in the background
- Verify code signature
- Install on next app launch
- Keep the old version available for rollback
Rollback procedure:
# Sparkle keeps old versions in ~/Library/Caches/com.openclaw.OpenClaw
ls -la ~/Library/Caches/com.openclaw.OpenClaw/
# To rollback, quit the app and restore the previous version
killall OpenClaw
cp -r ~/Library/Caches/com.openclaw.OpenClaw/OpenClaw-2026.4.3.app /Applications/OpenClaw.app
open /Applications/OpenClaw.app
npm Version Updates
For npm installations, updates are manual:
# Check current version
openclaw --version
# Update to latest
npm update -g openclaw@latest
# Or install specific version
npm install -g [email protected]
# Verify update
openclaw --version
Safe update procedure:
#!/bin/bash
# safe-update.sh - Update OpenClaw with rollback path
CURRENT_VERSION=$(openclaw --version)
BACKUP_DIR="$HOME/.openclaw/backup/$(date +%Y%m%d-%H%M%S)"
echo "Current version: $CURRENT_VERSION"
# Create backup of config and state
mkdir -p "$BACKUP_DIR"
cp -r ~/.openclaw/config "$BACKUP_DIR/"
cp -r ~/.openclaw/agents "$BACKUP_DIR/"
# Update
npm update -g openclaw@latest
NEW_VERSION=$(openclaw --version)
echo "Updated to: $NEW_VERSION"
# Test gateway start
if openclaw gateway run --bind loopback --port 18790 --test; then
echo "Update successful, backup at: $BACKUP_DIR"
# Cleanup old backups (keep last 5)
ls -dt ~/.openclaw/backup/*/ | tail -n +6 | xargs rm -rf
else
echo "Update failed, rolling back..."
npm install -g "openclaw@$CURRENT_VERSION"
echo "Rolled back to: $CURRENT_VERSION"
exit 1
fi
Safe Rollback Procedures
Rollback is your safety net. Design your deployment process with rollback in mind:
Docker rollback:
# Tag images before deployment
docker tag openclaw:2026.4.4 openclaw:production
docker tag openclaw:2026.4.4 openclaw:previous
# Deploy new version
docker build -t openclaw:2026.4.5 .
docker tag openclaw:2026.4.5 openclaw:production
# If issues occur, rollback
docker tag openclaw:previous openclaw:production
docker compose up -d --force-recreate
Source build rollback:
# Always keep the previous working commit
git tag working-$(date +%Y%m%d)
git push origin working-$(date +%Y%m%d)
# Deploy new version
git pull origin main
pnpm install && pnpm build
# If issues occur
git checkout working-20260320
pnpm install && pnpm build
Version Coordination
OpenClaw has multiple versioned components that must stay in sync:
| Component | Location | Coordination Method |
|---|---|---|
| CLI/npm package | package.json | version field |
| macOS app | apps/macos/Sources/Info.plist | CFBundleShortVersionString |
| iOS app | apps/ios/Info.plist | CFBundleShortVersionString |
| Android app | apps/android/app/build.gradle.kts | versionName |
| Docs | docs/install/updating.md | Pinned version |
When releasing, update all locations simultaneously. The project provides a verification script:
# Check version alignment
pnpm version:check
# Bump all versions together
pnpm version:patch # 2026.4.4 → 2026.4.5
pnpm version:minor # 2026.4.4 → 2026.5.0
pnpm version:major # 2026.4.4 → 2027.0.0
🤿 深入底层: Version misalignment causes subtle bugs. For example, if the CLI is at 2026.4.5 but the macOS app is still at 2026.4.4, the app may try to use Gateway protocol features that the older CLI doesn't support, causing connection failures. Always verify version alignment after updates.
Docker and Container Operations
Docker deployment adds a layer of indirection but provides significant operational benefits: isolation, resource controls, and easy rollback. Let's dive deeper into Docker-specific considerations.
Dockerfile Configuration
The multi-stage Dockerfile optimizes for security and size:
# Build stage with Bun for compilation
FROM node:24-bookworm AS build
RUN curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:${PATH}"
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build:docker
RUN pnpm ui:build
# Runtime stage without build tools
FROM node:24-bookworm-slim AS runtime
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
procps hostname curl git lsof openssl
COPY --from=build --chown=node:node /app/dist ./dist
COPY --from=build --chown=node:node /app/node_modules ./node_modules
USER node
HEALTHCHECK CMD node -e "fetch('http://127.0.0.1:18789/healthz')..."
CMD ["node", "openclaw.mjs", "gateway", "--allow-unconfigured"]
Key security features:
- Non-root user: Runs as
node(uid 1000) to prevent container escape via root privileges - Minimal base: Uses
bookworm-slimto reduce attack surface - No build tools: Strips Bun, compilers, and dev dependencies from runtime image
- SHA256 pinning: Base image digests are pinned for reproducible builds
docker-compose Setup
The provided docker-compose.yml is production-ready but requires configuration:
Environment variables:
# .env file
OPENCLAW_CONFIG_DIR=/data/openclaw/config
OPENCLAW_WORKSPACE_DIR=/data/openclaw/workspace
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)
OPENCLAW_IMAGE=openclaw:local
OPENCLAW_TZ=America/New_York
Automated setup script:
# The scripts/docker/setup.sh handles:
# - Image building or pulling
# - Directory creation and permissions
# - Config file generation
# - Initial onboarding
# - Gateway startup
./scripts/docker/setup.sh
The setup script is idempotent—safe to run multiple times.
Volume Management
Volumes persist state outside the container lifecycle:
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
Volume considerations:
- Permissions: Container runs as uid 1000. Ensure host directories are writable by this UID.
- Backup: Use Docker volume backup commands or direct filesystem backups:
# Backup via tar tar -czf openclaw-backup-$(date +%Y%m%d).tar.gz /data/openclaw # Restore tar -xzf openclaw-backup-20260320.tar.gz -C / - Migration: To migrate volumes between hosts, use docker-volume-copy or similar tools.
Networking
Docker networking affects how clients reach the Gateway:
Bridge networking (default):
ports:
- "18789:18789" # HOST:CONTAINER mapping
With bridge networking, clients connect via host-ip:18789. The Gateway must bind to 0.0.0.0 (lan mode) for this to work.
Host networking:
services:
openclaw-gateway:
network_mode: "host"
With host networking, the container shares the host's network stack. Clients connect via localhost:18789. This bypasses Docker's network overhead but reduces isolation.
Tailscale integration:
For remote access, run Tailscale on the host and use the host's Tailscale IP:
# Get Tailscale IP
tailscale ip -4
# Connect clients via TAILSCALE_IP:18789
Container-Specific Considerations
Sandbox support:
The Gateway can spawn sandboxed containers for agent execution. This requires Docker-in-Docker:
# Build with Docker CLI
docker build --build-arg OPENCLAW_INSTALL_DOCKER_CLI=1 -t openclaw:local .
# Mount Docker socket
docker run -v /var/run/docker.sock:/var/run/docker.sock openclaw:local
The setup script (scripts/docker/setup.sh) handles this automatically when OPENCLAW_SANDBOX=1 is set.
Resource limits:
services:
openclaw-gateway:
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
Set limits based on your workload. Message-heavy workloads need more CPU; agents with large contexts need more memory.
Log rotation:
services:
openclaw-gateway:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Configure rotation to prevent log files from consuming disk space.
☕ 茶水间时间: The Gateway's health check uses
fetch()instead ofcurlbecause the Node base image doesn't include curl to stay small. The one-linernode -e "fetch(...)"works everywhere Node runs, avoiding the 50MB curl dependency. This is a micro-optimization that matters at scale but can confuse newcomers who expect standard Unix tools.
Production deployment requires security considerations...
You now have the tools to deploy OpenClaw using npm, Docker, or source builds. You can monitor health, collect metrics, aggregate logs, and handle updates safely. But production deployment also requires security: authentication, encryption, access control, and secrets management. A well-deployed system that's insecure is worse than no deployment at all.