webhook 2.8.3 配置参数详解

拆解 webhook 2.8.3 两层配置体系:hook 定义字段(id/trigger-rule 全类型/参数传递/响应控制)与服务启动参数,每类配实测回显,附 GitHub 自动部署生产配置模板与重载排障。

webhook自托管中间件2026/10/25

webhook 2.8.3 配置参数详解

目标:系统拆解 webhook 2.8.3 的两层配置体系——hook 定义字段(hooks.json/yaml,决定「端点行为」)与服务启动参数(CLI flags,决定「进程运行方式」),每类参数配实测回显,并给出一套可直接落地的 GitHub 自动部署生产配置模板。本文全部配置与回显已在 Ubuntu 22.04 + webhook 2.8.3 环境实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04.4 LTS(x86_64)
  • webhook 版本:2.8.3(2026-02-12 发布,官方二进制安装,/usr/local/bin/webhook)
  • 配置目录:/etc/webhook/,主配置 /etc/webhook/hooks.json
  • 服务监听:0.0.0.0:9000(默认端口),演示脚本目录 /opt/webhook/scripts/
  • 安装与 systemd 托管过程见 《webhook 2.8.3 安装指南》第四章
  • 参数口径来源:官方 Wiki《Hook definition》《Hook rules》《Webhook parameters》《Referencing request values》(2026-10-25 查证)+ 本地逐项实测

二、前置条件

  • 已按安装篇完成 webhook 2.8.3 部署且服务运行中,验证命令与回显:
systemctl is-active webhook
curl -s http://127.0.0.1:9000/hooks/ping

实测回显:

active
pong
  • 演示脚本就绪(/opt/webhook/scripts/ 下的 ping.sh、echo.sh、redeploy.sh、github.sh,内容见安装篇 4.5 节与本文各节);
  • 修改配置后需让进程重新加载,三种方式任选其一(详见 3.3 节)。

三、参数查看与修改方式

3.1 两层参数体系

webhook 的「配置」分两层,修改位置与生效方式不同:

层内容存放位置生效方式
hook 定义端点路径、执行命令、触发规则、参数与响应/etc/webhook/hooks.json(或 .yaml)重载配置(USR1/-hotreload/重启),进程可不重启
服务启动参数监听地址/端口、TLS、日志、权限等进程级行为systemd 单元 ExecStart 行的 CLI flags必须重启进程(systemctl restart webhook)

3.2 查看当前生效配置

hook 层直接读配置文件:

cat /etc/webhook/hooks.json | python3 -m json.tool | head -8

实测回显:

[
    {
        "id": "ping",
        "execute-command": "/opt/webhook/scripts/ping.sh",
        "response-message": "pong"
    },

服务层用 -h 查看全部 CLI 参数与默认值(完整输出与逐项解读见 《webhook 2.8.3 常用 CLI 命令与实战详解》第四章):

webhook -h 2>&1 | head -12

实测回显:

Usage of webhook:
  -cert string
    	path to the HTTPS certificate pem file (default "cert.pem")
  -cipher-suites string
    	comma-separated list of supported TLS cipher suites
  -debug
    	show debug output
  -header value
    	response header to return, specified in format name=value, use multiple times to set multiple headers
  -hooks value
    	path to the json file containing defined hooks the webhook should serve, use multiple times to load from different files
  -hotreload
    	watch hooks file for changes and reload them automatically

3.3 hook 配置的三种重载方式

方式一:USR1 信号重载(生产推荐,改完立即生效):

kill -USR1 $(pgrep -f 'webhook -hooks')

实测回显(日志尾部):

[webhook] 2026/10/25 01:34:18 attempting to reload hooks from /etc/webhook/hooks.json
[webhook] 2026/10/25 01:34:18 	loaded: strict-token
[webhook] 2026/10/25 01:34:18 	loaded: regex-branch

方式二:-hotreload 启动参数(开发环境推荐,保存即加载)——启动时加 -hotreload,日志出现 setting up file watcher:

[webhook] 2026/10/25 00:58:09 setting up file watcher for /etc/webhook/hooks-hotreload.yaml

方式三:重启进程(改了 systemd 单元内容时必须走这条):

systemctl restart webhook

⚠️ 注意:重载失败(新配置语法错误)时进程保留旧配置继续服务,日志会打出解析错误——每次重载后看一眼日志尾部或触发一次验证,不要默认重载成功。

四、参数总览

4.1 hook 定义字段表(hooks.json)

每个 hook 对象必须有 id 与 execute-command,其余可选(来源:官方《Hook definition》,2026-10-25 查证):

字段类型作用默认行为
idstring端点 ID,决定 URL /hooks/<id>必填
execute-commandstring触发时执行的命令(脚本绝对路径)必填
command-working-directorystring脚本执行时的工作目录进程当前目录
response-messagestring触发成功返回给调用方的固定文案空响应体
response-headers[]object触发成功附加的响应头(name/value)无
include-command-output-in-responsebool把脚本 stdout 原样回传(成功 200,脚本失败 500)false(不回传)
parse-parameters-as-json[]object把指定参数的值再按 JSON 解析成对象值按纯字符串处理
pass-arguments-to-command[]object以命令行参数传给脚本无
pass-environment-to-command[]object以环境变量传给脚本(默认名 HOOK_<引用名>)无
pass-file-to-command[]object把数据序列化成临时文件,路径经环境变量告知脚本无
trigger-ruleobject触发条件规则(见 5.2 节)无规则=任何请求都触发
trigger-rule-mismatch-http-response-codeint规则不满足时返回的 HTTP 状态码200

4.2 服务启动参数表(CLI flags)

常用启动参数(完整清单见命令篇;默认值取自 webhook -h 实测输出):

参数默认值作用
-hooks无hooks 配置文件路径,可重复传多个文件叠加
-ip0.0.0.0监听地址
-port9000监听端口
-urlprefixhooksURL 前缀(/<prefix>/<hook-id>)
-hotreload关监视配置文件自动重载
-verbose关详细日志(含每次触发的请求级记录)
-logfile无日志落文件(隐含开启 verbose)
-template关把 hooks 文件按 Go 模板解析
-secure关启用 HTTPS(配 -cert/-key)
-tls-min-version1.2TLS 最低版本
-header无全局响应头(如 CORS),可重复
-max-multipart-mem1048576multipart 表单解析内存上限(字节),超出落盘
-socket无改用 Unix socket 监听(供反代连接)
-setuid/-setgid无打开端口后降权运行
-pidfile无写 PID 文件
-nopanic关配置加载失败时不退出,空跑继续

五、核心参数分类详解

5.1 端点基础字段:id 与 execute-command

id 拼进 URL,execute-command 是触发后 fork 执行的脚本。最小可用定义(安装篇已验证):

[
  {
    "id": "ping",
    "execute-command": "/opt/webhook/scripts/ping.sh",
    "response-message": "pong"
  }
]

实测触发:

curl -si http://127.0.0.1:9000/hooks/ping

实测回显:

HTTP/1.1 200 OK
Date: Sun, 25 Oct 2026 00:56:29 GMT
Content-Length: 4
Content-Type: text/plain; charset=utf-8

pong

command-working-directory 影响脚本的 pwd。演示配置把 redeploy-webhook 的工作目录设为 /opt/webhook,脚本输出 pwd 验证:

{
  "id": "redeploy-webhook",
  "execute-command": "/opt/webhook/scripts/redeploy.sh",
  "command-working-directory": "/opt/webhook"
}

脚本内容 echo "redeploy script started, working dir: $(pwd)",触发后经日志确认(脚本 stdout 不回传时进日志):

[webhook] 2026/10/25 00:56:35 [e91a2c] executing /opt/webhook/scripts/redeploy.sh (/opt/webhook/scripts/redeploy.sh) with arguments ["/opt/webhook/scripts/redeploy.sh"] and environment [] using /opt/webhook as cwd

💡 说明:脚本里避免依赖工作目录的相对路径,一律写绝对路径;确需工作目录语义(如 git pull)时用 command-working-directory 显式声明。

5.2 触发规则 trigger-rule(安全核心)

规则是一棵可嵌套的表达式树:and/or/not 组合若干 match,match 从 header/url/payload 三个数据源取值比对。全部 match 类型:

type比对方式关键字段
value取值 == 给定字符串value
regex取值匹配 Go 正则regex
payload-hmac-sha1请求体 HMAC-SHA1 签名校验secret + 签名所在 header
payload-hmac-sha256同上 SHA256同上
payload-hmac-sha512同上 SHA512同上
ip-whitelist来源 IP 在 CIDR 内ip-range
scalr-signatureScalr 平台签名(含 5 分钟时效)secret

💡 技术拓展:HMAC 签名是 webhook 类服务防伪造的主流手段,三档哈希强度对比——

算法签名头示例适用方
HMAC-SHA1GitHub X-Hub-Signature(sha1=<hex>)GitHub 旧版/多数 Git 托管平台
HMAC-SHA256GitHub X-Hub-Signature-256(sha256=<hex>)GitHub 新版、Gitea 等,安全推荐
HMAC-SHA512自定义头(如 X-Signature)自研系统间强校验

本文演示采用 GitHub 生态最通用的 HMAC-SHA1;新接入的平台优先配 SHA256。签名规则支持一头上传多个签名(逗号分隔逐个尝试),密钥轮换期新旧签名可并存。

(1)value 规则:URL token 校验。 规则不满足时默认返回 200 + 提示文案(这是 webhook 默认行为,见 trigger-rule-mismatch-http-response-code):

curl -si -X POST 'http://127.0.0.1:9000/hooks/redeploy-webhook?token=wrong' \
  -H 'Content-Type: application/json' -d '{"ref": "refs/heads/main"}'

实测回显:

HTTP/1.1 200 OK
Date: Sun, 25 Oct 2026 00:56:35 GMT
Content-Length: 30
Content-Type: text/plain; charset=utf-8

Hook rules were not satisfied.

(2)and 组合规则:token + 分支双条件。 redeploy-webhook 的规则为 and[value(url.token == q1w2e3r4), value(payload.ref == refs/heads/main)],两条件同时满足才触发:

curl -si -X POST 'http://127.0.0.1:9000/hooks/redeploy-webhook?token=q1w2e3r4' \
  -H 'Content-Type: application/json' \
  -d '{"ref": "refs/heads/main", "after": "abc123"}'

实测回显(注意自定义响应头 X-Deploy-Status 一并返回):

HTTP/1.1 200 OK
X-Deploy-Status: accepted
Date: Sun, 25 Oct 2026 00:56:35 GMT
Content-Length: 17
Content-Type: text/plain; charset=utf-8

redeploy accepted

(3)regex 规则:分支名匹配。 只放行 main 与 release/* 分支:

{
  "id": "regex-branch",
  "execute-command": "/opt/webhook/scripts/ping.sh",
  "response-message": "branch accepted",
  "trigger-rule": {
    "match": {
      "type": "regex",
      "regex": "refs/heads/(main|release/.*)",
      "parameter": { "source": "payload", "name": "ref" }
    }
  }
}

实测两分支对比:

curl -si -X POST 'http://127.0.0.1:9000/hooks/regex-branch' \
  -H 'Content-Type: application/json' -d '{"ref": "refs/heads/release/1.0"}'

实测回显:

HTTP/1.1 200 OK
Date: Sun, 25 Oct 2026 01:34:22 GMT
Content-Length: 15
Content-Type: text/plain; charset=utf-8

branch accepted

不匹配分支(refs/heads/feature-x)实测回显:

Hook rules were not satisfied.

(4)HMAC-SHA1 签名规则:GitHub 回调标准防护。 规则结构为 and[payload-hmac-sha1(X-Hub-Signature, secret), or[payload.ref==main, X-GitHub-Event==ping]]。计算签名并触发:

PAYLOAD='{"ref": "refs/heads/main", "after": "abc123def456"}'
SIG="sha1=$(printf '%s' "$PAYLOAD" | openssl dgst -sha1 -hmac 'q1w2e3r4' | awk '{print $2}')"
curl -si -X POST http://127.0.0.1:9000/hooks/github-webhook \
  -H 'Content-Type: application/json' \
  -H "X-Hub-Signature: $SIG" \
  -H 'X-GitHub-Event: push' \
  -d "$PAYLOAD"

实测回显(脚本把 entire-payload 与事件头打回):

HTTP/1.1 200 OK
Date: Sun, 25 Oct 2026 00:57:47 GMT
Content-Length: 105
Content-Type: text/plain; charset=utf-8

github webhook verified and executed
event=push
payload={"after":"abc123def456","ref":"refs/heads/main"}

错误签名(hex 全 0)实测回显——注意签名类规则不匹配返回的是 500 而非 200:

HTTP/1.1 500 Internal Server Error
Date: Sun, 25 Oct 2026 00:57:05 GMT
Content-Length: 43
Content-Type: text/plain; charset=utf-8

Error occurred while evaluating hook rules.

(5)ip-whitelist 规则:来源网段白名单。 只允许 10.89.60.0/24(演示内网段)触发:

curl -si 'http://127.0.0.1:9000/hooks/ip-protected' | head -7

实测回显(来源 10.89.60.1 在白名单内):

HTTP/1.1 200 OK
Date: Sun, 25 Oct 2026 00:57:55 GMT
Content-Length: 20
Content-Type: text/plain; charset=utf-8

from trusted network

把来源换成白名单外地址(127.0.0.1)实测回显:

HTTP/1.1 200 OK
Date: Sun, 25 Oct 2026 00:57:55 GMT
Content-Length: 30
Content-Type: text/plain; charset=utf-8

Hook rules were not satisfied.

⚠️ 注意:官方 README 明确说明——webhook 部署在反向代理之后时,ip-whitelist 检查到的是代理的 IP 而非真实客户端,IP 限制应在代理层实施。该规则只适合 webhook 直接暴露在内网的拓扑。

(6)自定义不满足状态码。 默认 200 对监控不友好,trigger-rule-mismatch-http-response-code 改为 403 后实测:

curl -si 'http://127.0.0.1:9000/hooks/strict-token?token=wrong' | head -6

实测回显:

HTTP/1.1 403 Forbidden
Date: Sun, 25 Oct 2026 00:57:47 GMT
Content-Length: 30
Content-Type: text/plain; charset=utf-8

5.3 参数传递:把请求值喂给脚本

三类数据源 header/url/payload 既能用于规则(5.2 节),也能装配给脚本。JSON payload 支持点号嵌套与数组下标(如 commits.0.commit.id,来源:官方《Referencing request values》,2026-10-25 查证)。演示定义(一次覆盖五类参数来源):

{
  "id": "echo-args",
  "execute-command": "/opt/webhook/scripts/echo.sh",
  "include-command-output-in-response": true,
  "pass-arguments-to-command": [
    { "source": "url", "name": "name" },
    { "source": "payload", "name": "ref" },
    { "source": "payload", "name": "data.version" },
    { "source": "header", "name": "X-Build-Number" },
    { "source": "string", "name": "static-arg" }
  ],
  "pass-environment-to-command": [
    { "source": "url", "name": "name", "envname": "HOOK_NAME" }
  ]
}

字段解读:前四项按顺序成为脚本的 $1~$4;source: "string" 是静态参数($5,不来自请求);环境变量默认命名 HOOK_<引用名>,用 envname 改名(本例 HOOK_NAME)。

实测触发:

curl -si 'http://127.0.0.1:9000/hooks/echo-args?name=api-service' \
  -H 'Content-Type: application/json' \
  -H 'X-Build-Number: build-20261025-042' \
  -d '{"ref": "refs/heads/main", "data": {"version": "2.8.3"}}'

实测回显:

HTTP/1.1 200 OK
Date: Sun, 25 Oct 2026 00:56:41 GMT
Content-Length: 115
Content-Type: text/plain; charset=utf-8

arg1=api-service
arg2=refs/heads/main
arg3=2.8.3
arg4=build-20261025-042
arg5=static-arg
env HOOK_NAME=api-service

缺参场景实测(空 payload、无 query、无 header)——缺失的引用值为空字符串,静态参数不受影响:

arg1=
arg2=
arg3=
arg4=
arg5=static-arg
env HOOK_NAME=

整块引用三兄弟(来自官方文档,用于「转发原始请求给脚本」):

source传给脚本的内容
entire-payload整个请求体(重新序列化的 JSON 字符串)
entire-headers全部请求头(JSON 字符串)
entire-query全部查询参数(JSON 字符串)

pass-file-to-command 补充:数据写进临时文件,文件路径经环境变量(默认 HOOK_<引用名>)告知脚本,base64decode: true 时先做 base64 解码——适合二进制负载(如构建产物);文件随请求结束自动清理。

5.4 响应控制:response-message / response-headers / include-command-output-in-response

字段效果实测状态码
response-message固定文案回传(如 pong)200
response-headers自定义响应头,本系列实测 X-Deploy-Status: accepted200
include-command-output-in-response: true脚本 stdout 逐字回传成功 200;脚本执行失败 500
trigger-rule-mismatch-http-response-code规则不满足的状态码配 403 则 403

include-command-output-in-response 的 500 行为值得专门记住:调用方(尤其监控系统)可据此直接从 HTTP 状态码判断脚本成败,无需解析响应体。

5.5 服务级启动参数要点

  • -hooks 多文件叠加:-hooks /etc/webhook/hooks-a.json -hooks /etc/webhook/hooks-b.json,端点合并服务,适合按团队/项目拆分配置;
  • -urlprefix:默认前缀 hooks,改 -urlprefix actions 后端点变 /actions/<id>——实测改前缀后旧路径 404:
[webhook] 2026/10/25 00:58:27 serving hooks on http://0.0.0.0:9002/hooks/{id}   ← 默认
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:9002/hooks/health     ← 404
curl -si http://127.0.0.1:9002/actions/health                                    ← 200 hotreload instance alive
  • -template:hooks 文件按 Go 模板解析,内置 getenv 函数从环境变量注入差异化值(2.8.3 新增 cat/credential 模板函数,credential 用于环境变量密钥)。实测模板:
- id: "{{ getenv "TIER" }}-deploy"
  execute-command: "/opt/webhook/scripts/ping.sh"
  response-message: "deploy hook for {{ getenv "TIER" }} tier ready"

以 TIER=prod 启动(-template -port 9006),加载日志与触发实测回显:

[webhook] 2026/10/25 01:03:14 	loaded: prod-deploy
HTTP/1.1 200 OK
Date: Sun, 25 Oct 2026 01:03:16 GMT
Content-Length: 31
Content-Type: text/plain; charset=utf-8

deploy hook for prod tier ready

⚠️ 注意:模板上下文是 getenv "变量名" 函数而非 .env 对象——误用会渲染出 loaded: <no value>-deploy(本文实测踩过的坑)。

  • -secure + -cert/-key:启用 HTTPS;配合 -tls-min-version(默认 1.2)与 -cipher-suites(用 -list-cipher-suites 列出全部可用套件)收紧 TLS 配置;
  • -max-multipart-mem:multipart 表单(如 Slack 文件上传类回调)解析内存上限默认 1 MB,超出部分写临时文件,防大包撑爆内存;
  • -setuid/-setgid:webhook 先以 root 打开 1024 以下特权端口,随后切换到普通用户运行——「特权端口 + 低权限进程」两全。

六、生产配置模板(GitHub 自动部署场景)

适用规模:4 GB 内存、普通 SSD、单机承载每天数千次级 Git 推送回调;webhook 进程空载内存 1.5–7 MB(本文实测区间),CPU 占用可忽略,资源瓶颈通常在触发的部署脚本本身。

完整 /etc/webhook/hooks.json(GitHub push → 校验签名与分支 → 执行部署脚本,全部要素生产可用):

[
  {
    "id": "github-webhook",
    "execute-command": "/opt/webhook/scripts/redeploy.sh",
    "command-working-directory": "/srv/myapp",
    "response-message": "deploy accepted",
    "response-headers": [
      { "name": "X-Deploy-Status", "value": "accepted" }
    ],
    "trigger-rule-mismatch-http-response-code": 403,
    "pass-environment-to-command": [
      { "source": "payload", "name": "ref", "envname": "DEPLOY_REF" },
      { "source": "payload", "name": "after", "envname": "DEPLOY_COMMIT" },
      { "source": "header", "name": "X-GitHub-Event", "envname": "DEPLOY_EVENT" }
    ],
    "trigger-rule": {
      "and": [
        {
          "match": {
            "type": "payload-hmac-sha256",
            "secret": "q1w2e3r4",
            "parameter": { "source": "header", "name": "X-Hub-Signature-256" }
          }
        },
        {
          "match": {
            "type": "value",
            "value": "refs/heads/main",
            "parameter": { "source": "payload", "name": "ref" }
          }
        }
      ]
    }
  }
]

逐项说明:

  1. payload-hmac-sha256 + X-Hub-Signature-256:GitHub 仓库 Settings→Webhooks 的 Secret 填同一值,GitHub 每次推送自动携带签名(演示密钥 q1w2e3r4,生产用强随机串,经 -template 的 getenv/credential 从环境变量注入,避免密钥进配置文件);
  2. value 规则锁定 main 分支:feature 分支推送不触发部署;
  3. trigger-rule-mismatch-http-response-code: 403:非法请求显式拒绝,GitHub 侧也能看到失败;
  4. pass-environment-to-command:把推送分支、提交哈希、事件类型注入部署脚本环境变量,脚本内 $DEPLOY_COMMIT 直接可用;
  5. 不开 include-command-output-in-response:部署脚本往往长耗时,GitHub webhook 默认 10 秒超时,异步执行 + 固定文案更稳。

systemd 单元(生产推荐形态,日志落 journald):

[Service]
ExecStart=/usr/local/bin/webhook -hooks /etc/webhook/hooks.json -verbose -tls-min-version 1.2
Restart=always
RestartSec=5

上线前自检清单:签名不匹配请求应得 403(curl -si 验证);GitHub 侧 Recent Deliveries 显示绿勾;journalctl -u webhook -f 能看到每次触发的请求日志。

七、常见问题(FAQ)

Q1:改了 hooks.json 为什么行为没变? 忘记重载。USR1 信号(kill -USR1 $(pgrep -f 'webhook -hooks'))或重启服务;且重载后要确认日志打出新的 loaded: 清单(见 3.3 节),重载失败会静默保留旧配置。

Q2:规则明明满足却返回 500 Error occurred while evaluating hook rules.? 签名类规则(payload-hmac-*)对请求体求 HMAC 时失败——最常见原因是计算签名用的 payload 与实际发送的不一致(如计算时用紧凑 JSON、发送时带空格换行)。HMAC 必须对原始字节计算:先落盘 payload 文件再用 openssl dgst -sha1 -hmac <secret> <file>,或直接从 GitHub 侧的 X-Hub-Signature 对照调试。本文实测中 hex 全 0 的假签名同样得到 500。

Q3:entire-payload 传给脚本的 JSON 键序变了? 正常现象。webhook 会把请求体重新序列化(键按字母序排列),本文实测 {"ref": "...", "after": "..."} 传出时变为 {"after":"abc123def456","ref":"refs/heads/main"}。脚本解析 JSON 字段即可,不要对原始字符串做前缀匹配。

Q4:部署在 Nginx 后面,ip-whitelist 放行范围如何写? 写代理的地址没有意义(见 5.2 节 ⚠️)。两种正确姿势:在内网直连拓扑用 ip-whitelist;经过反代时改用「代理层做 IP 限制 + webhook 侧 HMAC/token 规则」的组合。

Q5:同一份配置想区分测试/生产环境? 用 -template + getenv:模板里 {{ getenv "TIER" }} 注入环境名、密钥等差异值,一份模板两套环境变量启动,本文 5.5 节有实测。

八、参考链接