问题的起源
用 Hexo 博客,源代码放在 Gitee,每次发完文章都要手动跑 npm run deploy 才能上线。后来进入了Mac生态,有多个电脑都要维护这个博客,"push 代码"和"deploy 代码"的两步就特别烦。容易忘,也容易出错。
我就想:为什么不能 push 到 Gitee 就自动部署了?
于是折腾了一套 Gitee WebHook + Node.js 服务 + systemd 的自动化系统。前两天在云端完整验证了一遍,现在把整个过程和坑都记录下来。以后参考用。
整体架构:四个关键组件
先理解这套系统的工作流程:
1 | 本地编辑 markdown |
四个关键组件:
- Gitee 仓库 - 事件源(push 时触发 WebHook)
- 云端 WebHook 服务 - 事件处理器(接收通知,执行部署)
- systemd - 服务管理(保证 WebHook 服务持久运行)
- 裸仓库 + post-receive hook - 可选的备用方案(冗余保险)
第一个坑:npm 版本冲突(最烦人)
用的腾讯云服务器,系统自带 Node.js 8.10.0,npm 3.5.2。年代太久。
在云端跑 npm install 时:
1 | npm ERR! Linux 4.15.0-54-generic |
这错误特别烦。npm 3.5.2 自身有 bug,没法装新包。而且新的 npm 要 Node.js 20+ 才行。系统自己的 npm 也升级不了。
原因:系统 Node.js 太老,新的包管理工具没法用。
怎么办:用 NVM(Node Version Manager)装新版本 Node.js。别改系统的。
1 | # 用国内镜像安装 NVM(腾讯云会很慢,用镜像快很多) |
验证成功,问题搞定。
教训:服务器系统包太老别费劲升级,直接 NVM 装新版本。这样也不会把系统其他依赖搞坏。
第二个坑:systemd 中的 PATH 环境变量问题
WebHook 脚本写好,想用 systemd 开机自启。配置很简单。
启动后,看日志:
1 | ERROR: npm is known not to run on Node.js v8.10.0 |
奇怪啊,我明明装了 Node.js 16,怎么还在用 8.10.0?
原因:systemd 环境隔离得特别彻底。执行命令时的 PATH 变量不包含 NVM 的 node 路径。所以 npm 找到的还是系统旧版本(/usr/bin/npm)。
怎么办:在 WebHook 脚本中,显式设置 PATH 环境变量。
先创建一个启动脚本 /home/ubuntu/start-webhook.sh:
1 |
|
然后在 webhook.js 中,明确指定环境变量:
1 | const env = Object.assign({}, process.env, { |
这样 npm 就用 NVM 的新版本了。
教训:systemd 隔离环境特别彻底,一定要检查 PATH。不止 npm,其他命令也容易掉坑。
完整的配置步骤
下面说怎么从零开始搭。分成 4 步:
步骤 1:云端准备源代码库
假设云端服务器是 [某个域名],用户名是 ubuntu。
1 | ssh ubuntu@[某个域名] |
步骤 2:编写 WebHook 接收服务
创建 /home/ubuntu/webhook.js:
1 | const http = require('http'); |
注意关键部分:环境变量的设置。这是解决第二个坑的核心。
步骤 3:配置 systemd 自启动
创建 /etc/systemd/system/blog-webhook.service:
1 | [Unit] |
然后启用和启动服务:
1 | sudo systemctl daemon-reload |
步骤 4:在 Gitee 配置 WebHook
进入你的 Gitee 仓库 → 管理 → WebHooks → 新增 WebHook
填写:
- URL:
http://[某个域名]:8912/webhook - 事件: 选择 “Push” 事件
保存后,Gitee 就会在你 push 时自动发送通知给你的服务器。
测试流程
配置完了,验证一下是否真的工作:
- 本地修改一个文章文件
- 提交并 push:
git push origin master - 登录云端,查看 webhook 日志:
journalctl -u blog-webhook -f
看到这样的日志说明成功了:
1 | [2025-11-08T13:30:57.210Z] WebHook received from Gitee |
坑的总结和避免方法
我遇到的两个主要坑:
| 坑 | 原因 | 避免方法 |
|---|---|---|
| npm 版本冲突 | 系统 Node.js 太老 | 用 NVM 安装新版本,不要升级系统包 |
| systemd PATH 问题 | 环境隔离,找不到新的 npm | 显式设置 PATH 环境变量,或用完整的二进制路径 |
这两个坑其实指向一个核心问题:开发环境和运行环境要一致。
本地用新版 Node.js,服务器也得用新版。不能因为"系统默认有"就将就着用,要主动管理版本。
后续维护
配置完了,日常用特别简单:
- 本地编辑文章,push 到 Gitee
- 服务器自动部署(5-10 秒)
- 刷新网站,新内容上线了
再也不用想起来还要手动 deploy。
唯一要注意的:定期看日志,确保部署没出错。
1 | # 查看最近 50 条日志 |
为什么选这个方案,不选 CI/CD?
为什么没选 Gitee Actions、GitHub Actions?
主要原因:
- 完全自主:不依赖第三方平台(平台故障就完蛋)
- 简单直接:就一个 Node.js 脚本,好理解好维护
- 成本低:没有额外的配额限制
- 好扩展:以后可以加签名验证、多分支部署等
当然,要是用 GitHub,GitHub Actions 更方便。但 Gitee 这个方案够用。
总结
从"手动 deploy"到"push 自动部署",只是多了几个组件,但减少了日常维护的脑子消耗。
更重要的是,过程中理解了一些运维的关键概念:
- 版本管理(NVM 的用处)
- 环境隔离(systemd 的设计)
- 事件驱动(WebHook 思路)
- 持久化服务(systemd 的自启和自恢复)
这些概念在其他运维场景也能用。
如果你也想搭类似系统,按上面步骤逐步来,碰到坑时对照我的解决方案。应该能少走弯路。