引言
"Push notifications without complexity."
这是"一天一个开源项目"系列的第 201 篇文章。今天带你了解的项目是 ntfy(读作 "notify")。
你有没有遇到过这种场景:一个长时间运行的脚本跑完了,你想知道结果;备份任务成功了,你想收到一条提示;服务器磁盘快满了,你想第一时间收到告警。
解决方案有很多------Email、Slack、Telegram Bot......但每一种都要注册账号、配置 API key、装 SDK,一圈折腾下来,通知功能本身反而成了开销最大的部分。
ntfy 把这件事还原到最本质的形态:
bash
curl -d "备份完成!" ntfy.sh/我的频道
就这一行,手机上就能收到推送。不需要账号,不需要 API key,不需要任何配置。33.8k Stars,支持完全自托管,是运维、开发者和自动化爱好者的必备工具。
你将学到什么
- ntfy 的发布-订阅模型是如何运作的
- 消息的高级特性:优先级、标签、操作按钮、延迟发送、附件
- 如何用 Docker 搭建私有 ntfy 服务器
- 认证与访问控制的配置方式
- ntfy 与 Alertmanager、GitHub Actions、Home Assistant 等工具的集成
前置知识
- 了解基本的 HTTP 概念(GET/POST 请求)
- 有 Linux 命令行基础(会用 curl)
- 自托管部分需要了解 Docker 基本操作
项目背景
项目简介
ntfy 是一个基于 HTTP 的发布-订阅(pub-sub)推送通知服务。它的设计理念极简:
- 发布方:向一个"主题(topic)"发一条 HTTP 请求
- 订阅方:在手机 App 或浏览器里订阅这个主题
主题不需要预先创建,消息体就是通知内容,整个流程没有多余的抽象层。
官方提供 ntfy.sh 公共服务,免费使用(有速率限制),也可以完全自托管------二者功能完全相同,代码完全开源。
作者/团队介绍
- 作者:Philipp C. Heckel(网站:heckel.io)
- 背景 :德国软件工程师,个人作者,同时也是文件同步工具
znapzend等开源项目的作者 - 项目创建:2021 年,从"我只是想在脚本结束时收到一条通知"的个人需求出发
项目数据
- ⭐ GitHub Stars: 33,800+
- 🍴 Forks: 1,600+
- 📄 License: Apache 2.0 + GPLv2(双协议)
- 🌐 官方服务: ntfy.sh
- 📚 文档: docs.ntfy.sh
- 📱 Android: Google Play + F-Droid(完全免费)
- 🍎 iOS: App Store
主要功能
核心作用
ntfy 的本质是一个极简的消息中间件,把"发通知"这件事抽象成最朴素的 HTTP 请求:
erlang
发布方(任何能发 HTTP 的东西)
curl / 脚本 / GitHub Actions / Prometheus Alertmanager ...
↓ POST/PUT ntfy.sh/my-topic
ntfy 服务器(公共 ntfy.sh 或自托管实例)
↓ 推送
订阅方(任何订阅了该主题的客户端)
手机 App / 浏览器 / CLI ...
主题名就是"频道地址",没有注册流程,没有 API key 管理------猜不到的主题名本身就是访问控制的第一道门(当然还有正式的认证机制)。
使用场景
-
脚本/任务完成通知
- 长时间运行的备份、编译、数据处理任务跑完后,立刻把结果推到手机,不用盯着终端等。
-
服务器监控告警
- 配合 Uptime Kuma、Prometheus Alertmanager、Healthchecks.io,服务挂了第一时间收到通知。
-
CI/CD 流水线通知
- GitHub Actions、GitLab CI 跑完后,成功或失败都能推送通知,不用轮询 Web UI。
-
智能家居事件
- Home Assistant 的自动化规则触发时推送通知,比如"门锁已解开""洗衣机跑完了"。
-
个人自动化脚本
- 任何写 shell 脚本的场景:定时任务、文件下载完成、爬虫跑完......一行 curl 搞定通知。
快速开始
方法 1:直接用公共服务,零配置
bash
# 第一步:手机装 App,订阅主题(iOS/Android)
# 打开 App → 添加订阅 → 输入主题名,例如 "my-alerts-abc123"
# 第二步:发送通知(任意设备上)
curl -d "Hello from ntfy!" ntfy.sh/my-alerts-abc123
# 带标题
curl \
-H "Title: 备份完成" \
-d "所有文件已成功备份到 S3" \
ntfy.sh/my-alerts-abc123
方法 2:自托管服务器(Docker)
bash
# 最简单的启动方式
docker run -p 80:80 -it binwiederhier/ntfy serve
# 带持久化存储
docker run \
-v /var/cache/ntfy:/var/cache/ntfy \
-v /etc/ntfy:/etc/ntfy \
-p 80:80 \
-it binwiederhier/ntfy serve
然后把 ntfy.sh 替换成你的服务器地址,其他用法完全相同。
核心特性
1. 消息优先级(1-5 级)
bash
# 紧急:强振动 + 弹窗
curl -H "Priority: urgent" -d "磁盘快满了!" ntfy.sh/alerts
# 低优先级:静默送达
curl -H "Priority: low" -d "定时备份已完成" ntfy.sh/alerts
| 级别 | 名称 | Android 行为 |
|---|---|---|
| 5 | urgent | 强烈振动 + 全屏弹窗 |
| 4 | high | 长振动 + 默认铃声 |
| 3 | default | 默认行为 |
| 2 | low | 无振动/声音 |
| 1 | min | 折叠在"其他通知"中 |
2. 标签与 Emoji
标签名与 emoji 短代码匹配时自动转换:
bash
curl \
-H "Tags: warning,computer" \
-d "CPU 使用率超过 90%" \
ntfy.sh/alerts
# 手机上显示:⚠️ 💻 CPU 使用率超过 90%
3. 操作按钮(最多 3 个)
在通知上直接添加可点击的操作,不用打开 App:
bash
# 点按钮直接触发 HTTP 请求
curl \
-H "Actions: http, 关闭告警, https://myserver.com/api/silence, method=POST" \
-d "CPU 持续高负载,是否静默告警?" \
ntfy.sh/alerts
# 操作类型
# view → 打开 URL
# http → 发送 HTTP 请求
# broadcast → Android 广播
# copy → 复制文本到剪贴板
4. 延迟发送
bash
# 30 分钟后发送
curl -H "In: 30min" -d "该喝水了" ntfy.sh/reminders
# 明天早上 9 点发送
curl -H "At: tomorrow, 9am" -d "周会提醒" ntfy.sh/reminders
# Dead man's switch:如果脚本没在 1 小时内再次 ping,就发告警
curl -H "In: 1h" -H "Title: 脚本失联告警" \
-d "脚本超过 1 小时没有心跳,请检查!" \
ntfy.sh/watchdog
5. 附件
bash
# 上传本地文件(最大 15MB,3 小时后过期)
curl -T screenshot.png \
-H "Filename: screenshot.png" \
ntfy.sh/alerts
# 附加外部 URL(不占用服务器存储)
curl \
-H "Attach: https://example.com/report.pdf" \
-H "Filename: 月度报告.pdf" \
-d "本月报告已生成" \
ntfy.sh/reports
6. 消息模板
ntfy 内置 Alertmanager 和 Grafana 的通知模板,直接配置 Webhook URL 即可:
ini
https://ntfy.sh/my-alerts?template=alertmanager
也可以自定义 Go 模板处理任意 JSON 数据。
项目优势
| 对比项 | ntfy | Telegram Bot | Slack Webhook | Pushover |
|---|---|---|---|---|
| 无需账号 | ✅ | ❌ 需要 Telegram | ❌ 需要 Slack | ❌ 需要注册 |
| 自托管 | ✅ 完整支持 | ❌ | ❌ | ❌ |
| 免费自托管 | ✅ 完全免费 | --- | --- | ❌ 需付费 |
| Android 免费 | ✅ | ✅ | ✅ | ❌ 付费 App |
| 操作按钮 | ✅ | ✅ | ✅ | ✅ 有限 |
| 延迟发送 | ✅ | ❌ | ❌ | ❌ |
| 发送方式 | 纯 HTTP | Bot API | Webhook | API |
| 开源 | ✅ | --- | --- | ❌ |
项目详细剖析
架构设计:极简的 pub-sub
ntfy 的架构刻意保持简单:
scss
┌─────────────────────────────────────────────┐
│ ntfy 服务器 │
│ │
│ HTTP API ──→ 消息路由 ──→ 主题(Topic) │
│ ↓ │
│ 消息缓存 │
│ (SQLite / PostgreSQL) │
│ ↓ │
│ ┌───────────────┼───────────── │
│ ↓ ↓ │
│ WebSocket FCM/APNs │
│ (Web/CLI) (移动端推送) │
└─────────────────────────────────────────────┘
消息路由:主题名即路由 key,消息进来就广播给所有订阅者。
消息缓存:服务器默认缓存最近 12 小时的消息,客户端重连时可以拉取错过的消息------这是 ntfy 比纯 Webhook 方案优越的地方,不需要接收端实时在线。
推送通道:
- Web/桌面:通过 Server-Sent Events(SSE)或 WebSocket 实时接收
- Android:通过 Firebase Cloud Messaging(FCM)或直接长轮询(F-Droid 版无 FCM)
- iOS:通过 APNs,需要中转到
ntfy.sh官方服务器
技术栈细节
后端用 Go 编写,这个选择非常合适:
- 单个二进制文件,零依赖,直接部署
- 并发处理多个 WebSocket 连接性能极好
- 跨平台编译,Linux/macOS/Windows 通吃
数据库默认 SQLite,配置文件里一行切换到 PostgreSQL:
yaml
# /etc/ntfy/server.yml
database-url: "postgres://user:pass@localhost/ntfy"
SQLite 模式因单写限制不能水平扩展,生产高并发场景建议用 PostgreSQL。
自托管配置详解
完整的服务端配置示例:
yaml
# /etc/ntfy/server.yml
# 基础设置
base-url: "https://ntfy.example.com"
listen-http: ":80"
listen-https: ":443"
key-file: "/etc/letsencrypt/live/ntfy.example.com/privkey.pem"
cert-file: "/etc/letsencrypt/live/ntfy.example.com/fullchain.pem"
# 数据存储
cache-file: "/var/cache/ntfy/cache.db"
cache-duration: "12h"
attachment-cache-dir: "/var/cache/ntfy/attachments"
attachment-total-size-limit: "5G"
attachment-file-size-limit: "15M"
attachment-expiry-duration: "3h"
# 访问控制(关闭匿名访问,需要登录)
auth-file: "/var/lib/ntfy/user.db"
auth-default-access: "deny-all"
# 声明式用户配置(服务启动时自动创建)
auth-users:
- "alice:$2a$10$hashhere:admin"
auth-access:
- "alice:*:rw" # alice 可读写所有主题
- "*:public-*:ro" # 所有人可订阅 public- 开头的主题
# Web Push(浏览器推送)
web-push-public-key: "BNbxxx..."
web-push-private-key: "xxx..."
web-push-file: "/var/lib/ntfy/webpush.db"
# 邮件转发
smtp-sender-addr: "mail.example.com:587"
smtp-sender-user: "ntfy@example.com"
smtp-sender-pass: "your-smtp-password"
smtp-sender-from: "ntfy@example.com"
认证与访问控制
ntfy 支持三种认证方式:
bash
# 用户名密码
curl -u alice:password -d "私人消息" ntfy.example.com/private-topic
# Bearer Token(推荐,比密码安全)
curl -H "Authorization: Bearer tk_AbcDefGhi..." \
-d "私人消息" ntfy.example.com/private-topic
# URL 参数(适合不方便设置 Header 的场景)
curl -d "私人消息" \
"ntfy.example.com/private-topic?auth=dXNlcjpwYXNz"
Token 可以设置过期时间,也可以随时吊销,比直接用密码更安全。
与主流工具集成
GitHub Actions:
yaml
- name: 发送构建通知
run: |
curl \
-H "Title: ${{ github.repository }} 构建${{ job.status }}" \
-H "Priority: ${{ job.status == 'success' && 'default' || 'high' }}" \
-H "Tags: ${{ job.status == 'success' && 'white_check_mark' || 'x' }}" \
-d "分支:${{ github.ref_name }},提交:${{ github.sha }}" \
${{ secrets.NTFY_URL }}/${{ secrets.NTFY_TOPIC }}
Prometheus Alertmanager:
yaml
# alertmanager.yml
receivers:
- name: "ntfy"
webhook_configs:
- url: "https://ntfy.sh/my-alerts?template=alertmanager"
send_resolved: true
Home Assistant:
yaml
# configuration.yaml
notify:
- platform: rest
name: ntfy
resource: https://ntfy.sh/my-home-alerts
method: POST_JSON
title_param_name: title
message_param_name: message
项目地址与资源
官方资源
- 🌟 GitHub : github.com/binwiederhi...
- 📚 文档 : docs.ntfy.sh
- 🌐 公共服务 : ntfy.sh
- 📱 Android App (F-Droid) : f-droid.org/packages/io...
- 🐛 Issues : github.com/binwiederhi...
相关资源
- Uptime Kuma --- 配合 ntfy 做服务监控告警的好搭档
- Healthchecks.io --- 定时任务心跳监控,支持 ntfy 通知
- ntfy Android 源码 --- Android 客户端独立仓库
总结与展望
核心要点回顾
- 极简 pub-sub 模型:主题即地址,HTTP 请求即发布,无需账号无需 SDK
- 丰富的消息特性:优先级、标签、操作按钮、延迟发送、附件,覆盖绝大多数通知场景
- 完整自托管支持:单个 Go 二进制,Docker 一行启动,SQLite 或 PostgreSQL 可选
- 强大的集成生态:Alertmanager、GitHub Actions、Home Assistant、Uptime Kuma 无缝对接
- 消息缓存设计:12 小时缓存保证离线也不丢消息,比纯 Webhook 方案更可靠
适用人群
- 运维和 DevOps 工程师:服务器告警、CI/CD 通知、定时任务监控
- 独立开发者和一人公司:自动化脚本的通知需求,便宜好用无依赖
- 自托管爱好者:完全掌控自己的通知基础设施,不依赖任何第三方服务
- 智能家居玩家:Home Assistant、Node-RED 等平台的事件推送
一句话评价
ntfy 是"够用就是最好的"这句话的最佳注脚------它把推送通知这件事剥离到只剩一条 curl 命令,却在需要的时候又提供了足够深的功能纵深。
欢迎访问 PrimeSkills ------ 一个精心策划的 AI Agent 与技能市场,所有内容均经过真实企业级工作流验证。没有噱头,只有真正有效的东西。
更多实用知识和有趣产品,欢迎访问我的个人主页