飞书下线旧 webhook 机器人后,本文已同步更新至 open-api 方案。
由于近期网站速度不稳定,只好再把博客解析改到服务器上。博客源代码托管在 GitHub 上,每次更新的流程如下:
- 提交源码到私有仓库
- 私有仓库执行 Action
2.1. 执行 hexo g 生成静态文件
2.2. 部署到 xaoxuu.github.io 公开仓库
2.3. 触发服务器同步拉取 xaoxuu.github.io 更新 本文内容 - Vercel/Netlify/Cloudflare等平台同步部署(基于 xaoxuu.github.io 静态内容)
2.3 曾经是 rsync 同步到服务器、也曾是同步到 oss,但前者配置复杂,这次我已经忘了怎么操作了;后者用了几天感觉同步速度极慢。
rsync 方案: 服务器问题记录
整理思路
全自动化部署,当然要避免手动 pull,所以我希望实现:
- 每次推送后,GitHub Action 自动触发 Webhook
- Webhook 服务运行在服务器上,收到请求后拉取仓库最新代码
- 同时,通过飞书发送部署成功、失败的通知
技术栈选型
| 模块 | 工具 |
|---|---|
| Web 服务 | Node.js + Express |
| 后台守护 | pm2 |
| 通知方式 | 飞书开放平台自建应用(机器人服务) |
飞书开放平台这套 open-api 我也比较熟,用来发部署通知足够稳定,而且可控性更强。
网站根目录下关联 GitHub 仓库
以下是我的配置,可以根据实际情况修改为你自己的:
- 我的网站目录是:
/opt/1panel/www/sites/xaoxuu.com/index- 要同步的 GitHub 静态文件仓库是:
https://github.com/xaoxuu/xaoxuu.github.io
执行前确保没有重要数据
cd /opt/1panel/www/sites/xaoxuu.com |
忽略 .git
我用的 1panel,在网站的【配置文件】中的 server 块中增加以下设置:
location ~ /\.git { |
效果类似于:
server { |
创建两个 js 文件
我放在了网站项目目录下,放在别处也可以,但注意不要放到网站根目录下,也就是 git clone 的地方,否则会被覆盖掉。
index/ <- 网站根目录,也就是 git 仓库 |
ecosystem.config.js 内容
module.exports = { |
SYNC_TOKEN 就是随便创建一串字符串,粘贴到 GitHub Secrets 中,简单防刷保护,不需要的话,下文的
SYNC_TOKEN部分删掉即可。这里的
FEISHU_APP_SECRET/SYNC_TOKEN都属于敏感信息,不要提交到仓库,也不要在日志里明文输出。
webhook.js 内容
监听本地 2333 端口的 Webhook 服务如下:
const express = require('express'); |
反代到监听服务
- 增加一个反代配置,反代路径随便设置,例如:
/your-sync-path - 后端代理地址填写:(http)
127.0.0.1:2333/sync - (可选)如果你想用本文的事件回调来获取 open_id 或调试飞书事件,再加一个反代,例如:
/your-feishu-events-path→ (http)127.0.0.1:2333/feishu/events
创建并执行 pm2 任务
如果没有安装依赖,需要先安装一下:
安装 Node.js
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - |
安装 pm2(全局)
npm install -g pm2 |
启动 webhook 服务并设置开机自启
pm2 start ecosystem.config.js |
检查一下:
pm2 ls |
配置飞书通知
本文的通知方式是「飞书开放平台自建应用 + 机器人」,通过 open-api 给指定用户发送“卡片消息”(私聊)。
创建自建应用并启用机器人
- 打开飞书开放平台,创建一个企业自建应用。
- 在应用能力里启用「机器人」。
- 发布版本,并确保应用对你自己可用(通常需要在企业内安装/开通可用范围,否则机器人无法给你发消息)。
配置权限
在应用的权限管理中,申请并开通“发送消息”等 IM 相关权限(以控制台展示为准)。如果权限不全,im/v1/messages 会返回无权限之类的错误。
配置环境变量
把下列信息填入 ecosystem.config.js 的 env(示例见上文):
FEISHU_APP_ID:应用的 App IDFEISHU_APP_SECRET:应用的 App SecretFEISHU_USER_OPEN_ID:接收通知的用户 open_id
如果你修改了 ecosystem.config.js,记得这样重载并更新环境变量:
获取接收人的 open_id(推荐做法:事件回调)
最省事的方法是启用事件订阅,让目标账号给机器人发一条消息,然后从日志里取 open_id。
- 在飞书开放平台的「事件订阅」里配置请求地址:
https://yourdomain.com/your-feishu-events-path - 订阅消息事件(例如收到消息一类的事件);本文代码示例里会处理并打印
im.message.receive_v1的 sender open_id - 让接收通知的那个人给机器人发一条任意消息
- 查看日志:
然后把日志里打印出的 open_id 填回 FEISHU_USER_OPEN_ID,再重载 pm2。
注意:本文示例代码只做了最基础的
url_verification校验,并没有实现回调签名校验/消息体加解密。如果你在开放平台里开启了“加密策略”,这份示例需要额外适配才能解析事件内容。
安全与隐私提示
- 不要在日志里输出
SYNC_TOKEN(无论放在 query 还是 header);本文代码为了调试会打印 headers/body,生产使用建议去掉或做脱敏。 - 反代路径尽量用不容易猜的随机字符串,并在网关层加上限流或 IP 白名单,避免
/sync被扫到。 FEISHU_APP_SECRET属于高敏感信息,任何时候都不要写进仓库,也不要粘贴到公开平台。
GitHub Action 调用 Webhook
name: auto-deploy |
调试与验证
修改了 webhook.js 之后重启一下:
如果也有修改 ecosystem.config.js 文件,则这样重启:
查看日志:
在服务器上测试效果:
在本地电脑上测试效果,这个能通就代表全流程通了: