# ═══════════════════════════════════════════════ # 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001 # 📜 Copyright: 国作登字-2026-A-00037559 # ═══════════════════════════════════════════════ # 🌐 铸渊专线 · 部署与管理 # # 铸渊核心身体 · 锻心器官扩展 # 管理代理服务的安装、更新、订阅发送 # ═══════════════════════════════════════════════ name: '🌐 铸渊专线 · 部署' on: workflow_dispatch: inputs: action: description: '操作类型' required: true type: choice options: - install - update - status - restart - send-subscription - update-dashboard - setup-cn-relay default: 'status' email: description: '目标邮箱 (仅send-subscription时需要)' required: false type: string permissions: contents: write jobs: # ═══ §1 代理服务部署 ═══ deploy-proxy: name: '🌐 代理服务 · ${{ github.event.inputs.action }}' runs-on: ubuntu-latest if: >- github.event.inputs.action == 'install' || github.event.inputs.action == 'update' || github.event.inputs.action == 'status' || github.event.inputs.action == 'restart' steps: - name: '📥 检出代码' uses: actions/checkout@v4 - name: '🔑 配置SSH密钥' env: SSH_KEY: ${{ secrets.ZY_SERVER_KEY }} run: | mkdir -p ~/.ssh echo "$SSH_KEY" > ~/.ssh/id_deploy chmod 600 ~/.ssh/id_deploy # 验证密钥格式 if ! head -1 ~/.ssh/id_deploy | grep -q "BEGIN"; then echo "❌ SSH密钥格式异常" exit 1 fi ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null # 连接测试 ssh -i ~/.ssh/id_deploy \ -o StrictHostKeyChecking=accept-new \ -o BatchMode=yes \ -o ConnectTimeout=15 \ ${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} \ "echo '✅ SSH连接成功'" - name: '📦 上传代理服务代码' if: >- github.event.inputs.action == 'install' || github.event.inputs.action == 'update' run: | rsync -avz --delete \ -e "ssh -i ~/.ssh/id_deploy -o StrictHostKeyChecking=accept-new" \ server/proxy/ \ ${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }}:/opt/zhuyuan/proxy-deploy/ - name: '🚀 执行部署' run: | ssh -i ~/.ssh/id_deploy \ -o StrictHostKeyChecking=accept-new \ ${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} \ "cd /opt/zhuyuan/proxy-deploy && \ export ZY_SERVER_HOST='${{ secrets.ZY_SERVER_HOST }}' && \ export ZY_CN_RELAY_HOST='${{ secrets.ZY_CN_SERVER_HOST }}' && \ bash deploy-proxy.sh ${{ github.event.inputs.action }}" - name: '🧹 清理SSH密钥' if: always() run: rm -f ~/.ssh/id_deploy # ═══ §2 发送订阅链接 ═══ send-subscription: name: '📧 发送订阅链接' runs-on: ubuntu-latest if: github.event.inputs.action == 'send-subscription' steps: - name: '📥 检出代码' uses: actions/checkout@v4 - name: '🔑 配置SSH密钥' env: SSH_KEY: ${{ secrets.ZY_SERVER_KEY }} run: | mkdir -p ~/.ssh echo "$SSH_KEY" > ~/.ssh/id_deploy chmod 600 ~/.ssh/id_deploy ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null - name: '📧 发送订阅邮件' run: | TARGET_EMAIL="${{ github.event.inputs.email }}" if [ -z "$TARGET_EMAIL" ]; then TARGET_EMAIL="${{ secrets.ZY_SMTP_USER }}" fi echo "📧 发送订阅到: $TARGET_EMAIL" ssh -i ~/.ssh/id_deploy \ -o StrictHostKeyChecking=accept-new \ ${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} \ "cd /opt/zhuyuan/proxy && \ ZY_SMTP_USER='${{ secrets.ZY_SMTP_USER }}' \ ZY_SMTP_PASS='${{ secrets.ZY_SMTP_PASS }}' \ ZY_SERVER_HOST='${{ secrets.ZY_SERVER_HOST }}' \ node service/send-subscription.js send '$TARGET_EMAIL'" - name: '🧹 清理SSH密钥' if: always() run: rm -f ~/.ssh/id_deploy # ═══ §3 更新仪表盘 ═══ update-dashboard: name: '📊 更新仪表盘' runs-on: ubuntu-latest if: github.event.inputs.action == 'update-dashboard' steps: - name: '📥 检出代码' uses: actions/checkout@v4 with: token: ${{ secrets.ZY_GITHUB_PAT }} - name: '🔑 配置SSH密钥' env: SSH_KEY: ${{ secrets.ZY_SERVER_KEY }} run: | mkdir -p ~/.ssh echo "$SSH_KEY" > ~/.ssh/id_deploy chmod 600 ~/.ssh/id_deploy ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null - name: '📊 获取流量数据' run: | # 从服务器获取配额数据 ssh -i ~/.ssh/id_deploy \ -o StrictHostKeyChecking=accept-new \ ${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} \ "cat /opt/zhuyuan/proxy/data/quota-status.json 2>/dev/null || echo '{}'" \ > /tmp/quota-status.json cat /tmp/quota-status.json - name: '📝 更新README仪表盘' run: | node server/proxy/dashboard/update-dashboard.js --json /tmp/quota-status.json - name: '📤 提交更新' run: | git config user.name "铸渊 · ZhuYuan" git config user.email "zhuyuan-bot@guanghulab.com" if git diff --quiet README.md; then echo "仪表盘无变化" else git add README.md git commit -m "📊 铸渊专线仪表盘更新 · $(date -u +%Y-%m-%d)" git push echo "✅ 仪表盘已更新并推送" fi - name: '🧹 清理' if: always() run: rm -f ~/.ssh/id_deploy /tmp/quota-status.json # ═══ §4 CN中转配置 ═══ # 架构: GitHub Actions(美国) → SG(新加坡·跳板) → CN(广州·目标) # 原因: GitHub Actions无法直接SSH到中国服务器(网络路由/GFW) # 方案: 通过已连通的SG服务器作为SSH ProxyJump跳板 setup-cn-relay: name: '🇨🇳 CN中转配置' runs-on: ubuntu-latest if: github.event.inputs.action == 'setup-cn-relay' steps: - name: '📥 检出代码' 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 # SG跳板机密钥 echo "$SG_SSH_KEY" > ~/.ssh/id_sg chmod 600 ~/.ssh/id_sg # CN目标机密钥 echo "$CN_SSH_KEY" > ~/.ssh/id_cn chmod 600 ~/.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 密钥格式正确" # 扫描SG跳板机主机密钥 ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null # 配置SSH跳板 (ProxyJump: GitHub Actions → SG → CN) 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 # 测试跳板连接 echo "🔗 测试SSH跳板连接: GitHub Actions → SG → CN..." ssh cn-target "echo '✅ CN服务器SSH连接成功 (通过SG跳板)'" || { echo "" echo "❌ SSH跳板连接失败 · 排查清单:" echo " 1. 确认SG服务器SSH可达 (ZY_SERVER_KEY / ZY_SERVER_HOST)" echo " 2. 确认CN服务器从SG可达 (ZY_CN_SERVER_HOST: ${{ secrets.ZY_CN_SERVER_HOST }})" echo " 3. 确认CN服务器SSH密钥正确 (ZY_CN_SERVER_KEY)" echo " 4. 确认CN服务器SSH端口 (ZY_CN_SSH_PORT, 当前: ${CN_PORT})" echo " 5. 腾讯云防火墙 → 确认端口 ${CN_PORT} 对SG服务器IP开放" exit 1 } - name: '📦 上传CN中转脚本' run: | scp server/proxy/setup/setup-cn-relay.sh \ cn-target:/tmp/setup-cn-relay.sh - name: '🇨🇳 执行CN中转配置' run: | ssh cn-target \ "chmod +x /tmp/setup-cn-relay.sh && \ export ZY_SG_SERVER_HOST='${{ secrets.ZY_SERVER_HOST }}' && \ sudo -E bash /tmp/setup-cn-relay.sh" - name: '💚 CN中转验证' run: | # 通过SG跳板验证CN中转服务状态 echo "🔍 通过SG跳板验证CN中转..." ssh cn-target " echo '§1 Nginx状态:' systemctl is-active nginx && echo ' ✅ Nginx运行中' || echo ' ❌ Nginx未运行' echo '§2 中转端口 2053:' ss -tlnp | grep -q ':2053 ' && echo ' ✅ 端口2053监听中' || echo ' ⚠️ 端口2053未监听' echo '§3 HTTP健康检查:' curl -sf http://127.0.0.1/health 2>/dev/null && echo ' ✅ HTTP健康检查正常' || echo ' ⚠️ HTTP健康检查未响应' " # 从外部验证CN HTTP (GitHub Actions可以通过HTTP访问中国服务器) CN_HOST="${{ secrets.ZY_CN_SERVER_HOST }}" HTTP_CODE=$(curl -sf -o /dev/null -w "%{http_code}" "http://${CN_HOST}/health" 2>/dev/null || echo "000") if [ "$HTTP_CODE" = "200" ]; then echo "✅ CN HTTP外部健康检查: 正常" else echo "⚠️ CN HTTP外部检查: 状态码 $HTTP_CODE (可能需要等待或在防火墙开放80端口)" fi - name: '🧹 清理SSH密钥' if: always() run: rm -f ~/.ssh/id_sg ~/.ssh/id_cn ~/.ssh/config