跳转至

Gitea Webhook:Push 后立即构建 MkDocs(notes)

目标:消除「Obsidian 定时 push」与「cron 定时 pull+build」叠加造成的 最长约 20 分钟延迟;远端一有提交,几秒内更新 notes 站点。
思路:Gitea 仓库 Webhook(push 事件) → 宿主机 HTTP 钩子 → 执行现有 /opt/rebuild-notes.shgit 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 时增加:

--add-host=host.docker.internal:host-gateway

Podman 同理(版本需支持 host-gateway)。

Webhook URL 填:

http://host.docker.internal:9000/hooks/rebuild-mkdocs

方案 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 示例:

http://172.17.0.1:9000/hooks/rebuild-mkdocs

若为空或多网卡,用 ip addrdocker0/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)。最简单起步:

ExecStart=/usr/local/bin/webhook -hooks /etc/webhook/hooks.json -port 9000 -ip 0.0.0.0 -verbose

并在阿里云安全组 不要放行公网 9000;仅内网访问。

systemctl daemon-reload
systemctl enable --now webhook-mkdocs
journalctl -u webhook-mkdocs -f

3.4 本机试调

curl -sS "http://127.0.0.1:9000/hooks/rebuild-mkdocs?token=$(cat /etc/webhook/secret.txt)"

应返回 ok,且 /opt/mkdocs-site 时间戳更新(或看脚本日志)。


四、允许 Gitea 向「内网地址」发 Webhook(必做)

Gitea 1.16+ 默认可能禁止 Webhook 请求发往私网 / 回环地址,不放开则 Delivery 会一直失败。

在宿主机编辑 /data/gitea/gitea/conf/app.ini(路径随你数据卷挂载而定),增加或合并:

[webhook]
ALLOWED_HOST_LIST = private,loopback,external

说明:private172.17.x.x 等桥接地址;loopback127.0.0.1(若你把 webhook 只绑在回环且用端口转发)。在生产对公网开放时用 * 除非清楚风险。

docker restart gitea

五、Gitea 后台配置 Webhook

  1. 打开仓库 → SettingsWebhooksAdd webhook → 选 Gitea
  2. Target URL(二选一,与第二节一致):
  3. http://host.docker.internal:9000/hooks/rebuild-mkdocs?token=你的密钥
  4. http://172.17.0.1:9000/hooks/rebuild-mkdocs?token=你的密钥
  5. Webhook Secret:可与 token 相同或留空(本方案以 URL token 为准,Secret 可不依赖)。
  6. Trigger On:勾选 Push events(必要时含 Branch filtermain/master)。
  7. 保存后点 Test Delivery 或在本地 git push 一次,看 Recent Deliveries 是否 200。

六、cron 调整(建议)

原先每 10 分钟构建可改为 兜底,例如每小时:

0 * * * * /opt/rebuild-notes.sh >> /var/log/mkdocs-build.log 2>&1

或保留 10 分钟作为双保险(会多跑几次空 build,一般可接受)。


七、排错清单

现象 检查
Delivery 连接超时 Webhook URL 是否用了容器内 127.0.0.1;改用 host.docker.internal 或 bridge Gateway
401/404 URL 路径是否为 /hooks/rebuild-mkdocshooks.jsonid 是否一致
200 但页面未变 rebuild-notes.sh 是否 git pull 到正确目录;Nginx root 是否指向 site_dir
多次重复构建 正常;若需合并推送可后续再加队列

版本记录

版本 日期 说明
v1.0 2026-04-29 初稿:Webhook + webhook 接收器 + systemd;补充 Gitea ALLOWED_HOST_LIST