个人站点也能 GitOps:一个私有仓库加定时拉取,做出带回滚的自动部署

个人站点 GitOps 自动部署流程示意图

个人站点、小工具、定时任务,改一次就要登录服务器手动上传、重启,时间长了很容易出错:忘了备份、传错文件、改完不知道有没有生效。我把自己的博客、工作台和日报任务全部改成了"提交代码即上线",整套方案只用了一个私有仓库、一个定时脚本,没有装任何 CI 平台。这篇记录思路和踩过的坑。

为什么选"服务器主动拉取"

常见做法是在 CI 里通过 SSH 把代码推到服务器。这要求服务器对外开放登录,并且把私钥交给 CI 平台保管。个人项目没必要背这个风险,所以我反过来:服务器自己定时去仓库看有没有新提交,有就拉下来部署。

  • 不需要额外开放入口:服务器只做出站访问,不接受任何来自部署系统的连接。
  • 权限最小:服务器上只放一把只读的部署密钥,最坏情况也改不了仓库。
  • 简单:一个 cron 条目加一个 shell 脚本,出问题时直接读日志就能定位。

整体流程

  1. 本地修改后提交并推送到私有仓库的 main 分支。
  2. 服务器每 5 分钟运行一次拉取脚本,对比远端和本地的提交号,没有变化就直接退出。
  3. 有变化时,先根据改动的目录判断影响了哪个组件(网页、后端接口、定时任务等),只部署受影响的部分。
  4. 部署前备份旧文件,部署后做一次健康检查。
  5. 检查失败就自动用备份回滚,并把结果写进一个状态文件。

拉取脚本的核心只有几行:

#!/bin/bash
set -euo pipefail
cd /opt/ops
git fetch --quiet origin main
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse origin/main)
[ "$LOCAL" = "$REMOTE" ] && exit 0   # 没有新提交,什么都不做

git reset --hard origin/main
./deploy/deploy.sh "$LOCAL" "$REMOTE"   # 按改动范围部署,失败自动回滚

三个让它可靠的细节

1. 部署失败必须能自动回到上一个好版本。没有回滚的自动部署比手动部署更危险,因为出错时你可能根本不在电脑前。每次部署前把旧文件复制一份,健康检查不通过就原样还原,整个过程不需要人参与。

2. 密码和令牌永远不进仓库。仓库里只放代码和配置模板,真正的密钥留在服务器的环境文件里,并且在忽略列表中排除。这样即使仓库被误公开,也不会泄露任何凭据。

3. 让部署结果看得见。每次部署都把提交号、时间和成功与否写进一个小文件,我的工作台直接读取它,在"站点运维"卡片里显示"自动部署 + 提交号 + 时间"。一眼就能确认线上跑的是哪个版本。

代价和取舍

  • 最多有 5 分钟延迟:对个人站点完全可以接受,需要更快可以缩短间隔,或手动触发一次脚本。
  • 服务器上的手工改动会被覆盖:因为用了强制对齐远端,所有修改都必须走仓库。这是优点也是纪律,能避免"线上和代码不一致"。
  • 不适合复杂发布:需要灰度、数据库迁移编排的项目,还是应该用更完整的发布系统。

小结

对个人项目来说,"主动拉取 + 局部部署 + 自动回滚 + 结果可见"这四点已经覆盖了大部分需求,实现成本却很低。改完代码推送,然后就可以去做别的事,几分钟后线上自然更新,出问题也会自己退回去。这种"放心提交"的感觉,是它最大的价值。


上一篇
下一篇