核心要點

  • OpenClaw Gateway 是整個代理架構的中樞神經,預設在 ws://127.0.0.1:18789 運行,負責任務排程、記憶管理與 LLM 協調
  • Headless 模式結合 systemd 服務或 screen/tmux,可在無圖形介面的雲端伺服器上穩定持續運行
  • Docker Compose 是最低阻力的雲端部署方案;Kubernetes 則適合需要高可用性與自動擴縮的生產環境
  • WebSocket 反向代理必須正確設定 UpgradeConnection 標頭,TLS 終止應在 Nginx/Caddy 層完成
  • Cron Job 場景下,Gateway 的連線逾時(timeout)參數需與任務最長執行時間對齊,否則長任務將被強制中斷
  • 多節點架構須透過共享狀態層(Redis / etcd)實現 Gateway 間的 Workspace 同步與任務去重

當 OpenClaw 從個人桌面工具演進為企業級 AI 代理基礎設施,Gateway 的部署方式便成為決定整體系統可靠性的關鍵變數。[3] 預設的 http://127.0.0.1:18789 僅適合單機開發測試;一旦需要遠端存取、多人協作或 24/7 無人值守運行,工程師就必須面對 Headless 模式、Port 安全、容器化部署、WebSocket 代理與叢集協調等一系列複雜的基礎設施問題。[1]

本文從 Gateway 的架構角色出發,系統性地覆蓋從本地到雲端的完整部署路徑,包含每個環節的組態範例、安全考量與效能調優建議,是目前繁體中文社群中最完整的 OpenClaw Gateway 技術參考。

一、Gateway 在 OpenClaw 架構中的核心角色

理解 Gateway 的部署需求,必須先理解它在整個 OpenClaw 四層架構中的位置與職責。[1]

1.1 四層架構回顧

OpenClaw 的運行架構由四個層次組成,由上而下依序為:

在這個架構中,Gateway 不只是一個簡單的訊息轉發器,它承擔以下核心責任:

1.2 任務排程與優先級管理

Gateway 維護一個內部任務佇列(Task Queue),負責接收來自 Channel 的任務請求,並根據優先級、資源可用性與依賴關係,將任務分配給適當的 Node。這個排程邏輯類似於作業系統的進程排程器,確保多個並行任務不會相互干擾或爭用資源。

在 Cron 驅動的自動化場景中,Gateway 還需要維護定時任務的觸發記錄,防止在重啟後發生任務重複執行的問題。

1.3 記憶管理與 Workspace 維護

OpenClaw 的記憶系統(Memory System)以 Gateway 為中心。每個 Workspace 的上下文記憶、對話歷史、工具呼叫記錄都儲存在 Gateway 管理的持久化存儲中。當 Node 重新連接時,Gateway 負責恢復相應的 Workspace 狀態。

這意味著 Gateway 的存儲層是整個系統的單點真相來源(Single Source of Truth),其資料一致性和持久性直接影響代理的行為正確性。

1.4 LLM 請求協調

Gateway 扮演 LLM 請求的統一協調者。它管理對各個 LLM 提供商(OpenAI、Anthropic、本地 Ollama 等)的 API 金鑰、速率限制(Rate Limiting)與請求路由。當多個 Node 同時需要呼叫 LLM 時,Gateway 的協調機制防止同時觸發過多請求而超出 API 配額。

1.5 預設端點:ws://127.0.0.1:18789

Gateway 預設監聽 ws://127.0.0.1:18789,其中:

這個預設組態在本地開發環境中是安全且便利的,但在任何需要網路存取的場景下,都需要重新規劃。[2]

二、本地 vs 遠端 Gateway 部署策略

選擇正確的部署策略取決於使用場景的具體需求。以下是三種主要部署模式的系統性比較。

2.1 本地部署模式

適用場景:個人開發、探索性研究、需要存取本機硬體資源的任務

優點

限制

2.2 遠端 Gateway 模式

適用場景:24/7 自動化任務、團隊共用代理、需要穩定算力的 AI 工作負載

在遠端模式下,Gateway 運行在雲端伺服器(如 AWS EC2、GCP Compute Engine、Azure VM 或 VPS),Node 可以從任何有網路連線的地方連接。

架構示意

本地工作站 (Node)
    |
    | wss://gateway.example.com:443
    v
