openclaw-twoway deployment

# OpenClaw 三种部署方案完整技能

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "openclaw-twoway deployment" with this command: npx skills add openclaw-two-way-deployment

OpenClaw 三种部署方案完整技能

技能使用说明

运行 /openclaw-deploy 选择部署方案,自动完成环境检测、防火墙配置、服务部署。


方案一:云端网关 + Tailscale + SSH 隧道控制本地

完整架构流程图

┌─────────────────────────────────────────────────────────────────────────────┐
│                              云端服务器 (Linux)                              │
│  ┌──────────────────────────────────────────────────────────────────────┐   │
│  │                     OpenClaw Gateway                                  │   │
│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                 │   │
│  │  │ 钉钉/飞书     │  │ 核心处理     │  │ AI 模型 API    │                 │   │
│  │  └──────────────┘  └──────────────┘  └──────────────┘                 │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────────────────┐   │
│  │  SSH Server (22)           Tailscale (<YOUR_CLOUD_IP>:18789)         │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
              ┌─────────────────────┴─────────────────────┐
              │ Tailscale VPN (加密)                       │
              │ SSH 隧道:localhost:2222 → <YOUR_CLOUD_IP>:18789
              ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                              本地电脑 (Windows)                              │
│  ┌──────────────────────────────────────────────────────────────────────┐   │
│  │  SSH Client (后台)           OpenClaw CLI / VSCode                   │   │
│  │                              连接:ws://localhost:2222                │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘
                                    ▲
                                    │
                          ┌─────────┴─────────┐
                          ▼                   ▼
                   ┌──────────┐        ┌──────────┐
                   │ 钉钉 APP │        │ 浏览器   │
                   └──────────┘        └──────────┘

数据流向:

  1. 钉钉/飞书 → Webhook → 云端网关 (18789)
  2. 云端网关 → AI 模型 API → 获取回复
  3. 云端网关 → Webhook → 返回钉钉/飞书
  4. 本地通过 SSH 隧道访问云端网关进行配置/监控

### 部署前检查清单

| 检查项 | 本地 | 云端 | 验证命令 |
|--------|------|------|----------|
| Tailscale 账号 | ✅ 同一账号 | ✅ 同一账号 | `tailscale status` |
| Tailscale 连接 | ✅ 已连接 | ✅ 已连接 | `tailscale ip` |
| Node.js (v18+) | ✅ 已安装 | ✅ 已安装 | `node -v` |
| SSH 客户端 | ✅ 已配置 | ❌ | `ssh -V` |
| SSH 服务端 | ❌ | ✅ 已运行 | `systemctl status sshd` |
| 防火墙 18789 | ❌ | ⚠️ 需放行 | `ufw status` / `firewall-cmd --list-all` |
| 防火墙 22 | ❌ | ⚠️ 需放行 | `ufw status` |
| 云安全组 18789 | ❌ | ⚠️ 需放行 | 云控制台检查 |
| 云安全组 22 | ❌ | ⚠️ 需放行 | 云控制台检查 |

### 云端完整部署脚本(含防火墙 + 安全组检测)

