SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-26

Uptime KumaをDockerで構築して死活監視する方法

Uptime KumaをDockerで別VPSに構築し、Webサイト、ポート、DNS、cronを監視します。メールやTelegram、Discord、webhook通知と公開ステータスページの設定方法を解説します。

構築するもの

外部から他のサーバーや Web サイトを監視し、応答しなくなった瞬間にメール、Telegram、Discord、または webhook で通知する小さなコンテナを1つ構築します。Uptime Kuma は SQLite ファイルをバックエンドとする1つの Node プロセスとして動作するため、256-512 MB の RAM で無理なく稼働し、ライブダッシュボード、履歴グラフ、公開ステータスページを提供します。インストールに必要な Compose ファイルは10行です。ただし、本当に重要なのは どこで実行するか と、テストでアラートが実際に発報したことがあるか です。到達性を一度も確認していない監視は、存在しない監視より危険です。何も監視していないのに、保護されていると思い込ませるからです。

監視対象に及ばない場所でモニターを実行する

この判断が全体の成否を左右するため、最初に説明します。Uptime Kuma は、監視対象と同じホストで実行しないでください。 モニターを監視対象のサーバー上で動かすと、検知したい事象、つまりそのサーバーの停止やメモリ不足が発生した際に、モニターも停止します。その結果、アラートは一切届きません。停止したモニターから何も通知されない状態は、「すべて正常です」という状態と区別できません。サーバーが稼働している場合にも、別の問題があります。localhost を監視するモニターはワークロードと CPU を共有するため、負荷が急増すると自身のチェックがタイムアウトし、実際にはユーザーへのサービス提供が正常でも、対象を down と判定する誤警報が発生します。

そのため、Uptime Kuma は監視対象とは 別の VPS で実行してください。できれば、プロバイダーまたはリージョンも分けます。ユーザーと同じ方法で、つまりホスト名を使ってパブリックインターネット経由でサービスへ接続させます。安価なインスタンスで十分です。1 台の小規模な監視用 VPS で、すべてのサーバーを監視できます。この分離は、ホストしている負荷の高いアプリケーションで特に重要です。たとえば PhotoPrism や Immich の写真ライブラリ は、新しく取り込んだデータのインデックス作成中に数時間 CPU を占有することがあります。同じハードウェア上で動くモニターは、単に処理が忙しいだけのサービスを down と誤判定します。Kuma 自体の停止も検知するには、別の場所から cron で push heartbeat を送信してください。

前提条件とリソース規模

  • Docker 独自の apt リポジトリから Docker Engine と Compose v2 plugin をインストールした、まっさらな Ubuntu 24.04 VPS。遅れている docker.io distro package は使用しません。
  • 256 MB RAM で少数の monitor を実行できます。数十個の monitor と reverse proxy を運用する場合は、512 MB から 1 GB が余裕のある構成です。チェックの合間は CPU 使用率がほぼアイドル状態になります。
  • TLS と公開 status page が必要な場合だけ、domain と DNS A record(例: status.example.com が VPS を指す設定)。private instance では DNS を省略し、VPN または SSH tunnel を使用できます。
  • アラートの送信先への outbound network。メールプロバイダーには SMTP、Telegram と Discord には HTTPS を使用します。

Compose ファイル

/srv/uptime-kuma/compose.yaml に記述します。

services:
  uptime-kuma:
    image: louislam/uptime-kuma:2
    container_name: uptime-kuma
    restart: unless-stopped
    ports:
      - "127.0.0.1:3001:3001"
    volumes:
      - kuma-data:/app/data

volumes:
  kuma-data:

起動して、初回起動時の動作を確認します。

sudo mkdir -p /srv/uptime-kuma
# save the file above as /srv/uptime-kuma/compose.yaml, then:
cd /srv/uptime-kuma && sudo docker compose up -d
sudo docker compose logs -f uptime-kuma

正常に起動すると、Listening on 3001 がログに記録された後、出力が止まります。このファイルには、意図的に指定している点が3つあります。

127.0.0.1:3001:3001 を指定し、3001:3001 は指定しない。 Docker は ufw がパケットを認識する前に DNAT ルールを評価してポートを公開します。そのため、単純な 3001:3001 では、ファイアウォールの設定に関係なくダッシュボードがインターネットに公開されます。loopback にバインドすれば非公開のままになり、外部に公開するのはリバースプロキシだけで済みます。プライベートなインスタンスではプロキシを省略し、自己ホスト型の WireGuard VPN 経由で 3001 に接続できます。

