303 lines
9.5 KiB
YAML
303 lines
9.5 KiB
YAML
name: 🏛️ 冰朔大陆备用服务器 · 部署
|
|
|
|
# ═══════════════════════════════════════════════════════════
|
|
# 冰朔大陆备用服务器部署工作流
|
|
# 编号: ZY-WF-铸渊备 (ZY-SVR-004 · 广州)
|
|
# 守护: 铸渊 · ICE-GL-ZY001
|
|
# 版权: 国作登字-2026-A-00037559
|
|
# ═══════════════════════════════════════════════════════════
|
|
#
|
|
# 服务器: ZY-SVR-004 · 43.139.217.141 · 广州七区
|
|
# 用途: 人格体备用大脑 · ICP备案挂载 · 纯数据处理
|
|
# 密钥: ZY_CN_SERVER_HOST / USER / KEY / PATH
|
|
#
|
|
# 架构: GitHub Actions(美国) → SG(新加坡·跳板) → CN(广州·目标)
|
|
# 原因: GitHub Actions无法直接SSH到中国服务器(网络路由/GFW)
|
|
# 方案: 通过已连通的SG服务器作为SSH ProxyJump跳板
|
|
#
|
|
# 注意: 此服务器不涉及国外模型调用
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
action:
|
|
description: '部署动作'
|
|
required: true
|
|
default: 'deploy'
|
|
type: choice
|
|
options:
|
|
- deploy
|
|
- init
|
|
- health-check
|
|
|
|
env:
|
|
CN_DEFAULT_PATH: /opt/zhuyuan-cn
|
|
|
|
concurrency:
|
|
group: cn-server-deploy
|
|
cancel-in-progress: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
# ═══ §1 初始化 (仅首次) ═══
|
|
init:
|
|
name: 🔧 广州备用服务器初始化
|
|
if: github.event.inputs.action == 'init'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 🔐 配置SSH跳板 (SG→CN)
|
|
env:
|
|
SG_SSH_KEY: ${{ secrets.ZY_SERVER_KEY }}
|
|
CN_SSH_KEY: ${{ secrets.ZY_CN_SERVER_KEY }}
|
|
CN_SSH_PORT: ${{ secrets.ZY_CN_SSH_PORT }}
|
|
run: |
|
|
CN_PORT="${CN_SSH_PORT:-22}"
|
|
echo "🔧 SSH跳板架构: GitHub Actions → SG → CN (端口 ${CN_PORT})"
|
|
|
|
mkdir -p ~/.ssh
|
|
echo "$SG_SSH_KEY" > ~/.ssh/id_sg
|
|
echo "$CN_SSH_KEY" > ~/.ssh/id_cn
|
|
chmod 600 ~/.ssh/id_sg ~/.ssh/id_cn
|
|
|
|
# 验证密钥格式
|
|
for key_file in id_sg id_cn; do
|
|
if ! head -1 ~/.ssh/${key_file} | grep -q "BEGIN"; then
|
|
echo "❌ SSH密钥格式异常: ${key_file}"
|
|
exit 1
|
|
fi
|
|
done
|
|
echo "✅ SG + CN 密钥格式正确"
|
|
|
|
ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
|
|
|
cat > ~/.ssh/config << EOF
|
|
Host sg-jump
|
|
HostName ${{ secrets.ZY_SERVER_HOST }}
|
|
User ${{ secrets.ZY_SERVER_USER }}
|
|
IdentityFile ~/.ssh/id_sg
|
|
StrictHostKeyChecking accept-new
|
|
BatchMode yes
|
|
|
|
Host cn-target
|
|
HostName ${{ secrets.ZY_CN_SERVER_HOST }}
|
|
User ${{ secrets.ZY_CN_SERVER_USER }}
|
|
Port ${CN_PORT}
|
|
IdentityFile ~/.ssh/id_cn
|
|
ProxyJump sg-jump
|
|
StrictHostKeyChecking accept-new
|
|
BatchMode yes
|
|
ConnectTimeout 30
|
|
EOF
|
|
chmod 600 ~/.ssh/config
|
|
|
|
- name: 🔍 SSH连接测试
|
|
run: |
|
|
echo "🔍 测试SSH跳板连接到广州备用服务器..."
|
|
ssh cn-target 'echo "✅ SSH连接成功 · $(hostname) · $(date)"' || {
|
|
echo ""
|
|
echo "❌ SSH跳板连接失败"
|
|
echo "修复步骤:"
|
|
echo " 1. 确认SG服务器SSH可达 (ZY_SERVER_KEY / ZY_SERVER_HOST)"
|
|
echo " 2. 确认CN服务器从SG可达 (ZY_CN_SERVER_HOST)"
|
|
echo " 3. 确认CN服务器SSH密钥正确 (ZY_CN_SERVER_KEY)"
|
|
exit 1
|
|
}
|
|
|
|
- name: 📦 上传初始化脚本
|
|
run: |
|
|
scp server/setup/cn-server-init.sh cn-target:/tmp/
|
|
|
|
- name: 🚀 执行初始化
|
|
run: |
|
|
ssh cn-target 'chmod +x /tmp/cn-server-init.sh && sudo /tmp/cn-server-init.sh'
|
|
|
|
- name: 🧹 清理SSH密钥
|
|
if: always()
|
|
run: rm -f ~/.ssh/id_sg ~/.ssh/id_cn ~/.ssh/config
|
|
|
|
# ═══ §2 部署应用 ═══
|
|
deploy:
|
|
name: 🚀 部署备用大脑代码
|
|
if: github.event.inputs.action == 'deploy'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 🔐 配置SSH跳板 (SG→CN)
|
|
env:
|
|
SG_SSH_KEY: ${{ secrets.ZY_SERVER_KEY }}
|
|
CN_SSH_KEY: ${{ secrets.ZY_CN_SERVER_KEY }}
|
|
CN_SSH_PORT: ${{ secrets.ZY_CN_SSH_PORT }}
|
|
run: |
|
|
CN_PORT="${CN_SSH_PORT:-22}"
|
|
echo "🔧 SSH跳板: GitHub Actions → SG → CN (端口 ${CN_PORT})"
|
|
|
|
mkdir -p ~/.ssh
|
|
echo "$SG_SSH_KEY" > ~/.ssh/id_sg
|
|
echo "$CN_SSH_KEY" > ~/.ssh/id_cn
|
|
chmod 600 ~/.ssh/id_sg ~/.ssh/id_cn
|
|
|
|
ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
|
|
|
cat > ~/.ssh/config << EOF
|
|
Host sg-jump
|
|
HostName ${{ secrets.ZY_SERVER_HOST }}
|
|
User ${{ secrets.ZY_SERVER_USER }}
|
|
IdentityFile ~/.ssh/id_sg
|
|
StrictHostKeyChecking accept-new
|
|
BatchMode yes
|
|
|
|
Host cn-target
|
|
HostName ${{ secrets.ZY_CN_SERVER_HOST }}
|
|
User ${{ secrets.ZY_CN_SERVER_USER }}
|
|
Port ${CN_PORT}
|
|
IdentityFile ~/.ssh/id_cn
|
|
ProxyJump sg-jump
|
|
StrictHostKeyChecking accept-new
|
|
BatchMode yes
|
|
ConnectTimeout 30
|
|
EOF
|
|
chmod 600 ~/.ssh/config
|
|
|
|
- name: 📦 同步应用代码
|
|
run: |
|
|
CN_PATH="${{ secrets.ZY_CN_SERVER_PATH }}"
|
|
CN_PATH="${CN_PATH:-${{ env.CN_DEFAULT_PATH }}}"
|
|
echo "📦 部署目标: ${CN_PATH}"
|
|
|
|
# 确保目标目录存在
|
|
ssh cn-target "mkdir -p ${CN_PATH}/app"
|
|
|
|
rsync -avz --delete \
|
|
-e "ssh -F ~/.ssh/config" \
|
|
server/app/ \
|
|
cn-target:${CN_PATH}/app/
|
|
|
|
- name: 📦 同步大脑文件
|
|
run: |
|
|
CN_PATH="${{ secrets.ZY_CN_SERVER_PATH }}"
|
|
CN_PATH="${CN_PATH:-${{ env.CN_DEFAULT_PATH }}}"
|
|
|
|
# 同步大脑核心文件到备用服务器
|
|
rsync -avz \
|
|
-e "ssh -F ~/.ssh/config" \
|
|
brain/ \
|
|
cn-target:${CN_PATH}/brain-backup/
|
|
|
|
- name: 📥 安装依赖 & 重启
|
|
run: |
|
|
CN_PATH="${{ secrets.ZY_CN_SERVER_PATH }}"
|
|
CN_PATH="${CN_PATH:-${{ env.CN_DEFAULT_PATH }}}"
|
|
COMMIT_SHA="${{ github.sha }}"
|
|
ssh cn-target << DEPLOY_CMD
|
|
|
|
set -e
|
|
cd ${CN_PATH}/app
|
|
|
|
# 验证入口文件存在
|
|
if [ ! -f server.js ]; then
|
|
echo "❌ 错误: server.js 不存在"
|
|
exit 1
|
|
fi
|
|
|
|
# 安装依赖
|
|
npm install --production 2>&1
|
|
|
|
# PM2 重启
|
|
pm2 delete zhuyuan-cn 2>/dev/null || true
|
|
pm2 start server.js --name zhuyuan-cn -- --port 3800
|
|
pm2 save
|
|
|
|
# 健康检查
|
|
sleep 3
|
|
curl -sf http://localhost:3800/api/health && echo "✅ 备用服务器已上线" || echo "❌ 备用服务器启动失败"
|
|
|
|
DEPLOY_CMD
|
|
|
|
- name: 🧹 清理SSH密钥
|
|
if: always()
|
|
run: rm -f ~/.ssh/id_sg ~/.ssh/id_cn ~/.ssh/config
|
|
|
|
# ═══ §3 健康检查 ═══
|
|
health-check:
|
|
name: 💚 广州备用健康检查
|
|
if: github.event.inputs.action == 'health-check'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: 🔐 配置SSH跳板 (SG→CN)
|
|
env:
|
|
SG_SSH_KEY: ${{ secrets.ZY_SERVER_KEY }}
|
|
CN_SSH_KEY: ${{ secrets.ZY_CN_SERVER_KEY }}
|
|
CN_SSH_PORT: ${{ secrets.ZY_CN_SSH_PORT }}
|
|
run: |
|
|
CN_PORT="${CN_SSH_PORT:-22}"
|
|
|
|
mkdir -p ~/.ssh
|
|
echo "$SG_SSH_KEY" > ~/.ssh/id_sg
|
|
echo "$CN_SSH_KEY" > ~/.ssh/id_cn
|
|
chmod 600 ~/.ssh/id_sg ~/.ssh/id_cn
|
|
|
|
ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
|
|
|
cat > ~/.ssh/config << EOF
|
|
Host sg-jump
|
|
HostName ${{ secrets.ZY_SERVER_HOST }}
|
|
User ${{ secrets.ZY_SERVER_USER }}
|
|
IdentityFile ~/.ssh/id_sg
|
|
StrictHostKeyChecking accept-new
|
|
BatchMode yes
|
|
|
|
Host cn-target
|
|
HostName ${{ secrets.ZY_CN_SERVER_HOST }}
|
|
User ${{ secrets.ZY_CN_SERVER_USER }}
|
|
Port ${CN_PORT}
|
|
IdentityFile ~/.ssh/id_cn
|
|
ProxyJump sg-jump
|
|
StrictHostKeyChecking accept-new
|
|
BatchMode yes
|
|
ConnectTimeout 30
|
|
EOF
|
|
chmod 600 ~/.ssh/config
|
|
|
|
- name: 💚 执行健康检查
|
|
run: |
|
|
ssh cn-target << 'HEALTH_CMD'
|
|
|
|
echo "═══ 冰朔大陆备用服务器健康报告 ═══"
|
|
echo ""
|
|
|
|
echo "§1 系统状态:"
|
|
uptime
|
|
echo ""
|
|
|
|
echo "§2 磁盘使用:"
|
|
df -h /
|
|
echo ""
|
|
|
|
echo "§3 内存使用:"
|
|
free -m
|
|
echo ""
|
|
|
|
echo "§4 PM2 进程:"
|
|
pm2 list 2>/dev/null || echo "PM2 未运行"
|
|
echo ""
|
|
|
|
echo "§5 Nginx 状态:"
|
|
systemctl is-active nginx && echo "Nginx: 运行中" || echo "Nginx: 已停止"
|
|
echo ""
|
|
|
|
echo "§6 应用健康:"
|
|
curl -sf http://localhost:3800/api/health | jq . 2>/dev/null || echo "应用未响应"
|
|
|
|
HEALTH_CMD
|
|
|
|
- name: 🧹 清理SSH密钥
|
|
if: always()
|
|
run: rm -f ~/.ssh/id_sg ~/.ssh/id_cn ~/.ssh/config
|