```bash
#!/bin/bash
# plan1-cloud-gateway.sh - 方案一:云端网关完整部署
set -e

echo "╔════════════════════════════════════════════════════════════════╗"
echo "║     方案一:云端网关 + Tailscale + SSH 隧道                       ║"
echo "║                    云端网关完整部署                              ║"
echo "╚════════════════════════════════════════════════════════════════╝"

# ============== 1. 系统环境检测 ==============
echo -e "\n[1/8] 系统环境检测..."

if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS=$ID
    echo "  系统:$OS ($PRETTY_NAME)"
else
    echo "  ✗ 无法识别系统"
    exit 1
fi

if [ "$EUID" -ne 0 ]; then
    echo "  ✗ 请使用 root 权限运行"
    exit 1
fi
echo "  ✓ 权限检查通过 (root)"

# 检测 SSH 服务
if systemctl is-active --quiet sshd || systemctl is-active --quiet ssh; then
    echo "  ✓ SSH 服务:运行中"
else
    echo "  ⚠ SSH 服务未运行,正在启动..."
    systemctl enable --now sshd 2>/dev/null || systemctl enable --now ssh 2>/dev/null || true
fi

# ============== 2. Tailscale 配置 ==============
echo -e "\n[2/8] 配置 Tailscale..."

if ! command -v tailscale &> /dev/null; then
    echo "  安装 Tailscale..."
    if [ "$OS" = "ubuntu" ] || [ "$OS" = "debian" ]; then
        curl -fsSL https://tailscale.com/install.sh | sh
    elif [ "$OS" = "centos" ] || [ "$OS" = "rhel" ] || [ "$OS" = "rocky" ]; then
        yum install -y yum-utils
        yum-config-manager --add-repo https://pkgs.tailscale.com/stable/centos/9/tailscale.repo
        yum install -y tailscale
    else
        echo "  ✗ 不支持的系统,请手动安装:https://tailscale.com/download"
        exit 1
    fi
fi

systemctl enable --now tailscaled 2>/dev/null || tailscaled &
sleep 3

if tailscale status 2>&1 | grep -q "connected"; then
    TAILSCALE_IP=$(tailscale ip | head -1)
    echo "  ✓ Tailscale: 已连接 ($TAILSCALE_IP)"
else
    echo "  ⚠ Tailscale 未连接"
    echo "  请运行以下命令完成认证:"
    echo "    tailscale up"
    AUTH_URL=$(tailscale up 2>&1 | grep -o 'https://login.tailscale.com/a/[a-zA-Z0-9]*' || echo "")
    if [ -n "$AUTH_URL" ]; then
        echo "  认证链接:$AUTH_URL"
    fi
    read -p "  完成认证后按回车继续..."
    TAILSCALE_IP=$(tailscale ip | head -1)
    echo "  ✓ Tailscale: 已连接 ($TAILSCALE_IP)"
fi

# ============== 3. 防火墙配置 ==============
echo -e "\n[3/8] 配置防火墙..."

FIREWALL_CONFIGURED=false

# UFW (Ubuntu/Debian)
if command -v ufw &> /dev/null; then
    echo "  检测到 UFW 防火墙..."
    if ufw status | grep -q "Status: active"; then
        echo "  UFW 已启用,配置规则..."
        ufw allow 18789/tcp comment "OpenClaw Gateway" 2>/dev/null || ufw allow 18789/tcp
        ufw allow 22/tcp comment "SSH" 2>/dev/null || ufw allow 22/tcp
        ufw reload 2>/dev/null || true
        echo "  ✓ UFW: 18789/tcp, 22/tcp 已放行"
        FIREWALL_CONFIGURED=true
    else
        echo "  UFW 未启用"
    fi
fi

# Firewalld (CentOS/RHEL)
if [ "$FIREWALL_CONFIGURED" = false ] && command -v firewall-cmd &> /dev/null; then
    echo "  检测到 Firewalld..."
    if systemctl is-active --quiet firewalld; then
        echo "  Firewalld 运行中,配置规则..."
        firewall-cmd --permanent --add-port=18789/tcp 2>/dev/null || true
        firewall-cmd --permanent --add-service=ssh 2>/dev/null || true
        firewall-cmd --reload 2>/dev/null || true
        echo "  ✓ Firewalld: 18789/tcp, ssh 已放行"
        FIREWALL_CONFIGURED=true
    else
        echo "  Firewalld 未运行"
    fi
fi

# iptables (通用)
if [ "$FIREWALL_CONFIGURED" = false ] && command -v iptables &> /dev/null; then
    echo "  检测到 iptables..."
    if ! iptables -L INPUT -n 2>/dev/null | grep -q "dpt:18789"; then
        iptables -I INPUT -p tcp --dport 18789 -j ACCEPT 2>/dev/null || true
        iptables -I INPUT -p tcp --dport 22 -j ACCEPT 2>/dev/null || true
        echo "  ✓ iptables: 18789/tcp, 22/tcp 已添加"
        FIREWALL_CONFIGURED=true
    else
        echo "  端口规则已存在"
    fi
fi

if [ "$FIREWALL_CONFIGURED" = false ]; then
    echo "  ℹ 未检测到防火墙工具"
fi

echo "  ⚠ 重要:如使用云服务器 (阿里云/腾讯云/AWS 等),请确保云控制台安全组已放行:"
echo "     - 18789/tcp (Tailscale IP: $TAILSCALE_IP)"
echo "     - 22/tcp (SSH)"

# ============== 4. Node.js 配置 ==============
echo -e "\n[4/8] 配置 Node.js 环境..."

if command -v node &> /dev/null; then
    NODE_VER=$(node -v)
    echo "  ✓ Node.js 已安装:$NODE_VER"
else
    echo "  安装 Node.js 22..."
    if [ "$OS" = "ubuntu" ] || [ "$OS" = "debian" ]; then
        curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
        apt-get install -y nodejs
    elif [ "$OS" = "centos" ] || [ "$OS" = "rhel" ] || [ "$OS" = "rocky" ]; then
        curl -fsSL https://rpm.nodesource.com/setup_22.x | bash -
        yum install -y nodejs
    else
        echo "  ✗ 不支持的系统,请手动安装 Node.js"
        exit 1
    fi
    echo "  ✓ Node.js 安装完成:$(node -v)"
fi

npm config set registry https://registry.npmmirror.com 2>/dev/null || true

# ============== 5. OpenClaw 安装 ==============
echo -e "\n[5/8] 安装 OpenClaw..."

if command -v openclaw &> /dev/null; then
    echo "  ✓ OpenClaw 已安装"
    openclaw --version
else
    echo "  安装 OpenClaw..."
    npm install -g openclaw
    echo "  ✓ OpenClaw 安装完成"
fi

# ============== 6. 网关配置 ==============
echo -e "\n[6/8] 配置 OpenClaw 网关..."

mkdir -p ~/.openclaw

cat > ~/.openclaw/openclaw.json << 'EOF'
{
  "gateway": {
    "port": 18789,
    "mode": "local",
    "bind": "lan"
  }
}
EOF

echo "  ✓ 配置文件:~/.openclaw/openclaw.json"

# ============== 7. systemd 服务配置 ==============
echo -e "\n[7/8] 创建 systemd 服务..."

cat > /etc/systemd/system/openclaw-gateway.service << 'EOF'
[Unit]
Description=OpenClaw Gateway Service
After=network.target tailscaled.service
Wants=tailscaled.service

[Service]
Type=simple
User=root
WorkingDirectory=/root/.openclaw
ExecStart=/usr/bin/node /usr/lib/node_modules/openclaw/dist/index.js gateway --port 18789 --bind lan
Restart=always
RestartSec=5
StartLimitBurst=3
StartLimitIntervalSec=300

Environment=NODE_ENV=production

# 资源限制
LimitNOFILE=65535
Nice=-5
OOMScoreAdjust=-500

[Install]
WantedBy=multi-user.target
EOF

echo "  ✓ systemd 服务配置完成"

# ============== 8. 启动服务 ==============
echo -e "\n[8/8] 启动服务..."

systemctl daemon-reload
systemctl enable openclaw-gateway
systemctl start openclaw-gateway

echo "  等待服务启动..."
sleep 5

# ============== 验证 ==============
echo -e "\n╔════════════════════════════════════════════════════════════════╗"
if systemctl is-active --quiet openclaw-gateway; then
    echo "║                     ✓ 部署成功                                 ║"
    echo "╚════════════════════════════════════════════════════════════════╝"

    echo -e "\n【服务信息】"
    echo "  服务状态:$(systemctl is-active openclaw-gateway)"
    echo "  开机自启:$(systemctl is-enabled openclaw-gateway)"

    echo -e "\n【网络信息】"
    echo "  Tailscale IP: $TAILSCALE_IP"
    echo "  网关地址:ws://${TAILSCALE_IP}:18789"
    echo "  控制面板:http://${TAILSCALE_IP}:18789/"

    echo -e "\n【端口监听】"
    ss -tlnp | grep 18789 || netstat -tlnp | grep 18789 || true

    echo -e "\n【下一步操作】"
    echo "  1. 在本地电脑运行 SSH 隧道脚本 (start-tunnel.ps1)"
    echo "  2. 或在本地配置远程网关:openclaw gateway remote set ws://${TAILSCALE_IP}:18789"
    echo "  3. 查看日志:journalctl -u openclaw-gateway -f"

    echo -e "\n【本地 SSH 隧道脚本】"
    echo "  在本地 PowerShell 运行:"
    echo "  ssh -N -f -L 2222:${TAILSCALE_IP}:18789 root@${TAILSCALE_IP}"
else
    echo "║                     ✗ 部署失败                                 ║"
    echo "╚════════════════════════════════════════════════════════════════╝"
    echo -e "\n【错误日志】"
    journalctl -u openclaw-gateway --no-pager -n 20
    exit 1
fi

本地 SSH 隧道脚本(持久运行 + 开机自启)

# plan1-local-tunnel.ps1 - 方案一:本地 SSH 隧道持久部署
param(
    [string]$CloudIP = ""
)

$ErrorActionPreference = "Stop"
$TaskName = "OpenClaw-SSH-Tunnel"
$LocalPort = 2222
$RemotePort = 18789
$ScriptDir = "$env:USERPROFILE\.openclaw"

Write-Host "╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║     方案一:云端网关 + Tailscale + SSH 隧道                        ║" -ForegroundColor Cyan
Write-Host "║                  本地 SSH 隧道持久部署                            ║"
Write-Host "╚════════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan

# 1. 检查 Tailscale
Write-Host "`n[1/6] 检查 Tailscale..." -ForegroundColor Yellow
try {
    $tsStatus = tailscale status 2>&1
    if ($LASTEXITCODE -eq 0) {
        $tsIP = (tailscale ip | Select-Object -First 1).Trim()
        Write-Host "  ✓ Tailscale: 已连接 ($tsIP)" -ForegroundColor Green
    } else {
        Write-Host "  Tailscale 未运行,正在启动..." -ForegroundColor Yellow
        tailscale up
        Start-Sleep -Seconds 5
    }
} catch {
    Write-Host "  ✗ Tailscale 未安装" -ForegroundColor Red
    Write-Host "  下载:https://tailscale.com/download" -ForegroundColor Yellow
    exit 1
}

