这是什么
这是我 Homelab 里的一套「双通道告警系统」:磁盘、内存、CPU 温度、systemd 服务、容器健康、挂载盘、节点在线、网站/隧道可用性一出问题,手机 ntfy 立刻响,同时发一封邮件到自建邮箱 xiejun@xiejun-server.top。两个通道互为备份,谁挂了都还有另一个能喊人。
为什么做
之前只靠盯监控台页面,问题往往是我主动打开才看到。有一次照片盘 SMART 报警、一次容器不健康,都是事后才发现的。所以我想要的是「不主动看也能知道」——机器自己找上门。选 ntfy 是因为它手机端免费、无广告、订阅一个 topic 就完事;选邮件是因为它足够独立,不依赖同一台机器的推送链路。
怎么分工
告警分两层,互相独立:
- Gatus(跑在 .223)负责外部视角:16 项探测,网站/服务 URL、公网可用性、两条樱花隧道、照片盘 SMART、Windows 主机 SSH、三台机器在线。
- 监控台(.164 上的
notify.py)负责内部视角:节点离线、磁盘 ≥88%/94%、内存 ≥92%/96%、CPU 温度 ≥85/92°C、服务启动失败、容器不健康、挂载盘失效。
两层都做了防抖和冷却:连续失败 2 次才推,恢复后再推一条「已恢复」,同一问题 6 小时内只重复提醒一次。
现在的状态
运行中。Gatus→ntfy、监控台→ntfy 两条链路都做过真实触发的验证,状态机自检通过;邮件侧走自建 docker-mailserver + Brevo 免费中继,mail-tester 实测 DMARC/DKIM/SPF 全 pass。
已知边界
ntfy 用的是公共 ntfy.sh,topic 就是密码;.164 整体挂掉时,靠 .223 上的 Gatus 兜底报警。
功能
- Gatus 侧 16 项探测覆盖网站、公网可用性、隧道、SMART、SSH 与机器在线
- 监控台侧覆盖节点离线、磁盘/内存/温度阈值、服务与容器健康、挂载盘失效
- 连续失败 2 次才推送,恢复后补一条「已恢复」,避免抖动刷屏
- 同一问题 6 小时冷却,只重复提醒一次
- ntfy 手机推送 + 自建邮箱 SMTP 发信,双通道互为备份
- 通道可切换:notify.json 里换成企业微信或钉钉机器人,30 秒内生效
技术栈
PythonntfyGatusDockerdocker-mailserverBrevo SMTP 中继systemd
使用 / 部署教程
一、手机端订阅(1 分钟)
- 装 ntfy App(安卓应用商店 / F-Droid,iOS App Store)。
- 打开 App → 右上角 + → Subscribe to topic → 填入 topic 串(22 字节随机串,等于密码,别外传)。
- 完成后不用再管。刚订阅时可能看到几条 12 小时内的历史测试消息。
二、部署监控台侧 notify.py
- 把
notify.py(纯标准库实现,检测 + 推送)放到/opt/dashboard/,同目录建notify.json,权限设 600:
chmod 600 /opt/dashboard/notify.json
notify.json里写 topic、阈值和channels;默认{"type": "ntfy"},想换企业微信就把channels改成 webhook 形式,30 秒内自动生效,不用重启。- 在
server.py里加两行接入:import notify和notify.start(stats)。改前先备份server.py。 - 自检状态机(含「恢复」路径断言):
python3 /opt/dashboard/notify.py --selftest
- 验证:临时把某个阈值调到当前真实值以下触发一轮,确认收到告警与「已恢复」两条,再改回正式阈值,检查
notify-state.json为{"problems": {}}。
三、配置 Gatus 侧
- 编辑
/opt/gatus/config/config.yaml,先备份。 - 新增
alerting.ntfy段,填 topic 与推送地址。 - 给需要告警的每个 endpoint 加
alerts: [- type: ntfy](当前 16 项)。 - 重启 Gatus,然后临时加一个必定失败的端点,确认手机收到告警,再删掉。
四、接邮件通道
- 在 VPS 上用 docker-mailserver 建发信账号(
docker exec mailserver setup email add <addr> <password>)。 - 出站 25 被封的环境必须走 ESP 中继:在
mailserver.env配RELAY_HOST/RELAY_PORT=587/RELAY_USER/RELAY_PASSWORD,改完docker compose restart mailserver。 - 在 ESP 侧完成域名认证(根域必须与 From 地址的域一致),否则签名对不上。
- 用 mail-tester 发一封测试信,确认
spf=pass、dkim=pass、dmarc=pass。
五、日常维护
阈值按机器实际负载调整;冷却时间用 cooldown_sec 控制;每加一台机器或一个服务,记得在 Gatus 和监控台两边都补上对应项。
注意
- ntfy topic 相当于密码,公开博客、截图和仓库里都不要出现完整串;
notify.json保持 600 权限。资料原文里的邮箱密码、Brevo 账号密码等明文凭据不应随文档一起发布。 - 用的是公共 ntfy.sh:消息在对方服务器保留 12 小时,且推送可用性依赖第三方;想彻底自建要在 DNS 加一条
ntfy.xiejun-server.top再配。 - 邮件通道依赖 Brevo 免费中继(300 封/天),且
.top后缀在 SpamAssassin 有固定扣分,正式依赖前先给 Gmail/QQ 各发一封确认进收件箱。