告别异地登录告警!用 GitHub Self-Hosted Runner 打造“零打扰”全栈自动化部署

前言

作为一个全栈开发者,最爽的时刻莫过于 git push 之后,端起咖啡,看着代码自动跑通测试、构建镜像、并在服务器上平滑更新。 但在实现这个目标的过程中,我经历了从"手动搬砖"到"SSH 自动登录",再到最终"Self-Hosted Runner"的三个阶段。特别是解决了云服务器频繁误报"异地登录安全告警"的痛点。

本文将以我的个人全栈项目 Fronty(React + Python FastAPI)为例,分享这套自动化部署体系的搭建过程。

🚧 第一阶段:痛苦的手动挡

最初,我的部署流程是这样的:

  1. 本地代码写完, ·git pull·
  2. 打开终端, SSH连上服务器
  3. cd /opt/fronty->git pull
  4. npm run build->docker build->docker rm->docker run...

后端项目也要重复一遍。这简直是体力和耐心的双重折磨,而且一旦命令输错,服务直接挂掉。

🚧 第二阶段:GitHub Actions + SSH (报警器响不停)

为了偷懒,我配置了 GitHub Actions,使用 appleboy/ssh-action 插件。原理是把服务器的 SSH 私钥交给 GitHub,每次 Push 代码,GitHub 的服务器(位于美国 Azure 机房)就会远程 SSH 连入我的云服务器执行脚本。

部署是自动化了,但烦恼来了: 每次部署,云服务器的安全系统都会疯狂报警:

[云服务器] 异地登录告警:检测到您的服务器在 美国 有 root 用户登录...

虽然我知道这是 GitHub 干的,但看着红色的告警心里总是不踏实。而且为了让 GitHub 能连进来,我不得不开放 SSH 端口,这始终是个安全隐患。

🚀 第三阶段:终极方案:GitHub Self-Hosted Runner

为了彻底解决安全告警和网络连接问题,我决定采用 Self-Hosted Runner 方案。

原理区别:
  • SSH模式: GitHub 主动推(Push)指令给服务器。需要开门(SSH端口),会有外部 IP 连入。
  • Runner模式: 在服务器装一个小助手(Runner),它主动去 GitHub 拉(Pull)任务。不需要开门,没有外部 IP 连入,完全走内部通道。
🛠️ 实施步骤

我的项目结构是前后端分离,两个独立的 GitHub 仓库:frontendProjectbackendProject

1. 服务器环境准备

由于我习惯使用 root 账户管理服务器(个人项目的特权),而 GitHub Runner 默认不建议 root 运行,这里有个关键坑需要避开。

2. 安装 Runner (遇到的网络坑)

在 GitHub 仓库 -> Settings -> Actions -> Runners -> New self-hosted runner 页面,官方提供了下载命令。

坑点 :服务器在国内,直接 curl 下载 GitHub 的 release 包经常超时或连接重置。

解决:采用"物理搬运法"。

  1. 在本地电脑(网络环境好)下载好 .tar.gz 包。
  2. 通过云服务器的文件上传功能,直接拖拽到服务器 /opt/runner-projectName 目录。
  3. 解压:tar xzf ./actions-runner-linux-x64-xxxx.tar.gz
3. 配置与注册 (遇到的权限坑)

在配置时,如果直接运行 ./config.sh,会报错不让用 root。必须加上环境变量:

bash 复制代码
# 允许 Root 用户运行 Runner
export RUNNER_ALLOW_RUNASROOT=1

# 执行配置 (URL 和 Token 从 GitHub 页面获取)
./config.sh --url https://github.com/yourname/projectName --token XXXXXX

配置过程中,我给后端的 Runner 起名为 runner-backendProjectName,前端的起名为 runner-frontendProjectName,分目录部署,互不干扰。

最后安装为系统服务,确保开机自启:

bash 复制代码
./svc.sh install
./svc.sh start

看到 Active: active (running) 的那一刻,感觉稳了。

4. 编写 Workflow 脚本

既然 Runner 已经在本地了,脚本里就不需要 SSH 连接了,直接写 Shell 命令即可。

后端部署脚本 .github/workflows/deploy.yml:

yaml 复制代码
name: Deploy Backend

on:
  push:
    # branch name
    branches: [ "master" ]

jobs:
  deploy:
    # [关键] 指定使用自己的服务器
    runs-on: self-hosted

    steps:
      - name: Deploy on Local Server
        run: |
          echo "🚀 Runner 接单,开始部署后端..."
          
          # 直接进入服务器目录操作
          cd /opt/projectName || exit
          
          # 拉取最新代码
          git fetch --all
          git reset --hard origin/master
          
          # 构建 Docker 镜像
          DOCKER_BUILDKIT=1 docker build -t projectName-app:latest .
          
          # 重启容器
          docker rm -f projectName-app || true
          docker run -d \
            --name projectName-app \
            -p 127.0.0.1:projectPort:projectPort \
            --restart unless-stopped \
            -e PYTHONPATH=/app \
            book-app:latest
          
          # 清理垃圾
          docker image prune -f
          echo "✅ 后端部署完成!"

前端的脚本逻辑类似,只是加上了 npm run build 和 Nginx 容器的启动(使用 --network host 模式配合宿主机 Nginx 反代)。

🎉 最终效果

现在,我在本地 VSCode 改完代码:

  1. git push
  2. GitHub Actions 页面立即显示任务被 runner-projectName 认领。
  3. 服务器悄悄地在后台完成了构建和重启。
  4. 云服务器没有任何告警! 因为全程没有外部 SSH 连接。

💡 总结与收获

  1. 安全感: 关闭了 SSH 密码登录,甚至可以限制 SSH 仅限内网访问,服务器固若金汤。
  2. 速度快: 因为 Runner 就在服务器本机,git pulldocker build 都是利用服务器带宽和 CPU,省去了 SSH 远程传输的开销。
  3. 灵活性: 想怎么改脚本就怎么改,拥有完全的 Root 权限控制。

如果你也是个人开发者,正在忍受云服务商的异地登录告警,强烈建议尝试 Self-Hosted Runner,这绝对是提升幸福感的最佳实践。

相关推荐
行百里er1 小时前
WebSocket 在 Spring Boot 中的实战解析:实时通信的技术利器
spring boot·后端·websocket
再学一点就睡2 小时前
前端网络实战手册:15个高频工作场景全解析
前端·网络协议
C_心欲无痕3 小时前
有限状态机在前端中的应用
前端·状态模式
C_心欲无痕3 小时前
前端基于 IntersectionObserver 更流畅的懒加载实现
前端
candyTong3 小时前
深入解析:AI 智能体(Agent)是如何解决问题的?
前端·agent·ai编程
柳杉3 小时前
建议收藏 | 2026年AI工具封神榜:从Sora到混元3D,生产力彻底爆发
前端·人工智能·后端
weixin_462446233 小时前
使用 Puppeteer 设置 Cookies 并实现自动化分页操作:前端实战教程
运维·前端·自动化
仙俊红3 小时前
spring的IoC(控制反转)面试题
java·后端·spring
CheungChunChiu3 小时前
Linux 内核动态打印机制详解
android·linux·服务器·前端·ubuntu
小楼v3 小时前
说说常见的限流算法及如何使用Redisson实现多机限流
java·后端·redisson·限流算法