mirror of
https://github.com/adnanh/webhook.git
synced 2026-07-20 16:53:47 +00:00
release
This commit is contained in:
parent
4018195ab5
commit
2098d78cdb
9 changed files with 821 additions and 8 deletions
140
.github/workflows/release.yml
vendored
Normal file
140
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Release version, for example v2.8.4"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
test:
|
||||
env:
|
||||
GOTOOLCHAIN: local
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22.x"
|
||||
- name: Test
|
||||
run: go test -v ./...
|
||||
|
||||
build:
|
||||
env:
|
||||
CGO_ENABLED: "0"
|
||||
GOTOOLCHAIN: local
|
||||
needs: test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- goos: darwin
|
||||
goarch: amd64
|
||||
- goos: darwin
|
||||
goarch: arm64
|
||||
- goos: freebsd
|
||||
goarch: 386
|
||||
- goos: freebsd
|
||||
goarch: amd64
|
||||
- goos: freebsd
|
||||
goarch: arm64
|
||||
- goos: linux
|
||||
goarch: 386
|
||||
- goos: linux
|
||||
goarch: amd64
|
||||
- goos: linux
|
||||
goarch: arm
|
||||
- goos: linux
|
||||
goarch: arm64
|
||||
- goos: openbsd
|
||||
goarch: 386
|
||||
- goos: openbsd
|
||||
goarch: amd64
|
||||
- goos: openbsd
|
||||
goarch: arm64
|
||||
- goos: windows
|
||||
goarch: 386
|
||||
- goos: windows
|
||||
goarch: amd64
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22.x"
|
||||
|
||||
- name: Resolve version
|
||||
id: version
|
||||
shell: bash
|
||||
run: |
|
||||
version="${{ github.event.inputs.version || github.ref_name }}"
|
||||
version="${version#v}"
|
||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build archive
|
||||
shell: bash
|
||||
run: |
|
||||
target="webhook-${{ matrix.goos }}-${{ matrix.goarch }}"
|
||||
mkdir -p "dist/$target"
|
||||
|
||||
binary="webhook"
|
||||
if [ "${{ matrix.goos }}" = "windows" ]; then
|
||||
binary="webhook.exe"
|
||||
fi
|
||||
|
||||
GOOS="${{ matrix.goos }}" GOARCH="${{ matrix.goarch }}" \
|
||||
go build -trimpath -ldflags="-s -w -X main.version=${{ steps.version.outputs.version }}" \
|
||||
-o "dist/$target/$binary" .
|
||||
|
||||
cp LICENSE README.md "dist/$target/"
|
||||
tar -czf "dist/$target.tar.gz" -C dist "$target"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: webhook-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||
path: dist/*.tar.gz
|
||||
if-no-files-found: error
|
||||
|
||||
publish:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
|
||||
- name: Generate checksums
|
||||
shell: bash
|
||||
run: |
|
||||
cd dist
|
||||
sha256sum *.tar.gz > checksums.txt
|
||||
|
||||
- name: Resolve tag
|
||||
id: tag
|
||||
shell: bash
|
||||
run: |
|
||||
tag="${{ github.event.inputs.version || github.ref_name }}"
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Publish GitHub release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ steps.tag.outputs.tag }}
|
||||
name: ${{ steps.tag.outputs.tag }}
|
||||
files: |
|
||||
dist/*.tar.gz
|
||||
dist/checksums.txt
|
||||
generate_release_notes: true
|
||||
25
README.md
25
README.md
|
|
@ -45,11 +45,26 @@ If you are using Debian linux ("stretch" or later), you can install webhook usin
|
|||
#### FreeBSD
|
||||
If you are using FreeBSD, you can install webhook using `pkg install webhook`.
|
||||
|
||||
### Download prebuilt binaries
|
||||
Prebuilt binaries for different architectures are available at [GitHub Releases](https://github.com/adnanh/webhook/releases).
|
||||
|
||||
## Configuration
|
||||
Next step is to define some hooks you want [webhook][w] to serve.
|
||||
### Download prebuilt binaries
|
||||
Prebuilt binaries for different architectures are available at [GitHub Releases](https://github.com/xtulnx/webhook/releases).
|
||||
|
||||
### One-line install or update
|
||||
The install scripts download the latest GitHub Release asset for your platform and replace the local binary.
|
||||
|
||||
Linux, macOS, FreeBSD, or OpenBSD:
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/xtulnx/webhook/master/scripts/install.sh | sh
|
||||
```
|
||||
|
||||
Windows PowerShell:
|
||||
```powershell
|
||||
irm https://raw.githubusercontent.com/xtulnx/webhook/master/scripts/install.ps1 | iex
|
||||
```
|
||||
|
||||
Set `WEBHOOK_VERSION` to install a specific release tag, `WEBHOOK_REPO` to install from a fork, or `WEBHOOK_INSTALL_DIR` to choose the destination directory.
|
||||
|
||||
## Configuration
|
||||
Next step is to define some hooks you want [webhook][w] to serve.
|
||||
[webhook][w] supports JSON or YAML configuration files, but we'll focus primarily on JSON in the following example.
|
||||
Begin by creating an empty file named `hooks.json`. This file will contain an array of hooks the [webhook][w] will serve. Check [Hook definition page](docs/Hook-Definition.md) to see the detailed description of what properties a hook can contain, and how to use them.
|
||||
|
||||
|
|
|
|||
456
README_CN.md
Normal file
456
README_CN.md
Normal file
|
|
@ -0,0 +1,456 @@
|
|||
# webhook 中文使用指南
|
||||
|
||||
`webhook` 是一个用 Go 编写的轻量级 HTTP 回调服务。它可以把请求中的 header、query、payload、文件等数据映射到命令参数或环境变量,并在规则校验通过后执行指定命令。
|
||||
|
||||
本仓库是从 `adnanh/webhook` fork 而来的增强版本,仓库地址为 [xtulnx/webhook](https://github.com/xtulnx/webhook)。除了上游原有能力外,本版本补充了 YAML 总配置、Admin 管理界面、命令超时、并发限制、反向代理真实 IP、PID 文件、一键安装脚本和 GitHub Release 编译发布流程。
|
||||
|
||||

|
||||
|
||||
## 主要特性
|
||||
|
||||
- 支持 JSON/YAML hook 配置。
|
||||
- 支持 `-c`、`-config`、`--config` 加载 YAML 总配置文件。
|
||||
- 支持 Admin UI 在线管理已加载的 hooks 文件。
|
||||
- Admin 登录使用 TOTP 动态验证码,登录后使用短期 JWT 会话。
|
||||
- 支持全局和单 hook 的命令执行超时。
|
||||
- 支持全局和单 hook 的并发执行限制。
|
||||
- 支持反向代理后的真实客户端 IP 提取,适配 `ip-whitelist`。
|
||||
- 支持 multipart 上传文件以临时环境变量形式传给命令。
|
||||
- 支持 PID 文件、日志文件、热重载、自定义响应头、TLS、Unix socket。
|
||||
- 提供 Linux/macOS/BSD 的 shell 一键安装脚本和 Windows PowerShell 一键安装脚本。
|
||||
- 提供 GitHub Actions 自动编译、打包、校验和发布脚本。
|
||||
|
||||
## 快速安装或更新
|
||||
|
||||
Linux、macOS、FreeBSD、OpenBSD:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/xtulnx/webhook/master/scripts/install.sh | sh
|
||||
```
|
||||
|
||||
Windows PowerShell:
|
||||
|
||||
```powershell
|
||||
irm https://raw.githubusercontent.com/xtulnx/webhook/master/scripts/install.ps1 | iex
|
||||
```
|
||||
|
||||
安装脚本默认安装最新 GitHub Release,并进行 SHA256 校验。再次执行同一条命令即可更新到最新版本。
|
||||
|
||||
可通过环境变量调整安装行为:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/xtulnx/webhook/master/scripts/install.sh | \
|
||||
WEBHOOK_VERSION=v2.8.4 WEBHOOK_INSTALL_DIR="$HOME/.local/bin" sh
|
||||
```
|
||||
|
||||
PowerShell 示例:
|
||||
|
||||
```powershell
|
||||
$env:WEBHOOK_VERSION = "v2.8.4"
|
||||
$env:WEBHOOK_INSTALL_DIR = "$env:USERPROFILE\bin"
|
||||
irm https://raw.githubusercontent.com/xtulnx/webhook/master/scripts/install.ps1 | iex
|
||||
```
|
||||
|
||||
常用变量:
|
||||
|
||||
- `WEBHOOK_REPO`: GitHub 仓库,默认 `xtulnx/webhook`。
|
||||
- `WEBHOOK_VERSION`: 版本 tag,默认 `latest`。
|
||||
- `WEBHOOK_INSTALL_DIR`: 安装目录。Unix 默认 `/usr/local/bin`,Windows 默认 `%LOCALAPPDATA%\Programs\webhook`。
|
||||
- `WEBHOOK_BINARY_NAME`: 安装后的 binary 名称,默认 `webhook` 或 `webhook.exe`。
|
||||
|
||||
## 从源码构建
|
||||
|
||||
需要 Go 1.21 或更新版本。
|
||||
|
||||
```bash
|
||||
git clone https://github.com/xtulnx/webhook.git
|
||||
cd webhook
|
||||
go build
|
||||
./webhook -version
|
||||
```
|
||||
|
||||
运行测试:
|
||||
|
||||
```bash
|
||||
go test ./...
|
||||
```
|
||||
|
||||
生成本地 release 包:
|
||||
|
||||
```bash
|
||||
make release
|
||||
make release-windows
|
||||
```
|
||||
|
||||
## 最小可用示例
|
||||
|
||||
创建 hook 文件 `hooks.yaml`:
|
||||
|
||||
```yaml
|
||||
- id: deploy
|
||||
execute-command: /usr/local/bin/deploy.sh
|
||||
command-working-directory: /srv/app
|
||||
http-methods:
|
||||
- POST
|
||||
response-message: Deploy triggered
|
||||
trigger-rule:
|
||||
match:
|
||||
type: value
|
||||
value: my-secret
|
||||
parameter:
|
||||
source: header
|
||||
name: X-Webhook-Secret
|
||||
```
|
||||
|
||||
启动服务:
|
||||
|
||||
```bash
|
||||
webhook -hooks hooks.yaml -verbose
|
||||
```
|
||||
|
||||
触发 hook:
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "X-Webhook-Secret: my-secret" \
|
||||
http://127.0.0.1:9000/hooks/deploy
|
||||
```
|
||||
|
||||
默认监听地址是 `0.0.0.0:9000`,默认 hook URL 前缀是 `/hooks/`。
|
||||
|
||||
## 使用 YAML 总配置文件
|
||||
|
||||
本 fork 新增了总配置文件能力。可以把命令行参数写进 YAML 文件,再用 `-c`、`-config` 或 `--config` 启动。
|
||||
|
||||
示例 `webhook.yaml`:
|
||||
|
||||
```yaml
|
||||
ip: 0.0.0.0
|
||||
port: 1987
|
||||
urlprefix: wh
|
||||
hooks:
|
||||
- /etc/webhook/admin.yaml
|
||||
- /etc/webhook/hooks.yaml
|
||||
hotreload: true
|
||||
nopanic: true
|
||||
verbose: true
|
||||
logfile: /var/log/webhook.log
|
||||
pidfile: /var/run/webhook.pid
|
||||
command-timeout: 30s
|
||||
max-concurrency: 4
|
||||
```
|
||||
|
||||
启动:
|
||||
|
||||
```bash
|
||||
webhook -c /etc/webhook/webhook.yaml
|
||||
```
|
||||
|
||||
命令行参数优先级高于配置文件。例如:
|
||||
|
||||
```bash
|
||||
webhook -c /etc/webhook/webhook.yaml -port 9000 -debug
|
||||
```
|
||||
|
||||
完整示例可参考 [webhook.yaml.example](webhook.yaml.example)。
|
||||
|
||||
## Admin 管理界面
|
||||
|
||||
本 fork 内置 Admin UI 和 API,可在线查看、新增、编辑和删除已加载的 hooks 文件。
|
||||
|
||||

|
||||
|
||||
启用方式:
|
||||
|
||||
```yaml
|
||||
admin: true
|
||||
admin-path: admin
|
||||
admin-totp-secret: "BASE32_TOTP_SECRET"
|
||||
admin-jwt-secret: "replace-with-a-long-random-secret"
|
||||
admin-session-ttl: 12h
|
||||
```
|
||||
|
||||
启动后访问:
|
||||
|
||||
```text
|
||||
http://127.0.0.1:1987/admin/
|
||||
```
|
||||
|
||||
生成 TOTP Base32 密钥:
|
||||
|
||||
```bash
|
||||
python3 -c 'import base64, os; print(base64.b32encode(os.urandom(20)).decode().rstrip("="))'
|
||||
```
|
||||
|
||||
把生成的密钥配置到 Google Authenticator、Microsoft Authenticator、1Password 等认证器中,然后在 Admin 登录页输入当前 6 位动态码。
|
||||
|
||||
注意事项:
|
||||
|
||||
- `admin-path` 不能和 `urlprefix` 相同。
|
||||
- `admin-totp-secret` 必须是 Base32 编码。
|
||||
- `admin-jwt-secret` 必须设置为足够长的随机字符串。
|
||||
- 如果启用了 `template: true`,Admin 写入会进入只读模式,避免覆盖模板配置。
|
||||
- 生产环境建议放在 HTTPS 或受保护的反向代理后面。
|
||||
|
||||

|
||||
|
||||
## Hook 配置要点
|
||||
|
||||
Hook 至少需要 `id` 和 `execute-command`:
|
||||
|
||||
```yaml
|
||||
- id: example
|
||||
execute-command: /usr/local/bin/example.sh
|
||||
```
|
||||
|
||||
常用字段:
|
||||
|
||||
- `command-working-directory`: 命令工作目录。
|
||||
- `pass-arguments-to-command`: 把请求值作为命令参数传入。
|
||||
- `pass-environment-to-command`: 把请求值作为环境变量传入。
|
||||
- `pass-file-to-command`: 把文件参数传入命令。
|
||||
- `parse-parameters-as-json`: 把指定参数按 JSON 解析。
|
||||
- `trigger-rule`: 触发规则,支持 `and`、`or`、`not`、`match`。
|
||||
- `response-message`: 成功响应文本。
|
||||
- `success-http-response-code`: 成功响应状态码。
|
||||
- `trigger-rule-mismatch-http-response-code`: 规则不匹配时的状态码。
|
||||
- `include-command-output-in-response`: 把命令输出写入响应。
|
||||
- `include-command-output-in-response-on-error`: 命令失败时也返回命令输出。
|
||||
- `command-timeout`: 覆盖全局命令超时。
|
||||
- `max-concurrency`: 覆盖全局并发限制。
|
||||
- `keep-file-environment`: 暴露上传文件临时路径给命令。
|
||||
|
||||
更完整的字段说明请参考 [docs/Hook-Definition.md](docs/Hook-Definition.md)。
|
||||
|
||||
## 命令超时与并发限制
|
||||
|
||||
全局命令超时:
|
||||
|
||||
```bash
|
||||
webhook -hooks hooks.yaml -command-timeout 30s
|
||||
```
|
||||
|
||||
单个 hook 覆盖:
|
||||
|
||||
```yaml
|
||||
- id: slow-task
|
||||
execute-command: /usr/local/bin/slow-task.sh
|
||||
command-timeout: 2m
|
||||
```
|
||||
|
||||
`0` 表示禁用超时:
|
||||
|
||||
```yaml
|
||||
- id: no-timeout-task
|
||||
execute-command: /usr/local/bin/task.sh
|
||||
command-timeout: "0"
|
||||
```
|
||||
|
||||
全局并发限制:
|
||||
|
||||
```bash
|
||||
webhook -hooks hooks.yaml -max-concurrency 2
|
||||
```
|
||||
|
||||
单个 hook 覆盖:
|
||||
|
||||
```yaml
|
||||
- id: deploy
|
||||
execute-command: /usr/local/bin/deploy.sh
|
||||
max-concurrency: 1
|
||||
```
|
||||
|
||||
当并发达到上限时,请求会返回 `503 Service Unavailable`。
|
||||
|
||||
## 反向代理与真实 IP
|
||||
|
||||
如果 webhook 部署在 Nginx、Traefik、Caddy 等反向代理后面,直接使用 `RemoteAddr` 会拿到代理 IP,而不是真实客户端 IP。本 fork 支持可信代理配置,配合 `ip-whitelist` 使用。
|
||||
|
||||
配置示例:
|
||||
|
||||
```yaml
|
||||
real-ip-header: X-Real-Ip
|
||||
trusted-proxies: "127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
|
||||
```
|
||||
|
||||
Nginx 示例:
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:1987;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
```
|
||||
|
||||
只有当请求来源属于 `trusted-proxies` 时,webhook 才会信任 `real-ip-header`,防止客户端伪造 IP header 绕过白名单。
|
||||
|
||||
## 上传文件处理
|
||||
|
||||
multipart 表单中,符合条件的 JSON 文件或被 `parse-parameters-as-json` 指定的文件会被解析到 payload。
|
||||
|
||||
如果命令需要直接读取上传文件,可启用:
|
||||
|
||||
```yaml
|
||||
- id: upload
|
||||
execute-command: /usr/local/bin/handle-upload.sh
|
||||
keep-file-environment: true
|
||||
```
|
||||
|
||||
字段名为 `pkg` 的上传文件会在命令运行期间暴露为:
|
||||
|
||||
```text
|
||||
HOOK_FILE_PKG=/tmp/...
|
||||
HOOK_FILENAME_PKG=original-file-name.tar.gz
|
||||
```
|
||||
|
||||
命令结束后临时文件会被清理。建议 multipart 字段名只使用字母、数字和下划线,方便 shell 脚本读取。
|
||||
|
||||
## HTTPS、日志和 PID 文件
|
||||
|
||||
HTTPS:
|
||||
|
||||
```bash
|
||||
webhook -hooks hooks.yaml -secure -cert /etc/webhook/cert.pem -key /etc/webhook/key.pem
|
||||
```
|
||||
|
||||
指定 TLS 最低版本:
|
||||
|
||||
```bash
|
||||
webhook -hooks hooks.yaml -secure -tls-min-version 1.2
|
||||
```
|
||||
|
||||
日志文件:
|
||||
|
||||
```bash
|
||||
webhook -hooks hooks.yaml -verbose -logfile /var/log/webhook.log
|
||||
```
|
||||
|
||||
PID 文件:
|
||||
|
||||
```bash
|
||||
webhook -hooks hooks.yaml -pidfile /var/run/webhook.pid
|
||||
```
|
||||
|
||||
热重载:
|
||||
|
||||
```bash
|
||||
webhook -hooks hooks.yaml -hotreload
|
||||
```
|
||||
|
||||
## systemd 示例
|
||||
|
||||
`/etc/systemd/system/webhook.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Webhook service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/webhook -c /etc/webhook/webhook.yaml
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
启用并启动:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now webhook
|
||||
sudo systemctl status webhook
|
||||
```
|
||||
|
||||
## GitHub 编译发布流程
|
||||
|
||||
本仓库新增 [release workflow](.github/workflows/release.yml)。当推送 `v*` tag 时,会自动:
|
||||
|
||||
1. 运行测试。
|
||||
2. 为 Linux、macOS、FreeBSD、OpenBSD、Windows 构建多架构 binary。
|
||||
3. 打包为 `webhook-{os}-{arch}.tar.gz`。
|
||||
4. 生成 `checksums.txt`。
|
||||
5. 发布到 GitHub Releases。
|
||||
|
||||
发布新版本:
|
||||
|
||||
```bash
|
||||
git tag v2.8.4
|
||||
git push origin v2.8.4
|
||||
```
|
||||
|
||||
也可以在 GitHub Actions 页面手动运行 `release` workflow,并填写版本号。
|
||||
|
||||
发布前建议确认:
|
||||
|
||||
- `webhook.go` 中默认版本号已更新,或确认 workflow 注入的 tag 版本符合预期。
|
||||
- GitHub Actions 对仓库有 `contents: write` 权限。
|
||||
- 目标 tag 不要重复使用,除非你明确要覆盖 Release。
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 一键安装下载失败
|
||||
|
||||
检查 GitHub Release 是否已经存在对应平台资产。例如 Linux amd64 需要:
|
||||
|
||||
```text
|
||||
webhook-linux-amd64.tar.gz
|
||||
```
|
||||
|
||||
也可以指定仓库和版本:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/xtulnx/webhook/master/scripts/install.sh | \
|
||||
WEBHOOK_REPO=xtulnx/webhook WEBHOOK_VERSION=v2.8.4 sh
|
||||
```
|
||||
|
||||
### Admin 无法登录
|
||||
|
||||
优先检查:
|
||||
|
||||
- `admin: true` 是否启用。
|
||||
- `admin-totp-secret` 是否为 Base32。
|
||||
- 认证器时间是否准确。
|
||||
- `admin-jwt-secret` 是否为空。
|
||||
- 请求路径是否为配置的 `admin-path`。
|
||||
|
||||
### IP 白名单在反向代理后不生效
|
||||
|
||||
需要同时配置:
|
||||
|
||||
- 反向代理写入 `X-Real-IP` 或 `X-Forwarded-For`。
|
||||
- webhook 设置 `real-ip-header`。
|
||||
- webhook 设置 `trusted-proxies`,并包含代理服务器 IP。
|
||||
|
||||
### Hook 文件无法通过 Admin 修改
|
||||
|
||||
如果使用 `template: true`,Admin 写入会被禁用。请关闭模板模式,或手动编辑模板源文件。
|
||||
|
||||
## 目录说明
|
||||
|
||||
- `webhook.go`: 主入口和 CLI 参数。
|
||||
- `config.go`: YAML 总配置加载。
|
||||
- `admin.go`、`admin_store.go`、`admin_ui.go`: Admin UI/API 和配置写入。
|
||||
- `execution.go`: 命令超时和并发控制。
|
||||
- `realip.go`: 反向代理真实 IP 处理。
|
||||
- `internal/hook/`: hook 解析、规则判断和请求映射。
|
||||
- `internal/middleware/`: HTTP 日志和请求辅助中间件。
|
||||
- `internal/pidfile/`: PID 文件处理。
|
||||
- `adminui/`: 内嵌 Admin 前端页面。
|
||||
- `scripts/`: 一键安装脚本。
|
||||
- `.github/workflows/`: GitHub Actions 构建和发布脚本。
|
||||
|
||||
## 安全建议
|
||||
|
||||
- 不要提交真实密钥、生产 hook 定义或 TOTP/JWT secret。
|
||||
- Admin UI 建议放在 HTTPS 后面,并限制访问来源。
|
||||
- `trusted-proxies` 只填写你真正控制的代理地址。
|
||||
- `include-command-output-in-response` 可能泄露命令输出,生产环境谨慎开启。
|
||||
- hook 执行的脚本要自行做好权限、参数校验和日志记录。
|
||||
|
||||
## 许可证
|
||||
|
||||
本项目沿用上游 MIT License。详见 [LICENSE](LICENSE)。
|
||||
BIN
images/img01.webp
Normal file
BIN
images/img01.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
images/img02.webp
Normal file
BIN
images/img02.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
images/img03.webp
Normal file
BIN
images/img03.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
83
scripts/install.ps1
Normal file
83
scripts/install.ps1
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
[CmdletBinding()]
|
||||
param(
|
||||
[string] $Repo = $env:WEBHOOK_REPO,
|
||||
[string] $InstallDir = $env:WEBHOOK_INSTALL_DIR,
|
||||
[string] $Version = $env:WEBHOOK_VERSION,
|
||||
[string] $BinaryName = $env:WEBHOOK_BINARY_NAME
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Repo)) {
|
||||
$Repo = "xtulnx/webhook"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($InstallDir)) {
|
||||
$InstallDir = Join-Path $env:LOCALAPPDATA "Programs\webhook"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($Version)) {
|
||||
$Version = "latest"
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($BinaryName)) {
|
||||
$BinaryName = "webhook.exe"
|
||||
}
|
||||
if (-not $BinaryName.EndsWith(".exe", [StringComparison]::OrdinalIgnoreCase)) {
|
||||
$BinaryName = "$BinaryName.exe"
|
||||
}
|
||||
|
||||
switch ($env:PROCESSOR_ARCHITECTURE) {
|
||||
"AMD64" { $Arch = "amd64" }
|
||||
"ARM64" { $Arch = "arm64" }
|
||||
"x86" { $Arch = "386" }
|
||||
default {
|
||||
throw "Unsupported architecture: $env:PROCESSOR_ARCHITECTURE"
|
||||
}
|
||||
}
|
||||
|
||||
$Asset = "webhook-windows-$Arch.tar.gz"
|
||||
if ($Version -eq "latest") {
|
||||
$Url = "https://github.com/$Repo/releases/latest/download/$Asset"
|
||||
$ChecksumsUrl = "https://github.com/$Repo/releases/latest/download/checksums.txt"
|
||||
} else {
|
||||
$Url = "https://github.com/$Repo/releases/download/$Version/$Asset"
|
||||
$ChecksumsUrl = "https://github.com/$Repo/releases/download/$Version/checksums.txt"
|
||||
}
|
||||
|
||||
$TempDir = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
|
||||
New-Item -ItemType Directory -Path $TempDir | Out-Null
|
||||
|
||||
try {
|
||||
$Archive = Join-Path $TempDir $Asset
|
||||
Write-Host "Downloading $Repo $Version for windows/$Arch..."
|
||||
Invoke-WebRequest -Uri $Url -OutFile $Archive
|
||||
$ChecksumsPath = Join-Path $TempDir "checksums.txt"
|
||||
Invoke-WebRequest -Uri $ChecksumsUrl -OutFile $ChecksumsPath
|
||||
|
||||
$ChecksumLine = Get-Content $ChecksumsPath | Where-Object { $_ -match "\s$([regex]::Escape($Asset))$" } | Select-Object -First 1
|
||||
if (-not $ChecksumLine) {
|
||||
throw "Checksum for $Asset not found"
|
||||
}
|
||||
|
||||
$ExpectedHash = ($ChecksumLine -split "\s+")[0].ToLowerInvariant()
|
||||
$ActualHash = (Get-FileHash -Algorithm SHA256 -Path $Archive).Hash.ToLowerInvariant()
|
||||
if ($ActualHash -ne $ExpectedHash) {
|
||||
throw "Checksum mismatch for $Asset"
|
||||
}
|
||||
|
||||
tar -xzf $Archive -C $TempDir
|
||||
|
||||
$Source = Join-Path $TempDir "webhook-windows-$Arch\webhook.exe"
|
||||
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
|
||||
Copy-Item -Path $Source -Destination (Join-Path $InstallDir $BinaryName) -Force
|
||||
|
||||
Write-Host "Installed $BinaryName to $InstallDir"
|
||||
& (Join-Path $InstallDir $BinaryName) -version
|
||||
|
||||
$UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
||||
$Paths = $UserPath -split ";" | Where-Object { $_ }
|
||||
if ($Paths -notcontains $InstallDir) {
|
||||
[Environment]::SetEnvironmentVariable("Path", (($Paths + $InstallDir) -join ";"), "User")
|
||||
Write-Host "Added $InstallDir to the user PATH. Open a new terminal to use webhook directly."
|
||||
}
|
||||
} finally {
|
||||
Remove-Item -Path $TempDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
121
scripts/install.sh
Executable file
121
scripts/install.sh
Executable file
|
|
@ -0,0 +1,121 @@
|
|||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
repo="${WEBHOOK_REPO:-xtulnx/webhook}"
|
||||
install_dir="${WEBHOOK_INSTALL_DIR:-/usr/local/bin}"
|
||||
version="${WEBHOOK_VERSION:-latest}"
|
||||
binary_name="${WEBHOOK_BINARY_NAME:-webhook}"
|
||||
|
||||
need() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
echo "error: required command not found: $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
detect_os() {
|
||||
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
||||
case "$os" in
|
||||
darwin|freebsd|linux|openbsd) printf '%s' "$os" ;;
|
||||
*) echo "error: unsupported OS: $os" >&2; exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
detect_arch() {
|
||||
arch="$(uname -m)"
|
||||
case "$arch" in
|
||||
x86_64|amd64) printf 'amd64' ;;
|
||||
aarch64|arm64) printf 'arm64' ;;
|
||||
i386|i686) printf '386' ;;
|
||||
armv6l|armv7l|arm) printf 'arm' ;;
|
||||
*) echo "error: unsupported architecture: $arch" >&2; exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
download() {
|
||||
url="$1"
|
||||
output="$2"
|
||||
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -fsSL "$url" -o "$output"
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -q "$url" -O "$output"
|
||||
else
|
||||
echo "error: curl or wget is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
verify_checksum() {
|
||||
checksums="$1"
|
||||
archive="$2"
|
||||
asset="$3"
|
||||
|
||||
expected="$(grep " $asset\$" "$checksums" | awk '{print $1}')"
|
||||
if [ -z "$expected" ]; then
|
||||
echo "error: checksum for $asset not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
actual="$(sha256sum "$archive" | awk '{print $1}')"
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
actual="$(shasum -a 256 "$archive" | awk '{print $1}')"
|
||||
elif command -v sha256 >/dev/null 2>&1; then
|
||||
actual="$(sha256 -q "$archive")"
|
||||
else
|
||||
echo "warning: no SHA256 command found; skipping checksum verification" >&2
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$actual" != "$expected" ]; then
|
||||
echo "error: checksum mismatch for $asset" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_binary() {
|
||||
src="$1"
|
||||
dst="$2"
|
||||
|
||||
mkdir -p "$install_dir" 2>/dev/null || true
|
||||
if [ -w "$install_dir" ]; then
|
||||
install -m 0755 "$src" "$dst"
|
||||
elif command -v sudo >/dev/null 2>&1; then
|
||||
sudo mkdir -p "$install_dir"
|
||||
sudo install -m 0755 "$src" "$dst"
|
||||
else
|
||||
echo "error: $install_dir is not writable and sudo is not available" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
need uname
|
||||
need tar
|
||||
|
||||
os="$(detect_os)"
|
||||
arch="$(detect_arch)"
|
||||
asset="webhook-$os-$arch.tar.gz"
|
||||
|
||||
if [ "$version" = "latest" ]; then
|
||||
url="https://github.com/$repo/releases/latest/download/$asset"
|
||||
checksums_url="https://github.com/$repo/releases/latest/download/checksums.txt"
|
||||
else
|
||||
url="https://github.com/$repo/releases/download/$version/$asset"
|
||||
checksums_url="https://github.com/$repo/releases/download/$version/checksums.txt"
|
||||
fi
|
||||
|
||||
tmp="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||
|
||||
archive="$tmp/$asset"
|
||||
echo "Downloading $repo $version for $os/$arch..."
|
||||
download "$url" "$archive"
|
||||
download "$checksums_url" "$tmp/checksums.txt"
|
||||
verify_checksum "$tmp/checksums.txt" "$archive" "$asset"
|
||||
|
||||
tar -xzf "$archive" -C "$tmp"
|
||||
install_binary "$tmp/webhook-$os-$arch/webhook" "$install_dir/$binary_name"
|
||||
|
||||
echo "Installed $binary_name to $install_dir"
|
||||
"$install_dir/$binary_name" -version
|
||||
|
|
@ -25,9 +25,7 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
const (
|
||||
version = "2.8.3"
|
||||
)
|
||||
var version = "2.8.3"
|
||||
|
||||
var (
|
||||
ip = flag.String("ip", "0.0.0.0", "ip the webhook should serve hooks on")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue