目 录CONTENT

文章目录

OpenClaw 一键部署实战:从裸机到生产就绪

PySuper
2026-02-21 / 0 评论 / 0 点赞 / 0 阅读 / 0 字
温馨提示:
本文最后更新于2026-05-22,若内容或图片失效,请留言反馈。 所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

作者:PySuper | 来源:zhengxingtao.com

前一篇 OpenClaw 实战讲了架构和日常使用,但部署部分一笔带过了。这篇专门补上——从 Docker 一键拉起到云服务器生产加固,给你一条龙搞定。末尾附一个真的能跑的一键部署脚本,不是摆设。

目录

  1. 部署前规划

  2. 方案一:Docker 一键部署(推荐)

  3. 方案二:裸机部署

  4. 方案三:云服务器一键部署

  5. 多渠道接入配置

  6. 模型配置

  7. Skill 管理

  8. 生产加固

  9. 一键部署脚本(完整版)

  10. 常见问题排查

一、部署前规划

部署之前先想清楚三件事:跑在哪、用什么模型、接哪些渠道。别上来就 docker run,后面改配置比重新部署还麻烦。

1.1 硬件需求

表格

场景

CPU

内存

存储

月成本参考

最小配置(体验/测试)

2C

4GB

20GB SSD

本地 0 元 / 云 ¥30-50

推荐配置(个人日常)

4C

8GB

40GB SSD

本地 0 元 / 云 ¥80-120

生产配置(团队/多渠道)

8C+

16GB+

100GB SSD

云 ¥200+

本地模型(Ollama 跑 7B)

4C+

16GB+

50GB+

本地电费

关键点:

  • OpenClaw 本身很轻,内存占用 200-500MB。瓶颈在 LLM API 调用,不在 Gateway。

  • 如果跑 Ollama 本地模型,7B 参数模型需要至少 8GB 内存,70B 需要 40GB+。建议用带 GPU 的机器。

  • 磁盘主要被会话记录和 Skill 缓存吃掉,SQLite 数据库增长不快,但日志要定期清理。

1.2 操作系统支持

表格

系统

支持情况

备注

Ubuntu 20.04+

✅ 最佳

官方首选测试平台

Debian 11+

✅ 良好

和 Ubuntu 基本一致

macOS (Intel/Apple Silicon)

✅ 良好

Docker Desktop 或 Homebrew

Fedora 34+

✅ 良好

dnf 包管理器

CentOS/RHEL 7+

⚠️ 可用

需手动处理依赖

Windows

⚠️ WSL2

不支持原生 Windows,必须用 WSL2

Arch Linux

✅ 社区支持

AUR 有包

1.3 网络要求

plaintext

┌─────────────────────────────────────────────────────────┐
│                    网络端口规划                           │
├──────────────┬──────────┬───────────────────────────────┤
│    端口       │  协议    │          用途                  │
├──────────────┼──────────┼───────────────────────────────┤
│  18789       │ TCP/WS   │ Gateway 主端口(WebSocket)     │
│  18793       │ TCP      │ Canvas Host(可选)            │
│  3000/8080   │ TCP/HTTP │ Web UI(部分镜像默认)          │
│  6379        │ TCP      │ Redis(如果用 Docker Compose)  │
│  80/443      │ TCP/HTTP │ Nginx 反向代理(生产必选)      │
│  11434       │ TCP/HTTP │ Ollama 本地模型(可选)         │
└──────────────┴──────────┴───────────────────────────────┘

域名和 SSL:

  • 测试环境localhost 就行,不需要域名和证书。

  • 生产环境:必须配域名 + SSL。Telegram/Discord Webhook 要求 HTTPS 回调地址。

  • 域名解析:A 记录指向服务器 IP,TTL 建议 300(5 分钟),方便切换。

  • SSL:用 Let's Encrypt 免费证书,Certbot 自动续期。Caddy 也能自动签发。

1.4 模型选择

这是影响成本最大的决策:

plaintext

┌────────────────────────────────────────────────────────────┐
│                    模型选择决策树                            │
│                                                            │
│  数据能出公网吗?                                           │
│  ├── 是 → 预算充足吗?                                     │
│  │       ├── 是 → Claude Sonnet 4 / GPT-4o(最佳质量)     │
│  │       └── 否 → GPT-4o-mini / Claude Haiku(性价比之王)│
│  └── 否 → 必须本地模型                                     │
│          ├── 有 GPU 吗?                                    │
│          │   ├── 是 → Ollama + Qwen2.5-Coder:32B           │
│          │   └── 否 → Ollama + Qwen2.5:7B(勉强可用)      │
│          └── 混合方案:简单任务本地,复杂任务走 API          │
└────────────────────────────────────────────────────────────┘

表格

方案

月成本

延迟

质量

适用场景

Claude Sonnet 4 (API)

$10-50

1-3s

⭐⭐⭐⭐⭐

日常助手、代码生成

GPT-4o (API)

$10-50

1-3s

⭐⭐⭐⭐⭐

通用任务

GPT-4o-mini (API)

$1-5

0.5-1s

⭐⭐⭐⭐

日常对话、简单任务

Claude Haiku (API)

$1-5

0.3-0.8s

⭐⭐⭐⭐

高频轻量调用

Ollama + Qwen2.5:7B (本地)

$0

2-10s

⭐⭐⭐

隐私敏感、零成本

OpenRouter (多模型)

$5-30

1-3s

⭐⭐⭐⭐

想用多个模型、不想绑死一家

我的建议:起步用 GPT-4o-miniClaude Haiku,月花几块钱够用。等发现不够了再升级,别一上来就用最贵的。

二、方案一:Docker 一键部署(推荐)

