Uptime Kuma Docker 自架監控與警報設定
使用 Docker 部署 Uptime Kuma,監控網站、連接埠、DNS 與 cron jobs,並透過電子郵件或 Telegram 發送警報,從獨立 VPS 發布狀態頁面。
您要建置的內容
這是一個小型容器,從外部監控其他伺服器與網站,並在其中任何一個停止回應時,立即透過電子郵件、Telegram、Discord 或 webhook 通知您。Uptime Kuma 是單一 Node 程序;在本設定中,後端使用 SQLite 檔案(v2 也可使用內嵌或外部 MariaDB)。它只需 256-512 MB RAM 即可穩定運作,並提供即時儀表板、歷史圖表及公開狀態頁面。安裝只需一份 10 行的 Compose 檔案;真正重要的是執行它的位置,以及是否曾在測試中確認警示確實觸發。因為,若從未確認監控系統能通知到您,還不如完全沒有監控:它會讓您以為已有防護,實際上卻什麼也沒有監控。
在監控目標無法影響的位置執行監控程式
這項決策會直接影響整體架構,因此優先處理。不要將 Uptime Kuma 與受監控的服務部署在同一台主機上。 如果監控程式位於受監控的伺服器上,當該伺服器故障或記憶體耗盡時,監控程式也會一併停止,完全不會發出警示:故障監控程式的無聲狀態,與「一切正常」看起來完全相同。即使主機仍在運作,也有較不明顯的問題:指向 localhost 的監控程式會與工作負載共用 CPU,因此負載突增時,自身的檢查可能逾時,並將目標誤判為 down,形成誤報;但實際使用者仍能正常存取服務。
因此,應將 Uptime Kuma 執行在與受監控主機不同的 VPS 上,最好位於不同的供應商或區域,並以使用者的存取方式連線至服務:透過公用網際網路,使用主機名稱。使用低價的執行個體即可,一台小型監控 VPS 就能監控所有伺服器。對於託管的高負載應用程式,這種隔離尤其重要。例如,PhotoPrism 或 Immich 相片庫在索引新匯入的資料時,可能讓 CPU 持續滿載數小時;如果監控程式共用同一套硬體,就會將僅是忙碌中的服務誤判為 down。若要偵測 Kuma 本身停止運作,請從其他位置透過 cron 傳送 push heartbeat。
先決條件與規模評估
- 全新 Ubuntu 24.04 VPS,已安裝 Docker Engine 與 Compose v2 plugin,且是從 Docker 自有的 apt repository 安裝,而非套件落後的
docker.iodistro package。 - 256 MB RAM 可執行少量監控項目;若要執行數十個監控項目並搭配反向代理,512 MB 至 1 GB 會較為充裕。各次檢查之間的 CPU 使用率接近閒置。
- 網域與 DNS
Arecord(例如status.example.com指向 VPS),僅在需要 TLS 與公開狀態頁面時才需要。私人 instance 可略過 DNS,改用 VPN 或 SSH tunnel。 - 可連出至警示目的地的網路:連往郵件供應商的 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 會使用 DNAT 規則發布連接埠,且這些規則在 ufw 看到封包之前就已套用。因此,單獨使用 3001:3001 會讓儀表板公開到網際網路,不受 ufw 規則影響;只有加入 Docker 自有的 DOCKER-USER chain 的規則才能篩選這些流量。繫結至 loopback 可將服務保持在私有狀態,只公開 reverse proxy。這也表示只有主機本身能連線至 3001:未使用 proxy 的私有 instance 應使用下方顯示的 SSH tunnel;若要透過 自行架設的 WireGuard VPN 存取,必須在伺服器的 WireGuard 位址上發布連接埠,例如 10.8.0.1:3001:3001,而不是 127.0.0.1。
在 /app/data 使用 named volume。 Uptime Kuma 記住的所有內容,包括 SQLite database、監控項目、通知設定與狀態頁面標誌,都會儲存在其中。遺失此 volume 後,管理介面會從空白狀態開始;這也是唯一必須備份的項目。
將 image 固定在 major tag :2。 這是目前的穩定版本線;複製設定前,請先查看 Docker Hub 是否有更新的 major 版本。不要追蹤 latest 這類會持續變動的 tag,因為該專案已將其標記為 deprecated。此 image 升級 major version 時會執行 database migration。你應在確認要升級時,先準備好最新備份再執行,不要在例行 pull 時意外觸發。
有一項注意事項:/app/data 必須位於支援 POSIX file locks 的檔案系統上。local Docker volume 沒有問題;在 NFS 上,SQLite database 會損毀,並出現 SQLITE_BUSY 與 database disk image is malformed。因此,請勿使用 network share。
首次執行:建立管理員帳號
透過代理伺服器瀏覽 https://status.example.com,或使用 SSH tunnel:執行 ssh -L 3001:127.0.0.1:3001 user@your-vps,然後開啟 http://localhost:3001。全新的 v2 安裝首次顯示的畫面會詢問要使用哪個資料庫;請選擇 SQLite。所有資料會保存在 /app/data volume 中,以下的備份與疑難排解步驟也都以此為前提。接著會顯示設定表單,要求輸入管理員使用者名稱與密碼;系統沒有預設登入資訊。請設定實際使用的密碼:這個儀表板會存取你監控之所有服務的內部位址與 token。之後忘記密碼了嗎?請從主機重設,不要透過瀏覽器:
sudo docker compose exec uptime-kuma npm run reset-password先新增通知頻道並進行測試
先設定警示,再新增監控項目。這樣建立每個監控項目時,就能直接附加通知頻道。前往 Settings then Notifications then Setup Notification,並使用每個頻道的 Test 按鈕確認訊息能正常送達,因為未經測試的通知,是設定無聲失敗的第二常見原因。
Email (SMTP)。 填寫主機、連接埠、加密方式、使用者名稱、密碼、From 與 To。常見組合是 465,並將「Secure」設為 TLS/SSL;或使用 587 搭配 STARTTLS。部分伺服器也在 25 提供 STARTTLS,因此請依服務供應商的文件使用正確的連接埠與模式。Gmail 與大多數啟用雙因素驗證的服務供應商都必須產生 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、自訂端點與家庭自動化 hook;Webhook 類型會將 JSON payload 以 POST 傳送至你提供的 URL,而內建的 Apprise 整合涵蓋清單中大多數其他約 90 個服務。如果你不希望第三方介於服務中斷與手機之間,請選擇內建的 ntfy 類型,並將其指向 自行執行的 ntfy 伺服器;它會透過由你完整控制的頻道,將通知推送到手機。
新增監控項目,一次設定一種類型
按一下 Add New Monitor,選擇類型,然後設定 Friendly Name、Check Interval(60 seconds 通常合適)、Retries(在判定「down」前允許的連續失敗次數;設定為 2 或 3,可避免單一封包遺失就觸發通知),以及要觸發的通知。以下是會使用的類型:
- HTTP(s). 完整 URL。狀態碼符合條件即視為正常(預設為 200-299;如果
301或401對你的服務屬正常狀態,可在 Accepted Status Codes 中放寬範圍)。這是網站與 API 的主要監控方式。 - HTTP(s) - Keyword. 使用相同的請求,但除了狀態碼正常外,回應內容中也必須包含指定字串;若啟用 Invert,則必須不包含該字串。這可偵測網站雖回傳
200 OK,卻顯示「Error establishing a database connection」的情況;單純的 HTTP 監控會將其判定為正常。對於連接獨立後端的瀏覽器前端,這也是適合的監控方式。例如 Jellyfin 上的 Halcyon 影音商店面板,其頁面外殼可能正常回傳200,但後方的媒體伺服器已無法連線。 - TCP Port. 對主機與連接埠建立基本 TCP 連線,適用於非 HTTP 服務,例如 22 上的 SSH、5432 上的 Postgres、25 上的 SMTP 伺服器,以及遊戲伺服器。
- Ping. ICMP echo,用於低成本檢查可連線性與延遲。不過許多網路與雲端防火牆會丟棄 ICMP,因此紅色的 ping 監控可能表示「主機停止運作」,也可能表示「供應商封鎖 ping」;請使用 TCP 監控確認。
- DNS. 使用指定的 resolver 查詢記錄(A、AAAA、MX、TXT 等),並可驗證回應內容,以便及早偵測註冊商或 DNS 中斷。
- Push. 由內向外的監控方式,下一節會說明。
監控 cron 工作的 push(heartbeat)監控
上述每個監控都會從外部主動連入您的服務。push 監控則相反:Uptime Kuma 會等待,由您的工作呼叫它並回報「我已執行」。這是監控備份或 cron 的唯一可靠方式:HTTP 檢查只能知道 URL 有回應,但只有該工作知道自己是否完成。
建立類型為 Push 的監控。Uptime Kuma 會產生類似以下的唯一 URL:
https://status.example.com/api/push/j8Xa2Kd9Qe?status=up&msg=OK&ping=將 Heartbeat Interval 設定為工作執行的週期,再預留一些寬限時間。接著在指令碼的最後加入一行,讓它只在成功時傳送 heartbeat:
#!/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 -e 會在執行 curl 前中止;如果主機故障,工作也不會執行。無論是哪種情況,heartbeat 都會停止。當「週期加上重試」的時間範圍過後,Uptime Kuma 會將監控切換為 down,並發出警示。請將這個 push token 視為 secret:任何取得它的人都能偽造正常的 heartbeat。
建立公開狀態頁面
狀態頁面是面向客戶的檢視畫面,可顯示哪些服務正常運作及其近期歷程,但不會公開儀表板。前往 Status Pages then New Status Page,輸入名稱與 slug(公開路徑,例如 /status/main),將所需的監控項目拖曳到「Websites」和「APIs」等群組,加入標誌與簡短說明,然後按一下 Save。您也可以將此頁面綁定至專用網域,讓 status.example.com 直接提供該頁面。
請注意兩點:只加入您願意公開的監控項目,因為狀態頁面會透露某項服務存在,以及目前是否正常運作;儀表板仍受您的登入保護,而狀態頁面則刻意設為公開,無需驗證。
使用 TLS 的反向代理,並注意 WebSocket
對於公開執行個體,請在綁定 loopback 的容器前方放置反向代理,以處理 TLS 與主機名稱。最容易被忽略的細節是:Uptime Kuma 的 UI 是即時 Socket.IO 應用程式,因此代理必須升級 WebSocket 連線。若遺漏此設定,頁面雖然能載入,卻永遠無法建立連線;儀表板會停留在「Connecting...」,即時 heartbeat 不會更新,瀏覽器主控台則會顯示 WebSocket connection to 'wss://.../socket.io/...' failed。
安裝 nginx 與 certbot,然後建立將請求代理至 loopback 埠的 vhost。現在先讓它監聽 port 80,之後再讓 certbot 加入 TLS;challenge、續期計時器及其失敗情況,請參閱 使用 certbot 與 nginx 申請 Let's Encrypt 憑證。
sudo apt install -y nginx certbot python3-certbot-nginx將以下內容儲存為 /etc/nginx/sites-available/status.example.com;其中兩行 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、加入憑證,並設定 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.comUpgrade 與 Connection "upgrade" 這一對設定是關鍵,proxy_read_timeout 3600s 則可避免 nginx 中斷長時間存在的 socket;certbot 會將兩者複製到它產生的 443 區塊中。如果你已經讓多個容器共用一台代理伺服器,使用自動 TLS 透過 Traefik 進行路由也能達到相同效果;它使用容器標籤,並預設轉送 WebSocket 升級要求。
不要對整個 vhost 啟用 basic authentication,因為這也會阻擋公開狀態頁面與 /api/push endpoint。保留 Uptime Kuma 內建的登入功能;如果服務直接暴露在網際網路上,可加入 使用 fail2ban 監控重複的登入失敗。如果儀表板不需要公開,則移除代理,改用 SSH tunnel 存取;也可以使用 VPN,將埠發布在 VPN 位址上,而不是 loopback。
正確設定憑證到期監控
HTTP(s) monitor 也能在 TLS 憑證到期前發出警告:勾選 Certificate Expiry Notification,Uptime Kuma 就會在指定天數前發出警示。以下兩個錯誤會導致判讀結果不正確。請依主機名稱而非 IP進行監控,否則未帶 SNI 的請求會取得伺服器的預設憑證,並顯示 Hostname/IP does not match certificate's altnames。如果希望 monitor 發出到期警告,請勿勾選 Ignore TLS/SSL Error:這項設定適用於使用自簽憑證的內部主機(unable to verify the first certificate、DEPTH_ZERO_SELF_SIGNED_CERT),但會使 Uptime Kuma 完全略過憑證檢查,包括到期日檢查。
備份:只有一個目錄
由於所有資料都位於 /app/data,因此備份就是在容器停止時複製該 volume,確保 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 確認 volume 的實際名稱,因為 Compose 會在名稱前加上專案目錄。接著將 tarball 複製到主機以外的位置,因為儲存在同一台 VPS 上的備份只是副本,不是真正的備份。還原時則反向操作:停止 stack,將內容解壓縮到空的 /app/data volume,然後啟動 stack。
升級
升級作業就是擷取映像:
cd /srv/uptime-kuma
sudo docker compose pull
sudo docker compose up -d新容器會在首次啟動時執行資料庫遷移;請監控 docker compose logs -f。請在擷取映像之前先完成上方的備份,並維持在同一個 major tag 內:從 :1 移至 :2 會遷移資料庫,而專案的遷移指南指出,遷移中斷時必須從備份還原後重試。因此,請先備份,並閱讀該指南與版本說明。
失效情況與你會看到的訊息
監控指向 localhost 時誤判為「停止」。 監控因 timeout of 48000ms exceeded 或 connect ETIMEDOUT 顯示紅色,但服務仍可從筆記型電腦連線。如果監控目標與 Uptime Kuma 執行於同一台主機,可能是 CPU 或記憶體尖峰導致監控檢查無法取得資源,而不是目標服務發生問題。請將監控移至獨立的 VPS,並以公開主機名稱作為目標。
connect ECONNREFUSED 127.0.0.1:443(或任何連接埠)。該連接埠沒有服務在監聽。可能是服務已停止,也可能是你在容器內監控 localhost,此時 127.0.0.1 指的是容器,不是你的伺服器。請監控公開主機名稱,不要監控 loopback。
Invalid login: 535-5.7.8 Username and Password not accepted 出現在電子郵件測試中。SMTP 憑證錯誤,或服務提供者要求應用程式專用密碼,但你輸入了帳戶密碼。請產生應用程式密碼並貼上該密碼。
connect ETIMEDOUT 或 queryA ETIMEDOUT <host> 出現在電子郵件測試中。連接埠錯誤,或服務提供者封鎖了輸出的 SMTP 流量。請確認 465 或 587 與 Secure/STARTTLS 設定一致,並使用 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 中加入 Upgrade 和 Connection "upgrade" 標頭,或使用 Traefik、Caddy 等預設會轉送這些標頭的代理。HTML 能載入,是因為那是一般的 HTTP GET;只有即時 socket 需要升級。
憑證到期監控從不發出警告,或警告內容錯誤。 可能勾選了 Ignore TLS/SSL Error,導致憑證檢查停用;也可能監控指向 IP,因缺少 SNI 而讀取錯誤的憑證,並顯示 Hostname/IP does not match certificate's altnames。請取消勾選忽略錯誤,並以主機名稱作為監控目標。
日誌中出現 SQLITE_BUSY 或 database disk image is malformed。 /app/data volume 位於未正確支援檔案鎖定的檔案系統上,通常是 NFS。請將其移至本機 Docker volume,並從備份還原。
FAQ
我應該在哪裡執行 uptime monitor?
請在與受監控主機不同的伺服器上執行,最好使用其他供應商或區域,並像使用者一樣,透過公開網際網路以主機名稱連線。如果監控程式與目標主機共用同一台伺服器,導致伺服器停止運作的中斷也會同時使監控程式失效;主機負載過高時,還可能將正常服務誤判為「down」。使用一台獨立的小型 VPS 即可避免這兩個問題。
如何在 Telegram 或電子郵件中接收警示?
在 Settings then Notifications 中新增通知管道,再將該管道套用至各個監控項目。若使用 Telegram,請透過 @BotFather 建立 bot,並從 https://api.telegram.org/bot<token>/getUpdates 讀取 chat.id;若使用電子郵件,請使用 465 進行 SSL,或使用 587 進行 STARTTLS。若供應商啟用雙因素驗證,請使用應用程式密碼。按下 Test,確認能收到訊息後再依賴此通知功能。
Uptime Kuma 能監控 cron 工作或備份指令碼嗎?
可以,這就是 Push 監控項目:Uptime Kuma 會提供 URL,您可在指令碼結尾執行 curl,如此只有在成功完成時才會送出通知。如果工作失敗或主機停止運作,監控訊號就不會送達;經過設定的間隔後,您會收到警示。這是確認排程工作確實執行的唯一可靠方式,因為外部檢查無法查看工作內部的執行狀態。
Uptime Kuma 與 Zabbix 之間,我應該使用哪一個?
Uptime Kuma 能在 10 分鐘內回答「服務是否正常、從外部是否可連線,以及是否已通知我」,幾乎不需要系統資源,並提供狀態頁面。它不會收集 CPU、記憶體和磁碟趨勢等深度指標,也不支援整個主機群組的閾值管理;如果需要這些功能,完整的 Zabbix 監控伺服器 是較為複雜且以 agent 為基礎的工具,許多人會同時使用兩者。如果您仍在考慮是否要執行監控服務,我們整理的 2026 年自架服務建議 可協助您了解監控在整體架構中的位置。