
やりたいこと
カメラが人や車両を検知したらスマホに Push 通知。
録画データの ts から mp4 へのエンコードが完了したらスマホに Push 通知。
Zabbix からのメールに連動してスマホに Push 通知。
毎朝、その日の天気予報をスマホに Push 通知。
もうね、なんでもあり。
NanoPi NEO の CPU 温度が50度を超えたらPush通知。とかでもいい。
とにかく手軽に情報をスマホに集めたかった。
ただ、メールのように保存されている必要もなく、本当にただ通知が表示されればそれだけでいい。
用意したもの
Raspberry Pi 4B だけ。スマホはお手元のものを…
使うのはNtfy(ノーティファイ)というセルフホスト型のサーバソフトウェア
ダウンロードとインストール
以下のリリースページからダウンロード。
これを書いている時点(2025/03/31)で V2.21.0 が最新。
そして、ラズパイに導入するので、ARM系のパッケージかつ64ビット版。
Docker版もあるっぽいけど、個人的には管理しやすい tar.gz を入手。
ダウンロードと解凍は以下の通り。
$ wget https://github.com/binwiederhier/ntfy/releases/download/v2.21.0/ntfy_2.21.0_linux_arm64.tar.gz
$ tar zxfv ntfy_2.21.0_linux_arm64.tar.gz
$ mv ntfy_2.21.0_linux_arm64 ntfy
$ cd ntfy
これだけでOK
ちょいと気を付ける点
自宅内限定とか社内限定とかで、サーバとスマホが同じネットワークにあって、そこでだけ受け取ればよいということであれば、サーバ設定等でローカルのIPアドレスを使えば特に問題ない。
けど、スマホを外に持ち出して、インターネット経由でも通知を受け取りたいとなった場合、スマホが自宅内(社内)にあるNtfyサーバと通信できなければならない。
よく言われる「自宅鯖の公開」みたいな感じ。
固定のグローバルIPアドレスを持つとか、DDNSを使用してアクセスできるようにするとか、さらにルータの設定を弄ってポート開放(ポートフォワード)するとか、そんな設定が必要になってくるので、その場合はちょい面倒かもね。
なにより、Ntfyサーバを動かす権限とか、各フォルダ/ファイルのパーミッションとか、外部からアクセスされる可能性があるのなら、気を付けないとならない点はいくつかある。(最後の方にまとめる)
サーバ設定
あとはチョチョイと設定すればすぐ動く。
設定ファイルは server 等ディレクトリ内の server.yml というファイルで行う。
$ cd server
$ vi server.yml
変更箇所は以下。
それぞれ、先頭の # を削除して、値を書いていく。
base-url: "http://yourdomain"
listen-http: ":80"
cache-file: "/var/lib/ntfy/cache.db"
auth-file: "/var/lib/ntfy/user.db"
attachment-cache-dir: "/var/cache/ntfy/attachments"
upstream-base-url: "https://ntfy.sh"
とりあえず、こんなもんで動くようにはなる。
「base-url: “http://yourdomain”」 ローカルで運用するだけならローカルIPで http://192.168.10.251 とかでも良い。
「listen-http: “:80″」は多分変えないとダメよね?Nginx か Apache が既に使っちゃってること多いと思うので。
「upstream-base-url: “https://ntfy.sh”」は iPhone に Push しなければ不要だけど、入れておいてもいいでしょう。
で、2つくらいファイル関連の設定も入れてあるけど、/var/lib/ntfy というディレクトリが存在しないので作っておく。
$ sudo mkdir /var/lib/ntfy
これで ./ntfy に戻って、下記のようにすると動き出す…
$ sudo ./ntfy serve -c ./server/server.yml
./ntfy のあと、serve なのにっちょっと注意かも。
ずっと server と打ってることに気づかなくて、しばらく悩んだw
もし、エラーが出たら server.yml に間違いがないか確認。
無事に起動した場合は以下のように表示される。
2026/04/01 00:03:19 INFO Listening on :80[http], ntfy 2.21.0, log level is INFO (tag=startup)
2026/04/01 00:04:19 INFO Server stats (emails_received=0, emails_received_failure=0, emails_received_success=0, emails_sent=0, emails_sent_failure=0, emails_sent_success=0, messages_cached=0, messages_published=0, subscribers=0, tag=manager, topics_active=0, users=1, visitors=0)
起動出来たら、ブラウザで base-url に記載した URL にアクセスしてみる。
以下のような(色合いは端末によって変わる)UI が表示されればOK