Docker 是部署 OpenClaw 最省心的方式。不挑系统、不污染宿主、一条命令搞定。据《Deploying OpenClaw with Docker》(https://openclaw-ai.online/tutorials/deployment/)和《Self-Host OpenClaw with Docker Compose》(https://rolandsoftwares.com/content/self-host-openclaw-docker-compose-setup/),Docker 部署是官方推荐的首选方案。

2.1 完整 docker-compose.yml

这个 Compose 文件包含 OpenClaw Gateway + Redis + 日志配置 + 健康检查,开箱即用:

yaml

# docker-compose.yml
# OpenClaw 生产级 Docker Compose 配置
# 作者: PySuper | zhengxingtao.com

version: "3.8"

services:
  openclaw-gateway:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw
    restart: unless-stopped
    ports:
      - "18789:18789"   # Gateway WebSocket 主端口
      - "18793:18793"   # Canvas Host(可选,用于浏览器技能)
    volumes:
      # 配置目录:openclaw.json、SOUL.md、凭证、会话数据
      - ./openclaw-config:/root/.openclaw
      # 工作区:Agent 可以读写的文件目录
      - ./openclaw-workspace:/root/workspace
    env_file:
      - .env
    environment:
      - NODE_ENV=production
      - TZ=Asia/Shanghai
    depends_on:
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:18789/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    deploy:
      resources:
        limits:
          cpus: "2"
          memory: 2G
        reservations:
          cpus: "0.5"
          memory: 512M
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"
    command: openclaw gateway

  redis:
    image: redis:7-alpine
    container_name: openclaw-redis
    restart: unless-stopped
    ports:
      - "127.0.0.1:6379:6379"   # 只绑定本地,不对外暴露
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 256M

volumes:
  redis-data:
    driver: local

2.2 环境变量详解

创建 .env 文件,和 docker-compose.yml 放同一目录:

bash

# .env — OpenClaw 环境变量配置
# ⚠️ 此文件包含敏感信息,不要提交到 Git!

# ============================================
# 模型 Provider 配置(至少填一个)
# ============================================

# Anthropic Claude(推荐)
ANTHROPIC_API_KEY=sk-ant-your-key-here

# OpenAI GPT
# OPENAI_API_KEY=sk-your-key-here

# Google Gemini
# GOOGLE_AI_API_KEY=AIza-your-key-here

# OpenRouter(多模型聚合)
# OPENROUTER_API_KEY=sk-or-your-key-here

# 本地 Ollama(不需要真实 key,任意值即可)
# OLLAMA_API_KEY=ollama-local

# ============================================
# Gateway 认证
# ============================================

# Gateway Token — 访问 Control UI 和 API 的凭证
# 生产环境务必设置,用以下命令生成:
#   openssl rand -hex 32
OPENCLAW_GATEWAY_TOKEN=your-secure-random-token-here

# ============================================
# 渠道 Token(按需启用)
# ============================================

# Telegram Bot
# TELEGRAM_BOT_TOKEN=123456:ABCdefGHIjklMNO

# Discord Bot
# DISCORD_BOT_TOKEN=MTIxxxxx

# Slack
# SLACK_APP_TOKEN=xapp-your-app-token
# SLACK_BOT_TOKEN=xoxb-your-bot-token

# ============================================
# 可选配置
# ============================================

# 默认模型
# DEFAULT_MODEL=claude-sonnet-4-20250514

# 月度消费上限(美元),防止 API 跑飞
# MAX_MONTHLY_SPEND=50

# 循环检测,防止 Agent 无限循环
# LOOP_DETECTION=true

# Redis 配置(Docker Compose 内部网络自动解析)
REDIS_HOST=redis
REDIS_PORT=6379
# REDIS_PASSWORD=your-redis-password

# 时区
TZ=Asia/Shanghai

环境变量优先级(从高到低):

  1. 进程环境变量(Docker runtime 传入)

  2. .env 文件(工作目录下)

  3. 全局 .env~/.openclaw/.env

  4. openclaw.json 中的 config 块

如果同一变量在多处定义,优先级高的覆盖低的。这个设计保证你不会意外覆盖系统级配置。

2.3 数据持久化

plaintext

┌──────────────────────────────────────────────────────────┐
│                 Volume 挂载方案                           │
│                                                          │
│  宿主机                        容器内                    │
│  ─────────                     ─────────                 │
│  ./openclaw-config/    →    /root/.openclaw/             │
│    ├── openclaw.json          ├── openclaw.json          │
│    ├── SOUL.md                ├── SOUL.md                │
│    ├── credentials/           ├── credentials/           │
│    ├── skills/                ├── skills/                │
│    └── data/                  └── data/                  │
│        ├── conversations/        ├── conversations/      │
│        └── users/                └── users/              │
│                                                          │
│  ./openclaw-workspace/ →    /root/workspace/             │
│    ├── projects/              ├── projects/              │
│    └── temp/                  └── temp/                  │
│                                                          │
│  redis-data (named vol)  →  /data/  (Redis 持久化)       │
└──────────────────────────────────────────────────────────┘

关键提醒

  • openclaw-config 是 Agent 的"大脑",丢了就失忆。务必备份。

  • openclaw-workspace 是 Agent 的工作台,放它操作的文件。

  • Redis 数据可以不备份,OpenClaw 只用它做缓存和会话临时存储,丢了会自动重建。

  • 权限问题:如果容器内报权限错误,执行 docker exec openclaw chown -R node:node /root/.openclaw

2.4 一键启动/停止/重启命令

bash

# ===== 首次部署 =====

# 1. 创建目录结构
mkdir -p openclaw-config openclaw-workspace

# 2. 创建 .env 文件(参考上面 2.2 节)
cp .env.example .env
nano .env   # 填入你的 API Key 和 Token

# 3. 启动所有服务
docker compose up -d

# 4. 查看启动日志
docker compose logs -f openclaw-gateway

# 5. 运行交互式配置向导(首次部署推荐)
docker compose run --rm openclaw-gateway openclaw onboard

# ===== 日常运维 =====

# 启动
docker compose up -d

# 停止
docker compose stop

# 重启(配置变更后)
docker compose restart openclaw-gateway

# 查看状态
docker compose ps

# 查看日志(实时跟踪)
docker compose logs -f openclaw-gateway

# 查看最近 50 行日志
docker compose logs --tail 50 openclaw-gateway

# ===== 升级 =====

# 拉取最新镜像
docker compose pull openclaw-gateway

# 重建并启动(镜像更新后)
docker compose up -d openclaw-gateway

# ===== 清理 =====

# 停止并删除容器(数据保留在 volume 中)
docker compose down

# 停止并删除容器 + volume(⚠️ 数据全丢)
docker compose down -v

2.5 验证部署

bash

# 1. 检查容器状态
docker ps | grep openclaw
# 应该看到 openclaw 和 openclaw-redis 两个容器都是 Up

# 2. 健康检查
curl -s http://localhost:18789/healthz
# 应该返回 200

# 3. 访问 Control UI
# 浏览器打开 http://localhost:18789
# 输入 .env 中设置的 OPENCLAW_GATEWAY_TOKEN

# 4. 检查 Gateway 日志中的启动信息
docker compose logs openclaw-gateway 2>&1 | grep "listening"
# 应该看到: [gateway] listening on ws://0.0.0.0:18789

三、方案二:裸机部署

不用 Docker,直接在主机上跑。适合不想装 Docker 的场景,或者 macOS 本地开发。

3.1 系统依赖安装

Ubuntu/Debian:

bash

# 更新系统
sudo apt update && sudo apt upgrade -y

# 安装基础工具
sudo apt install -y curl git build-essential

# 安装 Node.js 22+(推荐用 nvm)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
source ~/.bashrc
nvm install 22
nvm use 22
node --version   # 确认 v22+

# 安装 Redis(可选,推荐)
sudo apt install -y redis-server
sudo systemctl enable redis-server
sudo systemctl start redis-server
redis-cli ping   # 应该返回 PONG

# 安装 Chromium(浏览器自动化技能需要)
sudo apt install -y chromium-browser libnss3 libatk-bridge2.0-0 \
  libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 \
  libxrandr2 libgbm1 libasound2

macOS:

bash

# 安装 Homebrew(如果没有)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# 安装 Node.js
brew install node@22

# 安装 Redis
brew install redis
brew services start redis

# 安装 OpenClaw(通过 npm)
npm install -g openclaw

Fedora/RHEL:

bash

# 安装依赖
sudo dnf install -y curl git gcc make

# 安装 Node.js 22
curl -fsSL https://rpm.nodesource.com/setup_22.x | sudo bash -
sudo dnf install -y nodejs

# 安装 Redis
sudo dnf install -y redis
sudo systemctl enable --now redis

3.2 从源码编译安装

bash

# 克隆仓库
git clone https://github.com/openclaw/openclaw.git
cd openclaw

# 安装依赖
npm install

# 构建项目
npm run build

# 运行交互式配置向导
npm run onboard

# 启动 Gateway
npm start

或者用全局安装方式(更简洁):

bash

# 全局安装
npm install -g openclaw

# 运行 onboarding 向导
openclaw onboard

# 启动 Gateway
openclaw gateway

3.3 Systemd 服务配置

让 OpenClaw 开机自启、崩溃自恢复。OpenClaw 官方支持 --install-daemon 参数自动创建 systemd 服务(据《OpenClaw for Linux》https://openclaw-ai.online/platforms/linux/)。

方式一:用 OpenClaw 自带命令(推荐)

bash

# 安装时自动创建 systemd 用户服务
openclaw onboard --install-daemon

方式二:手动创建 systemd 服务

bash

# 创建 systemd 用户服务文件
mkdir -p ~/.config/systemd/user/

cat > ~/.config/systemd/user/openclaw-gateway.service << 'EOF'
[Unit]
Description=OpenClaw Gateway - AI Agent Runtime
After=network.target

[Service]
Type=simple
ExecStart=/home/%u/.nvm/versions/node/v22.16.0/bin/openclaw gateway
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

# 环境变量
Environment=NODE_ENV=production
Environment=TZ=Asia/Shanghai

# 安全限制
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/%u/.openclaw /home/%u/workspace

# 资源限制
LimitNOFILE=65536
MemoryMax=2G

[Install]
WantedBy=default.target
EOF

# 重新加载 systemd
systemctl --user daemon-reload

# 启用开机自启
systemctl --user enable openclaw-gateway

# 启动服务
systemctl --user start openclaw-gateway

# 确保用户注销后服务继续运行(重要!)
loginctl enable-linger $USER

服务管理命令速查:

bash

systemctl --user start openclaw-gateway     # 启动
systemctl --user stop openclaw-gateway      # 停止
systemctl --user restart openclaw-gateway   # 重启
systemctl --user status openclaw-gateway    # 查看状态
systemctl --user enable openclaw-gateway    # 开机自启
systemctl --user disable openclaw-gateway   # 取消自启
journalctl --user -u openclaw-gateway -f    # 查看实时日志
journalctl --user -u openclaw-gateway -n 100  # 查看最近 100 行日志

3.4 日志轮转配置

bash

# 创建 journald 配置,限制日志大小
sudo mkdir -p /etc/systemd/journald.conf.d/

cat > /etc/systemd/journald.conf.d/openclaw.conf << 'EOF'
[Journal]
# 日志最大占用 500MB
SystemMaxUse=500M
# 单个日志文件最大 50MB
SystemMaxFileSize=50M
# 保留最近 7 天
MaxRetentionSec=7day
EOF

sudo systemctl restart systemd-journald

四、方案三:云服务器一键部署

在云服务器上部署 OpenClaw,让它 7×24 小时在线。以下以 Ubuntu 24.04 为例,阿里云/腾讯云/AWS 通用。

4.1 云厂商最小成本方案

表格

厂商

机型

配置

月价

备注

阿里云

ECS 经济型 e

2C4G / 40G SSD

¥40-60

新用户有优惠

腾讯云

Lighthouse

2C4G / 60G SSD

¥50-70

有 OpenClaw 一键镜像

AWS

Lightsail

2C4G / 60G SSD

$12-18

海外延迟低

Vultr

Cloud Compute

1C2G / 25G SSD

$6

最便宜的海外选项

Hetzner

CX22

2C4G / 40G SSD

€5.8

性价比王,欧洲节点

腾讯云捷径:Lighthouse 应用市场有 OpenClaw 预装镜像,选了就能用,免手动部署。据《OpenClaw完全指南:部署你的7×24小时开源AI助手》(https://www.tencentcloud.com/techpedia/141458),一键即可在几秒内完成部署。

4.2 一键脚本:从裸机到 OpenClaw 运行

这是一个完整的部署脚本,从 SSH 登录到 OpenClaw 运行,一条命令搞定:

bash

#!/bin/bash
# quick-deploy.sh — 快速部署 OpenClaw 到云服务器
# 用法: curl -fsSL https://your-host/quick-deploy.sh | bash
# 或:   wget -qO- https://your-host/quick-deploy.sh | bash

set -euo pipefail

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

info()  { echo -e "${GREEN}[INFO]${NC} $*"; }
warn()  { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; }

# ===== 第一步:系统检测 =====
info "检测系统环境..."

if [[ ! -f /etc/os-release ]]; then
  error "无法检测操作系统,仅支持 Ubuntu/Debian"
fi

source /etc/os-release
info "操作系统: $PRETTY_NAME"

# 检查是否 root
if [[ $EUID -ne 0 ]]; then
  error "请使用 root 用户运行此脚本: sudo bash quick-deploy.sh"
fi

# 检查内存
TOTAL_MEM=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024)}')
info "内存: ${TOTAL_MEM}MB"
if [[ $TOTAL_MEM -lt 2000 ]]; then
  warn "内存不足 2GB,可能导致运行不稳定"
fi

# ===== 第二步:安装 Docker =====
if command -v docker &>/dev/null; then
  info "Docker 已安装: $(docker --version)"
else
  info "安装 Docker..."
  curl -fsSL https://get.docker.com | sh
  systemctl enable docker
  systemctl start docker
  info "Docker 安装完成: $(docker --version)"
fi

# 安装 Docker Compose 插件
if ! docker compose version &>/dev/null; then
  info "安装 Docker Compose 插件..."
  apt-get update -qq
  apt-get install -y docker-compose-plugin
fi

# ===== 第三步:创建目录和配置 =====
INSTALL_DIR="/opt/openclaw"
info "创建部署目录: $INSTALL_DIR"
mkdir -p "$INSTALL_DIR"/{openclaw-config,openclaw-workspace}
cd "$INSTALL_DIR"

# 生成 Gateway Token
GATEWAY_TOKEN=$(openssl rand -hex 32)
info "已生成 Gateway Token"

# 创建 .env 文件(需要用户交互输入 API Key)
cat > .env << EOF
# OpenClaw 环境变量 — 由 quick-deploy.sh 自动生成
# 生成时间: $(date)

# Gateway 认证
OPENCLAW_GATEWAY_TOKEN=${GATEWAY_TOKEN}

# 模型 Provider(请填入你的 API Key)
ANTHROPIC_API_KEY=sk-ant-YOUR-KEY-HERE
# OPENAI_API_KEY=sk-YOUR-KEY-HERE

# 时区
TZ=Asia/Shanghai
EOF

chmod 600 .env
warn "请编辑 ${INSTALL_DIR}/.env 填入你的 API Key!"

# 创建 docker-compose.yml
cat > docker-compose.yml << 'COMPOSE'
version: "3.8"
services:
  openclaw-gateway:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw
    restart: unless-stopped
    ports:
      - "18789:18789"
    volumes:
      - ./openclaw-config:/root/.openclaw
      - ./openclaw-workspace:/root/workspace
    env_file:
      - .env
    environment:
      - NODE_ENV=production
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:18789/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 2G
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"
    command: openclaw gateway

  redis:
    image: redis:7-alpine
    container_name: openclaw-redis
    restart: unless-stopped
    ports:
      - "127.0.0.1:6379:6379"
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

volumes:
  redis-data:
COMPOSE

# ===== 第四步:配置防火墙 =====
info "配置防火墙..."

# UFW
if command -v ufw &>/dev/null; then
  ufw allow 80/tcp
  ufw allow 443/tcp
  ufw allow 18789/tcp
  ufw --force enable
  info "UFW 防火墙已配置"
else
  warn "未检测到 UFW,请手动配置防火墙开放 80/443/18789 端口"
fi

# ===== 第五步:启动服务 =====
info "拉取 OpenClaw 镜像..."
docker compose pull

info "启动 OpenClaw..."
docker compose up -d

# 等待启动
info "等待服务启动..."
sleep 15

# ===== 第六步:验证 =====
if curl -sf http://localhost:18789/healthz > /dev/null 2>&1; then
  info "✅ OpenClaw 启动成功!"
else
  warn "Gateway 尚未就绪,请查看日志: docker compose logs -f openclaw-gateway"
fi

# 输出访问信息
PUBLIC_IP=$(curl -sf ifconfig.me || echo "YOUR_SERVER_IP")
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${GREEN}  OpenClaw 部署完成!${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
echo -e "  Control UI:  http://${PUBLIC_IP}:18789"
echo -e "  Gateway Token: ${GATEWAY_TOKEN}"
echo ""
echo -e "  ⚠️  下一步:"
echo -e "  1. 编辑 ${INSTALL_DIR}/.env 填入 API Key"
echo -e "  2. 重启服务: cd ${INSTALL_DIR} && docker compose restart"
echo -e "  3. 运行 onboarding: docker compose run --rm openclaw-gateway openclaw onboard"
echo ""
echo -e "  📖 生产环境建议配置 Nginx + SSL,见本文第四章。"
echo ""

4.3 防火墙/安全组配置

UFW(Ubuntu 默认防火墙):

bash

# 开放必要端口
sudo ufw allow 22/tcp      # SSH
sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS
sudo ufw allow 18789/tcp   # OpenClaw Gateway(如果不用 Nginx 代理)

# 如果用 Nginx 反向代理,可以不开放 18789
# sudo ufw deny 18789/tcp

sudo ufw enable
sudo ufw status

云安全组(阿里云/腾讯云/AWS 控制台):

表格

协议

端口

来源

用途

TCP

22

你的 IP

SSH 管理

TCP

80

0.0.0.0/0

HTTP(重定向到 HTTPS)

TCP

443

0.0.0.0/0

HTTPS 访问

TCP

18789

仅限 Nginx 所在网络

Gateway(不直接暴露)

⚠️ 绝对不要把 18789 端口直接暴露到公网,除非你清楚自己在做什么。Gateway Token 走的是 HTTP 明文,不配 HTTPS 就是在裸奔。

4.4 Nginx 反向代理 + SSL(Let's Encrypt)

生产环境必须配。据《Deploy OpenClaw Securely on a VPS》(https://www.virtua.cloud/learn/en/tutorials/deploy-openclaw-securely-vps)和《OpenClaw Reverse Proxy Setup Guide》(https://remoteopenclaw.com/blog/openclaw-reverse-proxy-setup),这是标准配置流程。

bash

# 1. 安装 Nginx 和 Certbot
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx

# 2. 创建 Nginx 配置
sudo tee /etc/nginx/sites-available/openclaw.conf > /dev/null << 'NGINX'
server {
    listen 80;
    listen [::]:80;
    server_name openclaw.example.com;   # ← 换成你的域名

    # Let's Encrypt 验证
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # HTTP 强制跳转 HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name openclaw.example.com;   # ← 换成你的域名

    # SSL 证书(Certbot 会自动填入,这里先占位)
    ssl_certificate     /etc/letsencrypt/live/openclaw.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/openclaw.example.com/privkey.pem;

    # SSL 加固
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # 安全头
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # 隐藏 Nginx 版本
    server_tokens off;

    # 反向代理到 OpenClaw Gateway
    location / {
        proxy_pass http://127.0.0.1:18789;

        # WebSocket 支持(关键!)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # 信任头(注意:用 $remote_addr 覆盖,不用 append)
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;

        # 超时设置(Agent 会话可能很长)
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}
NGINX

# 3. 启用站点配置
sudo ln -sf /etc/nginx/sites-available/openclaw.conf /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default

# 4. 测试 Nginx 配置
sudo nginx -t

# 5. 先用 HTTP 模式启动 Nginx(SSL 证书还没有)
# 临时注释掉 SSL 相关配置,或者直接获取证书
sudo systemctl reload nginx

# 6. 获取 SSL 证书(确保域名已解析到服务器 IP)
sudo certbot --nginx -d openclaw.example.com

# 7. 验证自动续期
sudo certbot renew --dry-run

配置 OpenClaw 信任代理:

编辑 ~/.openclaw/openclaw.json(或 Docker 挂载的 openclaw-config/openclaw.json):

json

{
  "gateway": {
    "bind": "loopback",
    "port": 18789,
    "trustedProxies": ["127.0.0.1", "172.16.0.0/12"],
    "auth": {
      "mode": "token",
      "token": "${OPENCLAW_GATEWAY_TOKEN}"
    },
    "controlUi": {
      "allowInsecureAuth": false
    }
  }
}

验证 HTTPS:

bash

# 从本地机器测试(不是服务器上)
curl -I https://openclaw.example.com/healthz
# 应该返回 200

# 检查证书信息
openssl s_client -connect openclaw.example.com:443 -servername openclaw.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates

五、多渠道接入配置

OpenClaw 的核心竞争力之一就是多渠道统一接入。下面逐个渠道讲配置步骤。

5.1 Telegram Bot 接入

这是最简单的渠道,5 分钟搞定。

plaintext

┌───────────────────────────────────────────────────────────┐
│                Telegram Bot 接入流程                       │
│                                                           │
│  ① @BotFather 创建 Bot → 获取 Bot Token                  │
│         │                                                 │
│         ▼                                                 │
│  ② 配置 Token 到 OpenClaw                                │
│     方式 A: .env 中 TELEGRAM_BOT_TOKEN=xxx               │
│     方式 B: openclaw.json 中 channels.telegram.token      │
│         │                                                 │
│         ▼                                                 │
│  ③ 重启 Gateway → Bot 自动上线                           │
│         │                                                 │
│         ▼                                                 │
│  ④ 在 Telegram 中找到 Bot → 发消息测试                   │
└───────────────────────────────────────────────────────────┘

步骤详解:

bash

# 第一步:在 Telegram 中找 @BotFather

# 1. 打开 Telegram,搜索 @BotFather
# 2. 发送 /newbot
# 3. 输入 Bot 名称(显示名),如 "My OpenClaw Assistant"
# 4. 输入 Bot 用户名(必须以 bot 结尾),如 "my_openclaw_bot"
# 5. @BotFather 返回 Bot Token,格式如: 7123456789:AAH...xxx
# 6. 保存这个 Token!

配置方式一:环境变量(推荐,简单)

bash

# 在 .env 文件中添加
echo 'TELEGRAM_BOT_TOKEN=7123456789:AAH...xxx' >> /opt/openclaw/.env

# 重启
cd /opt/openclaw && docker compose restart openclaw-gateway

配置方式二:openclaw.json(更灵活,可以配 DM 策略等)

json

{
  "channels": {
    "telegram": {
      "enabled": true,
      "token": "7123456789:AAH...xxx",
      "dm": {
        "enabled": true,
        "policy": "pairing",
        "allowFrom": ["your_telegram_user_id"]
      }
    }
  }
}

获取你的 Telegram User ID:

在 Telegram 中找 @userinfobot,发一条消息,它会返回你的 User ID。

5.2 Discord Bot 接入

plaintext

┌───────────────────────────────────────────────────────────┐
│                Discord Bot 接入流程                        │
│                                                           │
│  ① Discord Developer Portal 创建应用                      │
│     https://discord.com/developers/applications           │
│         │                                                 │
│         ▼                                                 │
│  ② 创建 Bot → 获取 Bot Token                             │
│     开启 Message Content Intent(Privileged Intents)      │
│         │                                                 │
│         ▼                                                 │
│  ③ 生成 OAuth2 邀请链接 → 邀请 Bot 到服务器              │
│     权限: Send Messages, Read Message History             │
│         │                                                 │
│         ▼                                                 │
│  ④ 配置 Token 到 OpenClaw → 重启                         │
└───────────────────────────────────────────────────────────┘

步骤详解:

bash

# 1. 访问 https://discord.com/developers/applications
# 2. 点击 "New Application",输入名称
# 3. 左侧菜单 → Bot → "Add Bot"
# 4. 复制 Bot Token(只显示一次!)
# 5. 开启 Privileged Gateway Intents:
#    - PRESENCE INTENT: 关
#    - SERVER MEMBERS INTENT: 按需
#    - MESSAGE CONTENT INTENT: 开(必须!否则 Bot 收不到消息内容)
# 6. 生成邀请链接:
#    左侧 → OAuth2 → URL Generator
#    Scopes: bot
#    Bot Permissions: Send Messages, Read Message History, Attach Files
#    复制生成的 URL,在浏览器中打开,选择你的 Discord 服务器

配置到 OpenClaw:

json

{
  "channels": {
    "discord": {
      "enabled": true,
      "token": "MTIxxxxx.your-bot-token",
      "dm": {
        "enabled": true,
        "policy": "pairing"
      },
      "guilds": {
        "your-guild-id": {
          "requireMention": false,
          "channels": {
            "general": { "allow": true },
            "bot-commands": {
              "allow": true,
              "requireMention": true
            }
          }
        }
      }
    }
  }
}

5.3 Slack 接入

plaintext

┌───────────────────────────────────────────────────────────┐
│                Slack App 接入流程                          │
│                                                           │
│  ① https://api.slack.com/apps → Create New App            │
│     选择 "From scratch"                                   │
│         │                                                 │
│         ▼                                                 │
│  ② 启用 Socket Mode → 获取 App-Level Token (xapp-)       │
│         │                                                 │
│         ▼                                                 │
│  ③ 配置 Event Subscriptions → 订阅 message.events        │
│         │                                                 │
│         ▼                                                 │
│  ④ Install App to Workspace → 获取 Bot Token (xoxb-)     │
│         │                                                 │
│         ▼                                                 │
│  ⑤ 配置两个 Token 到 OpenClaw → 重启                     │
└───────────────────────────────────────────────────────────┘

配置到 OpenClaw:

bash

# .env 文件
SLACK_APP_TOKEN=xapp-1-Axxx-Bxxx
SLACK_BOT_TOKEN=xoxb-xxx-xxx

或在 openclaw.json 中:

json

{
  "channels": {
    "slack": {
      "enabled": true,
      "appToken": "xapp-1-Axxx-Bxxx",
      "botToken": "xoxb-xxx-xxx"
    }
  }
}

Slack 配置注意事项:

  • Slack 使用 Socket Mode(WebSocket),不需要公网回调地址,本地部署也行。

  • Event Subscriptions 要订阅 message.channelsmessage.groupsmessage.immessage.mpim

  • Bot Token Scopes 需要:chat:writechannels:historygroups:historyim:history

5.4 微信/飞书接入说明

飞书(Feishu):

OpenClaw 原生支持飞书。配置流程:

  1. 飞书开放平台(https://open.feishu.cn)创建企业自建应用

  2. 添加"机器人"能力

  3. 配置事件订阅(消息接收)

  4. 获取 App ID 和 App Secret

  5. 配置到 openclaw.json

json

{
  "channels": {
    "feishu": {
      "enabled": true,
      "appId": "cli_xxx",
      "appSecret": "your-app-secret",
      "verificationToken": "your-verification-token",
      "encryptKey": "your-encrypt-key"
    }
  }
}

微信(WeChat):

微信没有官方 Bot API,需要通过以下方式间接实现:

表格

方案

原理

难度

稳定性

WeChat Official Account

公众号消息接口

itchat / WeChatFerry

逆向微信协议

低(随时封号)

ComWeChatBotClient

Hook 微信客户端

建议:个人用 Telegram/Discord 就够了。微信渠道仅限企业公众号场景,走公众号消息接口最稳定。

六、模型配置

OpenClaw 支持 14+ 家模型 Provider,配置方式灵活。据《How to Add Custom Models to OpenClaw》(https://blog.laozhang.ai/en/posts/openclaw-custom-model)和《OpenClaw Ollama 配置文档》(https://openclaws.io/docs/providers/ollama/),以下是各 Provider 的详细配置。

6.1 OpenAI API 配置

bash

# .env
OPENAI_API_KEY=sk-your-key-here

json

{
  "agents": {
    "defaults": {
      "model": {
        "primary": "openai/gpt-4o"
      }
    }
  }
}

可用模型:openai/gpt-4oopenai/gpt-4o-miniopenai/o3-miniopenai/gpt-4.1 等。

6.2 Anthropic Claude API 配置

bash

# .env
ANTHROPIC_API_KEY=sk-ant-your-key-here

json

{
  "agents": {
    "defaults": {
      "model": {
        "primary": "anthropic/claude-sonnet-4-20250514"
      }
    }
  }
}

可用模型:anthropic/claude-sonnet-4-20250514anthropic/claude-haiku-4-20250414anthropic/claude-opus-4-20250514

6.3 本地 Ollama 对接

bash

# 1. 安装 Ollama
curl -fsSL https://ollama.com/install.sh | sh

# 2. 拉取模型
ollama pull qwen2.5:7b           # 通用对话,4.7GB
ollama pull qwen2.5-coder:32b    # 代码生成,需 24GB+ 内存
ollama pull gemma4               # Google Gemma 4
ollama pull glm-4.7              # 智谱 GLM

# 3. 验证 Ollama 运行
ollama list
curl http://localhost:11434/api/tags

OpenClaw 配置(最简方式):

bash

# .env — 只需设置一个环境变量,OpenClaw 自动发现本地 Ollama 模型
OLLAMA_API_KEY=ollama-local

OpenClaw 配置(指定模型和参数):

json

{
  "models": {
    "providers": {
      "ollama": {
        "baseUrl": "http://127.0.0.1:11434",
        "apiKey": "ollama-local",
        "api": "ollama",
        "models": [
          {
            "id": "qwen2.5:7b",
            "name": "Qwen2.5 7B",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 32768,
            "maxTokens": 8192
          },
          {
            "id": "qwen2.5-coder:32b",
            "name": "Qwen2.5 Coder 32B",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 32768,
            "maxTokens": 8192
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "ollama/qwen2.5:7b"
      }
    }
  }
}

⚠️ 重要:Ollama 的 baseUrl 不要加 /v1 后缀!用 http://host:11434 而不是 http://host:11434/v1/v1 是 OpenAI 兼容模式,会导致 Tool Calling 不可靠。

Docker 中连接宿主机 Ollama:

yaml

# docker-compose.yml 中的 environment 追加
environment:
  - OLLAMA_API_KEY=ollama-local
  # Linux: host.docker.internal 不可用,用宿主机 IP
  # 查宿主机 IP: ip route | grep default | awk '{print $9}'

或者把 Ollama 也放进 Docker Compose:

yaml

  ollama:
    image: ollama/ollama:latest
    container_name: openclaw-ollama
    restart: unless-stopped
    ports:
      - "127.0.0.1:11434:11434"
    volumes:
      - ollama-data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

volumes:
  ollama-data:

6.4 OpenRouter 多模型切换

OpenRouter 是一个模型聚合服务,一个 API Key 访问 200+ 模型。

bash

# .env
OPENROUTER_API_KEY=sk-or-your-key-here

json

{
  "models": {
    "providers": {
      "openrouter": {
        "apiKey": "sk-or-your-key-here"
      }
    }
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "openrouter/anthropic/claude-sonnet-4-20250514"
      }
    }
  }
}

使用 OpenRouter 的好处:可以在不同模型之间自由切换,不用每个都注册账号。模型名格式是 openrouter/厂商/模型名

6.5 模型回退策略

当主模型不可用(限速、宕机)时,自动切换到备选模型:

json

{
  "agents": {
    "defaults": {
      "model": {
        "primary": "anthropic/claude-sonnet-4-20250514",
        "fallbacks": [
          "openai/gpt-4o",
          "openai/gpt-4o-mini",
          "ollama/qwen2.5:7b"
        ]
      }
    }
  }
}

回退逻辑

plaintext

┌───────────────────────────────────────────────────────────┐
│               模型回退链路                                 │
│                                                           │
│  请求 → Claude Sonnet 4                                   │
│           │                                               │
│           ├── 成功 → 返回结果                              │
│           │                                               │
│           └── 失败(限速/错误)→ GPT-4o                    │
│                                        │                  │
│                                        ├── 成功 → 返回    │
│                                        │                  │
│                                        └── 失败 → GPT-4o-mini
│                                                     │     │
│                                                     ├── 成功 → 返回
│                                                     │     │
│                                                     └── 失败 → Ollama 本地
│                                                              │
│                                                              └── 最后兜底
└───────────────────────────────────────────────────────────┘

建议:回退链的最后一环放一个本地 Ollama 模型,确保即使所有云 API 都挂了,Agent 也能响应(虽然质量下降)。

七、Skill 管理

Skill 是 OpenClaw 的插件系统。ClawHub 是官方 Skill 市场,被称为 "AI Agent 的 npm"。据《What is Claw Hub? The Complete OpenClaw Hub Guide》(https://claw-hub.net/what-is-clawhub.html),目前有 3,286+ 个验证过的 Skill。

7.1 ClawHub 热门 Skill 一键安装脚本

以下是根据安装量和社区评价整理的 Top 20 必装 Skill。据《ClawHub 与 Claude Code 技能生态专题报告》(https://blog.csdn.net/u012565112/article/details/160113455)整理。

bash

#!/bin/bash
# install-top-skills.sh — 安装 ClawHub Top 20 必装 Skill
# 前提: OpenClaw 已部署并运行

SKILLS=(
  # === 生存层(必装)===
  "web-browsing"           # 180K+ 安装 | 网页浏览、数据抓取
  "tavily-search"          # 85K+ 安装  | 高质量 AI 搜索
  "felo-search"            # 60K+ 安装  | 带引用来源的 AI 搜索

  # === 效率层(强烈推荐)===
  "capability-evolver"     # 35K+ 安装  | Agent 自我学习新技能
  "gog"                    # 48K+ 安装  | Google 全家桶(Gmail/Calendar/Drive)
  "context7"               # 28K+ 安装  | 查询最新库/框架文档
  "summarize"              # 37K+ 安装  | 多格式内容摘要
  "github"                 # 高安装量    | GitHub 完整操作能力

  # === 协作层(推荐)===
  "notion"                 # 20K+ 安装  | Notion 笔记管理
  "telegram-bot"           # 145K+ 安装 | Telegram 远程控制

  # === 安全层(重要)===
  "secret-scanner"         # 密钥泄露检测
  "skill-vetter"           # Skill 安全审查

  # === 开发工具 ===
  "docker"                 # Docker 容器管理
  "sql-query"              # 数据库查询

  # === 内容创作 ===
  "image-gen"              # AI 图片生成

  # === 数据分析 ===
  "data-viz"               # 数据可视化
  "excel"                  # Excel 处理

  # === 自进化 ===
  "ontology-agent"         # 知识本体管理
)

echo "🦞 开始安装 ClawHub Top ${#SKILLS[@]} 必装 Skill..."
echo ""

INSTALLED=0
FAILED=0

for skill in "${SKILLS[@]}"; do
  echo -n "  安装 ${skill}... "
  if npx clawhub@latest install "$skill" 2>/dev/null; then
    echo "✅"
    ((INSTALLED++))
  else
    echo "❌"
    ((FAILED++))
  fi
done

echo ""
echo "==================================="
echo "  安装完成: ✅ ${INSTALLED}  ❌ ${FAILED}"
echo "==================================="
echo ""
echo "  查看已安装 Skill: openclaw skills list"
echo "  更新全部 Skill:   openclaw skills update --all"
echo ""
echo "  ⚠️ 安全提醒:"
echo "  - 禁用自动更新: openclaw config set skills.autoUpdate false"
echo "  - 安装前务必审查 Skill 内容"
echo "  - 参考 ClawHavoc 事件: https://claw-hub.net/what-is-clawhub.html"

7.2 自定义 Skill 开发和部署

Skill 的核心就是一个 SKILL.md 文件 + 可选的脚本。据《Part 23: ClawHub Skills Marketplace》(https://github.com/OnlyTerp/openclaw-optimization-guide/blob/master/part23-clawhub-skills-marketplace.md),Skill 的结构如下:

plaintext

my-custom-skill/
├── SKILL.md          # 必须 - Skill 定义文件
├── scripts/          # 可选 - 执行脚本
│   ├── main.py       # Python 脚本
│   └── helper.sh     # Bash 脚本
└── references/       # 可选 - 参考文档
    └── template.md   # 模板文件

SKILL.md 模板:

markdown

---
name: my-custom-skill
version: 1.0.0
description: 简洁描述这个 Skill 做什么
author: your-username
---

# My Custom Skill

## 接口定义

这个 Skill 接受以下输入:
- `text`: 要处理的文本(必需)
- `format`: 输出格式,可选 json/markdown(可选,默认 markdown)

## 执行逻辑

1. 接收输入文本
2. 使用 `scripts/main.py` 处理
3. 返回格式化结果

## 使用示例

用户说:用 my-custom-skill 处理这段文字

安装自定义 Skill:

bash

# 方式一:本地安装(开发阶段)
mkdir -p ~/.openclaw/skills/my-custom-skill
cp -r my-custom-skill/* ~/.openclaw/skills/my-custom-skill/

# 方式二:发布到 ClawHub
npx clawhub@latest publish ./my-custom-skill

# 方式三:从 ClawHub 安装
npx clawhub@latest install your-username/my-custom-skill

7.3 Skill 更新和版本管理

bash

# 查看已安装的 Skill
openclaw skills list

# 更新单个 Skill
openclaw skills update author/skill-name

# 更新全部 Skill
openclaw skills update --all

# ⚠️ 重要:生产环境建议禁用自动更新
# ClawHavoc 事件证明自动更新是安全隐患
openclaw config set skills.autoUpdate false
openclaw config set skills.updateNotify true

# 安装时锁定版本(推荐)
npx clawhub@latest install author/skill-name --ref v1.2.0

# 移除 Skill
openclaw skills remove author/skill-name

Skill 安全最佳实践(据《ClawHub Skills Analyzed: 48% Show Security Issues》https://www.gradually.ai/en/clawhub-skills-analysis/):

  1. 安装前审查:读 SKILL.md 和脚本,检查有没有 execeval、网络请求到可疑地址

  2. 禁用自动更新:防止 Sleeper Update 攻击

  3. 锁定版本--ref v1.2.0 安装特定版本

  4. 优先选验证作者:ClawHub 上只有 6.8% 的开发者是验证过的

  5. 最小权限原则:Skill 不需要访问的文件/目录就不给权限

八、生产加固

部署完只是开始,生产环境需要安全、备份、监控三件套。

8.1 安全加固

1. API Key 加密

bash

# .env 文件权限锁定
chmod 600 /opt/openclaw/.env
chown root:root /opt/openclaw/.env

# 确保 .env 在 .gitignore 中
echo ".env" >> /opt/openclaw/.gitignore

2. Docker 网络隔离

yaml

# docker-compose.yml 中使用内部网络
services:
  openclaw-gateway:
    networks:
      - frontend    # 连接 Nginx
      - backend     # 连接 Redis
    # 不暴露端口到宿主机(由 Nginx 代理)

  redis:
    networks:
      - backend     # 只有 Gateway 能访问
    # 不暴露任何端口

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true   # 不能访问外网

3. 非 root 运行

yaml

# docker-compose.yml
services:
  openclaw-gateway:
    user: "1000:1000"   # 用非 root UID 运行
    read_only: true      # 只读文件系统
    tmpfs:
      - /tmp
      - /run

4. Gateway 安全配置

json

{
  "gateway": {
    "bind": "loopback",
    "auth": {
      "mode": "token",
      "token": "${OPENCLAW_GATEWAY_TOKEN}"
    },
    "trustedProxies": ["127.0.0.1"],
    "controlUi": {
      "allowInsecureAuth": false
    }
  },
  "skills": {
    "autoUpdate": false,
    "updateNotify": true
  }
}

5. 安全检查清单

plaintext

┌───────────────────────────────────────────────────────────┐
│               生产安全检查清单                             │
├───────────────────────────────────────────────────────────┤
│ ☐ Gateway 不直接暴露到公网(走 Nginx/Caddy 代理)        │
│ ☐ HTTPS 已启用(Let's Encrypt 或自签证书)               │
│ ☐ Gateway Token 已设置且足够随机                          │
│ ☐ .env 文件权限 600,不在 Git 仓库中                     │
│ ☐ Redis 不暴露到公网(127.0.0.1 或 internal network)    │
│ ☐ Skill 自动更新已关闭                                   │
│ ☐ Docker 容器设了内存限制                                │
│ ☐ 日志不含敏感信息(API Key、Token)                     │
│ ☐ 定期轮换 API Key                                      │
│ ☐ 安装的 Skill 都审查过源码                              │
│ ☐ UFW/防火墙已启用,仅开放必要端口                       │
│ ☐ SSH 禁用密码登录,仅用 Key 认证                        │
└───────────────────────────────────────────────────────────┘

8.2 备份方案

据《OpenClaw 备份与恢复指南》(https://github.com/lancelot3777-svg/openclaw-backup-guide),核心备份数据如下:

表格

数据

路径

重要性

大小

主配置

~/.openclaw/openclaw.json

🔴 极高

< 10KB

SOUL.md

~/.openclaw/SOUL.md

🔴 极高

< 5KB

Skill 文件

~/.openclaw/skills/

🟡 高

1-50KB 每个

会话记录

~/.openclaw/data/conversations/

🟡 中

看用量

MCP 配置

~/.openclaw/mcp/

🟡 高

< 100KB

凭证

~/.openclaw/credentials/

🔴 极高

< 5KB

SSL 证书

/etc/letsencrypt/

🟡 高

< 100KB

环境变量

.env

🔴 极高

< 5KB

自动备份脚本:

bash

#!/bin/bash
# openclaw-backup.sh — OpenClaw 自动备份脚本
# 建议加入 crontab: 0 3 * * * /opt/openclaw/openclaw-backup.sh

set -euo pipefail

# ===== 配置 =====
BACKUP_DIR="/opt/openclaw/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="openclaw-backup-${DATE}.tar.gz"
RETENTION_DAYS=30

# OpenClaw 数据路径(Docker 挂载的宿主机路径)
OPENCLAW_CONFIG="/opt/openclaw/openclaw-config"
OPENCLAW_WORKSPACE="/opt/openclaw/openclaw-workspace"
ENV_FILE="/opt/openclaw/.env"

# ===== 创建备份目录 =====
mkdir -p "$BACKUP_DIR"

# ===== SQLite 安全备份 =====
# 如果有 SQLite 数据库,使用 .backup API 而不是直接拷贝
# 直接拷贝正在使用的 SQLite 可能导致数据损坏
if command -v sqlite3 &>/dev/null; then
  for db in "$OPENCLAW_CONFIG"/data/*.db; do
    if [[ -f "$db" ]]; then
      db_name=$(basename "$db")
      sqlite3 "$db" ".backup '${BACKUP_DIR}/${db_name}.backup-${DATE}'"
    fi
  done
fi

# ===== 导出环境变量(脱敏) =====
ENV_BACKUP="/tmp/openclaw-env-${DATE}.txt"
if [[ -f "$ENV_FILE" ]]; then
  # 复制 .env 但替换 API Key 为占位符
  sed -E 's/(KEY=).+/\1 ***REDACTED***/g; s/(TOKEN=).+/\1 ***REDACTED***/g' \
    "$ENV_FILE" > "$ENV_BACKUP"
fi

# ===== 创建压缩备份 =====
echo "[$(date)] 开始备份 OpenClaw..."

tar -czf "${BACKUP_DIR}/${BACKUP_FILE}" \
  "$OPENCLAW_CONFIG" \
  "$OPENCLAW_WORKSPACE" \
  "$ENV_FILE" \
  2>/dev/null || true

# 清理临时文件
rm -f "$ENV_BACKUP"

# ===== 备份验证 =====
BACKUP_SIZE=$(du -h "${BACKUP_DIR}/${BACKUP_FILE}" | cut -f1)
echo "[$(date)] 备份完成: ${BACKUP_FILE} (${BACKUP_SIZE})"

# ===== 清理过期备份 =====
find "$BACKUP_DIR" -name "openclaw-backup-*.tar.gz" -mtime +${RETENTION_DAYS} -delete
echo "[$(date)] 已清理 ${RETENTION_DAYS} 天前的备份"

# ===== 可选:上传到远程存储 =====
# 取消注释以下行来启用远程备份
# AWS S3:
# aws s3 cp "${BACKUP_DIR}/${BACKUP_FILE}" s3://your-bucket/openclaw-backups/
# 阿里云 OSS:
# ossutil cp "${BACKUP_DIR}/${BACKUP_FILE}" oss://your-bucket/openclaw-backups/
# Rsync 到另一台机器:
# rsync -avz "${BACKUP_DIR}/${BACKUP_FILE}" user@backup-server:/backups/openclaw/

设置定时备份:

bash

# 加入 crontab,每天凌晨 3 点执行
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/openclaw/openclaw-backup.sh >> /opt/openclaw/backups/backup.log 2>&1") | crontab -

# 验证
crontab -l

8.3 监控方案

1. 健康检查

bash

# 简单的健康检查脚本
#!/bin/bash
# health-check.sh — OpenClaw 健康检查

GATEWAY_URL="http://localhost:18789"
ALERT_WEBHOOK="https://your-webhook-url"   # 替换为你的告警地址

response=$(curl -sf -o /dev/null -w "%{http_code}" "${GATEWAY_URL}/healthz")

if [[ "$response" != "200" ]]; then
  echo "[ALERT] OpenClaw Gateway 健康检查失败! HTTP ${response}"
  # 发送告警(Telegram/Slack/DingTalk)
  # curl -s -X POST "$ALERT_WEBHOOK" -d "OpenClaw Gateway DOWN! HTTP ${response}"
  exit 1
fi

echo "[OK] OpenClaw Gateway 健康, HTTP ${response}"

2. Docker 内置健康检查

已在 docker-compose.yml 中配置。查看状态:

bash

docker inspect --format='{{.State.Health.Status}}' openclaw
# 应该返回 "healthy"

# 查看健康检查历史
docker inspect --format='{{range .State.Health.Log}}{{.Output}}{{end}}' openclaw

3. Prometheus 指标(可选)

如果需要接入 Prometheus 监控体系:

yaml

# docker-compose.yml 追加
  prometheus:
    image: prom/prometheus:latest
    container_name: openclaw-prometheus
    restart: unless-stopped
    ports:
      - "127.0.0.1:9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus

volumes:
  prometheus-data:

yaml

# prometheus.yml
global:
  scrape_interval: 30s

scrape_configs:
  - job_name: 'openclaw'
    static_configs:
      - targets: ['openclaw-gateway:18789']
    metrics_path: /metrics

8.4 日志管理

Docker 日志轮转(已在 docker-compose.yml 中配置):

yaml

logging:
  driver: json-file
  options:
    max-size: "10m"    # 单个日志文件最大 10MB
    max-file: "5"      # 最多保留 5 个文件

集中式日志(Loki + Grafana)

yaml

# docker-compose.yml 追加
  loki:
    image: grafana/loki:latest
    container_name: openclaw-loki
    restart: unless-stopped
    ports:
      - "127.0.0.1:3100:3100"
    volumes:
      - loki-data:/loki

  grafana:
    image: grafana/grafana:latest
    container_name: openclaw-grafana
    restart: unless-stopped
    ports:
      - "127.0.0.1:3001:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    depends_on:
      - loki

volumes:
  loki-data:
  grafana-data:

日志查看命令速查:

bash

# Docker 部署
docker compose logs -f openclaw-gateway          # 实时日志
docker compose logs --tail 100 openclaw-gateway   # 最近 100 行
docker compose logs --since 1h openclaw-gateway   # 最近 1 小时

# 裸机部署
journalctl --user -u openclaw-gateway -f          # 实时日志
journalctl --user -u openclaw-gateway --since "1 hour ago"
journalctl --user -u openclaw-gateway --since today

# 搜索特定关键词
docker compose logs openclaw-gateway 2>&1 | grep -i "error"
docker compose logs openclaw-gateway 2>&1 | grep -i "channel.*connected"

九、一键部署脚本(完整版)

这是本文的重头戏——一个真的能跑的一键部署脚本。支持交互式选择渠道、模型、存储方式,自动检测环境,自动安装依赖。

bash

#!/bin/bash
# openclaw-setup.sh — OpenClaw 一键部署脚本
# 版本: 1.0.0
# 作者: PySuper | zhengxingtao.com
#
# 用法:
#   chmod +x openclaw-setup.sh
#   sudo ./openclaw-setup.sh
#
# 或一行命令:
#   curl -fsSL https://your-host/openclaw-setup.sh | sudo bash
#
# 功能:
#   1. 检测系统环境(OS/内存/Docker/网络)
#   2. 安装依赖(Docker/Docker Compose/其他)
#   3. 生成配置文件(.env + docker-compose.yml)
#   4. 交互式选择:渠道/模型/存储
#   5. 拉取镜像并启动
#   6. 自动配置 Nginx + SSL(可选)
#   7. 健康检查和验证
#   8. 输出访问地址和管理命令

set -euo pipefail

# ========================================
# 全局变量和工具函数
# ========================================

SCRIPT_VERSION="1.0.0"
INSTALL_DIR="/opt/openclaw"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

info()    { echo -e "${GREEN}[INFO]${NC}  $*"; }
warn()    { echo -e "${YELLOW}[WARN]${NC}  $*"; }
error()   { echo -e "${RED}[ERROR]${NC} $*"; }
section() { echo -e "\n${CYAN}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"; echo -e "${CYAN}${BOLD}  $*${NC}"; echo -e "${CYAN}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"; }

# 交互式选择函数
ask_yes_no() {
  local prompt="$1"
  local default="${2:-Y}"
  local yn=""
  while true; do
    echo -ne "${BLUE}?${NC} ${prompt} [${default}] "
    read -r yn
    yn=${yn:-$default}
    case "$yn" in
      [Yy]*) return 0 ;;
      [Nn]*) return 1 ;;
      *) echo "请输入 Y 或 N" ;;
    esac
  done
}

ask_input() {
  local prompt="$1"
  local default="$2"
  local value=""
  echo -ne "${BLUE}?${NC} ${prompt} [${default}] "
  read -r value
  echo "${value:-$default}"
}

ask_select() {
  local prompt="$1"
  shift
  local options=("$@")
  local i=1
  echo -e "${BLUE}?${NC} ${prompt}"
  for opt in "${options[@]}"; do
    echo -e "  ${CYAN}${i}${NC}) ${opt}"
    ((i++))
  done
  local choice=""
  while true; do
    echo -ne "  请选择 [1]: "
    read -r choice
    choice=${choice:-1}
    if [[ "$choice" =~ ^[0-9]+$ ]] && [[ "$choice" -ge 1 ]] && [[ "$choice" -le "${#options[@]}" ]]; then
      SELECTED_INDEX=$((choice - 1))
      return 0
    fi
    echo "  无效选择,请重试"
  done
}

# ========================================
# 第一步:系统检测
# ========================================

detect_system() {
  section "第 1 步:系统环境检测"

  # 检查 root
  if [[ $EUID -ne 0 ]]; then
    error "请使用 root 用户运行此脚本"
    echo "  sudo ./openclaw-setup.sh"
    exit 1
  fi

  # 检测操作系统
  if [[ -f /etc/os-release ]]; then
    source /etc/os-release
    OS_NAME="$NAME"
    OS_VERSION="$VERSION_ID"
    OS_ID="$ID"
    info "操作系统: ${OS_NAME} ${OS_VERSION}"
  elif [[ "$(uname)" == "Darwin" ]]; then
    OS_NAME="macOS"
    OS_ID="macos"
    OS_VERSION="$(sw_vers -productVersion)"
    info "操作系统: macOS ${OS_VERSION}"
    warn "macOS 建议使用 Homebrew 安装,此脚本针对 Linux 优化"
  else
    error "无法检测操作系统"
    exit 1
  fi

  # 检测架构
  ARCH=$(uname -m)
  info "系统架构: ${ARCH}"

  # 检测内存
  TOTAL_MEM_KB=$(grep MemTotal /proc/meminfo 2>/dev/null | awk '{print $2}' || echo "0")
  TOTAL_MEM=$((TOTAL_MEM_KB / 1024))
  info "内存: ${TOTAL_MEM}MB"
  if [[ $TOTAL_MEM -lt 2000 ]]; then
    warn "内存不足 2GB,OpenClaw 可能运行不稳定"
    if ! ask_yes_no "是否继续?" "N"; then
      exit 0
    fi
  fi

  # 检测磁盘空间
  DISK_AVAIL=$(df -BG / | awk 'NR==2 {print $4}' | tr -d 'G')
  info "可用磁盘: ${DISK_AVAIL}GB"
  if [[ $DISK_AVAIL -lt 10 ]]; then
    warn "可用磁盘不足 10GB,建议清理空间"
  fi

  # 检测 Docker
  if command -v docker &>/dev/null; then
    DOCKER_VERSION=$(docker --version | grep -oP '\d+\.\d+\.\d+')
    info "Docker: 已安装 (v${DOCKER_VERSION})"
    HAS_DOCKER=true
  else
    info "Docker: 未安装"
    HAS_DOCKER=false
  fi

  # 检测 Docker Compose
  if docker compose version &>/dev/null 2>&1; then
    COMPOSE_VERSION=$(docker compose version | grep -oP '\d+\.\d+\.\d+' || echo "unknown")
    info "Docker Compose: 已安装 (v${COMPOSE_VERSION})"
    HAS_COMPOSE=true
  else
    info "Docker Compose: 未安装"
    HAS_COMPOSE=false
  fi

  # 检测网络
  info "检测网络连通性..."
  if curl -sf --connect-timeout 5 https://ghcr.io > /dev/null 2>&1; then
    info "网络: 可访问 ghcr.io ✅"
    NETWORK_OK=true
  else
    warn "网络: 无法访问 ghcr.io(可能需要配置代理)"
    NETWORK_OK=false
  fi

  # 检测端口占用
  PORT_18789_IN_USE=false
  if ss -tlnp 2>/dev/null | grep -q ':18789 '; then
    warn "端口 18789 已被占用"
    PORT_18789_IN_USE=true
  fi

  info "系统检测完成"
}

# ========================================
# 第二步:安装依赖
# ========================================

install_dependencies() {
  section "第 2 步:安装依赖"

  # 安装 Docker
  if [[ "$HAS_DOCKER" == "false" ]]; then
    info "安装 Docker..."
    if [[ "$OS_ID" == "ubuntu" ]] || [[ "$OS_ID" == "debian" ]]; then
      apt-get update -qq
      apt-get install -y curl
      curl -fsSL https://get.docker.com | sh
      systemctl enable docker
      systemctl start docker
    elif [[ "$OS_ID" == "fedora" ]] || [[ "$OS_ID" == "rhel" ]]; then
      dnf install -y curl
      curl -fsSL https://get.docker.com | sh
      systemctl enable docker
      systemctl start docker
    else
      error "不支持的操作系统: ${OS_ID},请手动安装 Docker"
      exit 1
    fi
    info "Docker 安装完成: $(docker --version)"
    HAS_DOCKER=true
  fi

  # 安装 Docker Compose
  if [[ "$HAS_COMPOSE" == "false" ]]; then
    info "安装 Docker Compose 插件..."
    if [[ "$OS_ID" == "ubuntu" ]] || [[ "$OS_ID" == "debian" ]]; then
      apt-get update -qq
      apt-get install -y docker-compose-plugin
    elif [[ "$OS_ID" == "fedora" ]] || [[ "$OS_ID" == "rhel" ]]; then
      dnf install -y docker-compose-plugin
    else
      # 手动安装
      mkdir -p /usr/local/lib/docker/cli-plugins
      curl -SL "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m)" \
        -o /usr/local/lib/docker/cli-plugins/docker-compose
      chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
    fi
    HAS_COMPOSE=true
    info "Docker Compose 安装完成"
  fi

  # 安装辅助工具
  info "安装辅助工具 (curl, openssl)..."
  if [[ "$OS_ID" == "ubuntu" ]] || [[ "$OS_ID" == "debian" ]]; then
    apt-get install -y curl openssl
  elif [[ "$OS_ID" == "fedora" ]] || [[ "$OS_ID" == "rhel" ]]; then
    dnf install -y curl openssl
  fi

  info "依赖安装完成"
}

# ========================================
# 第三步:交互式配置
# ========================================

interactive_config() {
  section "第 3 步:交互式配置"

  # ----- 选择模型 -----
  echo -e "${BOLD}选择 AI 模型 Provider:${NC}"
  ask_select "选择你的主要 AI 模型 Provider" \
    "Anthropic Claude (推荐)" \
    "OpenAI GPT" \
    "Google Gemini" \
    "OpenRouter (多模型聚合)" \
    "Ollama (本地模型,零 API 成本)" \
    "混合模式 (API + 本地)"

  MODEL_CHOICE=$SELECTED_INDEX

  case $MODEL_CHOICE in
    0)  # Anthropic
      ANTHROPIC_KEY=$(ask_input "输入 Anthropic API Key (sk-ant-...)" "")
      DEFAULT_MODEL="anthropic/claude-sonnet-4-20250514"
      MODEL_PROVIDER="anthropic"
      ;;
    1)  # OpenAI
      OPENAI_KEY=$(ask_input "输入 OpenAI API Key (sk-...)" "")
      DEFAULT_MODEL="openai/gpt-4o"
      MODEL_PROVIDER="openai"
      ;;
    2)  # Google Gemini
      GOOGLE_KEY=$(ask_input "输入 Google AI API Key (AIza...)" "")
      DEFAULT_MODEL="google/gemini-2.5-pro"
      MODEL_PROVIDER="google"
      ;;
    3)  # OpenRouter
      OPENROUTER_KEY=$(ask_input "输入 OpenRouter API Key (sk-or-...)" "")
      DEFAULT_MODEL="openrouter/anthropic/claude-sonnet-4-20250514"
      MODEL_PROVIDER="openrouter"
      ;;
    4)  # Ollama
      OLLAMA_KEY="ollama-local"
      DEFAULT_MODEL="ollama/qwen2.5:7b"
      MODEL_PROVIDER="ollama"
      info "确保 Ollama 已安装并在 11434 端口运行"
      ;;
    5)  # 混合模式
      ANTHROPIC_KEY=$(ask_input "输入 Anthropic API Key (留空跳过)" "")
      OPENAI_KEY=$(ask_input "输入 OpenAI API Key (留空跳过)" "")
      OLLAMA_KEY="ollama-local"
      DEFAULT_MODEL="anthropic/claude-sonnet-4-20250514"
      MODEL_PROVIDER="hybrid"
      ;;
  esac

  # ----- 选择渠道 -----
  echo -e "\n${BOLD}选择消息渠道 (可多选):${NC}"
  ENABLE_TELEGRAM=false
  ENABLE_DISCORD=false
  ENABLE_SLACK=false

  if ask_yes_no "启用 Telegram Bot?" "Y"; then
    ENABLE_TELEGRAM=true
    TELEGRAM_TOKEN=$(ask_input "输入 Telegram Bot Token" "")
  fi

  if ask_yes_no "启用 Discord Bot?" "N"; then
    ENABLE_DISCORD=true
    DISCORD_TOKEN=$(ask_input "输入 Discord Bot Token" "")
  fi

  if ask_yes_no "启用 Slack?" "N"; then
    ENABLE_SLACK=true
    SLACK_APP_TOKEN=$(ask_input "输入 Slack App Token (xapp-...)" "")
    SLACK_BOT_TOKEN=$(ask_input "输入 Slack Bot Token (xoxb-...)" "")
  fi

  # ----- 存储配置 -----
  echo -e "\n${BOLD}存储配置:${NC}"
  INSTALL_DIR=$(ask_input "安装目录" "/opt/openclaw")

  # ----- Nginx + SSL -----
  SETUP_NGINX=false
  if ask_yes_no "配置 Nginx 反向代理 + SSL?(生产环境推荐)" "N"; then
    SETUP_NGINX=true
    DOMAIN=$(ask_input "输入域名 (如 openclaw.example.com)" "")
  fi

  # ----- 月度预算 -----
  MAX_SPEND=$(ask_input "月度 API 消费上限 (美元,0=不限制)" "50")
}

# ========================================
# 第四步:生成配置文件
# ========================================

generate_configs() {
  section "第 4 步:生成配置文件"

  # 创建目录
  mkdir -p "${INSTALL_DIR}"/{openclaw-config,openclaw-workspace,backups}
  cd "$INSTALL_DIR"

  # 生成 Gateway Token
  GATEWAY_TOKEN=$(openssl rand -hex 32)
  info "Gateway Token: ${GATEWAY_TOKEN}"

  # 生成 .env
  info "生成 .env 文件..."
  cat > .env << EOF
# ============================================
# OpenClaw 环境变量配置
# 由 openclaw-setup.sh v${SCRIPT_VERSION} 自动生成
# 生成时间: $(date)
# ============================================

# Gateway 认证
OPENCLAW_GATEWAY_TOKEN=${GATEWAY_TOKEN}

# 模型 Provider
EOF

  # 根据选择写入 API Key
  case $MODEL_PROVIDER in
    anthropic)
      echo "ANTHROPIC_API_KEY=${ANTHROPIC_KEY}" >> .env
      ;;
    openai)
      echo "OPENAI_API_KEY=${OPENAI_KEY}" >> .env
      ;;
    google)
      echo "GOOGLE_AI_API_KEY=${GOOGLE_KEY}" >> .env
      ;;
    openrouter)
      echo "OPENROUTER_API_KEY=${OPENROUTER_KEY}" >> .env
      ;;
    ollama)
      echo "OLLAMA_API_KEY=ollama-local" >> .env
      ;;
    hybrid)
      [[ -n "$ANTHROPIC_KEY" ]] && echo "ANTHROPIC_API_KEY=${ANTHROPIC_KEY}" >> .env
      [[ -n "$OPENAI_KEY" ]] && echo "OPENAI_API_KEY=${OPENAI_KEY}" >> .env
      echo "OLLAMA_API_KEY=ollama-local" >> .env
      ;;
  esac

  # 写入渠道 Token
  cat >> .env << EOF

