部署
GitPigeon 是单租户的:每人为自己的博客部署一份。各平台共用同一份核心代码,只需换入口。
前置准备
- 一个 GitHub 仓库(用来存评论,可以和你博客仓库分开)
- 一个 Fine-grained PAT(见 GitHub 配置)
- 一个 Cloudflare Turnstile Site Key / Secret Key(可选,配置即启用人机验证)
- 一个发件方式:Resend 或 MailPort(见 邮件配置)
Vercel
- 导入本仓库
- 在 Project Settings → Environment Variables 填入 环境变量
- Framework Preset 选 Other,Build Command 留空,Output Directory 留空
- 部署完成后访问
/api/health自检
Netlify
- 导入本仓库
netlify.toml已配置好publish = "public"与 functions 目录- 在 Site settings → Environment variables 填入变量
- 部署后访问
/api/health
Cloudflare Workers
- 执行
npm run build生成public/embed.js与public/review.js - 用
wrangler deploy部署,wrangler.toml已声明静态资源目录 - 用
wrangler secret put逐项写入敏感变量 - 访问
https://<worker>.workers.dev/api/health
用 GitHub Actions 自动部署
仓库内置了 .github/workflows/deploy-worker.yml:向 main 推送时自动构建、部署到 Workers,并把你在 GitHub 配置的应用变量同步为 Worker 的运行时配置。
在 Settings → Secrets and variables → Actions 中配置。鉴权用的两个值可以放在 Secret,也可以放在 Variables:
| 名称 | 说明 |
|---|---|
CLOUDFLARE_API_TOKEN | 具有 Workers Scripts: Edit 权限的 API Token |
CLOUDFLARE_ACCOUNT_ID | Cloudflare 账户 ID(Dashboard 右侧栏可见) |
工作流会先读 Secret,读不到再读 Variables。两者都没配置时不会失败:check 任务输出一条 notice,随后跳过 deploy。配置后,后续推送自动生效,也可在 Actions 页面手动触发(workflow_dispatch)。
应用变量同步
下表两类变量都可以放在 Secret 或 Variables 里,工作流会两边都扫一次。若同一个名字在两边都配置了,按类型决定优先级:
- 敏感类(Secret 列表):以 Secret 为准,Secret 为空时才回退到 Variables
- 普通类(变量列表):以 Variables 为准,Variables 为空时才回退到 Secret
| 敏感类(写成 Worker Secret) | 普通类(写成 Worker 变量) |
|---|---|
COMMENTS_GITHUB_TOKEN → GITHUB_TOKEN | COMMENTS_REPO |
COMMENTS_SECRET | COMMENTS_BRANCH |
TURNSTILE_SECRET | COMMENTS_PATH |
MODERATOR_EMAIL | SELF_ORIGIN |
RESEND_API_KEY | SELF_REPO |
MAILPORT_API_KEY | ALLOWED_ORIGINS |
TURNSTILE_SITE_KEY | |
MODERATION_REQUIRED | |
MAIL_PROVIDER | |
RESEND_FROM | |
MAILPORT_BASE_URL | |
MAILPORT_PID |
注意事项:
- 应用仓库的 PAT 必须叫
COMMENTS_GITHUB_TOKEN。GitHub 禁止创建以GITHUB_开头的 Secret 名,工作流会把它映射成 Worker 的GITHUB_TOKEN CLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_ID只用于部署鉴权,不会写入 Worker- 留空的项不会被传递,Worker 端保持原值(不会清空)
- 普通变量以
--var传给wrangler deploy,并开启了--keep-vars,因此不会删除 Worker 上已有的其他变量 - 只有
comments/**目录变更时不会触发部署,避免评论写入引起无意义的重新部署 - 需要确认 Worker 名称与
wrangler.toml中的name一致 - Worker Secret 一旦写入会保留,即使之后把对应 GitHub 配置清空,也不会自动删除;需要手动
wrangler secret delete
Cloudflare Pages
functions/api/[[path]].ts 已把 /api/* 转发到共享路由,public/_routes.json 限定只有 /api/* 走函数,其余走静态资源。
- 在 Cloudflare Dashboard → Workers & Pages → Create → Pages,连接本仓库
- Build command 填
npm run build,Build output directory 填public - 在 Settings → Environment variables 填入 环境变量
- 部署后访问
https://<project>.pages.dev/api/health
注意事项:
- Pages 的环境变量在改动后需要重新部署才生效
- 若你的博客也在 Pages 上,注意本系统的
/api/*与博客自身的 worker 路由不要冲突 - Pages 免费版函数有每日请求上限,作为评论系统通常足够
本地部署(不推荐)
WARNING
不建议用于生产环境。 本地方式适合调试、内网自用或快速验证接入效果。它在生产上存在这些现实问题:
- 没有 TLS:默认是
http://,博客如果是https://,浏览器会因混合内容拦截 widget(详见下文「HTTPS 博客」) - 没有边缘缓存:每次读评论都要现场请求 GitHub API,延迟取决于你的网络
- 进程要常驻:机器重启或终端关闭后服务就没了,需要自己配守护进程
- 限频只在内存里:进程重启会清空,多实例也无法共享
- 与平台 Git 集成无关:你不会得到推送即部署、自动回滚等能力
如果只是想让博客有稳定的评论服务,请直接使用上文任意一个平台。本地部署请确认你清楚以上取舍。
1. 准备环境
| 依赖 | 要求 | 检查命令 |
|---|---|---|
| Node.js | 20 或更高(脚本按 node20 打包) | node --version |
| npm | 随 Node 安装即可 | npm --version |
| 网络 | 能访问 api.github.com 与发件服务 | curl -I https://api.github.com |
本文命令以 macOS / Linux 为例。Windows 请使用 PowerShell 或 WSL,PORT=9000 这类前置赋值要改成 $env:PORT=9000 或 set PORT=9000。
2. 克隆并安装依赖
git clone https://github.com/wool-hmq/GitPigeon.git
cd GitPigeon
npm install3. 生成 widget 产物
npm run build会生成 public/embed.js 与 public/review.js。这两个文件已被 .gitignore 忽略,所以每次全新克隆后都必须先执行这一步,否则本地页面能打开但评论区是空的。
4. 准备评论仓库与 PAT
- 新建一个仓库专门存评论(推荐),例如
your-name/blog-comments,并确保它有main分支 - 按 GitHub 配置 创建 Fine-grained PAT,只勾选这个仓库,权限给
Contents: Read and write - 记下
owner/repo的完整写法,大小写要和 GitHub 页面一致
5. 配置 .env
cp .env.example .env编辑 .env,本地最小可用配置如下(其余可留空):
# 评论数据仓库
GITHUB_TOKEN=github_pat_xxxxxxxx
COMMENTS_REPO=your-name/blog-comments
COMMENTS_BRANCH=main
COMMENTS_PATH=comments
# 审批签名与加密主密钥:至少 32 字节,随机生成
COMMENTS_SECRET=请替换为至少32字节的随机字符串xxxxxxxx
# 本服务自身地址(本地就是端口地址,无尾斜杠)
SELF_ORIGIN=http://localhost:8787
# 允许提交评论的博客 Origin,逗号分隔,无尾斜杠
ALLOWED_ORIGINS=http://localhost:8787说明:
COMMENTS_SECRET必须至少 32 字节。可以这样生成:
openssl rand -hex 32- 本地想先验证「直接写入」流程,可设置
MODERATION_REQUIRED=false,此时不需要配置任何发件变量 - 想验证邮件审核流程,则保持
MODERATION_REQUIRED=true,并按 邮件配置 填好MODERATOR_EMAIL与一组RESEND_*或MAILPORT_* SELF_ORIGIN用于拼接审核链接,如果改了端口要同步修改.env已被.gitignore忽略,不会误提交;也请不要把它提交到任何仓库
6. 启动服务
npm run serve:local脚本会先打包 dev-server.mjs,再启动 Node 内置 HTTP 服务。看到下面这行说明启动成功:
preview server on http://localhost:8787服务会读取项目根目录的 .env。同名系统环境变量优先级更高,可用于临时覆盖。
7. 自检
先确认配置正确:
curl http://localhost:8787/api/health预期:
status为okgit.readable为true- 开启审核时
mail.configured为true - 不同仓库时
sameRepoWarning为null
若不是 ok,issues 数组会列出具体字段,对照 故障排查 修正。
然后打开 http://localhost:8787/,页面自带一个演示评论区(post=hello-world),可以直接测试提交。
8. 接入你的博客
把博客页面的 script 指向本地服务:
<div id="comments"></div>
<script src="http://localhost:8787/embed.js"
data-server="http://localhost:8787"
defer></script>同时确保博客的 Origin(如 http://localhost:4321)已加入 ALLOWED_ORIGINS,否则提交会被 403 origin_not_allowed 拒绝。
9. 换端口
PORT=9000 npm run serve:local换端口后记得同步改 SELF_ORIGIN、ALLOWED_ORIGINS 和博客里的 data-server,三者不一致会出现审核链接错位或 CORS 拒绝。
常见问题
评论区空白
- 是否执行过
npm run build(public/embed.js是否存在) - 浏览器控制台是否有跨域报错,检查
ALLOWED_ORIGINS是否包含博客 Origin /api/comments?post=<slug>是否返回 200
提交返回 503
/api/health 看 issues:通常是 COMMENTS_SECRET、GITHUB_TOKEN、COMMENTS_REPO 缺失,或开启了审核但发件配置不完整。
批准链接打不开
审核链接基于 SELF_ORIGIN 生成。若用 127.0.0.1 启动却把 SELF_ORIGIN 写成 localhost(或反之),链接会指向另一个地址。保持端口和主机名一致。
HTTPS 博客无法加载 widget
https:// 页面不能加载 http:// 脚本,这是浏览器强制的混合内容限制。可行做法:
- 给本地服务套一层反向代理并配置证书(如 Caddy / Nginx),让服务本身走
https - 或者把博客在本地也用
http://调试
停机与清理
在终端按 Ctrl+C 停止。本地模式不写数据库,所有状态都在你的评论仓库里,删除本地 .env 或重新克隆都不会影响已审核的评论。
部署后自检
访问 /api/health,确认:
status为okgit.readable为true(PAT 能读到评论仓库)mail.configured为true(若开启了审核)sameRepoWarning为null(若你选择不同仓库)