通知のための設定:Topicの購読
左ペインの「+ トピックを購読する」をクリックして、新たに開かれたウィンドウ内にある「トピック名」に適当に名前を登録する。
「free_topic」とか「talk_to_oneself」とか、なんでもいい。
で、「購読する」をクリックすればOK

…なんか、Chrome は英語を日本語に自動で翻訳しちゃうので、新たに始まったTopic「talk_to_oneself」が「独り言を言う」に訳されちゃってるけど…まぁ、気にしない。

試しに通知を出してみる。
左ペインの「購読トピック」の「talk_to_oneself」(ブラウザ上の表示は「独り言を言う」)をクリックし、ブラウザ内左上に表示されている内容も「独り言を言う」になったら「通知を公開する」をクリック。
すると、新たなウィンドウが開かれるので、「タイトル」と「メッセージ」に適当に文章を書いて「送信」

で、ちゃんと通知が飛んだ。

PC上のブラウザで履歴が見れたので、基本的な動作はこれでOKということに。
では、次、目的の「スマホにPush通知」に移ろう。
スマホでは「ntfy」アプリを使う
iPhone でも Android でも、同じ名称のアプリがあるので、検索してインストール。

アプリを立ち上げたら、画面下にある「Settings」をタップして、その中の「Default server」を server.yml 内 base-url に設定したURLを書いておくと、あとが楽。
尚、舌では USERS に何かユーザーが入っちゃってるけど、通知の送受信に認証が必要になったら登録すればよいので、動作確認の段階では空欄のままでOK(ブラウザで通知送信確認した時も、特にユーザーの登録はしていないので問題ない)

で、お次は画面下にある「Notifications」へ移動。
購読したいトピックの登録をするので、画面右上の「+」をタップ。

「Topic name, e.g. phil_alerts」となっているところに、さっきブラウザで登録したトピックの「talk_to_onself」を入力。
「Use another server」は上の「Settings」の「Default server」に間違いなければそのままで良い。
入力が終わったら「Subscribe」

これで一通り設定完了。
さっきブラウザで通知を送ったけど、もう一度メッセージを変えて送ってみる。
また、今度はブラウザ下部にある「ここにメッセージを入力してください」に入力して試してみる…

数秒後…

