ntfyをVPSにセルフホストする手順|サーバーの異常や日報をスマホにプッシュ通知【2026年版】

※内容は2026年9月25日時点の情報(ntfy v2.28.0)をもとにしています。

「サーバーの異常やアクセスの急増に、外出先でもすぐ気づきたい」「LINE Notifyが終わってしまい、代わりの通知手段を探している」。そんな方に向けて、自分のサーバーで動かせるプッシュ通知サービス「ntfy(ノーティファイ)」を紹介します。

当サイトOSSMatchを運営する私たちは、自社の5つのWebサイトのアクセス状況を監視していて、その通知をntfyでスマホに届けています。この記事では、ntfyをVPSにセルフホストする手順を、実際の運用をもとに、つまずきやすい点も含めてまとめました。

サーバーの通知をスマホで受け取りたい、でも手段に困っていませんか

サーバーの監視やバッチ処理の結果は、メールで受け取るのが定番です。ただ、メールには次のような弱点があります。

  • ほかのメールに混ざって、急ぎの通知ほど見落としやすい
  • 「急ぎ」と「あとで見ればよい」の区別がつけにくい
  • 通知をタップして、すぐ管理画面を開くといった使い方がしにくい

一方で、スマホへのプッシュ通知の手段は、この数年で選択肢が減りました。手軽に使われていたLINE Notifyは2025年3月末でサービスを終了しています。SlackやDiscordへの通知も便利ですが、仕事用のチャットに監視の通知が大量に流れると、今度はそちらが埋もれてしまいます。

なぜntfyを自分のサーバーで動かすのか

ntfyは、HTTPでメッセージを送るだけで、スマホやPCにプッシュ通知を届けられるオープンソースのソフトです。iPhone・Android向けのアプリと、ブラウザで使える画面が用意されています。

ntfyには、公式が運営する公開サーバー(ntfy.sh)があり、登録なしで無料で使えます。ただし、公開サーバーの「トピック」(通知の宛先の名前)は、名前さえ分かれば誰でも読んだり送ったりできます。サーバーの監視結果のように、他人に見られたくない通知には向きません。

そこで、ntfyを自分のVPSに立て、ログインしないと送受信できないように設定します。有料の通知サービスと比べると、次のようになります。

項目 ntfy(セルフホスト) ntfy.sh(公開サーバー) Pushover
料金 無料(VPS代のみ) 無料(有料プランあり) 各プラットフォーム4.99ドルの買い切り(30日間無料)
通知の中身 自分のサーバーに保存 公式サーバーを経由 Pushoverのサーバーを経由
アクセス制限 ユーザー・トピックごとに設定できる トピック名が分かれば誰でも使える アカウント単位
送り方 HTTP(curlの1行でOK) HTTP API

※Pushoverの料金は2026年9月25日時点の公式サイトの表示です。

ntfyの詳しいデータ(GitHubのスター数、最終更新、日本語化率など)は、OSSMatchのntfyページで確認できます。

私たちのntfyの使い方

私たちは、自社のWebサイト5つを、オープンソースのアクセス解析ツールUmamiで計測しています(構築の手順はUmamiをVPSにセルフホストする手順で紹介しています)。そのUmamiのデータを定期的にチェックするスクリプトを動かし、結果をntfyで送っています。

通知 タイミング 優先度
アクセス日報(サイトごとのPVの要約) 毎朝7時 低(音を鳴らさない)
アクセスの急増 毎時のチェックで検知したとき 高
計測停止の疑い(24時間PVが0件) 毎時のチェックで検知したとき 高

通知をタップすると、そのサイトのUmamiの画面が開くようにしています。ntfyはとても軽く、実測のメモリ使用量は約20MBでした。Umamiなどほかのサービスと同じVPSに同居させています。

サーバーの監視結果をntfyのサーバー経由でスマホに通知する構成のイメージ

ntfyをVPSに構築する手順

ここからは、Dockerでntfyを動かし、Caddyで自動的にHTTPS化する手順を紹介します。前提は次のとおりです。

  • Ubuntu 24.04のVPSに、Dockerがインストール済み
  • 通知用のサブドメイン(例:ntfy.example.com)のAレコードが、VPSのIPアドレスを向いている
  • ファイアウォールで80番・443番を開けている

DockerのインストールやVPSの初期設定は、Umamiの構築記事の手順1・手順2と同じです。