雲端伺服器 (Gateway + Nginx)
    |
    +-- OpenClaw Gateway :18789
    |
    +-- 持久化存儲 (記憶/Workspace)
    |
    +-- LLM API 路由

優點

限制

2.3 混合部署模式

混合模式(Hybrid Mode)是許多中型團隊的最佳實踐:Gateway 部署在雲端,但 Node 根據任務類型靈活分配:

Gateway 作為統一調度中心,透過任務標籤(Task Tags)或 Node 能力聲明(Capability Declaration)將任務路由到最適合的 Node。

三、Headless 模式設定

Headless 模式是指在無圖形顯示環境下運行 OpenClaw Gateway,這是雲端部署的基本要求。

3.1 什麼是 Headless 模式

OpenClaw 的預設啟動方式會嘗試初始化 GUI 元件(系統托盤圖示、設定視窗等)。在沒有桌面環境的 Linux 伺服器上,這會導致啟動失敗。Headless 模式透過環境變數或啟動參數告知 OpenClaw 跳過所有 GUI 初始化,僅啟動 Gateway 的核心服務。

3.2 SSH 遠端部署基本流程

透過 SSH 連接到遠端伺服器後,首先確認環境:

# 確認 Python 版本(OpenClaw 需要 Python 3.10+)
python3 --version

# 安裝 OpenClaw
pip install openclaw

# 設定必要的環境變數
export OPENCLAW_HEADLESS=true
export OPENCLAW_GATEWAY_HOST=0.0.0.0
export OPENCLAW_GATEWAY_PORT=18789

# 以 Headless 模式啟動 Gateway
openclaw gateway start --headless

3.3 使用 screen 保持 Gateway 持續運行

screen 是最簡單的後台持久化方案,SSH 斷開後進程繼續運行:

# 建立名為 openclaw-gateway 的 screen 會話
screen -S openclaw-gateway

# 在 screen 中啟動 Gateway
export OPENCLAW_HEADLESS=true
openclaw gateway start --headless

# 分離 screen(不終止進程)
# 按下 Ctrl+A,然後按 D

# 之後重新連接
screen -r openclaw-gateway

# 查看所有 screen 會話
screen -ls

3.4 使用 tmux 的進階管理

tmux 提供更豐富的多視窗管理能力,適合需要同時監控多個服務的場景:

# 建立新的 tmux 會話
tmux new-session -d -s openclaw -n gateway

# 在 gateway 視窗中執行啟動指令
tmux send-keys -t openclaw:gateway \
  'OPENCLAW_HEADLESS=true openclaw gateway start --headless' Enter

# 新增監控視窗
tmux new-window -t openclaw -n logs
tmux send-keys -t openclaw:logs \
  'tail -f ~/.openclaw/logs/gateway.log' Enter

# 分離會話
tmux detach

# 重新附加
tmux attach -t openclaw

3.5 systemd 服務設定(生產環境推薦)

對於生產環境,建議使用 systemd 服務管理 Gateway,以獲得自動重啟、日誌整合與開機自動啟動等功能:

# 建立服務設定檔
# /etc/systemd/system/openclaw-gateway.service

[Unit]
Description=OpenClaw Gateway Service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=openclaw
Group=openclaw
WorkingDirectory=/opt/openclaw
Environment="OPENCLAW_HEADLESS=true"
Environment="OPENCLAW_GATEWAY_HOST=127.0.0.1"
Environment="OPENCLAW_GATEWAY_PORT=18789"
Environment="OPENCLAW_LOG_LEVEL=info"
EnvironmentFile=/opt/openclaw/.env
ExecStart=/usr/local/bin/openclaw gateway start --headless
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=openclaw-gateway

# 資源限制
LimitNOFILE=65536
LimitNPROC=4096

[Install]
WantedBy=multi-user.target
# 啟用並啟動服務
sudo systemctl daemon-reload
sudo systemctl enable openclaw-gateway
sudo systemctl start openclaw-gateway

# 查看服務狀態
sudo systemctl status openclaw-gateway

# 查看日誌
sudo journalctl -u openclaw-gateway -f

注意:建議建立專用的 openclaw 系統使用者,避免以 root 身份運行服務,降低安全風險。[7]

四、網路組態與 Port 設定

4.1 預設 Port 18789 的選擇邏輯