うん、OKだね。
いろいろな通知方法
ここまではブラウザで試していたけど、これは目的の使い方じゃない。
ラズパイのGPIOにスイッチが繋がっててそれが押されたら、とか、何らかのアクションがあって、それに連動して通知を飛ばしたいわけなので、ブラウザでってのはまずない。
python で送信
じゃぁ、何が使われるかって言ったら、やっぱり python が多いのかな?と。
てことで、簡単なコードは以下の通り。
import requests
def send_ntfy(msg, title="アラート", priority="high"):
# トピックのURL
url = "http://yourdomain/talk_to_oneself"
headers = {
"Title": title.encode('utf-8'),
"Priority": priority,
"Tags": "warning,computer"
}
# メッセージ送信
response = requests.post(url, data=msg.encode('utf-8'), headers=headers)
if response.status_code == 200:
print("送信完了")
else:
print(f"なんかエラー出た: {response.status_code}")
# 実行
send_ntfy("こうすれば通知を送信できるはず", title="Pythonから")
curl で送信
これは超簡単。
$ curl -d "curlで送ってみる" http://yourdomain/talk_to_oneself
単純なのならこれで送れる。
けど、もう少し工夫すると以下のような感じかな。
$ curl -H "Title: curlから通知送信" -H "Priority: urgent" -H "Tags: warning,rotating_light" -d "curlならやろうと思えば1行でイケる!" http://yourdomain/talk_to_oneself
wget で送信
curl と同じくらいシンプルにイケる。
$ wget --post-data="wgetから送信" http://yourdomain/talk_to_oneself
同様に、ちょっと工夫すればもう少し情報増やせる。ちょっと長いけど…
$ wget --header="Title: curlから通知送信" --header="Priority: urgent" --header="Tags: warning,rotating_light" --post-data="wgetでも1行がちょっと長いけど、イケる!" -qO- http://yourdomain/talk_to_oneself
とりあえず、これだけできれば困らないかな。
サービスとして登録してラズパイ起動時にも自動で使えるようにする
そのためのファイルが既に用意されてる。
./ntfy/server/ntfy.service
これをそのまま /etc/systemd/system/ にコピーしても良い。
$ sudo cp ./ntfy/server/ntfy.service /etc/systemd/system/
$ cd /etc/systemd/system
$ sudo chown root:root ntfy.service
$ sudo vi ntfy.service
で、ファイルを書き換えるのは以下の部分だけでもとりあえずはOK
ExecStart=/usr/bin/ntfy serve --no-log-dates
うちは Ntfy サーバの設定ファイル(server.yml)を実験的に切り替えて使ったりしたいので、以下のような感じにしてる。
ExecStart=/etc/ntfy/ntfy serve -c /etc/ntfy/server/server_hogehoge.yml
/etc/ntfy 配下に実行ファイルがあるのはちょっと違和感あるので、ここは後々 /us/bin あたりにファイルを移動して変えよう。
で、もう一つ気を付けたいのが、Ntfyサーバを実行するユーザーやグループの設定。
デフォルトは以下になっている。
User=ntfy
Group=ntfy
ここはできればそのままを維持したい。
root にしてしまえばディレクトリや設定ファイルのパーミッション関係なしに最強権限で動いてくれるから面倒はない。
面倒はないけど…セキュリティ的にはザルよね。
(上の方でも sudo ./ntfy serve -c ./server/server.yml なんて動かし方してるのも一時的だからこそ)
なので、いったん動作確認をするためだけにここを root / root にするのはギリOKとして、最終的には必ず次項の
「外部からのアクセスがあり得るならやっておくこと」
をやっておくべき。
で、とりあえず動作確認してみよか。
$ sudo systemctl daemon-reload
$ sudo systemctl enable ntfy.service
$ sudo systemctl start ntfy.service
$ sudo systemctl status ntfy.service
で設定リロード、Ntfyサービス有効化、Ntfyサーバ開始、Ntfyサーバステータス表示、としていく。
もし、上手く動かない等があったら、下記のようにして挙動を見るのもあり。
$ sudo journalctl -u ntfy.service -f
-f を付けることで、履歴を見るという挙動ではなく、リアルタイムで最新のログを自動表示してくれるモードになる。
ここまでやっておけば、Ntfyサーバがラズパイの起動と同時にスタートするのであとはPythonやcurl、wget等を使って、通知を出したい機能に設定を加えていけばよいでしょう。
外部からのアクセスがあり得るならやっておくこと
まず、User/Group は是非とも ntfy を作っておきたい。
ntfy.service ファイルでも User/Group は ntfy になっているのでね。
$ sudo adduser --system --ingroup ntfy --no-create-home --shell /usr/sbin/nologin ntfy
普通に adduser すると、ホームディレクトリを自動で作ってくれたり、ログインできるユーザーとして作成してくれたりして便利だけど、Ntfy のようにただバックグラウンドでサーバを動かしててほしいだけのユーザーはホームディレクトリは不要だしログインもできなくても良いので、上記のように –system を付けていろいろ指定しておく。
続いて、設定ファイル等が入ったディレクトリを以下のように移動して権限も変更しておく。
$ sudo mv ./ntfy /etc/ntfy
$ sudo chmod 750 /etc/ntfy
$ sudo chown -R root:ntfy /etc/ntfy
ユーザー/キャッシュデータベースファイルやアタッチファイルのデータベースなんかもあるので、そっちも権限変更。
$ sudo chown -R ntfy:ntfy /var/lib/ntfy
$ sudo chmod 770 /var/lib/ntfy
$ sudo chmod 600 /var/lib/ntfy/cache.db
$ sudo chmod 600 /var/lib/ntfy/user.db
$ sudo chown -R ntfy:ntfy /var/cache/ntfy
$ sudo chmod 700 /var/cache/ntfy
$ sudo chmod 700 /var/cache/attachments
面倒だけどね、外部からアクセスできるようになっている部分は必要最低限やっておかないとね。
てことで、サービス再起動…うまくいくかな?
$ sudo systemctl restart ntfy.service
$ sudo systemctl status ntfy.service
無事起動したら完了~
この記事にコメントしてみる