手順1:設定ファイルを2つ作る

作業用のフォルダを作ります。

mkdir -p ~/ntfy/data && cd ~/ntfy

nano docker-compose.ymlで、次の内容を保存します。ntfy.example.comは自分のサブドメインに置き換えてください。

services:
  ntfy:
    image: binwiederhier/ntfy
    container_name: ntfy
    command: serve
    restart: always
    environment:
      TZ: Asia/Tokyo
      NTFY_BASE_URL: https://ntfy.example.com
      NTFY_BEHIND_PROXY: "true"
      NTFY_CACHE_FILE: /var/lib/ntfy/cache.db
      NTFY_AUTH_FILE: /var/lib/ntfy/auth.db
      NTFY_AUTH_DEFAULT_ACCESS: deny-all
      NTFY_ENABLE_LOGIN: "true"
      NTFY_ATTACHMENT_CACHE_DIR: /var/lib/ntfy/attachments
      NTFY_UPSTREAM_BASE_URL: https://ntfy.sh
    volumes:
      - ./data:/var/lib/ntfy
    healthcheck:
      test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -q healthy"]
      interval: 60s
      timeout: 5s
      retries: 3

  caddy:
    image: caddy:2
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - ntfy

volumes:
  caddy_data:
  caddy_config:

ポイントになる設定は次のとおりです。

設定 意味
NTFY_AUTH_DEFAULT_ACCESS: deny-all ログインしていない人は、送信も受信もできない。自分専用の通知サーバーにするための一番大事な設定
NTFY_BEHIND_PROXY Caddyなどの後ろで動かすときに必要。設定しないと、すべてのアクセスが同じ1人として扱われ、回数制限にかかりやすくなる
NTFY_UPSTREAM_BASE_URL iPhoneで即時に通知を受け取るための設定。公式サーバーには「新着あり」の合図(メッセージID)だけが送られ、通知の本文は送られない
NTFY_ENABLE_LOGIN ブラウザの画面からログインできるようにする

次に、nano Caddyfileで次の3行を保存します。

ntfy.example.com {
    reverse_proxy ntfy:80
}

手順2:起動する

2つのファイルがそろっていることを確認してから起動します。設定ファイルを作る前に起動すると、同じ名前のフォルダが作られてしまうので注意してください。

ls -l docker-compose.yml Caddyfile
sudo docker compose up -d
sudo docker compose ps

証明書の取得に数十秒かかることがあります。次のコマンドで{"healthy":true}と返ってくれば準備完了です。

curl https://ntfy.example.com/v1/health

手順3:ユーザーを作る

ユーザーは、役割ごとに分けて2つ作ります。

  • 自分用(管理者):スマホのアプリで通知を受け取る
  • 送信専用:監視スクリプトなどが通知を送るときだけに使う。受信はできない

送信専用のユーザーを分けておくと、スクリプトのトークンが万一漏れても、通知を読まれることはありません。

# スマホで受け取る自分用(管理者)。パスワードを聞かれるので入力
sudo docker exec -it ntfy ntfy user add --role=admin myname

# スクリプトの送信専用ユーザー
sudo docker exec -it ntfy ntfy user add notifier
sudo docker exec ntfy ntfy access notifier 'alerts-*' write-only

# 送信専用ユーザーのアクセストークンを発行(表示された tk_ で始まる値を控える)
sudo docker exec ntfy ntfy token add notifier

ログインせずに送ろうとすると、拒否される(403)ことも確認しておきましょう。

curl -d "test" https://ntfy.example.com/alerts-server

手順4:通知を送ってみる

控えておいたアクセストークンを使って、curlで通知を送ります。

curl \
  -H "Authorization: Bearer tk_xxxxxxxxxxxxxxxx" \
  -H "Title: バックアップ完了" \
  -H "Priority: low" \
  -H "Tags: white_check_mark" \
  -d "umami のバックアップが終わりました" \
  https://ntfy.example.com/alerts-server
  • Priority:優先度。min・low・default・high・max(urgent)の5段階。lowは音や振動なし、highは長めの振動で知らせます
  • Tags:絵文字の名前を書くと、通知の先頭に絵文字が付きます(例:white_check_markで✅)
  • Click:通知をタップしたときに開くURLを指定できます

手順5:スマホのアプリで受け取る

