配置参数说明

August 6, 2026 · View on GitHub

English

HookRun 使用两级 YAML 配置:

  1. 全局配置 (config.yaml) — 服务器、日志、目录设置
  2. 规则配置 (hooks/*.yaml) — 每个场景的认证、过滤和动作

1. 全局配置 — config.yaml

字段类型默认值说明
server.portint9000HTTP 监听端口(1–65535)
server.routestring/webhookWebhook 基础路由路径
server.allow_allboolfalse是否允许基础路由 /webhook 遍历所有配置文件
server.max_body_size_mbint10请求体大小上限 MB。0 = 不限制
server.max_async_tasksint32后台异步任务最大并发数,超出时新请求返回 HTTP 429
server.relay_registry_tokenstring""注册池 API 鉴权 token。非空时启用注册池
server.max_relay_ttlint0(不限)注册目标的最大 TTL 上限(秒)
server.max_registry_entriesint100注册池最大容量
log.modestringdaily日志模式:"daily"(按天轮转)或 "single"(单文件)
log.pathstring./logs日志目录(daily)或基础路径(single)
log.retention_daysint30日志保留天数(仅 daily 模式)
log.max_size_mbint0(不限)日志文件大小上限 MB,超过后轮转(仅 single 模式)
config_dirstring./hooks规则 YAML 文件所在目录

示例

server:
  port: 9000
  route: "/webhook"
  allow_all: false

log:
  mode: "daily"                # "daily"(默认)| "single"
  path: "./logs"
  retention_days: 30           # 仅 daily 模式
  # max_size_mb: 0             # 仅 single 模式,0 = 不限(默认)

config_dir: "./hooks"

server.allow_all

控制基础路由 /webhook 是否遍历所有 YAML 配置文件。

  • true — 请求 /webhook 时遍历所有配置文件,匹配第一个规则后停止
  • false(默认)— 请求 /webhook 返回 400,必须使用 /webhook/{filename} 定向路由

server.max_body_size_mb

限制传入请求体的最大大小,防止 DoS 攻击。

  • 10(默认)— 超过 10 MB 的请求体返回 HTTP 413
  • 0 — 不限制(谨慎使用)
  • 任意正整数 — 自定义限制(单位:MB)

server.relay_registry_token — 动态目标发现

启用 relay 注册池 API,允许下游 HookRun 实例自动注册。

# 上游(主 HookRun)
server:
  port: 9000
  relay_registry_token: "your-registry-secret"   # 注册 API 鉴权
  max_relay_ttl: 300                               # TTL 上限 5 分钟
  max_registry_entries: 100                        # 注册池容量

Relay API 端点

方法路径认证功能
GET/api/relay/status无需查看 relay 角色和状态(始终可用)
POST/api/relay/registerBearer Token注册或刷新目标 *
DELETE/api/relay/registerBearer Token注销目标 *
GET/api/relay/targetsBearer Token查看所有已注册目标 *

* 仅当 relay_registry_token 非空时可用。

注册请求体POST /api/relay/register):

{
  "url": "http://10.0.0.5:9000/webhook/deploy-app",
  "token": "downstream-auth-token",
  "tags": ["web", "prod"],
  "ttl": 120
}
字段类型必填说明
urlstring下游 webhook URL
tokenstring下游自身的 webhook 认证 token(上游中转事件时用于向下游认证)
tagsarray目标匹配标签
ttlintTTL 秒数(可能被上游 max_relay_ttl 截断)

认证示例(Bearer Token = 上游配置的 relay_registry_token):

curl -X POST http://upstream:9000/api/relay/register \
  -H "Authorization: Bearer your-registry-secret" \
  -H "Content-Type: application/json" \
  -d '{"url":"http://10.0.0.5:9000/webhook","token":"downstream-auth-token","tags":["prod"],"ttl":120}'

relay_client — 自动注册(下游)

配置下游 HookRun 实例在启动时自动向上游注册,并保持心跳续期:

# 下游 HookRun config.yaml
server:
  port: 9000

relay_client:
  upstream: "http://main-hookrun:9000"          # 上游地址(必填)
  url: "http://10.0.0.5:9000/webhook/deploy-app" # 本机可达 URL(不配则自动推断)
  token: "my-auth-token"                         # 下游认证 token
  registry_token: "your-registry-secret"         # 注册 API 鉴权 token
  tags: ["web", "prod"]                          # 标签(用于动态目标匹配)
  ttl: 120                                       # TTL(秒)
  webhook_path: "/webhook/deploy-app"            # 用于 URL 自动推断
字段类型必填说明
upstreamstring上游 HookRun 地址
urlstring本机可达 URL(不配则从 IP + port + webhook_path 自动推断)
tokenstring上游转发到此实例时使用的认证 token
registry_tokenstring注册 API 的 Bearer token
tagsarray标签列表(用于动态目标匹配)
ttlint建议 TTL(秒),可能被上游 max_relay_ttl 截断
webhook_pathstring用于 URL 自动推断的 webhook 路径(默认 /webhook

log.mode

控制日志文件的生成方式。

模式行为文件命名
daily(默认)每天一个文件,自动清理过期日志hookrun-2026-06-11.log
single固定一个文件,可按大小轮转hookrun.log

Daily 模式适合长期运行的服务,配合 retention_days 自动清理。

Single 模式适合容器环境(Docker/Kubernetes)或使用外部工具(logrotate)管理轮转。max_size_mb: 0 表示不限大小。

# 容器友好配置:单文件,不限制
log:
  mode: "single"
  path: "./logs"
  # max_size_mb: 0  (不限,交给 Docker 处理轮转)

2. 规则配置 — hooks/*.yaml

config_dir 目录下的每个 YAML 文件定义一个规则集。文件名(不含 .yaml 扩展名)用作 /webhook/{filename} 的路由标识。

顶层字段

字段类型必填说明
namestring规则集名称,用于日志和响应
asyncbooltrue = 立即返回 HTTP 202,后台执行 actions(默认 false
authobject认证设置(AND 关系)
executionobject文件级执行策略
filtersarray文件级全局过滤条件(与规则级 AND 组合)
logobject规则级独立日志文件(与全局双写)
rulesarray规则列表(至少一个)

2.1 auth — 认证

所有已配置的验证项为 AND 关系 — 每一项都必须通过。

字段类型必填说明
auth.token.sourcestring设置 token 时必填"header""query" — token 来源
auth.token.keystring设置 token 时必填Header 名称或 Query 参数名
auth.token.valuestring设置 token 时必填期望的 token 值
auth.hmac.headerstring设置 hmac 时必填签名 Header 名称,如 X-Hub-Signature-256
auth.hmac.secretstring设置 hmac 时必填HMAC 密钥(来自 Webhook 提供商设置)
auth.hmac.algorithmstring"sha256"(默认)| "sha1" | "sha512"
auth.hmac.prefixstring签名前缀,如 "sha256="(为空时根据 algorithm 自动推导)
auth.ip_whitelistarray允许的 IP 列表(支持 CIDR)

示例

auth:
  token:
    source: "header"
    key: "X-Webhook-Token"
    value: "secret123"
  hmac:
    header: "X-Hub-Signature-256"
    secret: "your-webhook-secret"
    algorithm: "sha256"
  ip_whitelist:
    - "192.168.1.100"
    - "10.0.0.0/24"

如果仅设置了 token,只需 token 验证。如果仅设置了 hmac,只需 HMAC 签名验证。如果仅设置了 ip_whitelist,只需 IP 验证。如果设置了多个,所有已设置项都必须通过(AND 关系)。

HMAC 签名验证

HMAC 验证使用配置的密钥和算法对原始请求体计算签名,然后与请求 Header 中的签名进行比对。这是 GitHub、GitLab、Bitbucket 等平台的标准验证方式。

平台Header算法前缀
GitHubX-Hub-Signature-256sha256sha256=
GitLabX-Gitlab-Token—(明文 Token,请使用 auth.token
BitbucketX-Hub-Signaturesha256sha256=

GitHub 配置示例:

auth:
  hmac:
    header: "X-Hub-Signature-256"
    secret: "your-github-webhook-secret"
    # algorithm 默认为 "sha256",prefix 自动推导为 "sha256="

自定义前缀示例(适配非标准格式的平台):

auth:
  hmac:
    header: "X-Signature"
    secret: "my-secret"
    algorithm: "sha512"
    prefix: "sha512="

2.2 execution — 执行策略

可在文件级(应用于所有规则)或规则级(覆盖文件级)设置。

字段类型必填说明
policystring"block" | "always" | "cooldown"
cooldown_secondsintcooldown 时必填冷却间隔秒数(必须 > 0)

策略类型

策略行为HTTP 响应适用场景
block上次执行未完成则拒绝409部署、构建、耗时任务
always每次都新开执行200无状态通知、日志记录
cooldown冷却窗口内拒绝429限频场景

继承关系

# 文件级默认
execution:
  policy: "block"

rules:
  - name: "deploy"
    # 继承文件级: block
    ...

  - name: "notify"
    execution:
      policy: "always"    # 覆盖: 始终执行
    ...

优先级:规则级 > 文件级 > 默认值 (block)


2.2.5 async — 异步执行

配置 async: true 后,匹配成功的请求立即返回 HTTP 202,actions 在后台执行:

name: "deploy"
async: true                     # 返回 202,后台执行
execution:
  policy: "block"
rules:
  - name: "deploy-main"
    actions:
      - type: "command"
        cmd: "deploy.sh"

行为说明:

  • 202 响应携带 request_id,用于关联日志与执行记录
  • 执行策略(block / cooldown)依然生效 — 策略拒绝(409/429)同步返回
  • 背压保护:后台运行任务数达到 server.max_async_tasks 时,新请求返回 429
  • 最近的异步执行记录可通过 GET /api/executions 查询(见使用文档)
  • 关闭时在途异步任务有 30 秒宽限期,超时后强制退出

2.3 filters — 文件级过滤条件

文件级 filters 作为全局约束,应用于该文件下的所有规则。与规则级 filters 为 AND 关系:两者必须同时匹配才能执行规则。

如果文件级 filters 不匹配,所有规则都会被跳过(短路)— 不会逐条评估。

无任何 filter 的规则(文件级和规则级都为空)为 catch-all — 匹配所有到达它的请求。在 first-match-wins 的链式匹配中,将 catch-all 规则放在末尾作为兆底。

# 文件级:所有规则的公共约束
filters:
  - type: "header"
    key: "X-GitHub-Event"
    operator: "eq"
    value: "push"

rules:
  - name: "deploy-main"
    filters:                         # 与文件级 AND 组合
      - type: "body"
        key: "ref"
        operator: "eq"
        value: "refs/heads/main"
    actions: [...]

  - name: "notify-all"
    # 无规则级 filters — 只要文件级 filters 通过就执行
    actions: [...]

过滤字段的定义、类型和操作符与规则级 filters 相同(见 2.4 节)。


2.3.5 log — 规则级日志

每个规则配置文件可以指定独立的日志文件。日志会双写到全局日志和规则专属日志(类似 nginx 的 access_log)。

字段类型必填说明
pathstring完整日志文件路径(如 ./logs/deploy.log

文件命名跟随全局 log.mode

模式log.path生成文件
daily./logs/deploy.log./logs/deploy-2026-06-11.log
single./logs/deploy.log./logs/deploy.log
log:
  path: "./logs/deploy.log"

规则级日志继承全局的 retention_daysmax_size_mb 设置。


2.4 rules — 规则列表

每条规则包含名称、过滤条件和动作。

字段类型必填说明
namestring规则名称,用于日志和响应
executionobject规则级执行策略(覆盖文件级)
filtersarray匹配条件(AND 关系;为空则匹配所有请求)
actionsarray要执行的命令/脚本(至少一个)

2.5 filters — 规则级过滤条件

同一规则内多个 filter 为 AND 关系 — 必须全部匹配。与文件级 filters(如有)同样为 AND 组合。

字段类型必填说明
typestring"header" | "query" | "body"
keystring要检查的字段名(body 支持 JSON path)
operatorstring"eq" | "ne" | "contains" | "regex"
valuestring期望匹配的值

过滤类型

类型来源示例
headerHTTP 请求头X-GitHub-Event
queryURL 查询参数?event=push
bodyJSON 请求体refcommits[0].message

操作符

操作符说明示例
eq精确匹配ref eq refs/heads/main
ne不等于status ne closed
contains子串包含message contains deploy
regex正则表达式ref regex refs/tags/v.*

JSON Path(body 类型)

支持点号和数组索引:

- type: "body"
  key: "ref"                    # 顶层字段
- type: "body"
  key: "commits[0].message"     # 嵌套 + 数组索引
- type: "body"
  key: "repository.owner.name"  # 深层嵌套

2.6 actions — 执行动作

动作按定义顺序依次执行

字段类型必填默认值说明
typestring"command""script""webhook""relay"
cmdstringcommand 时必填Shell 命令(支持模板变量)
pathstringscript 时必填脚本文件路径(支持模板变量)
argsarray[]脚本参数(支持模板变量)
pass_argsarray[]从请求中提取参数并追加为命令参数
env_fromarray[]从请求中提取值并注入为环境变量
timeoutint0(无限制)超时秒数
isolateboolfalse是否在隔离子进程中运行
continue_on_errorboolfalse失败后是否继续执行下一个动作

动作类型

类型说明必填字段
command内联 Shell 命令cmd
script外部脚本文件path
webhook向外部 URL 发送 HTTP 请求url
relay向多个 HookRun 实例转发请求relay.targets

平台行为

平台Shell参数
Linux/macOSsh-c
Windowscmd/c

环境变量

所有执行的命令都会收到环境变量 HOOKRUN=1

Webhook 动作

webhook 类型向外部 URL 发送 HTTP 请求,适用于通知 Slack、钉钉、飞书、或级联 HookRun 实例。

字段类型必填默认值说明
urlstring目标 URL(支持模板变量)
methodstringPOSTHTTP 方法:POSTPUTPATCHGET
headersmap{}自定义 headers(支持模板变量)
forward_headersarray[]白名单转发原始请求 headers
bodystring""请求体模板(支持 {{.raw_body}}
timeoutint30超时时间(秒)

自动 Headers — 每个 webhook 请求自动携带:

Header
X-HookRun-SourceHookRun/v<version>
X-HookRun-Config配置文件名(如 deploy-app
X-HookRun-Rule规则名(如 on-push

Header 合并优先级:自动 Headers → forward_headersheaders(自定义最高优先)。

{{.raw_body}} 模板 — 将原始请求体以 JSON 原文注入。仅限 webhook 的 body 字段使用(command/script 不支持,防止 shell 注入)。

注意body 字段必须是 YAML 字符串。请用引号('...')包裹 JSON 或使用块标量(|)。模板变量如 {{.raw_body}} 必须包含 {{ }} 分隔符,单独写 .raw_body 会被当作普通文本。

# ✓ 正确 — body 是字符串,使用模板语法
body: '{"event":"push","payload":{{.raw_body}}}'

# ✓ 正确 — 块标量写法
body: |
  {"text": "Deploy: {{.body.ref}}", "payload": {{.raw_body}}}

# ✗ 错误 — YAML 映射(会导致解析错误)
body:
  event: "push"
  payload: .raw_body
actions:
  # 完整转发原始 body
  - type: "webhook"
    url: "https://another-hookrun.example.com/webhook/deploy"
    body: "{{.raw_body}}"

  # 包裹原始 body + 自定义字段
  - type: "webhook"
    url: "https://hooks.slack.com/services/xxx"
    body: |
      {"text": "Deploy: {{.body.ref}}", "payload": {{.raw_body}}}

  # 转发指定 headers + 自定义认证
  - type: "webhook"
    url: "https://api.example.com/notify"
    method: "PUT"
    forward_headers:
      - "X-GitHub-Event"
      - "X-Request-Id"
    headers:
      Authorization: "Bearer {{.body.token}}"
    body: '{"event": "{{.header.x-event}}"}'

失败重试

Action 支持失败后自动重试,采用指数退避策略:

字段类型必填默认值说明
max_attemptsint1总尝试次数(含首次),必须 >= 1
interval_secondsint0基础间隔秒数,必须 >= 0
actions:
  - type: "command"
    cmd: "deploy.sh"
    retry:
      max_attempts: 3           # 最多尝试 3 次(首次 1 次 + 重试 2 次)
      interval_seconds: 5       # 基础间隔:5s

指数退避 — 重试间隔自动增长:interval × 2^(attempt-1),带 ±25% 随机抖动,上限 5 分钟。

interval_seconds: 5 示例:

  • 第 1 次重试:~5s
  • 第 2 次重试:~10s
  • 第 3 次重试:~20s

interval_seconds: 0 表示立即重试不等待。重试适用于所有 action 类型(command、script、webhook)。所有重试耗尽后才会评估 continue_on_error

模板变量

命令、脚本路径和脚本参数支持模板变量,在运行时从请求中解析实际值:

模板来源示例
{{.raw_body}}原始请求体完整 JSON body
{{.body.<path>}}JSON 请求体{{.body.ref}}{{.body.repository.owner.name}}
{{.header.<name>}}HTTP 请求头{{.header.X-GitHub-Event}}
{{.query.<name>}}URL 查询参数{{.query.token}}

body 路径支持点号和数组索引(与 filter body 类型相同)。

actions:
  - type: "command"
    cmd: "git checkout {{.body.ref}} && echo 'Event: {{.header.X-GitHub-Event}}'"

如果模板变量无法解析,将被替换为空字符串并记录警告日志。

pass_args — 提取并追加参数

pass_args 从请求中提取值并追加为命令或脚本的尾部参数。适合传递动态数据而无需在命令字符串中嵌入模板变量。

字段类型必填说明
sourcestring"header" | "query" | "body"
keystring字段名或 body 的 JSON path
actions:
  - type: "command"
    cmd: "echo 'Deploying:'"
    pass_args:
      - source: "body"
        key: "ref"
      - source: "header"
        key: "X-GitHub-Event"

当 webhook 收到 {"ref": "refs/heads/main"} 且 header 为 X-GitHub-Event: push 时,实际执行的命令为:

echo 'Deploying:' refs/heads/main push

env_from — 注入环境变量

env_from 从请求中提取值并作为环境变量注入到命令/脚本子进程中。所有变量名自动添加 HOOKRUN_ 前缀,防止与系统变量冲突。

字段类型必填说明
sourcestring"header" | "query" | "body"
keystring字段名或 body 的 JSON 路径
envstring环境变量后缀(自动添加 HOOKRUN_ 前缀)

默认环境变量(command/script 中始终可用):

变量说明
HOOKRUN_RAW_BODY原始请求体
HOOKRUN_TRIGGER_IP触发方 IP 地址
actions:
  - type: "script"
    path: "./scripts/deploy.sh"
    env_from:
      - source: "body"
        key: "ref"
        env: "GIT_REF"            # → $HOOKRUN_GIT_REF
      - source: "header"
        key: "X-GitHub-Event"
        env: "GITHUB_EVENT"       # → $HOOKRUN_GITHUB_EVENT

在脚本中:

#!/bin/bash
echo "Event: $HOOKRUN_GITHUB_EVENT"    # → push
echo "Ref: $HOOKRUN_GIT_REF"           # → refs/heads/main
echo "Full body: $HOOKRUN_RAW_BODY"    # → {"ref":"refs/heads/main",...}
echo "From: $HOOKRUN_TRIGGER_IP"       # → 192.30.252.0

注意:如果 env 已经以 HOOKRUN_ 开头,不会重复添加前缀。

Relay 动作 — 实例间中转

relay 类型将当前 webhook 请求原封不动地转发给多个 HookRun 实例,适用于多服务器部署、多环境联动、网络隔离等场景。

字段类型必填默认值说明
targetsarray目标列表(每个包含 url 和可选 token
forward_headersarray[]白名单转发原始请求 headers
max_relay_hopsint3防环上限(0 = 使用默认值 3)
timeoutint30单目标超时(秒)

目标配置

字段类型必填说明
urlstringurl/tag 二选一静态目标 HookRun 实例 URL
tokenstring下游认证 token
tagstringurl/tag 二选一动态目标标签 — 匹配所有包含该标签的已注册实例
actions:
  - type: "relay"
    relay:
      targets:
        - url: "http://10.0.0.2:9000/webhook/deploy-app"   # 静态目标
          token: "relay-secret-B"
        - url: "http://10.0.0.3:9000/webhook/deploy-app"
          token: "relay-secret-C"
        - tag: "prod"                                      # 动态:匹配所有带 "prod" 标签的已注册实例
      forward_headers:
        - "X-GitHub-Event"
      timeout: 30
      max_relay_hops: 3

自动 Headers — 每个 relay 请求自动携带:

Header
X-HookRun-Relaytrue
X-HookRun-Relay-From发送方 IP
X-HookRun-Request-ID唯一请求标识
X-HookRun-Relay-Hops当前跳数 + 1
X-HookRun-Relay-Token目标配置的 token
X-HookRun-SourceHookRun/v<version>

防环机制X-HookRun-Relay-Hops 每跳 +1,当跳数达到 max_relay_hops 时自动拒绝转发,防止无限循环。

幂等性去重:下游实例可配置去重窗口,防止因重试导致的重复执行:

# 下游 HookRun 实例的配置文件
name: "deploy-app"
auth:
  token:
    source: "header"
    key: "X-HookRun-Relay-Token"
    value: "relay-secret-B"
deduplicate:
  enabled: true
  window_seconds: 600    # 10分钟内相同 Request-ID 只执行一次

rules:
  - name: "deploy"
    actions:
      - type: "command"
        cmd: "cd /var/www/app && git pull && npm run build"
字段类型必填默认值说明
enabledboolfalse是否启用去重
window_secondsint启用时必填300去重窗口(秒)

示例

actions:
  - type: "command"
    cmd: "cd /var/www/app && git pull"
    timeout: 60
  - type: "command"
    cmd: "npm install --production"
    timeout: 120
    continue_on_error: true
  - type: "script"
    path: "./scripts/deploy.sh"
    args: ["production", "v2.1"]
    timeout: 300
    isolate: true

3. 完整示例

name: "github-auto-deploy"

auth:
  hmac:
    header: "X-Hub-Signature-256"
    secret: "your-github-webhook-secret"
  ip_whitelist:
    - "192.30.252.0/22"

execution:
  policy: "block"

# 文件级过滤条件:所有规则的全局约束
filters:
  - type: "header"
    key: "X-GitHub-Event"
    operator: "eq"
    value: "push"

rules:
  - name: "push-to-main"
    filters:   # 与文件级 AND 组合
      - type: "body"
        key: "ref"
        operator: "eq"
        value: "refs/heads/main"
    actions:
      - type: "command"
        cmd: "cd /var/www/app && git pull origin {{.body.ref}}"
        timeout: 30
      - type: "command"
        cmd: "cd /var/www/app && npm install --production && npm run build"
        timeout: 120
      - type: "script"
        path: "./scripts/restart.sh"
        args: ["{{.body.ref}}"]
        timeout: 60

  - name: "tag-release"
    execution:
      policy: "always"
    filters:
      - type: "body"
        key: "ref"
        operator: "regex"
        value: "refs/tags/v.*"
    actions:
      - type: "command"
        cmd: "echo 'Release tag:'"
        pass_args:
          - source: "body"
            key: "ref"
        timeout: 10

# 规则级独立日志(双写:全局 + 此文件)
log:
  path: "./logs/github-auto-deploy.log"

4. 密钥引用

YAML 配置中的所有字符串字段均支持 ${env:}${file:} 插值,避免明文存储密钥。

${env:VAR_NAME}

从环境变量读取值。

auth:
  token:
    source: "header"
    key: "X-Webhook-Token"
    value: "${env:WEBHOOK_TOKEN}"
  hmac:
    header: "X-Hub-Signature-256"
    secret: "${env:GITHUB_WEBHOOK_SECRET}"

如果环境变量未设置,HookRun 启动时会报错并终止。

${file:/path/to/secret}

从文件读取值,自动去除末尾的空白和换行符。

auth:
  token:
    source: "header"
    key: "X-Webhook-Token"
    value: "${file:/run/secrets/webhook_token}"

兼容 Docker Secrets、Kubernetes Secrets(挂载为文件)和 systemd credentials。

说明

  • 插值适用于 config.yamlhooks/*.yaml 中的所有字符串字段
  • 同一文件中可使用多个引用
  • 如果引用的环境变量或文件不存在,HookRun 在加载时报错(安全失败)