OpenClaw 選用 18789 作為預設埠,是因為此埠號位於動態/私有埠範圍(49152 以上為 IANA 動態埠,1024–49151 為已登記埠),相對不容易與其他常見服務衝突。在本機開發環境中,http://127.0.0.1:18789 是 OpenClaw Web UI 和 API 的訪問地址。

4.2 修改 Gateway 監聽埠

若預設埠因衝突或安全政策需要更改,可透過以下方式調整:

# 方式一:環境變數
export OPENCLAW_GATEWAY_PORT=18790

# 方式二:組態檔 (~/.openclaw/config.yaml)
gateway:
  host: 127.0.0.1
  port: 18790
  websocket_path: /ws

# 方式三:啟動參數
openclaw gateway start --port 18790

修改埠後,所有連接到此 Gateway 的 Node 和 Client 也需要同步更新其連接設定。

4.3 綁定地址(Binding Address)策略

Gateway 的監聽地址決定了哪些網路介面可以接受連線:

# 僅本機(預設,最安全)
OPENCLAW_GATEWAY_HOST=127.0.0.1

# 所有介面(配合反向代理使用)
OPENCLAW_GATEWAY_HOST=0.0.0.0

# 特定網路介面(推薦用於多網卡伺服器)
OPENCLAW_GATEWAY_HOST=10.0.1.5

重要安全原則:若要允許外部存取,不應直接將 Gateway 暴露在公網。正確的做法是讓 Gateway 繼續監聽 127.0.0.1,由 Nginx 或 Caddy 等反向代理在前端接受外部連線,再轉發至 Gateway。

4.4 防火牆規則設定

在使用反向代理的架構中,防火牆只需開放標準的 HTTPS 埠:

# Ubuntu/Debian (ufw)
sudo ufw allow 22/tcp    # SSH(限制來源 IP 更佳)
sudo ufw allow 80/tcp    # HTTP(用於 Let's Encrypt 驗證)
sudo ufw allow 443/tcp   # HTTPS / WSS
sudo ufw deny 18789/tcp  # 明確封鎖 Gateway 直接存取
sudo ufw enable

# CentOS/RHEL (firewalld)
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --remove-port=18789/tcp
sudo firewall-cmd --reload

五、Docker 部署完整指南

Docker 容器化部署是目前最廣泛使用的 OpenClaw 雲端部署方案,提供環境隔離、版本管理和快速部署的優勢。[4]

5.1 Dockerfile 設計

# Dockerfile
FROM python:3.11-slim-bookworm