# 2. 获取云端 IP
Write-Host "`n[2/6] 配置云端网关..." -ForegroundColor Yellow
if ($CloudIP -eq "") {
    Write-Host "  请输入云端网关 Tailscale IP:" -ForegroundColor Yellow
    $CloudIP = Read-Host "  Cloud IP"
    if ($CloudIP -eq "") {
        Write-Host "  ✗ 未输入 IP 地址" -ForegroundColor Red
        exit 1
    }
}
Write-Host "  云端网关:$CloudIP:$RemotePort" -ForegroundColor Green

# 3. 测试连接
Write-Host "`n[3/6] 测试云端连接..." -ForegroundColor Yellow
$testResult = Test-NetConnection -ComputerName $CloudIP -Port $RemotePort -WarningAction SilentlyContinue -InformationLevel Quiet
if ($testResult) {
    Write-Host "  ✓ 云端网关:可达" -ForegroundColor Green
} else {
    Write-Host "  ✗ 无法连接云端网关" -ForegroundColor Red
    Write-Host "  请检查:" -ForegroundColor Yellow
    Write-Host "    1. 云端 Tailscale 是否运行" -ForegroundColor Yellow
    Write-Host "    2. 云端网关服务是否启动" -ForegroundColor Yellow
    Write-Host "    3. 云安全组是否放行 18789" -ForegroundColor Yellow
    exit 1
}

# 4. 清理旧隧道
Write-Host "`n[4/6] 清理旧隧道进程..." -ForegroundColor Yellow
$sshProcesses = Get-Process | Where-Object { $_.ProcessName -eq "ssh" }
$stopped = 0
foreach ($p in $sshProcesses) {
    $cmd = (Get-CimInstance Win32_Process -Filter "ProcessId = $($p.Id)" -ErrorAction SilentlyContinue).CommandLine
    if ($cmd -like "*${LocalPort}*" -or $cmd -like "*${CloudIP}*") {
        Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
        $stopped++
    }
}
Write-Host "  已停止 $stopped 个旧隧道进程" -ForegroundColor Gray

# 5. 创建持久化脚本
Write-Host "`n[5/6] 创建持久化配置..." -ForegroundColor Yellow

New-Item -ItemType Directory -Force -Path $ScriptDir | Out-Null

$tunnelScript = @"
# OpenClaw SSH 隧道启动脚本
`$ErrorActionPreference = "SilentlyContinue"
`$sshArgs = "-N -L ${LocalPort}:${CloudIP}:${RemotePort} root@${CloudIP}"

# 检查 SSH 连接
while (`$true) {
    Start-Process ssh -ArgumentList `$sshArgs -WindowStyle Hidden -ErrorAction SilentlyContinue
    Start-Sleep -Seconds 60

    # 检查隧道是否通畅
    `$test = Test-NetConnection -ComputerName localhost -Port ${LocalPort} -WarningAction SilentlyContinue -InformationLevel Quiet
    if (-not `$test) {
        # 隧道断开,重启 SSH 进程
        Get-Process | Where-Object { `$_.ProcessName -eq "ssh" -and `$_.CommandLine -like "*${LocalPort}*" } | Stop-Process -Force
    }
}
"@

$scriptPath = "$ScriptDir\start-ssh-tunnel.ps1"
$tunnelScript | Out-File -FilePath $scriptPath -Encoding utf8 -Force
Write-Host "  ✓ 隧道脚本:$scriptPath" -ForegroundColor Green

# 6. 创建计划任务(开机自启)
Write-Host "`n[6/6] 创建计划任务(开机自启)..." -ForegroundColor Yellow

# 删除旧任务
schtasks /Delete /TN $TaskName /F 2>$null | Out-Null

# 创建新任务(系统启动时 + 用户登录时)
$argument = "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$scriptPath`""
schtasks /Create /TN $TaskName /TR "powershell.exe $argument" /SC ONLOGON /RU SYSTEM /F 2>$null

if ($LASTEXITCODE -eq 0) {
    Write-Host "  ✓ 计划任务:$TaskName (开机自启)" -ForegroundColor Green
} else {
    # 降级方案:当前用户登录时启动
    schtasks /Create /TN $TaskName /TR "powershell.exe $argument" /SC ONLOGON /F 2>$null
    if ($LASTEXITCODE -eq 0) {
        Write-Host "  ✓ 计划任务:$TaskName (用户登录自启)" -ForegroundColor Green
    } else {
        Write-Host "  ⚠ 计划任务创建失败,将手动启动" -ForegroundColor Yellow
    }
}

# 立即启动隧道
Write-Host "`n  立即启动 SSH 隧道..." -ForegroundColor Yellow
$sshArgs = "-N -L ${LocalPort}:${CloudIP}:${RemotePort} root@${CloudIP}"
Start-Process ssh -ArgumentList $sshArgs -WindowStyle Hidden

Start-Sleep -Seconds 3

