ntfy 自托管推送通知服务搭建:一条 curl 命令向手机发送通知

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 订阅

  1. 下载 ntfy 官方 App:
    • Android:Google Play 搜索 "ntfy" 或从 F-Droid 安装
    • iOS:App Store 搜索 "ntfy"
  2. 打开 App → 设置 → 添加自定义服务器:https://ntfy.example.com
  3. 输入用户名和密码(或 Access Token)
  4. 订阅 topic,例如 my-alerts
  5. 发送测试消息,确认手机收到推送

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。把它接入备份脚本、监控系统、部署流程,就有了一套属于自己的服务器消息推送中心。

相关推荐
Scott9999HH2 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔2 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社3 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海3 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖4 小时前
JDK 26 新特性详解
java·开发语言
马优晨5 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区6 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大7 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai7 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说7 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json