# 消息渠道
EOF

  [[ "$ENABLE_TELEGRAM" == "true" ]] && echo "TELEGRAM_BOT_TOKEN=${TELEGRAM_TOKEN}" >> .env
  [[ "$ENABLE_DISCORD" == "true" ]] && echo "DISCORD_BOT_TOKEN=${DISCORD_TOKEN}" >> .env
  [[ "$ENABLE_SLACK" == "true" ]] && cat >> .env << EOF
SLACK_APP_TOKEN=${SLACK_APP_TOKEN}
SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN}
EOF

  # 写入可选配置
  cat >> .env << EOF

# 可选配置
TZ=Asia/Shanghai
NODE_ENV=production
EOF

  [[ "$MAX_SPEND" != "0" ]] && echo "MAX_MONTHLY_SPEND=${MAX_SPEND}" >> .env

  chmod 600 .env
  info ".env 文件已生成"

  # 生成 docker-compose.yml
  info "生成 docker-compose.yml..."
  cat > docker-compose.yml << 'COMPOSE'
version: "3.8"

services:
  openclaw-gateway:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw
    restart: unless-stopped
    ports:
      - "18789:18789"
      - "18793:18793"
    volumes:
      - ./openclaw-config:/root/.openclaw
      - ./openclaw-workspace:/root/workspace
    env_file:
      - .env
    environment:
      - NODE_ENV=production
      - TZ=Asia/Shanghai
    depends_on:
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:18789/healthz"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    deploy:
      resources:
        limits:
          cpus: "2"
          memory: 2G
        reservations:
          cpus: "0.5"
          memory: 512M
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"
    command: openclaw gateway

  redis:
    image: redis:7-alpine
    container_name: openclaw-redis
    restart: unless-stopped
    ports:
      - "127.0.0.1:6379:6379"
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 256M