# 验证
$tunnelTest = Test-NetConnection -ComputerName localhost -Port $LocalPort -WarningAction SilentlyContinue -InformationLevel Quiet
if ($tunnelTest) {
    Write-Host "  ✓ SSH 隧道:已建立 (localhost:${LocalPort} -> ${CloudIP}:${RemotePort})" -ForegroundColor Green

    Write-Host "`n╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
    Write-Host "║                     ✓ 部署成功                                 ║" -ForegroundColor Green
    Write-Host "╚════════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan

    Write-Host "`n【隧道信息】"
    Write-Host "  本地端口:localhost:${LocalPort}"
    Write-Host "  远程地址:${CloudIP}:${RemotePort}"
    Write-Host "  计划任务:$TaskName (开机/登录自启)"

    Write-Host "`n【下一步操作】"
    Write-Host "  1. 配置远程网关:openclaw gateway remote set ws://localhost:${LocalPort}"
    Write-Host "  2. 检查状态:openclaw status"
    Write-Host "  3. 查看日志:openclaw logs --follow"
} else {
    Write-Host "  ✗ SSH 隧道建立失败" -ForegroundColor Red
    Write-Host "  请检查 SSH 密钥配置或手动运行:" -ForegroundColor Yellow
    Write-Host "    ssh -N -L ${LocalPort}:${CloudIP}:${RemotePort} root@${CloudIP}"
    exit 1
}

方案二:云端网关 + Tailscale + 本地节点

完整架构流程图

┌─────────────────────────────────────────────────────────────────────────────┐
│                              云端服务器 (Linux)                              │
│  ┌──────────────────────────────────────────────────────────────────────┐   │
│  │                  OpenClaw Gateway (Remote 模式)                       │   │
│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                 │   │
│  │  │ 钉钉/飞书     │  │ WebSocket    │  │ AI 模型 API    │                 │   │
│  │  │ Webhook      │  │ 服务端        │  │              │                 │   │
│  │  └──────────────┘  └──────────────┘  └──────────────┘                 │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────────────────┐   │
│  │  Tailscale: <YOUR_CLOUD_IP>:18789 (Token 认证)                       │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    │ Tailscale VPN (加密)
                                    │ WebSocket: ws://<YOUR_CLOUD_IP>:18789
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                              本地电脑 (Windows)                              │
│  ┌──────────────────────────────────────────────────────────────────────┐   │
│  │                  OpenClaw Node (本地节点)                             │   │
│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐                 │   │
│  │  │ WebSocket    │  │ 本地执行     │  │ 返回结果     │                 │   │
│  │  │ 客户端        │  │              │  │              │                 │   │
│  │  └──────────────┘  └──────────────┘  └──────────────┘                 │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────────────────┐   │
│  │  Tailscale: <YOUR_LOCAL_IP>         本地 CLI/VSCode                   │   │
│  └──────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────┘
                                    ▲
                                    │
                          ┌─────────┴─────────┐
                          ▼                   ▼
                   ┌──────────┐        ┌──────────┐
                   │ 钉钉 APP │        │ 浏览器   │
                   └──────────┘        └──────────┘

数据流向:

  1. 钉钉/飞书 → Webhook → 云端网关
  2. 云端网关 → WebSocket → 本地节点
  3. 本地节点 → 执行任务 → 返回结果 → 云端网关
  4. 云端网关 → AI 模型 API → 获取回复 → 返回钉钉/飞书

### 部署前检查清单

| 检查项 | 本地 | 云端 | 验证命令 |
|--------|------|------|----------|
| Tailscale 账号 | ✅ 同一账号 | ✅ 同一账号 | `tailscale status` |
| Tailscale 连接 | ✅ 已连接 | ✅ 已连接 | `tailscale ip` |
| Node.js (v18+) | ✅ 已安装 | ✅ 已安装 | `node -v` |
| 防火墙 18789 | ❌ | ⚠️ 需放行 | `ufw status` |
| 云安全组 18789 | ❌ | ⚠️ 需放行 | 云控制台检查 |
| Token 配置 | ✅ 一致 | ✅ 一致 | 检查配置文件 |

### 云端完整部署脚本(Remote 模式 + Token 认证)

