核心要點
- OpenClaw Gateway 是整個代理架構的中樞神經,預設在
ws://127.0.0.1:18789運行,負責任務排程、記憶管理與 LLM 協調 - Headless 模式結合
systemd服務或screen/tmux,可在無圖形介面的雲端伺服器上穩定持續運行 - Docker Compose 是最低阻力的雲端部署方案;Kubernetes 則適合需要高可用性與自動擴縮的生產環境
- WebSocket 反向代理必須正確設定
Upgrade與Connection標頭,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 層:系統唯一入口,以 WebSocket 伺服器形式運行,接受所有外部連線
- Node 層:執行代理工作流的處理單元,連接到 Gateway 以接收任務
- Channel 層:定義代理的溝通管道(CLI、Web UI、API 等)
- Skill 層:代理可調用的能力模組(瀏覽器控制、檔案操作、Shell 指令等)
在這個架構中,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,其中:
127.0.0.1:僅接受本機回環(loopback)連線,外部網路無法直接存取18789:OpenClaw 的預設服務埠,可透過組態修改ws://:使用 WebSocket 協議,支援雙向即時通訊
這個預設組態在本地開發環境中是安全且便利的,但在任何需要網路存取的場景下,都需要重新規劃。[2]
二、本地 vs 遠端 Gateway 部署策略
選擇正確的部署策略取決於使用場景的具體需求。以下是三種主要部署模式的系統性比較。
2.1 本地部署模式
適用場景:個人開發、探索性研究、需要存取本機硬體資源的任務
優點:
- 零網路延遲,Gateway 與 Node 在同一進程空間內通訊
- 無需考慮認證與 TLS,降低初始設定複雜度
- 直接存取本機檔案系統、螢幕截圖、鍵盤滑鼠控制
- LLM API 金鑰不會離開本機環境
限制:
- 關閉電腦或睡眠時 Gateway 中斷,長時間任務失敗
- 無法從其他裝置發送任務
- 單機資源限制,無法水平擴展
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 路由
優點:
- 伺服器持續運行,任務不因本地機器關機而中斷
- 集中式記憶管理,多個 Node 共享同一 Workspace
- 可結合 Cron 觸發器實現完全自動化工作流
限制:
- 需要妥善設定認證與 TLS,否則有安全風險[7]
- 網路延遲增加,對即時互動任務有輕微影響
- 需要額外的基礎設施成本
2.3 混合部署模式
混合模式(Hybrid Mode)是許多中型團隊的最佳實踐:Gateway 部署在雲端,但 Node 根據任務類型靈活分配:
- 本地 Node:執行需要存取本機資源的任務(GUI 控制、本機檔案操作)
- 雲端 Node:執行計算密集型或需要穩定網路的任務(Web 爬蟲、API 整合)
- 邊緣 Node:部署在樹莓派或工廠端設備上,執行 IoT 相關任務
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 實例若沒有協調機制,會出現以下問題:
- Workspace 狀態不一致:不同 Gateway 維護獨立的記憶,同一 Workspace 在不同 Gateway 上的狀態不同步
- 任務重複執行:Cron 觸發的任務可能在多個 Gateway 上同時被觸發
- Session 親和性:Node 重連時可能連到不同的 Gateway,導致 Workspace 丟失
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 安全審計
- 認證機制:確認所有 WebSocket 連線都需要 Bearer Token 或 mTLS 認證
- TLS 憑證:使用有效的 TLS 1.2+ 憑證,禁用 TLSv1.0 和 TLSv1.1
- API 金鑰隔離:LLM API 金鑰存儲在環境變數或 Secret Manager,不寫入程式碼或 Git
- 最小權限原則:Gateway 以非 root 使用者運行,僅具備必要的系統權限
- 網路隔離:Gateway 不直接暴露在公網,通過反向代理存取
- 埠掃描:確認 18789 埠對外部不可達(
nmap -p 18789 gateway.example.com) - 依賴更新:確認 OpenClaw 及所有依賴使用最新安全版本
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 效能調優建議
- Linux 核心調優:增大
net.core.somaxconn和net.ipv4.tcp_max_syn_backlog以支援更多並發連線 - 文件描述符限制:設定
ulimit -n 65536或透過 systemdLimitNOFILE調整 - 記憶體分頁:對於大型 Workspace,考慮增加 Swap 空間防止 OOM
- 網路緩衝區:調整
net.core.rmem_max和net.core.wmem_max優化 WebSocket 吞吐量
# /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 同步協議和多節點叢集管理方面,這些是目前社群正在積極開發的領域。