ntfy 开源的消息推送平台
ntfy 开源的消息推送平台
参考文档
GitHub - binwiederhier/ntfy: Send push notifications to your phone or desktop using PUT/POST
本地部署
其实你可以直接使用 ntfy.sh 这个官方服务,但是我始终觉得还是自己的安全点儿。
ntfy 提供了三种安装方式,
-
直接安装二进制 tar 包或者 rpm 包或者 deb 包,你可以根据不同的操作系统和 CPU 架构来选择不同的压缩包,同时支持 Windows 安装
虽然直接 docker 安装很方便,但是为了不出现性能损耗,我们这里选择直接通过 rpm 包安装
首先检查服务器版本
|
|
然后在 Releases · binwiederhier/ntfy · GitHub 中选择x86_64
对应的版本,即后缀为amd64
的包,然后直接安装,建议以 root 用户执行此代码
|
|
这里可能会遇到几个问题:
-
ntfy_2.7.0_linux_amd64.rpm
下不下来,我们可以在本机上将这个 rpm 包下载下来(大概 20 多 M),然后上传到目标服务器上 -
执行
rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v2.7.0/ntfy_2.7.0_linux_amd64.rpm
的时候,需要创建用户和用户组,此时可能报错:useradd: cannot open /etc/passwd
,这个问题,我们在《SSH 密钥登录》中也遇到过,解决方法很简单,先执行1 2
chattr -ia /etc/shadow chattr -ia /etc/passwd
然后再进行
rpm -ivh
安装,安装完成之后,再执行1 2
chattr +ia /etc/shadow chattr +ia /etc/passwd
-
执行
systemctl start ntfy
的时候发现无法启动成功,但是直接执行ntfy serve
确实可以启动成功的,感觉是因为安装过程中创建的ntfy
用户权限不够。直接更改/usr/lib/systemd/system/ntfy.service
文件,此文件由systemctl enable ntfy
命令创建1 2 3
# User 和 Group 默认是 ntfy User=root Group=root
然后重新加载
1
systemctl daemon-reload
然后即可通过
systemctl
启动1
systemctl restart ntfy
成功启动之后,访问 80 端口,即http://<ip>:80
即可访问 ntfy 的 web 服务。
但是这样是不够的
编辑/etc/ntfy/server.yml
,将 http 接口和 https 接口的端口都进行更换,同时配置 https 的证书位置。
关于如何这个证书怎么来的以及为什么在这个位置,请看《轻量应用服务器运维》的
为 Nginx 配置证书
小节注意,如果是阿里云,还得去控制台开
9010
和9011
这两个端口
|
|
我们正常情况下推送数据,应该是通过 https 进行推送,而不是 http
然后重启 ntfy
|
|
然后即可通过https://<ip>:9011
访问 ntfy 的 web 服务。
然后你就可以开始发布消息和订阅消息了。
配置
ntfy server.yml 配置项,默认在
/etc/ntfy/server.yml
官方文档给出了几个 [配置模板](Configuration - ntfy),其中最有用的就是这个:HTTP+HTTPS, 磁盘缓存 + 附件(attachments)磁盘缓存
|
|
这里要注意,如果你的listen-https
配置的不是:443
,那么在base-url
中就应该把这个端口给带上,比如base-url: "https://ntfy.example.com:445"
默认情况下,ntfy 服务器对所有人开放,这意味着每个人都可以读写任何主题(这就是 ntfy.sh 的配置方式)。此时,如果你的 ntfy 是部署在公网上,那么为了防止恶意的推送/订阅数据,你可以选择配置身份验证和授权。参考:私有化配置
对于放到互联网上的服务,一定要做限制。比如必须登录,如果不用登陆也需要对请求的频率和速率进行限制,防止恶意用户用脚本疯狂使用你的服务,造成内存和磁盘甚至流量的浪费,产生不必要的费用
ntfy 的授权是用一个简单的基于 sqlite 的后端实现的。它使用访问控制列表 (ACL) 实现两个角色 (user
和admin
) 和每个主题的read
和write
权限。访问控制项既可以应用于用户,也可以应用于每个用户 (*
),*
代表匿名 API 访问。
用户列表中默认有一个
*
用户,表示在推送消息到主题中时没有指定用户名的情况,即,开启了身份验证之后,在推送消息的时候,不指定用户依然是可以推送消息的,不过此时,对应的是匿名用户*
。匿名用户
*
的权限可以通过auth-default-access
控制
在/etc/ntfy/server.yml
中配置两个选项即可:
-
auth-file
配置的是用户访问记录数据库;如果不存在,它将自动创建;建议的位置/var/lib/ntfy/user.db
-
auth-default-access
定义的是,在没有找到访问控制项时的默认的访问权限;可以设置为read-write
(默认)、read-only
,write-only
ordeny-all
.
修改配置文件/etc/ntfy/server.yml
,进行 私有化配置
|
|
然后重启
|
|
配置好之后,可以使用ntfy user
命令 添加或修改用户,使用ntfy access
命令可以 修改特定用户对特定主题的访问控制列表。这两个命令都直接编辑 auth 数据库 (auth-file
中定义的那个),因此它们只在服务器上工作,并且只有在访问它们的用户具有正确权限的情况下才能工作。
注意,用户只能在服务器上添加,在客户端(比如 Android 客户端、web 客户端,都不能添加),在客户端添加的用户,是订阅主题,推送消息的时候所使用的已经存在的用户
你可以创建两种角色的用户
-
user
:具有此角色的用户没有特殊权限。需要额外配置针对某一个主题的读写权限 -
admin
:具有此角色的用户默认可以对所有主题进行读/写。没有必要进行更细粒度访问控制。
一般情况下添加一个 admin 用户即可,平时自己就用这个 admin 用户,有别的节点需要用到 ntfy,再额外创建用户配置权限
|
|
查看所有用户
|
|
后续我们跟 ntfy 进行任何交互,都需要带上身份信息,比如通过 curl 发布消息的时候,带上-u <user_name>:<user_password>
,否则会提示:身份认证错误
|
|
总的来说,ntfy 支持对以下功能的配置:
-
通过 FCM 推送消息到安卓设备,Firebase Cloud Messaging (FCM) 是 Google 批准的向 Android 设备发送推送消息的方式。FCM 是 Android 应用程序无需运行前台服务即可接收消息的唯一方法。
-
Web 推送,Web Push (RFC8030) 允许 ntfy 在 ntfy Web 应用程序甚至浏览器关闭的情况下接收推送通知
-
付费。ntfy 通过 Stripe 作为支付提供商支持付费级别。如果启用了付费功能,用户可以在 web 应用程序中注册、登录和切换付费计划。如果启用了付费功能,web 应用程序的行为会略有不同(例如显示升级横幅或“ntfy Pro”标签)。
-
对用户进行不同层级的功能限制。Ntfy 支持将用户关联到预定义的层。层可用于授予用户更高的限制,例如每日消息限制、附件大小,或者允许用户保留主题。如果启用了付费功能,就层级就可以是付费层级或未付费层级,用户可以在不同的付费等级之间升级或降级。如果禁用了付费功能,那么在不同级别之间切换的唯一方法是使用
ntfy user change-tier
命令。 -
电话呼叫。ntfy 支持通过 Twilio 作为电话提供商进行电话呼叫,用户需要自行购买 Twilio 服务
-
全局或者特定特征用户的速率限制,包括主题限制,消息条数限制,附件大小限制等等
-
性能优化,比如磁盘缓存的清理,比如同一个服务能打开的最大文件数
我们有需要再对其进行研究
安卓客户端
从 Google Play 上 下载安装即可,安装好之后,需要在设置 -> 管理用户中配置我们创建好的用户,比如管理员用户,这样,通过此客户端进行的消息推送和数据订阅,都是以配置的用户的权限进行的。
ntfy 的 APP 本身只能设置订阅的主题,而发送消息到主题的功能则放到了 Android 的分享功能中,只要是能分享的东西,比如文字、图片、链接等,都可以作为一个消息发送到 ntfy 主题,这个功能真的好用,可以很方便地在电脑和手机之间传递一些文字链接,图片啥的。
注意,如果是小米手机,需要给 ntfy 这个 APP 的通知权限开启悬浮通知权限,才可以从屏幕上方弹出通知,否则就只能在下拉通知栏中看通知了。
Web 端
直接访问 ntfy 服务的 web 页面。然后在 Settings -> Manage users 中配置我们创建好的用户,比如管理员用户,这样,通过此客户端进行的消息推送和数据订阅,都是以配置的用户的权限进行的。
Web 端既可以发送消息,也可以订阅消息。
-
Subscribe to topic
:订阅主题 -
Publish notification
:向指定的主题发送消息 -
All notifications
:订阅的所有主题的所有消息
只有官方提供的 ntfy web 有客户端,自己部署的 ntfy 服务端没有。
访问 ntfy web,点击地址栏的下载按钮可以下载下来一个 ntfy 桌面 APP,
生产消息
发布消息可以通过发起一个 HTTP PUT/POST 请求或通过 ntfy CLI 完成。发送消息的时候需要指定主题和内容,内容就相当于是 POST 请求的请求体,而主题是包含在请求路径中的,其他的信息比如消息标题,消息优先级,都是通过定制请求消息头来实现。
用户身份认证,是将
<user_name>:<user_password>
通过 Base64 编码,然后以Authorization: Basic <base64_code>
的格式放到消息头
主题是第一次订阅这个主题或第一次发布内容到这个主题的时候动态创建的,因此不会出现主题不存在的的情况。而且因为没有用户的注册,所以主题本质上是一个密码,只要知道一个主题,就可以往主题中推送数据或者消费主题中的数据,因此为了保证数据不被别人污染或者窃取,应该尽量选择一些不容易猜到的东西作为主题的名字,一般选择随机字符串。
我遇到了主题自动删除的bug,可能是因为长时间没有往这个主题中发送消息,系统自动删除了这个主题。
这个问题告诉我们,消息中间件只能作为消息传递的通道,不要将消息存储在消息通道中,或者说不要依赖消息通道的存储功能。
发布消息的方式很简单,只要是能发起一个 HTTP PUT/POST 请求就可以发布消息,各种编程语言都有 HTTP 客户端,通过这些客户端发起一个请求也很简单,这里就不多重复了,ntfy cli 这种方式只能在 ntfy 服务端使用,通用性不强,因此我们主要看通过 curl 命令生产消息的方式
关于 curl 命令,我们在《curl》中学习过
-u
参数设置连接到 http 服务的时候指定用户和密码
-d
参数指定 POST 请求的请求体,例如-d "i am a post body"
-H
参数指定请求头中特定属性的值,例如-H "Name: xiashuo"
-T
,以 PUT 请求上传文件,例如-T /opt/info.log
简单实践如下:
将
<ip>
换成 ntfy 所在的主机名或者 ip,将<port>
换成 ntfy 服务监听的端口,将<topic>
换成 ntfy 服务的主题如果 ntfy 服务进行了 私有化配置,还需要配置用户信息,如果 ntfy 服务器没有进行私有化配置,比如
ntfy.sh
,则不需要指定用户名密码
|
|
除此之外,我们还可以通过定制请求的消息头,来定制发送到主题的消息,例如指定消息标题、标签还有优先级:
|
|
总共有 5 个优先级可以指定
-
max
/urgent
:最大优先级,需要弹框,震动加声音提示 -
high
:高优先级 -
default
:默认优先级 -
low
:低优先级 -
min
:最小优先级
我们还可以带上图片附件,通过指定Attach
消息头指定附件,不过附件地址必须可以通过 URL 来访问,这样就无法将本地文件作为附件
|
|
如果要将本地文件作为附件,则需要通过将其作为 PUT 请求的消息体,同时指定消息头中的Filename
属性:
|
|
这样的话,我们就可以在系统报错的时候,把错误日志作为附件发出来。
发送消息的时候,总共可以支持以下这么多特性:
-
指定消息的标签,方便消息类型的区分
-
支持延时发送消息,延时最短 10s,最长 3 天
-
支持通过 GET 请求发布消息。除了使用 PUT/POST,您还可以通过简单的 HTTP GET 请求发送到主题。这使得它很容易使用一个主题作为一个 webhook,如果你的客户端有有限的 HTTP 支持的话可以使用这种方式,一般情况下没有必要使用这种方式发布消息
-
自定义消息通知框中的按钮,现在支持三种按钮,
-
点击按钮打开网站或者 APP
-
点击按钮发送一个 安卓广播 信息
-
点击按钮发送一个 HTTP POST/GET/PUT 请求,这种用法最多
有了这三种按钮,通知的玩法就变多了
-
-
自定义通知弹框的点击行为:您可以定义在单击通知时打开哪个 URL。如果您的通知与 Zabbix 警报或您希望为其提供深层链接的事务相关,这可能会很有用。点击通知将打开网页浏览器(或应用程序)并打开网站。
-
支持 ICON:目前仅支持** PNG 和 JPEG **图片
-
支持发布消息的时候支持转发到邮箱:这对于您希望保存更长时间的消息或在所有可能的通道上通知自己非常有用。
-
支持打电话:你可以用 ntfy 打电话,然后用文本转语音的方式大声读出信息。目前仅支持英语,底层为 Twilio,用户需要自行购买 Twilio 服务
-
支持身份认证:当使用 Basic 认证时,也就是用户密码验证,base64 只编码用户名和密码。它没有加密它。对于自托管服务器,请确保使用 HTTPS 以避免窃听和暴露您的密码。
-
支持高级特性:消息缓存(如果禁用,消息只会推送给订阅者一次,没消费到的话不会推送第二次)、禁用 Firebase、统一推送、矩阵网关,好吧,一个都不懂。
具体请看 发布消息时可以传递的所有参数的列表。
订阅消息
除了我们前面看到的,可以在 Android 端订阅消息,可以在 web 端订阅消息,除此之外,还可以在 桌面端 订阅消息。还可以在 命令行 中订阅消息,我们还可以 编写代码通过 API 的方式 订阅消息,也就是说,我们可以把 ntfy 当作一个消息中间件来用。
一个简单的场景就是,比如我们想跟阮一峰一样,想要做科技周刊,那么我们可以在平时把我们临时看到的有意思的东西或者新闻很,推送到指定主题,然后自己写一个 Python 脚本跑在服务器上,一直在订阅这个主题,并把信息保存在本地(不在 ntfy 中缓存)然后等一个星期到了,这个 Python 脚本根据你推送的内容,自动生成周刊,这真的是太棒了。
使用的例子
其实主要就是把 ntfy 当作是一种通知手段,尤其可以简单的通过命令来生产消息之后,我们可以将命令执行的结果传递。发送到手机或者桌面端,这极大地增加了 ntfy 的适用范围。
我们甚至还可以在系统内部内置 ntfy 相关的 API,与专门的 ntfy 服务器通信。
此外,ntfy 也可以用作是手机和电脑之间的通信工具,传一些文字或者图片上面的,还是很方便的
ntfy 和消息中间件相比,没有那么底层,也没有那么重,使用起来也没有那么复杂,作为一个消息推送平台,可以看做是轻量的消息中间件
有了 ntfy,我个人开发的应用的所有的消息推送都可以走 ntfy。
和其他工具的简单对比
-
Pushover:一个消息推送平台,可以给手机、桌面、浏览器发送自定义的推送消息。按照平台购买其客户端,即可享受此平台的永久推送服务。
-
Twilio:消息推送平台,支持发短信打电话发邮件等等,发短信(SMS:Short Messaging Service)功能国内不可用
-
Messagebird,消息推送平台,支持短信,电话,app 等,跟 Twilio 差不多,国内用的很少
-
Prowl:专注于 IOS 通知推送的工具
-
Bark:仅支持 IOS
-
smstools3:开源的短信网关服务
-
WxPusher:主要通过关注微信公众号来进行消息推送,有点太过曲折,不过这也是微信不开放聊天机器人的无奈之举,只能曲线救国
算来算去,还是 ntfy 最好用,开源,免费。