```bash
#!/bin/bash
# plan2-cloud-remote-gateway.sh - 方案二:云端远程网关完整部署
set -e

echo "╔════════════════════════════════════════════════════════════════╗"
echo "║     方案二:云端网关 + Tailscale + 本地节点                       ║"
echo "║                  云端远程网关部署 (Remote 模式)                   ║"
echo "╚════════════════════════════════════════════════════════════════╝"

# ============== 1. 系统环境检测 ==============
echo -e "\n[1/7] 系统环境检测..."

if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS=$ID
    echo "  系统:$OS ($PRETTY_NAME)"
else
    echo "  ✗ 无法识别系统"
    exit 1
fi

if [ "$EUID" -ne 0 ]; then
    echo "  ✗ 请使用 root 权限运行"
    exit 1
fi
echo "  ✓ 权限检查通过 (root)"

# ============== 2. Tailscale 配置 ==============
echo -e "\n[2/7] 配置 Tailscale..."

if ! command -v tailscale &> /dev/null; then
    echo "  安装 Tailscale..."
    if [ "$OS" = "ubuntu" ] || [ "$OS" = "debian" ]; then
        curl -fsSL https://tailscale.com/install.sh | sh
    else
        echo "  ✗ 不支持的系统,请手动安装"
        exit 1
    fi
fi

systemctl enable --now tailscaled 2>/dev/null || tailscaled &
sleep 3

if tailscale status 2>&1 | grep -q "connected"; then
    TAILSCALE_IP=$(tailscale ip | head -1)
    echo "  ✓ Tailscale: 已连接 ($TAILSCALE_IP)"
else
    echo "  ⚠ Tailscale 未连接"
    echo "  运行:tailscale up"
    read -p "  完成后按回车..."
    TAILSCALE_IP=$(tailscale ip | head -1)
fi

# ============== 3. 防火墙配置 ==============
echo -e "\n[3/7] 配置防火墙..."

if command -v ufw &> /dev/null && ufw status | grep -q "Status: active"; then
    ufw allow 18789/tcp comment "OpenClaw Gateway"
    echo "  ✓ UFW: 18789/tcp 已放行"
elif command -v firewall-cmd &> /dev/null && systemctl is-active --quiet firewalld; then
    firewall-cmd --permanent --add-port=18789/tcp
    firewall-cmd --reload
    echo "  ✓ Firewalld: 18789/tcp 已放行"
fi

echo "  ⚠ 云服务器安全组需手动放行 18789 (Tailscale IP: $TAILSCALE_IP)"

# ============== 4. Node.js 配置 ==============
echo -e "\n[4/7] 配置 Node.js..."

if ! command -v node &> /dev/null; then
    echo "  安装 Node.js 22..."
    if [ "$OS" = "ubuntu" ] || [ "$OS" = "debian" ]; then
        curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
        apt-get install -y nodejs
    else
        echo "  ✗ 不支持的系统"
        exit 1
    fi
fi
echo "  ✓ Node.js: $(node -v)"

npm config set registry https://registry.npmmirror.com 2>/dev/null || true

# ============== 5. OpenClaw 安装 ==============
echo -e "\n[5/7] 安装 OpenClaw..."

npm install -g openclaw
echo "  ✓ OpenClaw: 已安装"

# ============== 6. 生成 Token ==============
echo -e "\n[6/7] 生成认证 Token..."

TOKEN=$(openssl rand -hex 20)
echo "  ✓ Token: $TOKEN"
echo "  ⚠ 请保存此 Token,本地节点配置需要"

# ============== 7. 配置网关 + systemd ==============
echo -e "\n[7/7] 配置网关 (Remote 模式)..."

mkdir -p ~/.openclaw

cat > ~/.openclaw/openclaw.json << EOF
{
  "gateway": {
    "port": 18789,
    "mode": "remote",
    "bind": "lan",
    "auth": {
      "mode": "token",
      "token": "$TOKEN"
    }
  },
  "security": {
    "dangerouslyAllowInsecurePrivateWs": true
  }
}
EOF

echo "  ✓ 配置文件:~/.openclaw/openclaw.json"

echo -e "\n  创建 systemd 服务..."
cat > /etc/systemd/system/openclaw-gateway.service << 'EOF'
[Unit]
Description=OpenClaw Gateway (Remote Mode)
After=network.target tailscaled.service
Wants=tailscaled.service

[Service]
Type=simple
User=root
WorkingDirectory=/root/.openclaw
ExecStart=/usr/bin/node /usr/lib/node_modules/openclaw/dist/index.js gateway --port 18789 --bind lan --allow-unconfigured
Restart=on-failure
RestartSec=10
StartLimitBurst=3
StartLimitIntervalSec=300

Environment=NODE_ENV=production
Environment=OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1

LimitNOFILE=65535
Nice=-5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable openclaw-gateway
systemctl start openclaw-gateway

sleep 5

# ============== 验证 ==============
echo -e "\n╔════════════════════════════════════════════════════════════════╗"
if systemctl is-active --quiet openclaw-gateway; then
    echo "║                     ✓ 部署成功                                 ║"
    echo "╚════════════════════════════════════════════════════════════════╝"

    echo -e "\n【服务信息】"
    echo "  服务状态:$(systemctl is-active openclaw-gateway)"
    echo "  运行模式:remote"
    echo "  认证方式:token"

    echo -e "\n【网络信息】"
    echo "  Tailscale IP: $TAILSCALE_IP"
    echo "  网关地址:ws://${TAILSCALE_IP}:18789"
    echo "  Token: $TOKEN"

    echo -e "\n【端口监听】"
    ss -tlnp | grep 18789 || true

    echo -e "\n【本地节点配置示例 (PowerShell)】"
    cat << POWERSHELL
`$config = @{
  gateway = @{
    mode = "remote"
    auth = @{ token = "$TOKEN" }
    remote = @{ url = "ws://${TAILSCALE_IP}:18789" }
  }
} | ConvertTo-Json | Out-File ~/.openclaw/openclaw.json -Encoding utf8
POWERSHELL

    echo -e "\n【下一步操作】"
    echo "  1. 在本地运行 plan2-local-node.ps1"
    echo "  2. 检查连接:openclaw status"
    echo "  3. 查看日志:journalctl -u openclaw-gateway -f"
else
    echo "║                     ✗ 部署失败                                 ║"
    echo "╚════════════════════════════════════════════════════════════════╝"
    journalctl -u openclaw-gateway --no-pager -n 20
    exit 1
fi

本地节点完整部署脚本

# plan2-local-node.ps1 - 方案二:本地节点完整部署
param(
    [string]$CloudIP = "",
    [string]$Token = ""
)

$ErrorActionPreference = "Stop"
$OpenClawDir = "$env:USERPROFILE\.openclaw"
$NodeExe = "C:\Program Files\nodejs\node.exe"
$OpenClawMjs = "$env:APPDATA\npm\node_modules\openclaw\openclaw.mjs"
$TaskName = "OpenClaw-Node"

Write-Host "╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║     方案二:云端网关 + Tailscale + 本地节点                       ║" -ForegroundColor Cyan
Write-Host "║                    本地节点完整部署                              ║"
Write-Host "╚════════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan

# 1. 检查 Tailscale
Write-Host "`n[1/6] 检查 Tailscale..." -ForegroundColor Yellow
$tsStatus = tailscale status 2>&1
if ($LASTEXITCODE -ne 0) {
    Write-Host "  Tailscale 未运行,正在启动..." -ForegroundColor Yellow
    tailscale up
    Start-Sleep -Seconds 5
}
$tsIP = (tailscale ip | Select-Object -First 1).Trim()
Write-Host "  ✓ Tailscale IP: $tsIP" -ForegroundColor Green

# 2. 检查 Node.js
Write-Host "`n[2/6] 检查 Node.js..." -ForegroundColor Yellow
if (!(Test-Path $NodeExe)) {
    Write-Host "  ✗ Node.js 未安装" -ForegroundColor Red
    Write-Host "  下载:https://nodejs.org/" -ForegroundColor Yellow
    exit 1
}
$nodeVer = & $NodeExe -v
Write-Host "  ✓ Node.js: $nodeVer" -ForegroundColor Green

# 3. 检查/安装 OpenClaw
Write-Host "`n[3/6] 检查 OpenClaw..." -ForegroundColor Yellow
if (!(Test-Path $OpenClawMjs)) {
    Write-Host "  安装 OpenClaw..." -ForegroundColor Yellow
    npm install -g openclaw --registry=https://registry.npmmirror.com
    if ($LASTEXITCODE -ne 0) {
        Write-Host "  ✗ 安装失败" -ForegroundColor Red
        exit 1
    }
}
Write-Host "  ✓ OpenClaw: 已安装" -ForegroundColor Green

# 4. 获取云端信息
Write-Host "`n[4/6] 配置连接信息..." -ForegroundColor Yellow

if ($CloudIP -eq "") {
    Write-Host "  请输入云端网关 Tailscale IP:" -ForegroundColor Yellow
    $CloudIP = Read-Host "  Cloud IP"
}

if ($Token -eq "") {
    Write-Host "  请输入云端网关 Token:" -ForegroundColor Yellow
    $Token = Read-Host "  Token"
}

