一天一个开源项目(第201篇):ntfy - 用一行 curl 把消息推到手机

引言

"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 管理------猜不到的主题名本身就是访问控制的第一道门(当然还有正式的认证机制)。

使用场景

  1. 脚本/任务完成通知

    • 长时间运行的备份、编译、数据处理任务跑完后,立刻把结果推到手机,不用盯着终端等。
  2. 服务器监控告警

    • 配合 Uptime Kuma、Prometheus Alertmanager、Healthchecks.io,服务挂了第一时间收到通知。
  3. CI/CD 流水线通知

    • GitHub Actions、GitLab CI 跑完后,成功或失败都能推送通知,不用轮询 Web UI。
  4. 智能家居事件

    • Home Assistant 的自动化规则触发时推送通知,比如"门锁已解开""洗衣机跑完了"。
  5. 个人自动化脚本

    • 任何写 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

项目地址与资源

官方资源

相关资源


总结与展望

核心要点回顾

  1. 极简 pub-sub 模型:主题即地址,HTTP 请求即发布,无需账号无需 SDK
  2. 丰富的消息特性:优先级、标签、操作按钮、延迟发送、附件,覆盖绝大多数通知场景
  3. 完整自托管支持:单个 Go 二进制,Docker 一行启动,SQLite 或 PostgreSQL 可选
  4. 强大的集成生态:Alertmanager、GitHub Actions、Home Assistant、Uptime Kuma 无缝对接
  5. 消息缓存设计:12 小时缓存保证离线也不丢消息,比纯 Webhook 方案更可靠

适用人群

  • 运维和 DevOps 工程师:服务器告警、CI/CD 通知、定时任务监控
  • 独立开发者和一人公司:自动化脚本的通知需求,便宜好用无依赖
  • 自托管爱好者:完全掌控自己的通知基础设施,不依赖任何第三方服务
  • 智能家居玩家:Home Assistant、Node-RED 等平台的事件推送

一句话评价

ntfy 是"够用就是最好的"这句话的最佳注脚------它把推送通知这件事剥离到只剩一条 curl 命令,却在需要的时候又提供了足够深的功能纵深。


欢迎访问 PrimeSkills ------ 一个精心策划的 AI Agent 与技能市场,所有内容均经过真实企业级工作流验证。没有噱头,只有真正有效的东西。

更多实用知识和有趣产品,欢迎访问我的个人主页

相关推荐
redfred16 分钟前
hoppscotch 使用教程:开源 API 调试工具 Postman 免费替代 Web/桌面/Docker 部署详解
开源·postman·graphql
Erishen18 分钟前
💡 当 LLM 开始骗自己:用几行正则给 AI 生成的文章上一道可信度闸门
架构·开源·agent
冬奇Lab42 分钟前
企业知识库系列(04):HyperGraphRAG 实测——超图结构的多跳推理
人工智能·开源
赛博三把手1 小时前
DeepSeek Harness (dsh) 国内网络接入第三方大模型聚合平台 API:以 Claude Opus 5 /Fable 5为例
人工智能·架构·开源
chunmiao30321 小时前
英伟达129亿美元收购Hugging Face,开源AI枢纽易主
人工智能·开源
zhonyu鱼1 小时前
Drawpile:多人实时协作绘画,一起在同一块画布上画画
笔记·pdf·开源·开源软件
JGDT_2 小时前
社区跃迁:从“模型开源”到“生态共创”
开源
lswzw2 小时前
我开源了 ssh-mcp:让支持 MCP 的 AI 客户端通过 SSH 查服务器、查数据库、读文件和部署
人工智能·开源·ssh
TunerT_TQ2 小时前
三权分立式 Agent 架构:为什么“感知、规划、执行”必须彼此制衡?(第4期)
安全·架构·资讯