/app/data に named volume を指定する。 Uptime Kuma が保持する情報、SQLite データベース、監視設定、通知設定、ステータスページのロゴは、すべてそこに保存されます。失うと、空の管理画面からやり直すことになります。バックアップが必要なのはこれだけです。

イメージをメジャータグ :2 に固定する。 これは現在の安定版系列です。コピーする前に Docker Hub で最新のメジャーバージョンを確認してください。また、プロジェクトが非推奨としている latest のような移動するタグは使用しないでください。このイメージのメジャーバージョンを上げると、データベースが一方向に移行されます。通常の pull で意図せず実行するのではなく、明示的に実行する必要があります。

注意点が1つあります。/app/data は、POSIX ファイルロックをサポートするファイルシステム上に配置する必要があります。ローカルの Docker volume なら問題ありません。NFS では SQLite データベースが破損し、SQLITE_BUSYdatabase disk image is malformed が発生するため、ネットワーク共有は使用しないでください。

最初の起動: admin アカウントを作成する

プロキシ経由で https://status.example.com からインスタンスにアクセスするか、SSH トンネルを使用します。ssh -L 3001:127.0.0.1:3001 user@your-vps を実行して http://localhost:3001 を開きます。最初のページには、administrator のユーザー名とパスワードを設定するフォームが表示されます。デフォルトのログイン情報はありません。推測されにくいパスワードを設定してください。このダッシュボードでは、監視対象すべての内部アドレスとトークンを確認できます。後でパスワードを忘れた場合は、ブラウザーではなくホストからリセットします。

sudo docker compose exec uptime-kuma npm run reset-password

通知チャンネルを先に追加してテストする

監視対象を追加する前にアラートを設定します。各監視対象の作成時にチャンネルを割り当てられます。Settings then Notifications then Setup Notification に移動し、各チャンネルの Test ボタンを使ってメッセージが届くことを確認します。テストしていない通知は、設定が何も表示せずに失敗する原因として2番目に多いものです。

Email (SMTP)。 host、port、encryption、username、password、FromTo を入力します。動作する組み合わせは、"Secure" を TLS/SSL に設定した 465、または STARTTLS を使用する 587 です。Gmail と、2 要素認証を使用するほとんどのプロバイダーでは、app password を生成する必要があります。通常のアカウントパスワードを指定すると Error: Invalid login: 535-5.7.8 Username and Password not accepted が返されます。

Telegram。 @BotFather にメッセージを送り、/newbot を送信して、bot token をコピーします。chat ID を取得するには、新しい bot に一度メッセージを送り、https://api.telegram.org/bot<token>/getUpdates を開いて、JSON から chat.id を読み取ります。最初にメッセージを送っていない bot には getUpdates が空のままとなり、送信先もありません。

Discord。 チャンネルで Edit Channel then Integrations then Webhooks then New Webhook を開き、URL をコピーして、Discord 通知として貼り付けます。

Generic webhook。 Slack incoming webhook、カスタムエンドポイント、home-automation hook など、それ以外の用途には Webhook タイプを使用します。このタイプは、指定した URL に JSON ペイロードを POST します。組み込みの Apprise integration では、一覧にある90前後のその他のサービスのほとんどを利用できます。障害発生からスマートフォンへの通知経路に第三者を介在させたくない場合は、組み込みの ntfy タイプを選択し、自分で運用する ntfy server を指定します。これにより、エンドツーエンドで管理できる channel を通じて handset に通知がプッシュされます。

監視を追加する(種類ごとに設定)

