main
HookPilot
面向单管理员、单台 Linux 服务器的 Webhook 脚本管理平台:在网页上创建多个 Webhook 接口,为每个接口配置参数映射和 Bash 脚本;外部应用调用接口后,平台在宿主机上执行脚本并记录结果。
一个接口 = 调用地址 + 鉴权凭证 + 参数映射 + Bash 脚本 + 执行策略。
功能
- 单管理员登录、修改用户名与密码,不开放注册
- 接口管理:创建、编辑、复制、启用、停用、删除,支持分组
- 自定义接口标识(
/hooks/<标识>),GET / POST,独立 Token(只保存哈希,创建时显示一次) - 参数从 JSON、表单、Query 或指定 Header 提取,必填 / 默认值 / 字符串、数字、布尔、IP 校验,映射为
HOOK_环境变量 - Bash 编辑器(行号、缩进、语法高亮、示例模板),保存即生成脚本版本
- 执行策略:工作目录、超时、同步 / 异步响应、接口并发数
- 在线测试:预览参数映射,或真实执行并实时查看输出
- 执行记录:来源、参数摘要(敏感参数掩码)、脚本版本、状态、耗时、退出码;stdout / stderr 增量查看
- 任务控制:取消排队、终止运行(清理整个进程组)、使用原版本和参数再次执行
- 系统设置:全局并发上限、日志保留天数、输出大小上限
技术栈
| 层级 | 技术 |
|---|---|
| 前端 | Vite 8 + Vue 3 + TypeScript + CodeMirror 6 |
| 后端 | Node.js 22 + TypeScript + Fastify 5 |
| 数据库 | SQLite(Node 内置 node:sqlite,无原生编译依赖) |
| 执行层 | 宿主机 Bash 子进程,独立进程组 |
| 部署 | systemd + HTTPS 反向代理 |
目录结构
server/ 后端(模块化单体)
src/
index.ts 入口:初始化数据目录、恢复任务、启动服务
app.ts Fastify 应用装配、静态文件托管
config.ts 环境变量配置
db.ts SQLite 访问与迁移
settings.ts 系统设置
cli.ts 命令行工具(重置密码)
auth/ 密码哈希、管理员与会话、登录限流
hooks/ 接口配置存储、参数提取与校验
executor/ 任务存储(持久化队列)、调度器、Bash 执行器
routes/ 管理 API 与 Webhook 入口
web/ 前端
src/
api/ 接口类型与请求封装
components/ 布局、脚本编辑器、输出查看器、弹窗等
views/ 页面(接口详情的五个标签页在 views/hook/)
deploy/ systemd 单元、环境变量示例、Nginx / Caddy 示例
docs/ 部署说明、Lucky 对接示例
本地开发
需要 Node.js 22.13+ 和 Bash(Windows 下可使用 Git Bash,仅用于开发调试;进程组清理等行为以 Linux 为准)。
npm install
# 终端 1:后端(默认 http://127.0.0.1:8787,数据写入 ./data)
HOOKPILOT_ADMIN_PASSWORD=dev-password npm run dev:server
# 终端 2:前端开发服务器(http://localhost:5173,/api 与 /hooks 代理到后端)
npm run dev:web
首次启动若未设置 HOOKPILOT_ADMIN_PASSWORD,初始密码会随机生成并打印在后端日志中。
构建与运行
npm run build # 构建 web/dist 与 server/dist
npm start # 后端同时托管前端静态文件
npm run typecheck # 前后端静态类型检查
生产部署见 docs/deployment.md,Lucky 对接见 docs/lucky.md。
调用接口
curl -X POST 'https://hooks.example.com/hooks/home-ip' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"ip":"203.0.113.10"}'
Token 也可通过 X-Hook-Token 请求头或 ?token= 传递。
| 结果 | 同步模式 | 异步模式 |
|---|---|---|
| 已接收 | — | 202,返回任务 ID |
| 脚本成功 | 200 |
— |
| 脚本失败 / 超时 / 被终止 | 500 / 504 / 409 |
— |
| Token 错误 / 参数无效 / 已停用 / 方法不符 | 401 / 400 / 403 / 405(不执行脚本) |
同左 |
响应只包含任务 ID、状态与退出码,脚本输出只在管理界面查看。
脚本可用的环境变量
| 变量 | 说明 |
|---|---|
HOOK_* |
参数映射得到的变量,名称由管理员配置 |
HOOK_EXECUTION_ID |
任务 ID |
HOOK_SLUG |
接口标识 |
HOOK_TRIGGER |
触发方式:webhook / test / rerun |
HOOK_REQUEST_FILE |
本次任务专属的请求 JSON 文件(method、contentType、query、headers、bodyKind、body),执行结束后删除 |
PATH、HOME、USER、LOGNAME、SHELL、LANG、TZ |
基础运行环境;不继承服务自身的其他环境变量 |
请求数据不会替换进脚本文本,也不会拼接成 Shell 命令;含引号、换行或 Shell 特殊字符的参数都作为数据原样传递。脚本中请始终用双引号引用:"$HOOK_IP"。
执行规则
- 任务先持久化到 SQLite,再由调度器按接收顺序启动;同时受全局并发(默认 4)与接口并发(默认 1,即串行)限制。
- 入队时固定参数与脚本版本,之后修改脚本不影响已入队任务。
- 默认超时 30 秒;超时或手动终止时向整个进程组发送 SIGTERM,3 秒后 SIGKILL。
- 不自动重试。服务重启后排队任务继续执行,运行中的任务标记为“中断”,不自动重跑。
- 停用接口会拒绝新请求并取消该接口的排队任务;运行中的任务可单独终止。
- 单次执行输出上限默认 5 MiB(stdout + stderr),超出部分继续读取并丢弃,页面标记截断。
- 鉴权头、Cookie 与 query 中的 token 不写入执行记录;敏感参数在界面中以掩码显示,但脚本自己打印的内容仍会出现在输出里。
后续扩展(未实现)
第三方签名验证(如 GitHub)、定时执行与通知、可复用脚本库、配置导入导出、多节点与多用户、可视化工作流。
Description
Languages
TypeScript
53.7%
Vue
40.7%
CSS
5.3%
HTML
0.3%