---
disqus: ahb0222
GA : G-VF9ZT413CG
---
> [color=#40f1ef][name=LHB阿好伯, 2024/10/22][:earth_africa:](https://www.facebook.com/LHB0222/)
[TOC]

# Ntfy介紹
Ntfy 是一個簡單但功能強大的發布-訂閱(pub-sub)通知服務
通過 HTTP PUT/POST 請求發送通知到任何設備
這是一個自託管的替代方案
可以取代 Line Notify 等服務
## 主要特點:
- ### 通知方式多元化:
- 手機推播通知(Android / iOS)
- 電子郵件通知
- WebSocket 即時通知
- Webhook 整合
- ### 多種格式支援:
- 純文字訊息
- 結構化 JSON 資料
- 附加檔案傳輸
- 支援 Markdown 格式
- ### 安全性功能:
- 訪問控制與身份驗證
- 端到端加密
- 即時訊息傳遞確認
- 支援 HTTPS 加密傳輸
- ### 整合能力:
- REST API 支援
- 命令列工具
- 支援 Docker 部署
- 提供各種程式語言的套件(python/Go/PHP/C#/.NET/R/JS/Java/Node)
# Ntfy 相較於 Line Notify 的優點:
* 開源且可自行架設
* 支援多種通知方式
* 彈性的訂閱方案
* 具備檔案傳輸功能
* API 介面完整
* 不需要辦理帳號即可使用
使用上若是無自己架設的需求
使用官方伺服器路徑**https://ntfy.sh/** 即可
想一個不容易被猜到的topic(訊息主題)即可開始享用
其實跟MQTT很像
只是應用的方向不太一樣
有配套的APP使用上是能取代Line Notify
- 電腦端
- https://ntfy.sh/app

- 手機端
- 安卓
[
](https://play.google.com/store/apps/details?id=io.heckel.ntfy)
- 蘋果
[
](https://apps.apple.com/us/app/ntfy/id1625396347)

# 結合Node-Red

```json=
[
{
"id": "c956e688cc74ad8e",
"type": "http request",
"z": "fabdd7a3.4045a",
"name": "ntfy.sh",
"method": "POST",
"ret": "txt",
"paytoqs": "ignore",
"url": "https://ntfy.sh/mytopic",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"senderr": false,
"credentials":
{
"user": "",
"password": ""
},
"x": 590,
"y": 3160,
"wires":
[
[]
]
},
{
"id": "32ee1eade51fae50",
"type": "function",
"z": "fabdd7a3.4045a",
"name": "data",
"func": "msg.payload = \"Something happened\";\nmsg.headers = {};\nmsg.headers['tags'] = 'house';\nmsg.headers['X-Title'] = 'Home Assistant';\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 470,
"y": 3160,
"wires":
[
[
"c956e688cc74ad8e"
]
]
},
{
"id": "b287e59cd2311815",
"type": "inject",
"z": "fabdd7a3.4045a",
"name": "Manual start",
"props":
[
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": "20",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 330,
"y": 3160,
"wires":
[
[
"32ee1eade51fae50"
]
]
}
]
```
```javascript=
// 使用 Base64 編碼中文標題
function encodeHeaderAsRFC2047(text) {
// 轉換成 Base64
const base64 = Buffer.from(text).toString('base64');
return `=?UTF-8?B?${base64}?=`;
}
msg.payload = `測站: ${msg.payload.測站}
⏰ 時間: ${msg.payload.時間}
📊 偵測值: ${msg.payload.偵測值}
⚠️ 預警值: ${msg.payload.預警值}
`;
msg.headers = {};
msg.headers['tags'] = 'rotating_light'; // 加入警告和警報 emoji
msg.headers['X-Title'] = encodeHeaderAsRFC2047('監測警報');
msg.headers['Priority'] = 5; // 設定最高優先級 (5 = max/urgent)
return msg;
```
# Home Assistant
結合到HA也十分方便
```yaml=
notify:
- name: ntfy
platform: rest
method: POST_JSON
data:
topic: YOUR_NTFY_TOPIC
title_param_name: title
message_param_name: message
resource: https://ntfy.sh
```
# 收費方案
主要是可以辦帳號用於保存相關的資料

# 是否可以商用?
最後最重要一點
Ntfy 是以 Apache 許可證 2.0 和 GPLv2 許可證下獲得雙重許可發布的開源軟體
Apache License 2.0 主要特點:
* 完全允許商業使用:
* 可以免費用於商業目的
* 可以修改原始碼
* 可以自由分發
* 可以私有使用
* 主要要求:
* 必須保留原始版權聲明
* 必須包含 Apache License 的副本
* 若修改了代碼,需要明確說明
* 商業應用場景:
* 企業內部部署
* 整合到商業產品中
* 提供託管服務
* 二次開發後商用
* 授權相容性:
* 與大多數開源授權相容
* 可以與專有軟體結合
* 可以改變授權條款
# 相關文章
[Line Notify替代方案 - discord| Telegram Bot 以Node-Red 進行測試](/1j54odKDTvit8O3q5TktUw)
# 自架伺服器啟用文件發送
##創建緩存目錄:
```
sudo mkdir -p /var/cache/ntfy/attachments
sudo chown ntfy:ntfy /var/cache/ntfy/attachments
```
## 修改配置文件:
```
sudo nano /etc/ntfy/server.yml
```
添加以下內容:
```
base-url: "http://localhost:8080"
# 將 base-url 改為外部可訪問的 URL
#base-url: "URL"
attachment-cache-dir: "/var/cache/ntfy/attachments"
attachment-file-size-limit: "15M"
attachment-total-size-limit: "5G"
attachment-expiry-duration: "3h"
# 預設存取控制
auth-default-access: "read-write"
# 如果使用了 Cloudflare,建議添加以下設定
behind-proxy: true
```
## 預設存取控制(可選)
設定正確的權限:
```
sudo chown ntfy:ntfy /etc/ntfy/server.yml
sudo chmod 644 /etc/ntfy/server.yml
```
重啟服務:
```
sudo systemctl restart ntfy
```
確認服務狀態:
```
sudo systemctl status ntfy
```
## 啟動監測
### ntfy 服務配置
```
# 創建配置文件
sudo nano /etc/ntfy/server.yml
# 添加以下內容
base-url: "http://localhost:8080"
listen-http: ":8080"
log-level: info
log-file: /var/log/ntfy.log
enable-metrics: true
metrics-listen-http: ":9090"
# 創建所需目錄和設置權限
sudo mkdir -p /var/log/ntfy
sudo mkdir -p /var/cache/ntfy
sudo useradd -r -s /bin/false ntfy
sudo chown -R ntfy:ntfy /var/log/ntfy
sudo chown -R ntfy:ntfy /var/cache/ntfy
sudo chown -R ntfy:ntfy /etc/ntfy
# 重啟 ntfy 服務
sudo systemctl restart ntfy
```
### Prometheus 安裝和配置
```
# 安裝 Prometheus
sudo apt update
sudo apt install prometheus
# 配置 Prometheus
sudo nano /etc/prometheus/prometheus.yml
# 添加以下配置
global:
scrape_interval: 15s
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9091"]
- job_name: "ntfy"
static_configs:
- targets: ["localhost:9090"]
# 修改啟動配置
sudo nano /etc/default/prometheus
ARGS="--web.listen-address=:9091"
# 設置權限
sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml
sudo chmod 644 /etc/prometheus/prometheus.yml
# 重啟 Prometheus
sudo systemctl restart prometheus
```
### Grafana 安裝和配置
```
# 添加 Grafana GPG 密鑰
sudo apt-get install -y software-properties-common wget
sudo wget -q -O /usr/share/keyrings/grafana.key https://packages.grafana.com/gpg.key
# 添加 Grafana 倉庫
echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
# 更新並安裝 Grafana
sudo apt-get update
sudo apt-get install grafana
# 啟動 Grafana
sudo systemctl enable grafana-server
sudo systemctl start grafana-server
```
>[!Note]
>Grafana配置檔
>https://raw.githubusercontent.com/binwiederhier/ntfy/main/examples/grafana-dashboard/ntfy-grafana.json

# python使用範例
```python=
import requests
import os
from pathlib import Path
import mimetypes
def get_mime_type(file_path):
"""
取得檔案的 MIME 類型
"""
mime_type, _ = mimetypes.guess_type(file_path)
return mime_type or 'application/octet-stream'
def send_to_ntfy(server_url, topic, message=None, image_path=None):
"""
發送訊息和圖片到NTFY服務器
參數:
server_url (str): NTFY服務器的URL (不包含結尾的斜線)
topic (str): NTFY的主題名稱
message (str, optional): 要發送的文字訊息
image_path (str, optional): 圖片檔案的路徑
"""
# 確保 server_url 不以斜線結尾
server_url = server_url.rstrip('/')
# 構建完整的URL
full_url = f"{server_url}/{topic}"
try:
# 如果有文字訊息要發送
if message:
response = requests.post(
full_url,
data=message.encode('utf-8'),
headers={"Content-Type": "text/plain"}
)
print(f"訊息發送狀態碼: {response.status_code}")
print(f"訊息發送回應: {response.text}")
if response.status_code != 200:
print(f"發送訊息失敗: {response.status_code}")
return False
# 如果有圖片要發送
if image_path and os.path.exists(image_path):
# 檢查檔案是否存在
if not os.path.exists(image_path):
print(f"找不到檔案: {image_path}")
return False
# 取得檔案大小
file_size = os.path.getsize(image_path)
print(f"檔案大小: {file_size} bytes")
# 取得檔案的 MIME 類型
content_type = get_mime_type(image_path)
print(f"檔案類型: {content_type}")
with open(image_path, 'rb') as image_file:
filename = Path(image_path).name
headers = {
"Filename": filename,
"Content-Type": content_type,
# 避免使用中文標頭
"Title": "Image Upload",
"Tags": "upload,image"
}
print(f"發送請求到: {full_url}")
print(f"使用標頭: {headers}")
response = requests.put(
full_url,
data=image_file,
headers=headers
)
print(f"圖片發送狀態碼: {response.status_code}")
if response.text:
print(f"圖片發送回應: {response.text}")
if response.status_code != 200:
print(f"發送圖片失敗: {response.status_code}")
return False
return True
except Exception as e:
print(f"發送過程中發生錯誤: {str(e)}")
return False
# 使用範例
if __name__ == "__main__":
# 設定參數
SERVER_URL = "http://localhost:8080" # 不要在結尾加斜線
TOPIC = "FTIR_OCR"
MESSAGE = "這是一個測試訊息"
IMAGE_PATH = "/home/huan-yu/processed_image.png"
# 發送訊息和圖片
success = send_to_ntfy(
server_url=SERVER_URL,
topic=TOPIC,
message=MESSAGE,
image_path=IMAGE_PATH
)
if success:
print("訊息和圖片發送成功!")
else:
print("發送失敗,請檢查錯誤訊息。")
```
# 問題排除
## IOS 無法進行警訊通知
查看網路上討論上也有許多人發生一樣的問題
https://github.com/binwiederhier/ntfy/issues/880
https://github.com/binwiederhier/ntfy/issues/1191
https://docs.ntfy.sh/config/#web-push
目前最佳的解決方案為使用PWA
:::success
需求條件
* 有效的 HTTPS 憑證
* 需設定 VAPID 金鑰對
* 資料庫儲存訪客訂閱資訊
* 管理員郵箱
:::
```bash=
# 產生 VAPID 金鑰
sudo ntfy webpush keys
# 編輯設定檔
sudo nano /etc/ntfy/server.yml
# 重啟服務
sudo systemctl restart ntfy
```
server.yml中增加以下資訊
:::info
web-push-public-key: [公鑰]
web-push-private-key: [私鑰]
web-push-file: /var/cache/ntfy/webpush.db
web-push-email-address: [管理員郵箱]
:::
🌟全文可以至下方連結觀看或是補充
全文分享至
https://www.facebook.com/LHB0222/
https://www.instagram.com/ahb0222/
有疑問想討論的都歡迎於下方留言
喜歡的幫我分享給所有的朋友 \o/
有所錯誤歡迎指教
# [:page_with_curl: 全部文章列表](https://hackmd.io/@LHB-0222/AllWritings)