Add New Monitor をクリックして種類を選び、Friendly NameCheck Interval(60 seconds が妥当です)、Retries(「down」と判定するまでの連続失敗回数。1 回のパケットロスで通知されないよう、2 または 3 にします)、通知条件を設定します。使用する種類は次のとおりです。

  • HTTP(s). 完全な URL を指定します。200-299 がデフォルトの許容ステータスコードで、これを受け取ると稼働中と判定します。301 または 401 が正常な応答の場合は、Accepted Status Codes で範囲を広げます。Web サイトや API の基本的な監視に使用します。
  • HTTP(s) - Keyword. 同じリクエストを実行しますが、本文に指定した文字列が存在することも「up」の条件になります。Invert を指定した場合は、文字列が存在しないことが条件です。単純な HTTP 監視では正常と判定される、200 OK を返しながら「Error establishing a database connection」と表示するサイトも検出できます。また、Jellyfin 上で動作する Halcyon の動画ストア用スキンのように、別のバックエンドと通信するブラウザフロントエンドにも適しています。ページの外枠は 200 を正常に返していても、背後のメディアサーバーに到達できない場合を検出できます。
  • TCP Port. HTTP 以外のサービスに対して、ホストとポートへの TCP 接続だけを確認します。22 の SSH、5432 の Postgres、25 の SMTP サーバー、ゲームサーバーなどに使用します。
  • Ping. ICMP echo を使用して、到達性と遅延を低コストで確認します。ただし、多くのネットワークやクラウドファイアウォールは ICMP を破棄します。そのため、赤い ping 監視は「ホストが停止している」場合と「プロバイダーが ping をブロックしている」場合のどちらも示す可能性があります。TCP 監視で確認してください。
  • DNS. 指定した resolver に対して A、AAAA、MX、TXT などのレコードを解決します。応答内容も検証できるため、レジストラや DNS の障害を早期に検出できます。
  • Push. 内部から外部へ送信して確認する監視です。次で説明します。

プッシュ(ハートビート)モニターで cron ジョブを監視する

上記の各モニターは、外部からサービスにアクセスして確認します。プッシュモニターは逆です。Uptime Kuma が待機し、ジョブ自身が「実行した」と通知します。バックアップや cron を監視する方法として、これが唯一確実です。HTTP チェックで確認できるのは URL が応答することだけですが、ジョブの完了を知っているのはジョブ自身だけです。

タイプ Push のモニターを作成します。Uptime Kuma が次のような一意の URL を生成します。

https://status.example.com/api/push/j8Xa2Kd9Qe?status=up&msg=OK&ping=

Heartbeat Interval を、ジョブの実行間隔に少し余裕を加えた値に設定します。次に、スクリプトの末尾へ 1 行追加します。これにより、成功時だけ通知されます。

#!/usr/bin/env bash
set -euo pipefail
# ... your backup or job runs here; set -e aborts on any failure ...
curl -fsS --retry 3 "https://status.example.com/api/push/j8Xa2Kd9Qe?status=up&msg=backup+ok&ping="

ジョブが失敗すると、set -ecurl の前で終了するため、通知は実行されません。サーバーが停止している場合も、通知は実行されません。どちらの場合もハートビートが停止します。間隔にリトライ時間を加えた期間を過ぎると、Uptime Kuma はモニターを停止に変更し、通知します。このプッシュトークンは Secret として扱ってください。トークンを知っている人は、正常なハートビートを偽装できます。

公開ステータスページを作成する

ステータスページは、顧客向けの表示です。ダッシュボードを公開せずに、稼働中のサービスと直近の履歴を示します。Status Pages then New Status Page に移動し、名前と slug(/status/main のような公開パス)を指定します。使用する monitor を「Websites」や「APIs」などのグループにドラッグし、ロゴと短い説明を追加して、Save をクリックします。ページ専用のドメインに割り当てて、status.example.com から直接表示することもできます。

注意点は2つあります。ステータスページには、公開しても問題ない monitor だけを追加してください。サービスの存在と稼働状況が分かるためです。また、ダッシュボードはログインの背後に残りますが、ステータスページは意図的に公開され、認証は必要ありません。

TLS を使用するリバースプロキシの背後に配置し、WebSocket に対応する

公開インスタンスでは、loopback にバインドしたコンテナの前段にリバースプロキシを配置し、TLS とホスト名を設定します。特に注意が必要なのは、Uptime Kuma の UI がライブ接続を使用する Socket.IO アプリケーションであるため、プロキシで WebSocket 接続をアップグレードする必要があることです。 これを設定しないとページは読み込まれても接続できません。ダッシュボードは「Connecting...」のままになり、ライブのハートビートも更新されず、ブラウザーのコンソールに WebSocket connection to 'wss://.../socket.io/...' failed が表示されます。

nginx と certbot をインストールし、loopback のポートへプロキシする vhost を作成します。まずは port 80 で設定し、後から certbot に TLS を追加させます。チャレンジ、更新タイマー、失敗時の動作については、certbot と nginx で Let's Encrypt 証明書を発行するで説明しています。

