ntfy 自托管推送通知服务搭建:一条 curl 命令向手机发送通知
服务器跑完备份任务、定时脚本执行完毕、网站出现异常------这些事件如果能自动推送通知到手机,就不用守着终端盯日志了。实现这个需求的工具很多,但大多需要注册第三方账号、申请 API Key、配置 Webhook,流程繁琐。
ntfy 的设计思路完全不同:发送一条通知,只需要一行 curl 命令;接收通知,只需要在 App 里订阅一个 topic(主题)。没有注册流程,没有 SDK,没有复杂配置。自建服务器后,通知内容不经过任何第三方,适合推送包含敏感信息的业务告警。
本文介绍如何用 Docker Compose + Caddy 搭建 ntfy 私有推送通知服务。
服务器配置
ntfy 服务端资源消耗极低,和其他服务共享一台机器完全没问题。
| 项目 | 规格 |
|---|---|
| CPU | 1 核 |
| 内存 | 1GB |
| 硬盘 | 10GB(消息持久化缓存) |
| 系统 | Ubuntu 22.04 / Debian 12 |
推荐使用雨云服务器 rainyun-com 的 1 核 1GB 机型来部署 ntfy,价格低廉,资源绰绰有余。注册填优惠码 2026off 领 5 折优惠券,新用户首单直接半价。
准备工作
确保服务器已安装 Docker 和 Docker Compose:
bash
# 安装 Docker
curl -fsSL https://get.docker.com | sh
# 验证安装
docker --version
docker compose version
准备一个域名,例如 ntfy.example.com,将 DNS A 记录指向服务器 IP。
安装 Caddy:
bash
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install caddy -y
docker-compose.yml
创建部署目录:
bash
mkdir -p /opt/ntfy/{config,cache}
cd /opt/ntfy
创建 docker-compose.yml:
yaml
version: "3.8"
services:
ntfy:
image: binwiederhier/ntfy:latest
container_name: ntfy
command: serve
environment:
- TZ=Asia/Shanghai
volumes:
- ./config:/etc/ntfy
- ./cache:/var/cache/ntfy
ports:
- "127.0.0.1:8088:80"
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Iq \"healthy\":true"]
interval: 60s
timeout: 10s
retries: 3
start_period: 40s
创建 ntfy 服务端配置文件 /opt/ntfy/config/server.yml:
yaml
# 服务器基础地址(用于生成推送链接)
base-url: https://ntfy.example.com
# 消息持久化缓存(断线重连后能收到离线消息)
cache-file: /var/cache/ntfy/cache.db
cache-duration: 24h
cache-startup-queries: |
pragma journal_mode = WAL;
pragma synchronous = normal;
# 用户认证(强烈建议开启,防止陌生人滥用)
auth-file: /var/cache/ntfy/auth.db
auth-default-access: deny-all # 默认拒绝所有未认证访问
# 附件支持(发送图片、文件)
attachment-cache-dir: /var/cache/ntfy/attachments
attachment-total-size-limit: 5G
attachment-file-size-limit: 15M
attachment-expiry-duration: 3h
# 消息限制
message-size-limit: 4096
visitor-subscription-limit: 30
visitor-request-limit-burst: 60
visitor-request-limit-replenish: 10s
# Web 界面
web-root: app
enable-signup: false # 禁止通过 Web 界面自助注册
enable-login: true
启动服务:
bash
docker compose up -d
配置说明
Caddy 反向代理
编辑 /etc/caddy/Caddyfile:
ntfy.example.com {
reverse_proxy localhost:8088
}
重载 Caddy:
bash
sudo systemctl reload caddy
创建用户
ntfy 服务启动后,通过命令行创建用户:
bash
# 创建管理员(可以管理所有 topic)
docker exec -it ntfy ntfy user add --role=admin admin
# 创建普通用户
docker exec -it ntfy ntfy user add alice
# 查看用户列表
docker exec -it ntfy ntfy user list
设置 topic 访问权限
bash
# 允许用户 alice 对 topic "alerts" 有读写权限
docker exec -it ntfy ntfy access alice alerts rw
# 允许用户 alice 读取 topic "server-logs"
docker exec -it ntfy ntfy access alice server-logs ro
# 允许所有人(包括未认证)订阅某个 topic(公开 topic)
docker exec -it ntfy ntfy access everyone public-announcements ro
消息优先级说明
ntfy 支持五个优先级,影响通知的声音和展示方式:
| 优先级 | Header 值 | 效果 |
|---|---|---|
| 最高 | max / urgent |
持续振动报警,直到确认 |
| 高 | high |
高优先级通知声 |
| 普通 | default |
标准通知 |
| 低 | low |
无声通知 |
| 最低 | min |
仅出现在通知中心,无提示 |
使用方法
基础发送(curl)
bash
# 最简单的方式
curl -d "服务器备份完成" https://ntfy.example.com/my-alerts
# 带认证
curl -u alice:密码 \
-d "部署完成" \
https://ntfy.example.com/my-alerts
# 使用 Access Token(推荐)
curl \
-H "Authorization: Bearer tk_xxxxxxxxxxxxx" \
-d "消息内容" \
https://ntfy.example.com/my-alerts
生成 Access Token
bash
# 为用户 alice 创建 Access Token
docker exec -it ntfy ntfy token add alice
# 输出示例:
# token tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2, never expires
发送带标题和标签的通知
bash
curl \
-H "Authorization: Bearer tk_xxxxxxxxxxxxx" \
-H "Title: 服务器告警" \
-H "Priority: high" \
-H "Tags: rotating_light,computer" \
-d "磁盘使用率已超过 90%,请及时处理" \
https://ntfy.example.com/server-alerts
在备份脚本中使用
bash
#!/bin/bash
NTFY_URL="https://ntfy.example.com/my-alerts"
NTFY_TOKEN="tk_xxxxxxxxxxxxx"
notify() {
local title="$1"
local body="$2"
local priority="${3:-default}"
curl -s \
-H "Authorization: Bearer $NTFY_TOKEN" \
-H "Title: $title" \
-H "Priority: $priority" \
-d "$body" \
"$NTFY_URL" > /dev/null
}
# 执行备份
if tar czf /backup/data-$(date +%Y%m%d).tar.gz /data/; then
notify "备份成功" "今日备份已完成:/backup/data-$(date +%Y%m%d).tar.gz" "default"
else
notify "备份失败" "备份脚本执行失败,请立即检查服务器日志!" "urgent"
fi
配合 cron 使用
bash
# 编辑 crontab
crontab -e
# 凌晨 2 点执行备份,失败时发送通知
0 2 * * * /opt/scripts/backup.sh || curl -s -u alice:密码 \
-H "Title: 定时备份失败" -H "Priority: urgent" \
-d "凌晨备份任务失败!" https://ntfy.example.com/server-alerts
手机 App 订阅
- 下载 ntfy 官方 App:
- Android:Google Play 搜索 "ntfy" 或从 F-Droid 安装
- iOS:App Store 搜索 "ntfy"
- 打开 App → 设置 → 添加自定义服务器:
https://ntfy.example.com - 输入用户名和密码(或 Access Token)
- 订阅 topic,例如
my-alerts - 发送测试消息,确认手机收到推送
Web 界面
访问 https://ntfy.example.com 可以打开 ntfy 的 Web 界面,支持:
- 查看历史消息
- 订阅 topic
- 发送测试消息
- 管理 Access Token
常见问题
Q:发送通知返回 403 Forbidden?
说明 topic 需要认证但请求没有携带凭据。检查:
- 是否在请求中加了
-u user:password或-H "Authorization: Bearer token" - 用户是否有该 topic 的写权限(
ntfy access username topic-name rw)
Q:手机收不到推送通知?
- 检查手机 App 是否允许后台通知权限(各品牌 Android 手机可能需要单独设置)
- iOS 用户需要确认 App 通知权限已开启
- 检查 topic 名称是否拼写正确(区分大小写)
- 使用 Web 界面或 curl 验证消息是否发送成功
Q:如何发送带操作按钮的通知?
ntfy 支持在通知中添加操作按钮:
bash
curl \
-H "Authorization: Bearer $NTFY_TOKEN" \
-H "Title: 服务器 CPU 过高" \
-H "Actions: view, 查看详情, https://monitor.example.com; \
http, 重启服务, https://api.example.com/restart, method=POST" \
-d "CPU 使用率持续 30 分钟超过 95%" \
https://ntfy.example.com/server-alerts
Q:消息历史保留多久?
由 cache-duration 配置控制,本文设置为 24h。客户端离线后重连,会接收到缓存期内的离线消息。超出缓存时间的消息会被自动清理。
ntfy 的核心优势是极简------发送通知不需要任何预先配置,一条 curl 命令搞定;接收通知只需要 App 订阅一个 topic。把它接入备份脚本、监控系统、部署流程,就有了一套属于自己的服务器消息推送中心。