Write-Host "  云端网关:$CloudIP:18789" -ForegroundColor Green

# 5. 测试连接
Write-Host "`n[5/6] 测试云端连接..." -ForegroundColor Yellow
$testResult = Test-NetConnection -ComputerName $CloudIP -Port 18789 -WarningAction SilentlyContinue -InformationLevel Quiet
if (!$testResult) {
    Write-Host "  ✗ 无法连接云端网关" -ForegroundColor Red
    Write-Host "  请检查:" -ForegroundColor Yellow
    Write-Host "    1. 云端 Tailscale 是否运行" -ForegroundColor Yellow
    Write-Host "    2. 云端网关是否启动" -ForegroundColor Yellow
    Write-Host "    3. 云安全组是否放行 18789" -ForegroundColor Yellow
    exit 1
}
Write-Host "  ✓ 云端网关:可达" -ForegroundColor Green

# 6. 配置并启动
Write-Host "`n[6/6] 配置并启动节点..." -ForegroundColor Yellow

New-Item -ItemType Directory -Force -Path $OpenClawDir | Out-Null

$config = @{
    gateway = @{
        mode = "remote"
        auth = @{ token = $Token }
        remote = @{ url = "ws://$($CloudIP):18789" }
    }
} | ConvertTo-Json -Depth 10

$config | Out-File -FilePath "$OpenClawDir\openclaw.json" -Encoding utf8 -Force
Write-Host "  ✓ 配置:$OpenClawDir\openclaw.json" -ForegroundColor Green

# 创建启动脚本
$startScript = "$OpenClawDir\start-node.ps1"
@"
`$env:OPENCLAW_ALLOW_INSECURE_PRIVATE_WS = "1"
& "$NodeExe" "$OpenClawMjs" node run --host "$CloudIP" --port 18789
"@ | Out-File -FilePath $startScript -Encoding utf8 -Force

# 启动节点
Write-Host "  启动节点..." -ForegroundColor Yellow
$env:OPENCLAW_ALLOW_INSECURE_PRIVATE_WS = "1"
Start-Process $NodeExe -ArgumentList "$OpenClawMjs", "node", "run", "--host", $CloudIP, "--port", "18789" -WindowStyle Normal

Start-Sleep -Seconds 5

Write-Host "`n╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║                     ✓ 部署成功                                 ║" -ForegroundColor Green
Write-Host "╚════════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan

Write-Host "`n【连接信息】"
Write-Host "  云端网关:ws://$($CloudIP):18789"
Write-Host "  节点状态:启动中..."

Write-Host "`n【下一步操作】"
Write-Host "  1. 检查状态:openclaw status"
Write-Host "  2. 查看日志:openclaw logs --follow"
Write-Host "  3. 配置开机自启(可选):"
Write-Host "     schtasks /Create /TN `"$TaskName`" /TR `"powershell -File '$startScript'`" /SC ONLOGON /F"

方案三:云端网关 + 本地网关双部署(含同步备份)

完整架构流程图

                              ┌──────────────┐
                              │  通讯软件     │
                              │ (钉钉/飞书)   │
                              └──────┬───────┘
                                     │
                ┌────────────────────┴────────────────────┐
                │                                         │
                ▼                                         ▼
┌───────────────────────────┐               ┌───────────────────────────┐
│    云端网关 (Primary)     │               │   本地网关 (Secondary)     │
│  <YOUR_CLOUD_IP>:18789    │               │   127.0.0.1:18789         │
│                           │               │                           │
│  ┌─────────────────────┐  │               │  ┌─────────────────────┐  │
│  │ 通道插件 (钉钉/飞书) │  │               │  │ 本地通道 (测试/备用) │  │
│  └──────────┬──────────┘  │               │  └──────────┬──────────┘  │
│             │             │               │             │             │
│  ┌──────────▼──────────┐  │               │  ┌──────────▼──────────┐  │
│  │ AI 模型 (云端 API)    │  │               │  │ AI 模型 (本地 API)    │  │
│  │ Claude / Qwen       │  │               │  │ Ollama / LM Studio  │  │
│  └──────────┬──────────┘  │               │  └──────────┬──────────┘  │
│             │             │               │             │             │
│  ┌──────────▼──────────┐  │   同步通道    │  ┌──────────▼──────────┐  │
│  │ 数据同步模块        │◄─┼───────────────┼─►│ 数据同步模块        │  │
│  │ - 会话状态 (实时)   │  │   Tailscale   │  │ - 会话状态 (实时)   │  │
│  │ - 消息历史 (增量)   │  │   (加密)      │  │ - 消息历史 (增量)   │  │
│  └──────────┬──────────┘  │               │  └──────────┬──────────┘  │
│             │             │               │             │             │
│  ┌──────────▼──────────┐  │               │  ┌──────────▼──────────┐  │
│  │ SQLite (云端存储)   │  │               │  │ SQLite (本地存储)   │  │
│  └─────────────────────┘  │               │  └─────────────────────┘  │
└───────────────────────────┘               └───────────────────────────┘

故障转移:
  ┌─────────────────────────────────────────────────────────────────────┐
  │ 正常:通讯软件 → 云端网关 → 处理并回复                               │
  │ 云端故障:本地网关接管 → 离线队列 → 云端恢复后同步                   │
  │ 本地故障:云端继续运行 → 数据从云端恢复                              │
  └─────────────────────────────────────────────────────────────────────┘

### 部署前检查清单

| 检查项 | 本地 | 云端 | 验证命令 |
|--------|------|------|----------|
| Tailscale 账号 | ✅ 同一账号 | ✅ 同一账号 | `tailscale status` |
| Tailscale 连接 | ✅ 已连接 | ✅ 已连接 | `tailscale ip` |
| Node.js (v18+) | ✅ 已安装 | ✅ 已安装 | `node -v` |
| 防火墙 18789 | ⚠️ 仅本地 | ⚠️ 需放行 | `ufw status` |
| 云安全组 18789 | ❌ | ⚠️ 需放行 | 云控制台检查 |
| 同步 Token | ✅ 一致 | ✅ 一致 | 检查配置文件 |

### 本地网关完整部署(含开机自启 + 同步配置)

