配置
通知
hub 把节点掉线、流量将尽、即将到期和面板登录推送给你。渠道有两个:Telegram 机器人,以及请求体可以自定义的 Webhook。两个都配上时两边都发。
通知哪些事
| 事件 | 什么时候发 | 在哪开关 |
|---|---|---|
| 🔴 离线 | 节点断开超过宽限期(默认 3 分钟) | 每个节点单独开,默认关 |
| 🟢 恢复在线 | 发过离线通知的节点重新连上 | 跟着离线走 |
| ⚠️ 流量提醒 | 本期用量达到阈值(默认 80%)和 100% 时各一次 | 节点填了每月额度就生效 |
| ⏳ 即将到期 | 每天 9 点汇总一条,列出 7 天内到期的节点 | 节点填了到期日就生效 |
| 🔁 已自动续期 | 在线节点过了到期日,hub 把日期往后顺延时 | 同上 |
| 🔑 面板登录 | 应急密码或 GitHub 登录成功 | 全局开关,默认开 |
几条规则:
- 宽限期内断开又连上的,什么都不发。恢复通知只跟在离线通知后面,网络抖动不会刷屏。
- 反复掉线的节点自动降噪。节点在最近 1 小时内有过一次超过宽限期的掉线,下一次掉线要持续 30 分钟才报;稳定在线满 1 小时后恢复正常宽限期。真掉线仍然会报,最多晚 30 分钟。一台「在线 1 分钟、掉线 4 分钟」来回反复的机器,模拟中一小时的通知从 23 条降到 2 条。几十秒的断开(比如重启 agent)不算。
- 同时发生的事合并成一条。hub 每 30 秒检查一次,同一轮里新离线的、恢复的、流量超标的节点各合成一条。hub 自己断网时,40 台节点在模拟中是 2 条「N 台节点离线」,不是 40 条。
- 重启 hub 不会重发。已报过离线的节点记在数据库里,hub 重启后不再重报,节点回来时照样发恢复。hub 停机期间掉线的节点,hub 起来后过了宽限期也会补报。
- 流量按节点的计算方式和重置日算,和面板显示的是同一个数。进入新周期后重新计。
- 只报登录成功,不报失败。失败的尝试谁都能发起,报失败等于让别人往你的 Telegram 里刷屏;失败由登录限流处理,见登录与安全。
- 一条消息最多列 20 台节点,其余写成「……另外 N 台」。Discord 单条消息上限 2000 字符、企业微信 2048 字节,超出会被整条拒收。
- 每条通知最多送一次。渠道暂时不通时会重试,重试完仍失败就丢弃,渠道恢复后不补发。
- 不做 CPU、内存、磁盘这类负载告警,原因见设计哲学。
hub 自己停机或断网时,发不出任何通知。要监控 hub 本身,用外部拨测服务(UptimeRobot、Uptime Kuma 之类)定时访问 hub 的地址。
「每天 9 点」和消息里的时间都按 hub 所在机器的时区算。Docker 部署要设 TZ,否则是 UTC 的 9 点,见 Docker 部署。
配置
在面板的通知页填好渠道并保存,再点发送测试(测试用的是已保存的配置),每个渠道失败的原因会显示在面板上。企业微信、钉钉、飞书例外,见下文常见服务的写法。
然后在同一页的离线通知卡片里勾选要关注的节点,可以全选,也可以先按分组筛选再全选,点保存后生效;编辑节点里也有这个开关。流量和到期提醒不用单独开。
事件卡片里的三个数字:
| 设置 | 默认 | 范围 |
|---|---|---|
| 离线宽限期 | 3 分钟 | 1–30 |
| 流量提醒 | 80% | 0–100,填 0 关闭 |
| 到期提醒 | 7 天 | 0–365,填 0 同时关闭到期和续期通知 |
宽限期从 hub 发现连接断开时算起,hub 每 30 秒检查一次,所以宽限期 3 分钟时,通知在断开后 3 到 3.5 分钟之间到达,和 agent 的上报间隔无关。agent 进程退出、机器正常重启时连接立即关闭;机器断电、断网时连接不会正常关闭,hub 最长 150 秒后才发现,通知相应推迟。
Telegram
- 找 @BotFather 发
/newbot,按提示起名,得到形如123456:ABC-DEF…的 token。 - 拿 Chat ID:
- 发给自己:先给你的机器人随便发一句话,再打开
https://api.telegram.org/bot<token>/getUpdates,找"chat":{"id":…}里的数字。 - 发到群组:把机器人拉进群,在群里发一句话,同样看
getUpdates。群组的 ID 是负数,通常以-100开头。 - 发到公开频道:把机器人设为频道管理员,Chat ID 填
@频道名。
- 发给自己:先给你的机器人随便发一句话,再打开
- 两项填进面板,保存,发送测试。
消息是纯文本,默认第一行是标题,下面是正文:
🔴 香港 · 甲商家 离线
最后上报 09-15 20:13 +08:00改格式用消息模板,占位符见下文自定义内容。
hub 要能访问 api.telegram.org。访问不了时给 hub 设 HTTPS_PROXY 环境变量,hub 的所有出站请求(包括转发 agent 二进制、GitHub 登录、查询国家)都会走这个代理。一键脚本部署:
# 打开编辑器,写入下面两行后保存
systemctl edit monitor-hubbash[Service]
Environment=HTTPS_PROXY=http://127.0.0.1:7890inisystemctl restart monitor-hubbashDocker 部署在 docker run 里加 -e HTTPS_PROXY=http://…。
自定义内容
Telegram 的消息模板和 Webhook 的请求体各一个,所有事件共用。每类事件的标题和正文由 hub 生成,模板只决定怎么排列、加什么前后缀。输入框下方会用一条离线通知实时预览。
| 占位符 | 内容 |
|---|---|
{{title}} | 标题,如 🔴 香港 · 甲商家 离线、⚠️ 香港 · 甲商家 流量提醒 |
{{message}} | 正文,如 最后上报 09-15 20:13 +08:00;多台节点时一行一台 |
{{node}} | 涉及的节点名,多台用 , 隔开;登录和测试为空 |
{{event}} | offline online traffic expiry renew login test 之一 |
{{site}} | 设置页里的站点名称,默认 Monitor |
{{time}} | 通知产生的时间,如 09-15 20:16 +08:00;离线通知比断开晚一个宽限期 |
不认识的 {{…}} 原样保留。模板清空后保存,恢复默认。
有多个 hub 时,把站点名称设成能区分的名字,模板里加上 {{site}}:
[{{site}}] {{title}}
{{message}}钉钉、飞书要求消息包含关键词时,把关键词固定写在模板开头,每条消息才都带着它,见下文常见服务的写法。
Webhook
hub 以 POST 发送,Content-Type: application/json,请求体按模板生成。请求头里写了 Content-Type
时替换默认值。
URL 要填最终地址。hub 不跟随跳转:http:// 被跳到 https://、或少了末尾的 / 时,发送测试直接报
301 Moved Permanently,把 URL 改成它跳转的目标即可。跟随跳转的话,POST 会变成不带内容的 GET,对方照样回 200,面板显示发送成功而消息没有送到;请求头里的凭证也会被带到跳转后的主机。
请求体里的占位符会按 JSON 字符串转义(引号、反斜杠、换行),所以必须写在引号里。写错时预览会提示;保存时 hub 也会代入一组带引号和换行的样本,结果不是合法 JSON 就拒绝保存。
默认请求体:
{
"event": "{{event}}",
"node": "{{node}}",
"title": "{{title}}",
"message": "{{message}}"
}json请求头可选,一行一个,写成 Name: value,用于鉴权。
常见服务的写法
Discord:URL 填频道的 Webhook 地址。
{"content":"{{title}}\n{{message}}"}jsonSlack:URL 填 Incoming Webhook 地址。
{"text":"{{title}}\n{{message}}"}json企业微信群机器人:URL 填 https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=…。
{"msgtype":"text","text":{"content":"{{title}}\n{{message}}"}}json钉钉群机器人:URL 填 https://oapi.dingtalk.com/robot/send?access_token=…。安全设置选自定义关键词,只填一个固定的词(比如 探针),再把它写在模板开头。不要选只出现在部分消息里的词:「通知」只在测试消息里有,「节点」只在多台汇总里有,测试能收到,单台节点的离线、恢复却会被拒收。加签需要按时间戳实时计算签名,这里不支持。
{"msgtype":"text","text":{"content":"【探针】{{title}}\n{{message}}"}}json飞书群机器人:同样不能开签名校验,安全设置用自定义关键词,做法和钉钉相同。
{"msg_type":"text","content":{"text":"【探针】{{title}}\n{{message}}"}}json企业微信、钉钉、飞书拒收消息时(key 或 token 填错、关键词不匹配)仍返回 HTTP 200,错误码写在响应内容里,hub 分辨不出,发送测试照样显示已发送。配这三家时,以群里真正收到测试消息为准。
Bark:URL 填 https://api.day.app/push。
{"device_key":"你的 key","title":"{{title}}","body":"{{message}}"}jsonntfy:URL 填 https://ntfy.sh(或自建地址),需要鉴权时请求头加 Authorization: Bearer …。
{"topic":"你的 topic","title":"{{title}}","message":"{{message}}"}jsonGotify:URL 填 https://gotify.example.com/message,请求头加 X-Gotify-Key: 应用 token。
{"title":"{{title}}","message":"{{message}}"}json凭证不回读
Bot Token、Webhook URL、Webhook 请求头这三项保存后读不回来,面板只显示「已设置」。输入框留空保存表示不改;停用一个渠道点那张卡片上的清除,只删请求头点清除请求头。
Webhook URL 也算凭证:Discord、Slack、企业微信、钉钉、Bark 的地址本身就是密钥,拿到就能往你的频道里发消息。数据库备份里包含这些凭证,见数据与备份。
收不到通知
先点发送测试,各渠道失败的原因会直接显示在面板上(企业微信、钉钉、飞书除外,看群里有没有收到)。常见的:
| 面板上的提示 | 原因 |
|---|---|
Telegram:Bot Token 不对(HTTP 401) | token 填错,或者机器人被删了 |
Telegram:Chat ID 不对,或者 bot 还没有加入这个会话(HTTP 400) | Chat ID 不对,或者你还没给机器人发过消息、机器人不在群里 |
Telegram:bot 被这个会话移除或屏蔽了(HTTP 403) | 你屏蔽了机器人,或者机器人被移出了群 |
Webhook:地址发生了跳转,请填写跳转后的地址(HTTP 301) | URL 会跳转,改成它跳去的地址,见上面 Webhook 一节 |
Webhook:对方拒收了这条消息,检查请求体格式(HTTP 400) | 服务端拒收,多半是请求体不合它的格式 |
连不上对方服务器、请求超时 | hub 连不上那个地址 |
对方服务自己返回的错误信息写在 hub 日志里:
# 一键脚本
journalctl -u monitor-hub | grep 'not delivered'
# Docker
docker logs monitor 2>&1 | grep 'not delivered'bash测试能收到、真实事件收不到:
- 离线通知要在离线通知卡片里打开对应节点,默认是关的。
- 离线通知来得晚:节点最近 1 小时内有过一次超过宽限期的掉线,这次要掉满 30 分钟才报,见上文「反复掉线的节点自动降噪」。
- 流量提醒要节点填了每月额度,到期提醒要节点填了到期时间。
- 钉钉、飞书只收到一部分:关键词没有出现在每条消息里,见上文钉钉群机器人。
- 看 hub 日志。连不上、对方 5xx 或限流(429)时隔 10 秒重试,最多 3 次;token 错误、地址跳转这类重试也没用的错误不重试。最终没送出去的每条记一行:
# 一键脚本
journalctl -u monitor-hub | grep 'not delivered'
# Docker
docker logs monitor 2>&1 | grep 'not delivered'bash