volumes:
  redis-data:
    driver: local
COMPOSE

  info "docker-compose.yml 已生成"

  # 生成 openclaw.json
  info "生成 openclaw.json..."
  cat > openclaw-config/openclaw.json << JSON
{
  "gateway": {
    "bind": "loopback",
    "port": 18789,
    "trustedProxies": ["127.0.0.1", "172.16.0.0/12"],
    "auth": {
      "mode": "token",
      "token": "\${OPENCLAW_GATEWAY_TOKEN}"
    }
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "${DEFAULT_MODEL}"
JSON

  # 混合模式添加回退
  if [[ "$MODEL_PROVIDER" == "hybrid" ]]; then
    cat >> openclaw-config/openclaw.json << 'JSON'
,
        "fallbacks": ["openai/gpt-4o", "openai/gpt-4o-mini", "ollama/qwen2.5:7b"]
JSON
  fi

  cat >> openclaw-config/openclaw.json << 'JSON'
      }
    }
  },
  "skills": {
    "autoUpdate": false,
    "updateNotify": true
  }
}
JSON

  info "openclaw.json 已生成"

  # 生成备份脚本
  info "生成备份脚本..."
  cat > openclaw-backup.sh << 'BACKUP'
#!/bin/bash
# OpenClaw 自动备份脚本
set -euo pipefail

BACKUP_DIR="BACKUP_DIR_PLACEHOLDER/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="openclaw-backup-${DATE}.tar.gz"
RETENTION_DAYS=30

mkdir -p "$BACKUP_DIR"

tar -czf "${BACKUP_DIR}/${BACKUP_FILE}" \
  BACKUP_DIR_PLACEHOLDER/openclaw-config \
  BACKUP_DIR_PLACEHOLDER/openclaw-workspace \
  BACKUP_DIR_PLACEHOLDER/.env \
  2>/dev/null || true

find "$BACKUP_DIR" -name "openclaw-backup-*.tar.gz" -mtime +${RETENTION_DAYS} -delete

BACKUP_SIZE=$(du -h "${BACKUP_DIR}/${BACKUP_FILE}" | cut -f1)
echo "[$(date)] 备份完成: ${BACKUP_FILE} (${BACKUP_SIZE})"
BACKUP

  # 替换占位符
  sed -i "s|BACKUP_DIR_PLACEHOLDER|${INSTALL_DIR}|g" openclaw-backup.sh
  chmod +x openclaw-backup.sh

  # 加入 crontab
  (crontab -l 2>/dev/null | grep -v "openclaw-backup"; echo "0 3 * * * ${INSTALL_DIR}/openclaw-backup.sh >> ${INSTALL_DIR}/backups/backup.log 2>&1") | crontab -
  info "自动备份已配置(每天凌晨 3 点)"

  info "配置文件生成完成"
}