```powershell
# plan3-local-gateway.ps1 - 方案三:本地网关完整部署(含同步备份)
param(
    [string]$CloudIP = ""
)

$ErrorActionPreference = "Stop"
$OpenClawDir = "$env:USERPROFILE\.openclaw"
$NodeExe = "C:\Program Files\nodejs\node.exe"
$TaskName = "OpenClaw-Gateway"
$SyncPort = 18790

Write-Host "╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host "║     方案三:云端网关 + 本地网关双部署                              ║" -ForegroundColor Cyan
Write-Host "║                  本地网关完整部署(含同步备份)                  ║"
Write-Host "╚════════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan

# 1. 检查 Tailscale
Write-Host "`n[1/7] 检查 Tailscale..." -ForegroundColor Yellow
$tsStatus = tailscale status 2>&1
if ($LASTEXITCODE -ne 0) {
    Write-Host "  Tailscale 未运行,正在启动..." -ForegroundColor Yellow
    tailscale up
    Start-Sleep -Seconds 5
}
$tsIP = (tailscale ip | Select-Object -First 1).Trim()
Write-Host "  ✓ Tailscale IP: $tsIP" -ForegroundColor Green

# 2. 检查 Node.js
Write-Host "`n[2/7] 检查 Node.js..." -ForegroundColor Yellow
if (!(Test-Path $NodeExe)) {
    Write-Host "  ✗ Node.js 未安装" -ForegroundColor Red
    exit 1
}
Write-Host "  ✓ Node.js: $(& $NodeExe -v)" -ForegroundColor Green

# 3. 安装 OpenClaw
Write-Host "`n[3/7] 安装 OpenClaw..." -ForegroundColor Yellow
npm install -g openclaw --registry=https://registry.npmmirror.com
if ($LASTEXITCODE -ne 0) {
    Write-Host "  ✗ 安装失败" -ForegroundColor Red
    exit 1
}
Write-Host "  ✓ OpenClaw: 已安装" -ForegroundColor Green

# 4. 配置网关
Write-Host "`n[4/7] 配置网关..." -ForegroundColor Yellow

if ($CloudIP -eq "") {
    Write-Host "  请输入云端网关 Tailscale IP:" -ForegroundColor Yellow
    $CloudIP = Read-Host "  Cloud IP"
}

New-Item -ItemType Directory -Force -Path $OpenClawDir | Out-Null

$config = @{
    gateway = @{
        port = 18789
        mode = "local"
        bind = "localhost"
    }
    sync = @{
        enabled = $true
        remoteUrl = "https://$($CloudIP):${SyncPort}"
        token = $(openssl rand -hex 20)
        direction = "bidirectional"
        interval = 300
    }
} | ConvertTo-Json -Depth 10

$config | Out-File -FilePath "$OpenClawDir\openclaw.json" -Encoding utf8 -Force
Write-Host "  ✓ 配置:$OpenClawDir\openclaw.json" -ForegroundColor Green
Write-Host "  同步配置:双向同步 (5 分钟间隔)" -ForegroundColor Green

# 5. 创建开机自启脚本
Write-Host "`n[5/7] 创建开机自启配置..." -ForegroundColor Yellow

$startScript = "$OpenClawDir\start-gateway.ps1"
@"
`$env:OPENCLAW_ALLOW_INSECURE_PRIVATE_WS = "1"
& "$NodeExe" "$OpenClawMjs" gateway run
"@ | Out-File -FilePath $startScript -Encoding utf8 -Force

# 创建计划任务
$argument = "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$startScript`""
schtasks /Delete /TN $TaskName /F 2>$null | Out-Null
schtasks /Create /TN $TaskName /TR "powershell.exe $argument" /SC ONLOGON /F 2>$null

if ($LASTEXITCODE -eq 0) {
    Write-Host "  ✓ 计划任务:$TaskName (开机自启)" -ForegroundColor Green
} else {
    Write-Host "  ⚠ 计划任务创建失败" -ForegroundColor Yellow
}

# 6. 启动网关
Write-Host "`n[6/7] 启动网关..." -ForegroundColor Yellow

$env:OPENCLAW_ALLOW_INSECURE_PRIVATE_WS = "1"
Start-Process $NodeExe -ArgumentList "$OpenClawMjs", "gateway", "run" -WindowStyle Normal

Start-Sleep -Seconds 5

# 7. 验证
Write-Host "`n[7/7] 验证网关..." -ForegroundColor Yellow
$portTest = Test-NetConnection -ComputerName localhost -Port 18789 -WarningAction SilentlyContinue -InformationLevel Quiet
if ($portTest) {
    Write-Host "  ✓ 网关:运行中 (localhost:18789)" -ForegroundColor Green

    Write-Host "`n╔════════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
    Write-Host "║                     ✓ 部署成功                                 ║" -ForegroundColor Green
    Write-Host "╚════════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan

    Write-Host "`n【访问信息】"
    Write-Host "  网关地址:ws://localhost:18789"
    Write-Host "  控制面板:http://localhost:18789/"
    Write-Host "  开机自启:$TaskName"

    Write-Host "`n【同步配置】"
    Write-Host "  云端网关:$CloudIP"
    Write-Host "  同步端口:${SyncPort}"
    Write-Host "  同步方向:双向"
    Write-Host "  同步间隔:300 秒"

    Write-Host "`n【下一步操作】"
    Write-Host "  1. 在云端运行 plan3-cloud-gateway.sh"
    Write-Host "  2. 检查状态:openclaw status"
    Write-Host "  3. 配置同步:openclaw sync config"
} else {
    Write-Host "  ✗ 网关启动失败" -ForegroundColor Red
    exit 1
}

云端网关完整部署(含同步备份)

#!/bin/bash
# plan3-cloud-gateway.sh - 方案三:云端网关完整部署(含同步备份)
set -e

echo "╔════════════════════════════════════════════════════════════════╗"
echo "║     方案三:云端网关 + 本地网关双部署                              ║"
echo "║                  云端网关完整部署(含同步备份)                  ║"
echo "╚════════════════════════════════════════════════════════════════╝"

# 系统检测
if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS=$ID
else
    echo "✗ 无法识别系统"
    exit 1
fi

if [ "$EUID" -ne 0 ]; then
    echo "✗ 请使用 root 权限运行"
    exit 1
fi

# 1. Tailscale
echo -e "\n[1/7] 配置 Tailscale..."
if ! command -v tailscale &> /dev/null; then
    curl -fsSL https://tailscale.com/install.sh | sh
fi
systemctl enable --now tailscaled 2>/dev/null || tailscaled &
sleep 3
TAILSCALE_IP=$(tailscale ip | head -1)
echo "  ✓ Tailscale: $TAILSCALE_IP"

# 2. 防火墙
echo -e "\n[2/7] 配置防火墙..."
if command -v ufw &> /dev/null && ufw status | grep -q "active"; then
    ufw allow 18789/tcp comment "OpenClaw Gateway"
    ufw allow 18790/tcp comment "OpenClaw Sync"
    echo "  ✓ UFW: 18789, 18790 已放行"