sudo apt install -y nginx certbot python3-certbot-nginx

これを /etc/nginx/sites-available/status.example.com として保存します。重要なのは 2 つの WebSocket 用の行です。

server {
    listen 80;
    server_name status.example.com;

    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 3600s;
    }
}

サイトを有効化して設定をテストし、certbot にブロックを 443 で listen するよう書き換えさせます。証明書を配置し、HTTP から HTTPS へのリダイレクトも追加させます。

sudo ln -s /etc/nginx/sites-available/status.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d status.example.com

UpgradeConnection "upgrade" の組み合わせが要点です。proxy_read_timeout 3600s により、nginx が長時間維持されるソケットを切断するのを防ぎます。certbot は生成する 443 のブロックにこれらをコピーします。すでに 1 つのプロキシの背後で複数のコンテナを運用している場合は、自動 TLS を使用して Traefik 経由でルーティングすることで、同じ構成をコンテナラベルで実現できます。WebSocket のアップグレードもデフォルトで転送されます。

vhost 全体に Basic 認証を設定しないでください。これを設定すると、公開ステータスページと /api/push エンドポイントも利用できなくなります。Uptime Kuma の組み込みログインを使用し、インターネットからアクセス可能にする場合は、繰り返し発生するログイン失敗を fail2ban で監視する設定を追加します。ダッシュボードを公開する必要がない場合は、プロキシを削除して VPN 経由でアクセスしてください。

証明書の有効期限監視を正しく設定する

HTTP(s) モニターでは、TLS 証明書の有効期限が切れる前に警告することもできます。Certificate Expiry Notification にチェックを入れると、Uptime Kuma が指定した日数前に警告します。誤検知につながる設定が 2 つあります。IP ではなくホスト名で監視してください。SNI を付けないリクエストでは、サーバーのデフォルト証明書が返され、Hostname/IP does not match certificate's altnames が表示されます。また、有効期限の警告が必要なモニターでは Ignore TLS/SSL Error にチェックを入れないでください。この設定は自己署名の内部ホスト向けです(unable to verify the first certificateDEPTH_ZERO_SELF_SIGNED_CERT)。ただし、この設定を有効にすると、Uptime Kuma は有効期限を含め、証明書をまったく確認しなくなります。

バックアップ: ディレクトリは 1 つです

すべてが /app/data に保存されるため、バックアップはコンテナを停止した状態で取得したボリュームのコピーです。これにより、SQLite ファイルの整合性が保たれます。

cd /srv/uptime-kuma
sudo docker compose stop
sudo docker run --rm \
  -v uptime-kuma_kuma-data:/data \
  -v /var/backups/kuma:/backup \
  alpine tar czf /backup/kuma-$(date -u +%Y%m%dT%H%M%SZ).tgz -C /data .
sudo docker compose start

まず docker volume ls | grep kuma でボリュームの実際の名前を確認します。Compose はプロジェクトディレクトリ名を付加するためです。次に、tarball をサーバーの外部へコピーします。同じ VPS 上に保存したバックアップは、バックアップではなく単なるコピーだからです。復元は逆の手順です。スタックを停止し、空の /app/data ボリュームに展開してから、起動します。

アップグレード

アップグレードはイメージを pull して行います。

cd /srv/uptime-kuma
sudo docker compose pull
sudo docker compose up -d

新しいコンテナは初回起動時にデータベースのマイグレーションを実行します。docker compose logs -f を監視してください。pull の前に、上記のバックアップを必ず取得します。メジャータグの範囲内に留めてください。:1 から :2 への移行は一方向のマイグレーションです。先にバックアップを取得し、リリースノートを確認してください。

障害パターンと表示される文字列

localhost を対象にした監視で誤って「停止」と判定される。 監視画面が timeout of 48000ms exceeded または connect ETIMEDOUT で赤くなっているのに、ノート PC からはサービスが応答します。Uptime Kuma と同じホストを対象にしている場合、対象サービスではなく、CPU またはメモリの急増によって監視処理が実行できなくなった可能性があります。監視を別の VPS に移し、公開ホスト名を対象にしてください。

connect ECONNREFUSED 127.0.0.1:443(または任意のポート)。そのポートで待ち受けているプロセスがありません。サービスが停止しているか、コンテナ内から localhost を監視しており、その環境では 127.0.0.1 がサーバーではなく コンテナ を指しています。ループバックではなく、公開ホスト名を監視してください。