# ========================================
# 第五步:拉取镜像并启动
# ========================================

start_services() {
  section "第 5 步:拉取镜像并启动"

  cd "$INSTALL_DIR"

  info "拉取 OpenClaw 镜像(可能需要几分钟)..."
  docker compose pull

  info "启动服务..."
  docker compose up -d

  info "等待服务就绪..."
  local retry=0
  local max_retry=30
  while [[ $retry -lt $max_retry ]]; do
    if curl -sf http://localhost:18789/healthz > /dev/null 2>&1; then
      info "Gateway 已就绪 ✅"
      break
    fi
    ((retry++))
    echo -n "."
    sleep 2
  done
  echo ""

  if [[ $retry -eq $max_retry ]]; then
    warn "Gateway 未在预期时间内就绪,请查看日志:"
    echo "  docker compose -f ${INSTALL_DIR}/docker-compose.yml logs -f openclaw-gateway"
  fi
}

# ========================================
# 第六步:配置 Nginx + SSL(可选)
# ========================================

setup_nginx_ssl() {
  if [[ "$SETUP_NGINX" != "true" ]]; then
    return 0
  fi

  section "第 6 步:配置 Nginx + SSL"

  if [[ -z "$DOMAIN" ]]; then
    warn "未提供域名,跳过 Nginx + SSL 配置"
    return 0
  fi

  # 安装 Nginx 和 Certbot
  info "安装 Nginx 和 Certbot..."
  if [[ "$OS_ID" == "ubuntu" ]] || [[ "$OS_ID" == "debian" ]]; then
    apt-get install -y nginx certbot python3-certbot-nginx
  elif [[ "$OS_ID" == "fedora" ]] || [[ "$OS_ID" == "rhel" ]]; then
    dnf install -y nginx certbot python3-certbot-nginx
  fi

  # 创建 Nginx 配置
  info "创建 Nginx 配置..."
  cat > /etc/nginx/sites-available/openclaw.conf << NGINX
server {
    listen 80;
    listen [::]:80;
    server_name ${DOMAIN};

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

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

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name ${DOMAIN};

    ssl_certificate     /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    server_tokens off;

    location / {
        proxy_pass http://127.0.0.1:18789;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For \$remote_addr;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_set_header Host \$host;
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}
NGINX

  # 启用站点
  ln -sf /etc/nginx/sites-available/openclaw.conf /etc/nginx/sites-enabled/
  rm -f /etc/nginx/sites-enabled/default

  # 先用 HTTP 模式获取证书
  info "获取 SSL 证书..."
  nginx -t && systemctl reload nginx

  if certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos --register-unsafely-without-email 2>/dev/null; then
    info "SSL 证书获取成功 ✅"
    systemctl reload nginx
  else
    warn "SSL 证书获取失败,请确保域名已正确解析到本服务器"
    warn "你可以稍后手动运行: certbot --nginx -d ${DOMAIN}"
  fi

  # 防火墙
  if command -v ufw &>/dev/null; then
    ufw allow 80/tcp
    ufw allow 443/tcp
    ufw --force enable
  fi

  info "Nginx + SSL 配置完成"
}

# ========================================
# 第七步:健康检查和验证
# ========================================

health_check() {
  section "第 7 步:健康检查"

  cd "$INSTALL_DIR"

  # 容器状态
  info "检查容器状态..."
  docker compose ps

  # 健康检查
  info "检查 Gateway 健康..."
  local health_status
  health_status=$(docker inspect --format='{{.State.Health.Status}}' openclaw 2>/dev/null || echo "unknown")
  if [[ "$health_status" == "healthy" ]]; then
    info "Gateway: 健康 ✅"
  else
    warn "Gateway 状态: ${health_status}(可能需要等待启动完成)"
  fi

  # Redis
  info "检查 Redis..."
  if docker exec openclaw-redis redis-cli ping 2>/dev/null | grep -q "PONG"; then
    info "Redis: 正常 ✅"
  else
    warn "Redis: 未响应"
  fi

  # 磁盘使用
  info "磁盘使用:"
  df -h "$INSTALL_DIR" | tail -1 | awk '{print "  已用: "$3" / 总量: "$2" ("$5")"}'
}

# ========================================
# 第八步:输出部署信息
# ========================================

print_summary() {
  section "部署完成!"

  PUBLIC_IP=$(curl -sf --connect-timeout 5 ifconfig.me 2>/dev/null || echo "YOUR_SERVER_IP")

  if [[ "$SETUP_NGINX" == "true" ]] && [[ -n "$DOMAIN" ]]; then
    ACCESS_URL="https://${DOMAIN}"
  else
    ACCESS_URL="http://${PUBLIC_IP}:18789"
  fi

  cat << SUMMARY

  ${GREEN}${BOLD}🦞 OpenClaw 部署成功!${NC}

  ${BOLD}访问信息:${NC}
  ┌─────────────────────────────────────────────────────┐
  │  Control UI:    ${CYAN}${ACCESS_URL}${NC}
  │  Gateway Token: ${CYAN}${GATEWAY_TOKEN}${NC}
  │  安装目录:      ${INSTALL_DIR}
  └─────────────────────────────────────────────────────┘

  ${BOLD}常用命令:${NC}
  ┌─────────────────────────────────────────────────────┐
  │  启动:     cd ${INSTALL_DIR} && docker compose up -d
  │  停止:     cd ${INSTALL_DIR} && docker compose stop
  │  重启:     cd ${INSTALL_DIR} && docker compose restart
  │  日志:     cd ${INSTALL_DIR} && docker compose logs -f
  │  状态:     cd ${INSTALL_DIR} && docker compose ps
  │  更新:     cd ${INSTALL_DIR} && docker compose pull && docker compose up -d
  │  备份:     ${INSTALL_DIR}/openclaw-backup.sh
  └─────────────────────────────────────────────────────┘

  ${BOLD}下一步:${NC}
  1. 打开浏览器访问 Control UI
  2. 输入 Gateway Token 登录
  3. 运行 onboarding: docker compose run --rm openclaw-gateway openclaw onboard
  4. 安装 Skill: npx clawhub@latest install web-browsing
  5. 在 Telegram/Discord 中给你的 Bot 发消息测试

  ${BOLD}文档:${NC}
  - 官方文档: https://docs.openclaw.ai
  - ClawHub:  https://clawhub.ai
  - 博客:     https://zhengxingtao.com

  ${YELLOW}${BOLD}安全提醒:${NC}
  - 保管好 Gateway Token 和 API Key
  - Skill 自动更新已关闭,更新前请审查
  - 生产环境务必启用 HTTPS

SUMMARY
}

# ========================================
# 主流程
# ========================================

main() {
  echo -e "${CYAN}${BOLD}"
  echo "  ╔══════════════════════════════════════════╗"
  echo "  ║    🦞 OpenClaw 一键部署脚本 v${SCRIPT_VERSION}     ║"
  echo "  ║       zhengxingtao.com | PySuper         ║"
  echo "  ╚══════════════════════════════════════════╝"
  echo -e "${NC}"

  detect_system
  install_dependencies
  interactive_config
  generate_configs
  start_services
  setup_nginx_ssl
  health_check
  print_summary
}

main "$@"

使用方式:

bash

# 方式一:下载后运行
curl -fsSL https://your-host/openclaw-setup.sh -o openclaw-setup.sh
chmod +x openclaw-setup.sh
sudo ./openclaw-setup.sh

# 方式二:一行命令运行
curl -fsSL https://your-host/openclaw-setup.sh | sudo bash

十、常见问题排查

10.1 端口冲突

症状:启动失败,日志显示 EADDRINUSEport already in use

bash

# 查看占用 18789 端口的进程
sudo lsof -i :18789
# 或
sudo ss -tlnp | grep 18789

# 解决方案 1:杀掉占用进程
sudo kill -9 <PID>

# 解决方案 2:改 OpenClaw 端口
# 在 .env 中添加:
OPENCLAW_PORT=28789
# 同时修改 docker-compose.yml 的 ports 映射

# 解决方案 3:Docker 容器残留
docker rm -f openclaw 2>/dev/null
docker compose up -d

10.2 Docker 权限问题

症状permission denied while trying to connect to the Docker daemon socket

bash

# 把当前用户加入 docker 组
sudo usermod -aG docker $USER

# 重新登录或执行
newgrp docker

# 验证
docker ps

# 如果还不行,检查 Docker socket 权限
ls -la /var/run/docker.sock
# 应该是 srw-rw---- root docker

# 临时方案(不推荐,安全风险)
sudo chmod 666 /var/run/docker.sock

10.3 模型连接失败

症状:Bot 能收到消息但不回复,或回复错误信息。

bash

# 1. 检查 API Key 是否正确
docker compose exec openclaw-gateway env | grep API_KEY

# 2. 测试 API 连通性
# Anthropic
curl -s https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-4-20250514","max_tokens":10,"messages":[{"role":"user","content":"hi"}]}' | head -20

# OpenAI
curl -s https://api.openai.com/v1/chat/completions \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "content-type: application/json" \
  -d '{"model":"gpt-4o-mini","max_tokens":10,"messages":[{"role":"user","content":"hi"}]}' | head -20

# 3. Ollama 连接问题
curl http://localhost:11434/api/tags   # 宿主机上
curl http://host.docker.internal:11434/api/tags  # Docker 容器内(macOS)
# Linux Docker 中访问宿主机 Ollama:
# 用 ip route | grep default | awk '{print $9}' 获取宿主机 IP

# 4. 检查模型配置
docker compose exec openclaw-gateway openclaw models list

# 5. 常见错误码
# 401: API Key 无效或过期
# 429: 速率限制,等一会儿再试
# 500/503: 模型服务端问题,检查模型回退配置

10.4 渠道 Webhook 不通

症状:Bot 在平台上显示在线,但收不到消息。

bash

# Telegram: 不需要 Webhook,用 Polling
# 确认 Token 正确:
curl https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getMe
# 应该返回 bot 信息

# Discord: 需要 MESSAGE CONTENT INTENT
# 检查 Developer Portal → Bot → Privileged Gateway Intents
# MESSAGE CONTENT INTENT 必须开启

# Slack: 检查 Socket Mode
# 确认 App-Level Token (xapp-) 和 Bot Token (xoxb-) 都配置了
# 检查 Event Subscriptions 是否订阅了 message.* 事件

# 通用:查看 Gateway 日志中的渠道连接状态
docker compose logs openclaw-gateway 2>&1 | grep -i "channel\|connect\|error"

10.5 内存不足 OOM

症状:容器突然退出,日志显示 OOMKilled

bash

# 检查容器是否被 OOM Kill
docker inspect openclaw --format='{{.State.OOMKilled}}'

# 查看内存使用
docker stats openclaw --no-stream

# 解决方案 1:增加内存限制
# 修改 docker-compose.yml:
#   deploy:
#     resources:
#       limits:
#         memory: 4G    # 从 2G 提高到 4G

# 解决方案 2:减少会话上下文长度
# 在 openclaw.json 中:
# {
#   "agents": {
#     "defaults": {
#       "contextWindow": 4096   # 减小上下文窗口
#     }
#   }
# }

# 解决方案 3:增加 swap
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# 解决方案 4:清理 Docker 资源
docker system prune -a --volumes  # ⚠️ 会删除所有未使用的容器和镜像

10.6 日志查看命令速查表

bash

# ============================================
# OpenClaw 日志查看命令速查
# ============================================

# --- Docker 部署 ---

# 实时跟踪日志
docker compose logs -f openclaw-gateway

# 最近 N 行
docker compose logs --tail 100 openclaw-gateway

# 最近时间段
docker compose logs --since 30m openclaw-gateway
docker compose logs --since 2h openclaw-gateway

# 搜索错误
docker compose logs openclaw-gateway 2>&1 | grep -i "error"
docker compose logs openclaw-gateway 2>&1 | grep -i "crash"
docker compose logs openclaw-gateway 2>&1 | grep -i "timeout"

# 搜索渠道相关
docker compose logs openclaw-gateway 2>&1 | grep -i "telegram"
docker compose logs openclaw-gateway 2>&1 | grep -i "discord"
docker compose logs openclaw-gateway 2>&1 | grep -i "channel.*connect"

# 搜索模型调用
docker compose logs openclaw-gateway 2>&1 | grep -i "model\|llm\|completion"
docker compose logs openclaw-gateway 2>&1 | grep -i "rate.limit\|429"

# 容器事件
docker events --filter container=openclaw

# --- 裸机部署 ---

# 实时日志
journalctl --user -u openclaw-gateway -f

# 最近 100 行
journalctl --user -u openclaw-gateway -n 100

# 时间范围
journalctl --user -u openclaw-gateway --since "1 hour ago"
journalctl --user -u openclaw-gateway --since today

# 搜索
journalctl --user -u openclaw-gateway | grep -i "error"
journalctl --user -u openclaw-gateway | grep -i "gateway.*listen"

# --- 通用 ---

# 检查 Gateway 是否在监听
curl -s http://localhost:18789/healthz

# 检查进程
ps aux | grep openclaw

# 检查端口
ss -tlnp | grep 18789

# 磁盘使用
du -sh /opt/openclaw/*/

# Docker 磁盘使用
docker system df

附录

A. 环境变量完整参考

表格

变量名

必需

默认值

说明

ANTHROPIC_API_KEY

*

-

Anthropic Claude API Key

OPENAI_API_KEY

*

-

OpenAI GPT API Key

GOOGLE_AI_API_KEY

*

-

Google Gemini API Key

OPENROUTER_API_KEY

*

-

OpenRouter API Key

OLLAMA_API_KEY

*

-

Ollama 标识(任意值)

OPENCLAW_GATEWAY_TOKEN

自动生成

Gateway 访问 Token

OPENCLAW_PORT

18789

Gateway 监听端口

TELEGRAM_BOT_TOKEN

-

Telegram Bot Token

DISCORD_BOT_TOKEN

-

Discord Bot Token

SLACK_APP_TOKEN

-

Slack App Token

SLACK_BOT_TOKEN

-

Slack Bot Token

MAX_MONTHLY_SPEND

0

月度消费上限(美元)

TZ

UTC

时区

NODE_ENV

development

运行环境

REDIS_HOST

localhost

Redis 主机

REDIS_PORT

6379

Redis 端口

* 至少需要一个模型 Provider 的 API Key

B. 常用端口速查

表格

端口

服务

对外暴露

18789

OpenClaw Gateway

走 Nginx 代理,不直接暴露

18793

Canvas Host

仅内部

6379

Redis

仅内部(127.0.0.1)

80

Nginx HTTP

对外(重定向到 443)

443

Nginx HTTPS

对外

11434

Ollama API

仅内部

C. 版本升级流程

bash

# 1. 备份
/opt/openclaw/openclaw-backup.sh

# 2. 拉取最新镜像
cd /opt/openclaw
docker compose pull

# 3. 滚动升级(停机时间 < 10 秒)
docker compose up -d

# 4. 验证
docker compose ps
curl -s http://localhost:18789/healthz

# 5. 查看变更日志
docker compose logs --tail 20 openclaw-gateway

# 如果升级出问题,回滚:
docker compose down
# 修改 image tag 到上一个版本
docker compose up -d
# 或从备份恢复

D. 相关资源

表格

作者:PySuper | 来源zhengxingtao.com

本文是 #47 OpenClaw 实战文章的部署篇,专注于"怎么跑起来"和"怎么跑得稳"。如果你想了解 OpenClaw 的架构设计、Skill 系统和日常使用,请看上一篇。

有问题?在博客评论区讨论,或者直接来 Telegram 群组找我们。

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区