elif command -v firewall-cmd &> /dev/null && systemctl is-active --quiet firewalld; then
    firewall-cmd --permanent --add-port=18789/tcp
    firewall-cmd --permanent --add-port=18790/tcp
    firewall-cmd --reload
    echo "  ✓ Firewalld: 18789, 18790 已放行"
fi
echo "  ⚠ 云服务器安全组需手动放行 18789, 18790"

# 3. Node.js
echo -e "\n[3/7] 配置 Node.js..."
if ! command -v node &> /dev/null; then
    if [ "$OS" = "ubuntu" ] || [ "$OS" = "debian" ]; then
        curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
        apt-get install -y nodejs
    fi
fi
echo "  ✓ Node.js: $(node -v)"

# 4. OpenClaw
echo -e "\n[4/7] 安装 OpenClaw..."
npm install -g openclaw --registry=https://registry.npmmirror.com
echo "  ✓ OpenClaw: 已安装"

# 5. 配置
echo -e "\n[5/7] 配置网关(含同步)..."
mkdir -p ~/.openclaw

cat > ~/.openclaw/openclaw.json << 'EOF'
{
  "gateway": {
    "port": 18789,
    "mode": "local",
    "bind": "lan"
  },
  "sync": {
    "enabled": true,
    "port": 18790,
    "token": "auto-generated",
    "direction": "bidirectional",
    "interval": 300
  }
}
EOF

echo "  ✓ 配置文件:~/.openclaw/openclaw.json"

# 6. systemd 服务
echo -e "\n[6/7] 创建 systemd 服务..."

cat > /etc/systemd/system/openclaw-gateway.service << 'EOF'
[Unit]
Description=OpenClaw Gateway (with Sync)
After=network.target tailscaled.service
Wants=tailscaled.service

[Service]
Type=simple
User=root
WorkingDirectory=/root/.openclaw
ExecStart=/usr/bin/node /usr/lib/node_modules/openclaw/dist/index.js gateway --port 18789 --bind lan
Restart=always
Environment=NODE_ENV=production

LimitNOFILE=65535
Nice=-5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable openclaw-gateway
systemctl start openclaw-gateway

sleep 5

# 7. 验证
echo -e "\n[7/7] 验证服务..."

echo -e "\n╔════════════════════════════════════════════════════════════════╗"
if systemctl is-active --quiet openclaw-gateway; then
    echo "║                     ✓ 部署成功                                 ║"
    echo "╚════════════════════════════════════════════════════════════════╝"

    echo -e "\n【服务信息】"
    echo "  服务状态:$(systemctl is-active openclaw-gateway)"
    echo "  开机自启:$(systemctl is-enabled openclaw-gateway)"

    echo -e "\n【网络信息】"
    echo "  Tailscale IP: $TAILSCALE_IP"
    echo "  网关地址:ws://${TAILSCALE_IP}:18789"
    echo "  同步端口:${TAILSCALE_IP}:18790"

    echo -e "\n【端口监听】"
    ss -tlnp | grep -E "18789|18790" || true

    echo -e "\n【下一步操作】"
    echo "  1. 在本地运行 plan3-local-gateway.ps1"
    echo "  2. 配置双向同步:openclaw sync config"
    echo "  3. 查看同步状态:openclaw sync status"
else
    echo "║                     ✗ 部署失败                                 ║"
    echo "╚════════════════════════════════════════════════════════════════╝"
    journalctl -u openclaw-gateway --no-pager -n 20
    exit 1
fi

故障排查

通用诊断脚本

#!/bin/bash
# diagnostic.sh - OpenClaw 快速诊断

echo "╔════════════════════════════════════════════════════════════════╗"
echo "║              OpenClaw 诊断报告                                  ║"
echo "╚════════════════════════════════════════════════════════════════╝"

echo -e "\n【1. 系统信息】"
uname -a
grep PRETTY_NAME /etc/os-release 2>/dev/null || true

echo -e "\n【2. Tailscale 状态】"
tailscale status 2>&1 | head -10 || echo "Tailscale 未安装/未运行"

echo -e "\n【3. Node.js 版本】"
node -v 2>/dev/null || echo "Node.js 未安装"
npm -v 2>/dev/null || true

echo -e "\n【4. OpenClaw 状态】"
openclaw status 2>&1 | head -20 || echo "OpenClaw 未安装/无法运行"

echo -e "\n【5. 端口监听】"
ss -tlnp 2>/dev/null | grep -E "18789|18790" || netstat -tlnp 2>/dev/null | grep -E "18789|18790" || echo "无 OpenClaw 端口"

echo -e "\n【6. 防火墙状态】"
if command -v ufw &> /dev/null; then
    ufw status 2>&1 | head -10
fi
if command -v firewall-cmd &> /dev/null; then
    firewall-cmd --list-all 2>&1 | head -10
fi

echo -e "\n【7. 网关服务】"
systemctl status openclaw-gateway --no-pager -l 2>&1 | head -15 || echo "服务未安装"

echo -e "\n【8. 最近日志】"
journalctl -u openclaw-gateway --no-pager -n 10 2>&1 || echo "无日志"

常见问题速查

问题可能原因解决方案
端口不通防火墙阻挡ufw allow 18789/tcp
Tailscale 断开认证过期tailscale up --force
同步失败Token 不一致检查两边配置文件
服务无法启动端口占用ss -tlnp | grep 18789
Webhook 不响应安全组未放行云控制台添加入站规则

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

Huo15 Openclaw Enhance

火一五·克劳德·龙虾增强插件 v5.7.8 — 全面适配 openclaw 2026.4.24:peerDep ^4.24 + build/compat 同步到 4.24 + 14 处 api.on 全部去掉 as any 改成 typed hook(hookName 联合类型 + handler 自动推断 Pl...

Registry SourceRecently Updated
General

Content Trend Analyzer

Aggregates and analyzes content trends across platforms to identify hot topics, user intent, content gaps, and generates data-driven article outlines.

Registry SourceRecently Updated
General

Prompt Debugger

Debug prompts that produce unexpected AI outputs — diagnose failure modes, identify ambiguity and conflicting instructions, test variations, compare model re...

Registry SourceRecently Updated
General

Indie Maker News

独行者 Daily - 变现雷达。读对一条新闻,少走一年弯路。每天5分钟,给创业者装上商业雷达。聚焦一人公司、副业、创业变现资讯,智能分类,行动导向。用户下载即能用,无需本地部署!

Registry SourceRecently Updated