Gitea Webhook:Push 后立即构建 MkDocs(notes)
目标:消除「Obsidian 定时 push」与「cron 定时 pull+build」叠加造成的 最长约 20 分钟延迟;远端一有提交,几秒内更新
notes站点。
思路:Gitea 仓库 Webhook(push 事件) → 宿主机 HTTP 钩子 → 执行现有/opt/rebuild-notes.sh(git pull+mkdocs build)。
保留:cron 可改为 低频兜底(如每小时一次),防止 webhook 偶发失败导致长期不更新。
一、为什么不用「只靠缩短 cron」
| 方式 | 延迟 | 说明 |
|---|---|---|
| cron 每 10 分钟 | 平均 5min,最坏 10min+ | 仍与 Obsidian 推送周期叠加 |
| cron 每 1 分钟 | 仍非实时,且空转多 | 不推荐 |
| Gitea Webhook | 通常 秒级 | push 完成即触发,与客户端定时解耦 |
二、Gitea 在容器内如何访问宿主机上的钩子
Gitea 在 Podman/Docker 容器里发 Webhook 时,http://127.0.0.1 指向容器自己,不是宿主机。
任选其一(推荐顺序):
方案 A:host.docker.internal(推荐,需重建 Gitea 容器时加一行)
创建或重建 Gitea 时增加:
Podman 同理(版本需支持 host-gateway)。
Webhook URL 填:
方案 B:桥接网关 IP(不改 Gitea 容器时)
在宿主机执行:
docker inspect gitea --format '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}'
# Podman: podman inspect gitea --format '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}'
常见为 172.17.0.1。Webhook URL 示例:
若为空或多网卡,用 ip addr 看 docker0/podman0 地址,或改用方案 A。
三、安装 webhook 接收器(宿主机)
使用 adnanh/webhook,体积小、专用于「HTTP → 执行脚本」。
3.1 下载二进制(示例:amd64,按实际架构替换)
VER=2.8.1
ARCH=linux-amd64
curl -fsSL -o /tmp/webhook.tgz \
"https://github.com/adnanh/webhook/releases/download/${VER}/webhook-${ARCH}.tar.gz"
tar -xzf /tmp/webhook.tgz -C /tmp
install -m 755 "/tmp/webhook-${ARCH}/webhook" /usr/local/bin/webhook
若 GitHub 超时:在 Mac 下载同版本压缩包,scp 到服务器后同样 tar + install。
解压目录名以实际为准(部分压缩包顶层可能直接是 webhook 二进制)。
3.2 钩子配置 /etc/webhook/hooks.json
先生成密钥(与 Gitea 后台填的完全一致):
mkdir -p /etc/webhook
openssl rand -hex 32 | tee /etc/webhook/secret.txt
chmod 600 /etc/webhook/secret.txt
将下面 YOUR_SECRET_FROM_FILE 换成 /etc/webhook/secret.txt 里的字符串(或改用环境变量注入,见下节 systemd)。
[
{
"id": "rebuild-mkdocs",
"execute-command": "/opt/rebuild-notes.sh",
"command-working-directory": "/",
"response-message": "ok",
"trigger-rule": {
"match": {
"type": "value",
"value": "YOUR_SECRET_FROM_FILE",
"parameter": {
"source": "url",
"name": "token"
}
}
}
}
]
说明:使用 URL Query ?token= 校验,避免与 Gitea 各版本 X-Gitea-Signature 算法细节纠缠;务必配合 HTTPS 仅内网或仅 Docker 网关可达(监听见下)。
若更想用 Header,可把 parameter 改为 header / X-Webhook-Token 等(需 Gitea 自定义 Header 插件或代理,一般不必)。
3.3 systemd 单元 /etc/systemd/system/webhook-mkdocs.service
[Unit]
Description=Webhook receiver for MkDocs rebuild
After=network.target
[Service]
ExecStart=/usr/local/bin/webhook -hooks /etc/webhook/hooks.json -port 9000 -verbose
Restart=always
[Install]
WantedBy=multi-user.target
安全:只监听本机,让 仅容器网段能访问(需配合防火墙;若 Gitea 与 webhook 同机且用 host-gateway,可把 -ip 127.0.0.1 改为监听 0.0.0.0:9000 并在防火墙只允许 172.17.0.0/16 访问 9000)。最简单起步:
并在阿里云安全组 不要放行公网 9000;仅内网访问。
3.4 本机试调
应返回 ok,且 /opt/mkdocs-site 时间戳更新(或看脚本日志)。
四、允许 Gitea 向「内网地址」发 Webhook(必做)
Gitea 1.16+ 默认可能禁止 Webhook 请求发往私网 / 回环地址,不放开则 Delivery 会一直失败。
在宿主机编辑 /data/gitea/gitea/conf/app.ini(路径随你数据卷挂载而定),增加或合并:
说明:private 含 172.17.x.x 等桥接地址;loopback 含 127.0.0.1(若你把 webhook 只绑在回环且用端口转发)。勿在生产对公网开放时用 * 除非清楚风险。
五、Gitea 后台配置 Webhook
- 打开仓库 → Settings → Webhooks → Add webhook → 选 Gitea。
- Target URL(二选一,与第二节一致):
http://host.docker.internal:9000/hooks/rebuild-mkdocs?token=你的密钥- 或
http://172.17.0.1:9000/hooks/rebuild-mkdocs?token=你的密钥 - Webhook Secret:可与 token 相同或留空(本方案以 URL token 为准,Secret 可不依赖)。
- Trigger On:勾选 Push events(必要时含 Branch filter 仅
main/master)。 - 保存后点 Test Delivery 或在本地
git push一次,看 Recent Deliveries 是否 200。
六、cron 调整(建议)
原先每 10 分钟构建可改为 兜底,例如每小时:
或保留 10 分钟作为双保险(会多跑几次空 build,一般可接受)。
七、排错清单
| 现象 | 检查 |
|---|---|
| Delivery 连接超时 | Webhook URL 是否用了容器内 127.0.0.1;改用 host.docker.internal 或 bridge Gateway |
| 401/404 | URL 路径是否为 /hooks/rebuild-mkdocs,hooks.json 里 id 是否一致 |
| 200 但页面未变 | rebuild-notes.sh 是否 git pull 到正确目录;Nginx root 是否指向 site_dir |
| 多次重复构建 | 正常;若需合并推送可后续再加队列 |
版本记录
| 版本 | 日期 | 说明 |
|---|---|---|
| v1.0 | 2026-04-29 | 初稿:Webhook + webhook 接收器 + systemd;补充 Gitea ALLOWED_HOST_LIST |