# 安裝系統依賴
RUN apt-get update && apt-get install -y --no-install-recommends \
  curl \
  git \
  ca-certificates \
  && rm -rf /var/lib/apt/lists/*

# 建立非 root 使用者
RUN groupadd -r openclaw && useradd -r -g openclaw -d /app openclaw

WORKDIR /app

# 複製並安裝 Python 依賴
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 安裝 OpenClaw
RUN pip install --no-cache-dir openclaw

# 建立必要目錄
RUN mkdir -p /app/data /app/logs && \
  chown -R openclaw:openclaw /app

# 切換到非 root 使用者
USER openclaw

# 設定環境變數
ENV OPENCLAW_HEADLESS=true \
  OPENCLAW_GATEWAY_HOST=0.0.0.0 \
  OPENCLAW_GATEWAY_PORT=18789 \
  OPENCLAW_DATA_DIR=/app/data \
  OPENCLAW_LOG_DIR=/app/logs \
  OPENCLAW_LOG_LEVEL=info

# 暴露 Gateway 埠
EXPOSE 18789

# 健康檢查
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
  CMD curl -f http://localhost:18789/health || exit 1

# 啟動 Gateway
CMD ["openclaw", "gateway", "start", "--headless"]

5.2 docker-compose.yml 完整設定

# docker-compose.yml
version: '3.8'

services:
  openclaw-gateway:
    build:
      context: .
      dockerfile: Dockerfile
    image: openclaw-gateway:latest
    container_name: openclaw-gateway
    restart: unless-stopped
    environment:
      - OPENCLAW_HEADLESS=true
      - OPENCLAW_GATEWAY_HOST=0.0.0.0
      - OPENCLAW_GATEWAY_PORT=18789
      - OPENCLAW_LOG_LEVEL=info
    env_file:
      - .env.gateway  # 敏感資料(API 金鑰等)
    volumes:
      - openclaw-data:/app/data
      - openclaw-logs:/app/logs
      - ./config:/app/config:ro
    networks:
      - openclaw-internal
    # 不直接暴露到宿主機,由 nginx 代理
    expose:
      - "18789"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:18789/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  nginx:
    image: nginx:1.25-alpine
    container_name: openclaw-nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - certbot-www:/var/www/certbot:ro
      - certbot-conf:/etc/letsencrypt:ro
    networks:
      - openclaw-internal
      - openclaw-external
    depends_on:
      openclaw-gateway:
        condition: service_healthy

  certbot:
    image: certbot/certbot:latest
    container_name: openclaw-certbot
    volumes:
      - certbot-www:/var/www/certbot
      - certbot-conf:/etc/letsencrypt
    # 每 12 小時自動續期
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

volumes:
  openclaw-data:
    driver: local
  openclaw-logs:
    driver: local
  certbot-www:
    driver: local
  certbot-conf:
    driver: local

networks:
  openclaw-internal:
    internal: true
  openclaw-external:
    driver: bridge

5.3 環境變數檔案(.env.gateway)

# .env.gateway(不要提交到版本控制)
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
OPENCLAW_AUTH_SECRET=your-strong-secret-key-here
OPENCLAW_WORKSPACE_ENCRYPTION_KEY=your-32-char-encryption-key

# 可選:Ollama 本地 LLM
OLLAMA_HOST=http://ollama:11434

5.4 常用 Docker 管理指令

# 建置並啟動
docker compose up -d --build

# 查看日誌
docker compose logs -f openclaw-gateway

# 重啟 Gateway(保留資料)
docker compose restart openclaw-gateway

# 完全重建(更新版本時)
docker compose down
docker compose pull
docker compose up -d --build

# 進入容器除錯
docker compose exec openclaw-gateway /bin/bash

# 備份資料
docker run --rm -v openclaw-data:/data -v $(pwd):/backup \
  alpine tar czf /backup/openclaw-backup-$(date +%Y%m%d).tar.gz /data

六、Kubernetes 雲端部署

當需要高可用性、自動擴縮與企業級運維能力時,Kubernetes 是首選平台。[5]

6.1 Deployment Manifest

# openclaw-gateway-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: openclaw-gateway
  namespace: openclaw
  labels:
    app: openclaw-gateway
    version: "1.0"
spec:
  replicas: 1  # Gateway 單副本(多副本需要共享狀態)
  selector:
    matchLabels:
      app: openclaw-gateway
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  template:
    metadata:
      labels:
        app: openclaw-gateway
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9090"
        prometheus.io/path: "/metrics"
    spec:
      serviceAccountName: openclaw-gateway
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
      containers:
      - name: gateway
        image: your-registry/openclaw-gateway:1.0.0
        imagePullPolicy: Always
        ports:
        - containerPort: 18789
          name: websocket
        - containerPort: 9090
          name: metrics
        env:
        - name: OPENCLAW_HEADLESS
          value: "true"
        - name: OPENCLAW_GATEWAY_HOST
          value: "0.0.0.0"
        - name: OPENCLAW_GATEWAY_PORT
          value: "18789"
        envFrom:
        - secretRef:
            name: openclaw-secrets
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
          limits:
            cpu: "2000m"
            memory: "2Gi"
        livenessProbe:
          httpGet:
            path: /health
            port: 18789
          initialDelaySeconds: 60
          periodSeconds: 30
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /ready
            port: 18789
          initialDelaySeconds: 30
          periodSeconds: 10
        volumeMounts:
        - name: openclaw-data
          mountPath: /app/data
        - name: openclaw-config
          mountPath: /app/config
          readOnly: true
      volumes:
      - name: openclaw-data
        persistentVolumeClaim:
          claimName: openclaw-gateway-pvc
      - name: openclaw-config
        configMap:
          name: openclaw-config

6.2 Service 與 Ingress 設定

# openclaw-gateway-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: openclaw-gateway
  namespace: openclaw
spec:
  selector:
    app: openclaw-gateway
  ports:
  - name: websocket
    port: 18789
    targetPort: 18789
  type: ClusterIP

---
# openclaw-gateway-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: openclaw-gateway
  namespace: openclaw
  annotations:
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - gateway.example.com
    secretName: openclaw-gateway-tls
  rules:
  - host: gateway.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: openclaw-gateway
            port:
              number: 18789

6.3 PersistentVolumeClaim

# openclaw-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: openclaw-gateway-pvc
  namespace: openclaw
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: premium-ssd  # 依雲端提供商調整
  resources:
    requests:
      storage: 20Gi

6.4 HorizontalPodAutoscaler(適用於 Node 層)

Gateway 本身建議保持單副本(配合共享狀態);Node 層則可配置 HPA 實現自動擴縮:

# openclaw-node-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: openclaw-node-hpa
  namespace: openclaw
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: openclaw-node
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

七、反向代理與 TLS 安全

WebSocket 代理的設定比 HTTP 代理更為複雜,需要特別注意協議升級(Protocol Upgrade)機制。[6]

7.1 Nginx WebSocket 代理設定

# /etc/nginx/conf.d/openclaw.conf

upstream openclaw_gateway {
  server 127.0.0.1:18789;
  keepalive 32;
}

# HTTP → HTTPS 重導向
server {
  listen 80;
  server_name gateway.example.com;

  location /.well-known/acme-challenge/ {
    root /var/www/certbot;
  }

  location / {
    return 301 https://$host$request_uri;
  }
}

# HTTPS + WSS 主要伺服器
server {
  listen 443 ssl http2;
  server_name gateway.example.com;

  # TLS 憑證(由 Let's Encrypt 或其他 CA 提供)
  ssl_certificate /etc/letsencrypt/live/gateway.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/gateway.example.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/gateway.example.com/chain.pem;

  # TLS 安全設定
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 1d;

  # HSTS
  add_header Strict-Transport-Security "max-age=63072000" always;

  # WebSocket 代理關鍵設定
  location /ws {
    proxy_pass http://openclaw_gateway;
    proxy_http_version 1.1;

    # WebSocket 協議升級標頭(缺少此設定將導致連線失敗)
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    # 標準代理標頭
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    # 長連線 Timeout 設定(根據任務最長執行時間調整)
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;
    proxy_connect_timeout 30s;

    # 停用緩衝(WebSocket 需要即時傳輸)
    proxy_buffering off;
    proxy_cache off;
  }

  # REST API 端點(如有)
  location /api {
    proxy_pass http://openclaw_gateway;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_read_timeout 300s;
  }

  # 健康檢查端點
  location /health {
    proxy_pass http://openclaw_gateway;
    access_log off;
  }
}

7.2 Caddy 自動 TLS 設定(更簡潔的替代方案)

# Caddyfile
gateway.example.com {
  # Caddy 自動申請並續期 Let's Encrypt 憑證

  # WebSocket 代理
  reverse_proxy /ws localhost:18789 {
    header_up Upgrade {http.upgrade}
    header_up Connection "Upgrade"
    transport http {
      read_timeout 1h
      write_timeout 1h
    }
  }

  # 其他路徑
  reverse_proxy localhost:18789

  # 安全標頭
  header {
    Strict-Transport-Security "max-age=63072000"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "DENY"
  }

  # 記錄
  log {
    output file /var/log/caddy/openclaw.log
    format json
  }
}

7.3 Let's Encrypt 憑證申請

# 安裝 Certbot
sudo apt install certbot python3-certbot-nginx

# 申請憑證(Nginx 外掛自動設定)
sudo certbot --nginx -d gateway.example.com

# 測試自動續期
sudo certbot renew --dry-run

# 設定 Cron 自動續期
echo "0 3 * * * certbot renew --quiet" | sudo crontab -

Let's Encrypt 的自動化 TLS 管理大幅降低了憑證維護的人工成本。[9]

八、多節點叢集架構

當單一 Gateway 的容量或可用性無法滿足需求時,需要設計多節點叢集架構。

8.1 多 Gateway 協調的核心挑戰

多個 Gateway 實例若沒有協調機制,會出現以下問題:

8.2 共享狀態層設計

解決上述問題的標準方案是引入外部共享狀態層:

# docker-compose.cluster.yml(多 Gateway 叢集)
version: '3.8'

services:
  # 共享狀態:Redis(會話、任務鎖、Workspace 快取)
  redis:
    image: redis:7-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - openclaw-cluster

  # 共享狀態:etcd(分散式鎖、節點選舉)
  etcd:
    image: bitnami/etcd:3.5
    environment:
      - ALLOW_NONE_AUTHENTICATION=no
      - ETCD_ROOT_PASSWORD=${ETCD_PASSWORD}
    volumes:
      - etcd-data:/bitnami/etcd
    networks:
      - openclaw-cluster

  # Gateway 實例 1
  gateway-1:
    image: openclaw-gateway:latest
    environment:
      - OPENCLAW_HEADLESS=true
      - OPENCLAW_CLUSTER_MODE=true
      - OPENCLAW_REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379
      - OPENCLAW_ETCD_ENDPOINTS=http://etcd:2379
      - OPENCLAW_NODE_ID=gateway-1
    networks:
      - openclaw-cluster
      - openclaw-internal

  # Gateway 實例 2
  gateway-2:
    image: openclaw-gateway:latest
    environment:
      - OPENCLAW_HEADLESS=true
      - OPENCLAW_CLUSTER_MODE=true
      - OPENCLAW_REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379
      - OPENCLAW_ETCD_ENDPOINTS=http://etcd:2379
      - OPENCLAW_NODE_ID=gateway-2
    networks:
      - openclaw-cluster
      - openclaw-internal

  # 負載均衡器(支援 WebSocket Sticky Session)
  haproxy:
    image: haproxy:2.8-alpine
    volumes:
      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
    ports:
      - "18789:18789"
    networks:
      - openclaw-cluster
      - openclaw-external

8.3 HAProxy Sticky Session 設定

WebSocket 連線需要 Sticky Session(黏性會話)確保同一 Node 始終連到同一 Gateway:

# haproxy.cfg
global
  log stdout format raw local0

defaults
  mode http
  log global
  option httplog
  timeout connect 5s
  timeout client 1h
  timeout server 1h
  timeout tunnel 1h  # WebSocket 長連線

frontend openclaw-frontend
  bind *:18789
  default_backend openclaw-gateways

backend openclaw-gateways
  balance leastconn
  # 基於 Cookie 的 Sticky Session
  cookie GATEWAY_ID insert indirect nocache
  option http-server-close
  option forwardfor

  server gateway-1 gateway-1:18789 cookie gw1 check
  server gateway-2 gateway-2:18789 cookie gw2 check

8.4 節點發現機制

在動態擴縮的環境中,Gateway 需要自動發現新加入的 Node。可透過 OpenClaw 的節點登記 API 實現:

# 節點啟動時向 Gateway 登記(Node 端)
openclaw node register \
  --gateway wss://gateway.example.com/ws \
  --node-id node-$(hostname) \
  --capabilities "browser,shell,file" \
  --auth-token ${OPENCLAW_AUTH_TOKEN}

九、Timeout 與連線管理

Timeout 設定是 OpenClaw Gateway 部署中最容易被忽視卻最容易造成問題的環節,尤其在 Cron Job 自動化場景中。

9.1 WebSocket 連線的 Timeout 層次

一個 OpenClaw WebSocket 連線從建立到維持,需要通過多個 Timeout 關卡:

Client/Node
  → [TCP Timeout: 30s]
  → Nginx/Caddy
    → [proxy_connect_timeout: 30s]
    → [proxy_read_timeout: 3600s]
    → [proxy_send_timeout: 3600s]
    → Gateway
      → [ws_ping_interval: 30s]
      → [ws_ping_timeout: 10s]
      → [task_execution_timeout: 可設定]

任何一層的 Timeout 值小於任務的實際執行時間,都會導致連線被強制關閉,任務失敗。

9.2 Gateway 內部 Timeout 設定

# ~/.openclaw/config.yaml
gateway:
  websocket:
    # 心跳間隔(秒)
    ping_interval: 30
    # 心跳回應等待時間(秒)
    ping_timeout: 10
    # 最大訊息大小(bytes)
    max_message_size: 10485760  # 10MB
    # 連線閒置斷開時間(0 = 不斷開)
    idle_timeout: 0

  tasks:
    # 預設任務逾時(秒,0 = 不限制)
    default_timeout: 0
    # 長時間任務警告閾值(秒)
    long_task_warning: 300
    # 任務排隊最長等待時間(秒)
    queue_timeout: 600

  reconnect:
    # 自動重連嘗試次數(-1 = 無限)
    max_retries: -1
    # 初始重連等待(秒)
    initial_delay: 1
    # 最大重連等待(秒,指數退避上限)
    max_delay: 60
    # 退避係數
    backoff_factor: 2

9.3 Cron Job 場景的 Timeout 策略

Cron Gateway 觸發的自動化任務有幾個特殊的 Timeout 考量:

# Cron Job 觸發 OpenClaw 任務的正確方式

# 方式一:透過 CLI(短任務,< 5 分鐘)
0 * * * * /usr/local/bin/openclaw task run \
  --gateway wss://gateway.example.com/ws \
  --workspace my-workspace \
  --timeout 300 \
  "執行每小時資料同步任務"

# 方式二:透過 API(長任務,非同步)
0 0 * * * curl -X POST \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"task": "執行每日報告生成", "async": true, "timeout": 7200}' \
  https://gateway.example.com/api/tasks

# 方式三:防止任務重疊執行
0 * * * * flock -n /tmp/openclaw-hourly.lock \
  openclaw task run --timeout 3500 "每小時任務"

9.4 連線重試與斷線重連策略

Node 端應實作指數退避(Exponential Backoff)重連策略:

# Node 重連設定(~/.openclaw/node.yaml)
connection:
  gateway_url: wss://gateway.example.com/ws
  auth_token: ${OPENCLAW_AUTH_TOKEN}

  reconnect:
    enabled: true
    max_retries: -1  # 無限重試
    initial_delay_ms: 1000
    max_delay_ms: 60000
    backoff_multiplier: 2.0
    jitter: true  # 加入隨機抖動防止驚群效應

  keepalive:
    enabled: true
    interval_ms: 30000  # 每 30 秒發送 ping
    timeout_ms: 10000   # 10 秒內未收到 pong 視為斷線

十、監控與日誌

生產環境的 Gateway 必須有完善的可觀測性(Observability)設施,包含指標(Metrics)、日誌(Logs)與追蹤(Traces)三個面向。[10]

10.1 Prometheus 指標暴露

# Gateway 暴露的主要 Prometheus 指標
# 存取路徑:http://gateway:9090/metrics

# 連線指標
openclaw_gateway_connections_total          # 歷史總連線數
openclaw_gateway_connections_active         # 當前活躍連線數
openclaw_gateway_connections_failed_total   # 連線失敗數

# 任務指標
openclaw_tasks_queued                       # 佇列中的任務數
openclaw_tasks_running                      # 執行中的任務數
openclaw_tasks_completed_total              # 已完成任務數
openclaw_tasks_failed_total                 # 失敗任務數
openclaw_task_duration_seconds              # 任務執行時間分佈

# LLM 呼叫指標
openclaw_llm_requests_total                 # LLM 請求總數
openclaw_llm_tokens_total                   # 消耗的 token 總數
openclaw_llm_latency_seconds               # LLM 回應延遲

# 記憶體與存儲指標
openclaw_memory_entries_total              # 記憶條目總數
openclaw_workspace_count                    # 活躍 Workspace 數量

10.2 Prometheus + Grafana 部署

# monitoring/docker-compose.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.retention.time=30d
    networks:
      - monitoring

  grafana:
    image: grafana/grafana:latest
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
      - GF_AUTH_ANONYMOUS_ENABLED=false
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards
      - ./grafana/datasources:/etc/grafana/provisioning/datasources
    ports:
      - "3000:3000"
    networks:
      - monitoring
# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'openclaw-gateway'
    static_configs:
      - targets: ['openclaw-gateway:9090']
    metric_relabel_configs:
      - source_labels: [__name__]
        regex: 'openclaw_.*'
        action: keep

10.3 結構化日誌設定

# Gateway 日誌輸出為 JSON 格式(便於 ELK/Loki 解析)
# ~/.openclaw/config.yaml
logging:
  format: json
  level: info
  output:
    - type: file
      path: /var/log/openclaw/gateway.log
      max_size_mb: 100
      max_backups: 10
      compress: true
    - type: stdout

# 日誌範例輸出
{
  "timestamp": "2026-02-22T10:30:00.000Z",
  "level": "info",
  "component": "gateway",
  "event": "task_completed",
  "task_id": "task-abc123",
  "workspace": "prod-workspace",
  "duration_ms": 45230,
  "llm_tokens": 1823,
  "node_id": "node-server-01"
}

10.4 告警規則設定

# prometheus-alerts.yml
groups:
- name: openclaw-gateway
  rules:
  - alert: GatewayDown
    expr: up{job="openclaw-gateway"} == 0
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "OpenClaw Gateway 服務中斷"
      description: "Gateway {{ $labels.instance }} 已超過 1 分鐘無法存取"

  - alert: HighTaskFailureRate
    expr: |
      rate(openclaw_tasks_failed_total[5m]) /
      rate(openclaw_tasks_completed_total[5m]) > 0.1
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "任務失敗率過高"
      description: "過去 5 分鐘任務失敗率超過 10%"

  - alert: LLMLatencyHigh
    expr: |
      histogram_quantile(0.95, openclaw_llm_latency_seconds_bucket) > 30
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "LLM 回應延遲過高"
      description: "P95 LLM 延遲超過 30 秒,持續 10 分鐘"

十一、生產環境部署 Checklist

在將 OpenClaw Gateway 推送到生產環境之前,請逐項確認以下清單。[7]

11.1 安全審計

11.2 資源規劃

根據工作負載特性選擇適當的主機規格:

規模 並行任務 CPU 記憶體 存儲
小型(個人) 1–3 2 vCPU 4 GB 20 GB SSD
中型(小團隊) 5–10 4 vCPU 8 GB 50 GB SSD
大型(企業) 20+ 8+ vCPU 16+ GB 200 GB NVMe

11.3 備份策略

# 自動化備份腳本(/opt/scripts/backup-openclaw.sh)
#!/bin/bash
set -euo pipefail

BACKUP_DIR="/backups/openclaw"
DATE=$(date +%Y%m%d-%H%M%S)
RETENTION_DAYS=30

mkdir -p "$BACKUP_DIR"

# 備份 Workspace 資料
tar czf "$BACKUP_DIR/workspace-$DATE.tar.gz" \
  /opt/openclaw/data/workspaces/

# 備份設定檔
tar czf "$BACKUP_DIR/config-$DATE.tar.gz" \
  /opt/openclaw/config/ \
  ~/.openclaw/config.yaml

# 上傳到 S3(可選)
if [ -n "${AWS_S3_BUCKET:-}" ]; then
  aws s3 cp "$BACKUP_DIR/workspace-$DATE.tar.gz" \
    "s3://$AWS_S3_BUCKET/openclaw-backups/"
fi

# 清理舊備份
find "$BACKUP_DIR" -name "*.tar.gz" \
  -mtime +"$RETENTION_DAYS" -delete

echo "備份完成:workspace-$DATE.tar.gz"
# 加入 Cron 每日備份
0 2 * * * /opt/scripts/backup-openclaw.sh >> /var/log/openclaw-backup.log 2>&1

11.4 災難恢復程序

# Gateway 重啟程序(systemd)
# 1. 確認服務狀態
sudo systemctl status openclaw-gateway

# 2. 嘗試正常重啟
sudo systemctl restart openclaw-gateway

# 3. 若重啟失敗,查看錯誤日誌
sudo journalctl -u openclaw-gateway -n 100 --no-pager

# 4. 確認 Port 是否已被佔用
sudo ss -tlnp | grep 18789

# 5. 若 Port 被佔用,找到並終止進程
sudo fuser -k 18789/tcp

# 6. 重新啟動服務
sudo systemctl start openclaw-gateway

# Docker 環境重啟
docker compose restart openclaw-gateway

# 緊急從備份恢復(Workspace 資料)
docker compose down
tar xzf /backups/openclaw/workspace-latest.tar.gz -C /
docker compose up -d

11.5 效能調優建議

# /etc/sysctl.d/99-openclaw.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_fin_timeout = 15
fs.file-max = 1000000

# 套用設定
sudo sysctl -p /etc/sysctl.d/99-openclaw.conf

結語

OpenClaw Gateway 的部署策略選擇直接決定了整個 AI 代理系統的可靠性、安全性與可擴展性。從最簡單的 Headless + systemd 單機部署,到 Kubernetes 多節點叢集,每種方案都有其適用的場景與取捨。

最重要的原則是:從需求出發,而非從技術出發。一個個人開發者的 24/7 自動化助手,用 Docker Compose + Caddy 就足夠;一個服務數百用戶的企業代理平台,才需要考慮 Kubernetes 的複雜性。

隨著 OpenClaw 生態系持續成熟,[8] Gateway 的部署工具鏈也將持續演進。建議工程師密切關注官方文件的更新,[2] 特別是在 Workspace 同步協議和多節點叢集管理方面,這些是目前社群正在積極開發的領域。