消息推送有很多现成的平台,比如 Server 酱、微信甚至 E-mail 等等,基本上可以满足大多数场景。不过也有一些缺点,比如发送消息的要求格式固定、推送数据的隐私性问题等,这里以开源 ntfy 搭建一个自己的消息推送服务
配置服务器
使用 docker compose,首先新建一个 yaml 文件然后进行编辑:
mkdir -p /etc/ntfy
nano /etc/ntfy/ntfy.yaml
写入 docker 配置:
version: "3"
services:
ntfy:
image: binwiederhier/ntfy
container_name: ntfy
command:
- serve
environment:
- TZ=Asia/Shanghai # optional: set desired timezone
user: 0:0 # optional: replace with your own user/group or uid/gid
volumes:
- /var/cache/ntfy:/var/cache/ntfy
- /etc/ntfy:/etc/ntfy
- /var/lib/ntfy:/var/lib/ntfy
ports:
- 127.0.0.1:5080:80
healthcheck: # optional: remember to adapt the host:port to your environment
test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo'\"healthy\"\\s*:\\s*true'|| exit 1"]
interval: 60s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped
按 Ctrl+O
保存,Ctrl+X
退出。
写入 ntfy 配置
可以先运行下 docker compose 把上面的目录建出来,不运行的话,如下手动建,然后创建配置文件:
nano /etc/ntfy/server.yml
然后写入配置:
base-url: "https://ntfy.example.com"
cache-file: "/var/cache/ntfy/cache.db"
attachment-cache-dir: "/var/cache/ntfy/attachments"
attachment-total-size-limit: "5G"
attachment-file-size-limit: "15M"
attachment-expiry-duration: "3h"
visitor-attachment-total-size-limit: "100M"
visitor-attachment-daily-bandwidth-limit: "500M"
auth-file: "/var/lib/ntfy/auth.db"
auth-default-access: "deny-all"
behind-proxy: true
smtp-sender-addr: "smtp.example.com:587"
smtp-sender-user: "ntfy@example.com"
smtp-sender-pass: "xxxxxxxxxx"
smtp-sender-from: "ntfy@example.com"
按 Ctrl+O
保存,Ctrl+X
退出。
最后启动下 docker 容器:
docker compose -f /etc/ntfy.yaml up -d
nginx 反向代理
编辑 nginx 配置文件,加入如下代码(参考):
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name ntfy.example.com;
# ssl 证书地址
ssl_certificate /usr/local/nginx/cert/ssl.pem; # pem 文件的路径
ssl_certificate_key /usr/local/nginx/cert/ssl.key; # key 文件的路径
location / {
proxy_pass http://127.0.0.1:80;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 3m;
proxy_send_timeout 3m;
proxy_read_timeout 3m;
client_max_body_size 0; # Stream request body to backend
}
}
编辑完成后保存,重载下 nginx 配置:
nginx -s reload
使用 ntfy
说明
刚上手 ntfy 可能会感觉跟其他的消息推送服务有点不一样,这里简要说明一下!
其他的消息推送服务一般是注册个账号,登录以后会有专属连接,通过连接推送消息。而 ntfy 默认没有账号一说,它通过主题来区分推送的消息,举个例子:
比如 URL 是 https://ntfy.example.com,现在需要接收 nas 推送过来的消息,那么地址可以是 https://ntfy.example.com/nas,需要接收公司推送过来的消息,地址可以是 https://ntfy.example.com/company,地址后面跟着的,就是一个主题,任何人都可以用这个主题来发送消息,也可以用这个主题来接受消息!
所以主题就成了类似于“密码”的存在,如果需要保密,主题名就不要让其他人猜到!这就是 ntfy 设计的思路,默认消息是共享的,默认服务器不会长时间留存消息记录!
那如果我非要用户名和密码加密呢,别急,也可以设置,往下看设置认证那一节!
现在可以直接访问配置的域名打开 ntfy 了,在 settings 中可以更改语言。
设置认证
任何人都可以订阅主题,这当然有点不安全,因为是自建,所以这里就设定下最简单的规则:
开放一个用户,任何没经过用户名和密码认证的主题都禁止访问!
首先需要编辑 ntfy 的配置文件 /etc/ntfy/server.yml
,添加一行配置阻止未授权的用户访问主题:
auth-default-access: "deny-all"
auth-default-access
项默认为 "read-write"
然后保存,重启下容器:
docker compose -f /etc/ntfy.yaml restart
然后进入容器内部:
docker exec -it ntfy /bin/sh
添加用户:
ntfy user add --role=admin admin
这里添加了一个 admin 的用户,回车后,会要求输入密码和重复密码,确认后用户就创建完成了!
我们可以用 ntfy user list
查看下用户信息:
可以看到 admin 可以访问所有的主题,*(匿名用户)禁止所有主题访问就可以了!
[可选] 在后面的推送避免直接传递用户名和密码,可以为用户创建 token 来替代!
为 admin 创建 token:
ntfy token add admin
创建后可以复制出来备用,同样用 ntfy token list
可以查看已经创建的所有 token。
然后回到刚才的网页,此刻再次订阅主题时,就需要输入用户名和密码了。
注意事项
用户名和密码作为参数传递时,需要进行 base64 编码,官方样例:
username = "testuser"
password = "fakepassword"
authHeader = "Basic" + base64(username + ":" + password) // -> Basic dGVzdHVzZXI6ZmFrZXBhc3N3b3Jk
authParam = base64_raw(authHeader) // -> QmFzaWMgZEdWemRIVnpaWEk2Wm1GclpYQmhjM04zYjNKaw (no trailing =)
token 也一样,例:
token = "tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2"
authHeader = "Bearer" + base64(token) // -> Bearer tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2
authParam = base64_raw(authHeader) // -> QmVhcmVyIHRrX0FnUWRxN21WQm9GRDM3elFWTjI5Umh1TXpOSXoy
比如要发送到 test 主题,那么连接可能是 https://ntfy.example.com/test?auth= 上面生成的 authParam
值。
推送样例及说明
官方的样例已经很详细了,这里就不在赘述了,可以参考 官方样例