Invalid login: 535-5.7.8 Username and Password not accepted がメールテストで表示される。SMTP 認証情報が誤っているか、プロバイダーがアプリ専用パスワードを要求しているのに、アカウントのパスワードを入力しています。アプリ専用パスワードを生成し、それを入力してください。

connect ETIMEDOUT または queryA ETIMEDOUT <host> がメールテストで表示される。ポートが誤っているか、プロバイダーが外向き SMTP 接続をブロックしています。Secure/STARTTLS の設定に対して 465 または 587 が一致していることを確認し、ホスト上で nc -vz smtp.example.com 587 を使ってテストしてください。多くのプロバイダーは外向きの 25 をブロックし、一部のプロバイダーは申請するまで submission ポートもブロックします。

self signed certificate または unable to verify the first certificate がメールテストで表示される。SMTP サーバーが、Node が信頼できない証明書を提示しています。設定で無理に回避するのではなく、メールサーバーの証明書を修正してください。

ダッシュボードが「Connecting...」で停止し、コンソールに WebSocket connection ... failed が表示される。 リバースプロキシが WebSocket のアップグレードを処理していません。nginx に UpgradeConnection "upgrade" のヘッダーを追加するか、Traefik や Caddy のように標準でこれらを転送するプロキシを使用してください。HTML が読み込まれるのは、通常の HTTP GET だからです。アップグレードが必要なのはライブソケットだけです。

証明書有効期限の監視が警告しない、または誤って警告する。 Ignore TLS/SSL Error にチェックが入り、証明書の検証が無効になっている可能性があります。または、監視対象が IP アドレスで、SNI がないために誤った証明書を読み取り、Hostname/IP does not match certificate's altnames を表示している可能性があります。Ignore のチェックを外し、ホスト名で監視してください。

SQLITE_BUSY または database disk image is malformed がログに表示される。 /app/data ボリュームが、適切なファイルロックに対応していないファイルシステム上にあります。通常は NFS が原因です。ローカルの Docker ボリュームに移し、バックアップから復元してください。

FAQ

どこで uptime monitor を実行すべきですか?

監視対象とは別のサーバーで実行してください。理想的には、別のプロバイダーまたはリージョンを使い、ユーザーと同じようにパブリックインターネット経由でホスト名に接続します。監視対象と同じホストで monitor を実行すると、サーバーを停止させる障害によって monitor も停止します。また、ホストに過負荷がかかると、正常なサービスまで「down」と誤判定します。小規模な専用 VPS を用意すれば、これらを避けられます。

Telegram またはメールでアラートを受け取るにはどうすればよいですか?

Settings then Notifications で通知チャネルを追加し、各 monitor に割り当てます。Telegram では @BotFather で bot を作成し、https://api.telegram.org/bot<token>/getUpdates から chat.id を取得します。メールでは、SSL に 465、STARTTLS に 587 を使用します。プロバイダーが二要素認証を使用している場合は、app password も設定してください。Test を押し、メッセージが届くことを確認してから運用で使用します。

Uptime Kuma で cron job または backup script を監視できますか?

はい。Push monitor を使用します。Uptime Kuma が URL を発行するので、スクリプトの末尾で curl を実行します。これにより、成功した場合だけ通知が送信されます。ジョブが失敗した場合やホストが停止している場合は heartbeat が届かず、設定した間隔を過ぎるとアラートが送信されます。外部からの通常のチェックではジョブ内部の状態を確認できないため、スケジュールされたジョブが実際に実行されたことを確認するには、この方法が最も確実です。

Uptime Kuma と Zabbix では、どちらを実行すべきですか?

Uptime Kuma は、「外部から見て稼働しているか、アラートが届いたか」という確認を、ほとんどリソースを使わず10分で構成できます。status page も利用できます。一方、CPU、メモリ、ディスク使用量の推移や、全ホストを対象としたしきい値などの詳細なメトリクスは収集しません。その用途には、より本格的な Zabbix monitoring server が適しています。こちらはより大規模な agent ベースのツールであり、両方を運用するケースも多くあります。何を self-host するかまだ決めていない場合は、2026 年に self-host するもののまとめで monitoring の位置付けを確認できます。

#uptime-kuma#monitoring#docker#self-hosting#status-page