App StoreまたはGoogle Playで「ntfy」のアプリを入れ、次の順に設定します。

  1. アプリの設定(Settings)で、自分のサーバーのURLと、手順3で作った自分用のユーザー名・パスワードを登録する
  2. 「+」を押し、トピック名(例:alerts-server)を入力する
  3. 「Use another server(他のサーバーを使用)」を必ずオンにして、自分のサーバーのURLを入れる
  4. 「Subscribe(購読)」を押す

一覧に「ntfy.example.com/alerts-server」のように、自分のサーバーの名前付きで表示されていれば成功です。手順4で送ったテスト通知が表示されます。

通知を仕組みに組み込む例

定期実行の処理が失敗したときだけ知らせる

cronで動かしているバックアップなどは、失敗したときだけ通知すると便利です。コマンドのあとに||でcurlをつなぐと、失敗したときだけ送られます。

15 4 * * * /home/ユーザー名/umami/backup.sh || curl -s -H "Authorization: Bearer tk_xxxxxxxxxxxxxxxx" -H "Priority: high" -H "Tags: rotating_light" -d "バックアップに失敗しました" https://ntfy.example.com/alerts-server

Pythonのスクリプトから送る

私たちの監視スクリプトでは、次のような関数で送っています。ntfyはHTTPヘッダーのUTF-8に対応していますが、ライブラリによっては日本語のタイトルが文字化けすることがあります。公式ドキュメントにあるとおり、タイトルをRFC 2047形式にしておくと確実です。

import urllib.request
from base64 import b64encode

def push(title, message, priority="default", tags="", click=None):
    headers = {
        "Authorization": "Bearer tk_xxxxxxxxxxxxxxxx",
        "Priority": priority,
        # 日本語のタイトルは RFC 2047 形式にすると、どのライブラリでも安全に送れる
        "Title": "=?UTF-8?B?" + b64encode(title.encode()).decode() + "?=",
    }
    if tags:
        headers["Tags"] = tags
    if click:
        headers["Click"] = click
    req = urllib.request.Request("https://ntfy.example.com/alerts-server",
                                 data=message.encode(), headers=headers, method="POST")
    urllib.request.urlopen(req, timeout=15)

push("アクセス急増", "直近1時間のPVが平均の3倍です", priority="high", tags="chart_with_upwards_trend")
定期実行やスクリプトから、失敗したときだけ通知を送る仕組みのイメージ

ntfyのセルフホストでつまずきやすい点

症状 原因 対処
スマホで購読したのに通知が1件も届かない 「Use another server」をオンにし忘れ、公開サーバー(ntfy.sh)の同じ名前のトピックを購読している 一覧の表示が「ntfy.sh/トピック名」になっていないか確認し、購読し直す
アプリでログインできない 送信専用ユーザーの情報でログインしている アプリには、受信できる自分用のユーザーでログインする
トピックを選ぶ画面が出ない ntfyのトピックは一覧から選ぶのではなく、名前を自分で入力する方式 送信側と同じトピック名を入力する
iPhoneで通知が遅れる NTFY_UPSTREAM_BASE_URLが設定されていない 設定を追加して再起動する
日本語のタイトルが文字化けする ライブラリがHTTPヘッダーのUTF-8に対応していない タイトルをRFC 2047形式にする
起動直後にHTTPSでつながらない 証明書の取得中 数十秒待ってから再確認する

まとめ:ntfyなら、自分専用の通知サーバーをVPSで手軽に持てる

ntfyは、メモリ約20MBで動き、curlの1行で通知を送れる手軽なプッシュ通知サーバーです。ログイン必須の設定にすれば、サーバーの監視結果のような他人に見せたくない通知も、安心してスマホで受け取れます。

  1. 公開サーバーではなく、自分のVPSに立てる
  2. deny-allで、ログインしないと使えないようにする
  3. 受け取る用と送る用で、ユーザーを分ける
  4. スマホのアプリでは、自分のサーバーを指定して購読する

ntfyはとても軽いので、すでにVPSを持っていればそこに同居させるのがおすすめです。これからVPSを用意する場合も、メモリ512MB〜1GBの小さなプランで十分です。

シンVPSの料金・プランを見る(PR)

ほかの通知サービスの代わりになるオープンソースは、Pushoverの代替ツール一覧で比較できます。

参考にした公式情報