SSD Nodes Learn Hosting plans →
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-08-31

Uptime Kuma: self-hosted monitoring sa Docker

Patakbuhin ang Uptime Kuma sa Docker para mag-monitor ng website, port, DNS at cron, makatanggap ng alert sa email o Telegram, at mag-publish ng status page sa hiwalay na VPS.

Ano ang binubuo mo

Isang maliit na container ang binubuo mo para subaybayan mula sa labas ang iba mo pang server at website. Aabisuhan ka nito agad kapag hindi na sumasagot ang alinman sa mga ito, gamit ang email, Telegram, Discord, o webhook. Isang Node process ang Uptime Kuma na gumagamit ng SQLite file bilang backend. Dahil dito, maayos itong tumatakbo sa 256-512 MB na RAM. May live dashboard, history graphs, at public status page din ito. Sampung linya lamang ang Compose file para sa installation. Ang mahalaga ay kung saan mo ito tatakbuhin at kung nasubukan nang gumana ang iyong mga alert. Mas masahol pa sa walang monitor ang monitor na hindi mo kailanman napatunayang makapag-aabiso sa iyo. Nagbibigay ito ng maling pakiramdam na protektado ka kahit wala naman talaga itong nasusubaybayan.

Patakbuhin ang monitor sa lugar na hindi maaabot ng outage

Ito ang pinakamahalagang desisyon dahil dito nakasalalay ang buong setup. Huwag patakbuhin ang Uptime Kuma sa parehong server ng mga mino-monitor nito. Kung nasa server na mino-monitor nito ang monitor, mawawala rin ang monitor kapag nag-down ang server o naubusan ito ng memory—ang mismong event na gusto mong matukoy. Wala kang matatanggap na alert. Kapag tahimik ang isang patay na monitor, kapareho lang ito ng mensaheng “maayos ang lahat.” May mas banayad na problema kahit gumagana pa ang server: ang monitor na nakaturo sa localhost ay nakikihati sa CPU sa workload. Kapag biglang tumaas ang load, maaaring mag-timeout ang sarili nitong check at markahan ang target bilang down. False alarm ito dahil maayos pa ring naso-serve ang mga user.

Kaya patakbuhin ang Uptime Kuma sa ibang VPS kaysa sa mino-monitor nito. Mas mainam kung ibang provider o region ito. Kumonekta ito sa iyong mga serbisyo sa paraang ginagamit ng mga user: sa public internet, gamit ang hostname. Sapat na ang murang instance, at kayang i-monitor ng isang maliit na monitoring VPS ang lahat ng server mo. Lalo itong mahalaga para sa mabibigat na app na naka-host sa iyo. Halimbawa, maaaring gamitin ng PhotoPrism o Immich photo library ang CPU nang ilang oras habang ini-index nito ang bagong import. Kung nakikihati sa hardware na iyon ang monitor, mamarkahan nitong down ang serbisyong abala lamang. Para matukoy kung mismong ang Kuma ang namatay, magdagdag ng push heartbeat mula sa cron sa ibang server.

Mga prerequisite at pag-size

  • Isang bagong Ubuntu 24.04 VPS na may Docker Engine at Compose v2 plugin, na na-install mula sa sariling apt repository ng Docker, hindi mula sa docker.io distro package na nahuhuli ang bersyon.
  • Kayang patakbuhin ng 256 MB RAM ang ilang monitor. Sapat ang 512 MB hanggang 1 GB para sa dose-dosenang monitor kasama ang reverse proxy, at halos idle ang CPU sa pagitan ng mga check.
  • Isang domain at DNS A record, halimbawa status.example.com na nakaturo sa VPS, kung kailangan mo ng TLS at public status page. Maaaring laktawan ng private instance ang DNS at gumamit ng VPN o SSH tunnel.
  • Outbound network access papunta sa mga destinasyon ng alert: SMTP papunta sa iyong mail provider, o HTTPS papunta sa Telegram at Discord.

Ang Compose file

Ilagay ito sa /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:

I-start ito at bantayan ang unang boot:

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

Ang tamang pagsisimula ay nagla-log ng Listening on 3001 at pagkatapos ay tahimik na. Sinadya ang tatlong bagay sa file na iyon.

127.0.0.1:3001:3001, hindi 3001:3001. Nagpa-publish ang Docker ng mga port gamit ang DNAT rules na sinusuri bago pa makita ng ufw ang packet. Kaya ang simpleng 3001:3001 ay naglalantad sa iyong dashboard sa public internet kahit ano pa ang firewall configuration mo. Kapag naka-bind sa loopback, nananatili itong private at reverse proxy lamang ang exposed. Maaaring laktawan ng private instance ang proxy at maabot ang 3001 sa pamamagitan ng self-hosted WireGuard VPN.

Isang named volume sa /app/data. Nandoon ang lahat ng inaalaala ng Uptime Kuma: ang SQLite database, mga monitor, notification settings, at mga logo ng status page. Kapag nawala ito, babalik ka sa isang walang-laman na admin screen. Ito lamang ang kailangang i-back up.

Naka-pin ang image sa isang major tag, :2. Ito ang kasalukuyang stable line. Tingnan ang Docker Hub para sa pinakabagong major bago ito kopyahin. Huwag kailanman gumamit ng gumagalaw na tag gaya ng latest, na hindi na ginagamit ng project. Ang pagtalon sa panibagong major version ng image na ito ay one-way database migration. Dapat mo itong simulan nang sinasadya, hindi aksidenteng ma-trigger sa regular na pull.

May isang mahalagang kondisyon: dapat nasa filesystem na sumusuporta sa POSIX file locks ang /app/data. Ayos ang local Docker volume. Sa NFS, maaaring ma-corrupt ang SQLite database at makuha mo ang SQLITE_BUSY at database disk image is malformed. Kaya huwag kailanman gumamit ng network share.

Unang pag-run: gawin ang admin account

Buksan ang instance sa pamamagitan ng iyong proxy sa https://status.example.com, o gamit ang SSH tunnel: patakbuhin ang ssh -L 3001:127.0.0.1:3001 user@your-vps at buksan ang http://localhost:3001. Ang unang page ay setup form para sa administrator username at password; walang default login. Pumili ng secure na password: nakikita ng dashboard na ito ang mga internal address at token ng lahat ng mino-monitor mo. Nakalimutan mo ito kalaunan? I-reset ito mula sa host, hindi sa browser:

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

Idagdag muna ang iyong mga notification channel, at subukan ang mga ito

Mag-set up ng mga alert bago magdagdag ng mga monitor para mai-attach mo ang isang channel habang ginagawa ang bawat isa. Pumunta sa Settings then Notifications then Setup Notification, at gamitin ang Test button ng bawat channel upang kumpirmahing natatanggap ang mensahe. Ang hindi nasubukang notification ang ikalawang pinakakaraniwang dahilan ng tahimik na pag-fail ng setup.

Email (SMTP). Ilagay ang host, port, encryption, username, password, From, at To. Ang dalawang gumaganang kombinasyon ay 465 kapag naka-set sa TLS/SSL ang "Secure", o 587 kapag STARTTLS. Para sa Gmail at karamihan ng provider na may two-factor authentication, kailangan mong gumawa ng app password; magbabalik ng Error: Invalid login: 535-5.7.8 Username and Password not accepted ang normal na password ng account.

Telegram. I-message ang @BotFather, ipadala ang /newbot, at kopyahin ang bot token. Para sa iyong chat ID, i-message muna nang isang beses ang bagong bot, buksan ang https://api.telegram.org/bot<token>/getUpdates, at basahin ang chat.id mula sa JSON. Kapag hindi mo muna minessage ang bot, magiging walang laman ang getUpdates at wala itong mapagpapadalhan.

Discord. Sa channel, buksan ang Edit Channel then Integrations then Webhooks then New Webhook, kopyahin ang URL, at i-paste ito bilang Discord notification.

Generic webhook. Para sa iba pang gamit, gaya ng Slack incoming webhook, custom endpoint, o home-automation hook, nagpo-POST ang Webhook type ng JSON payload sa URL na ibinibigay mo. Saklaw naman ng bundled Apprise integration ang karamihan sa humigit-kumulang siyamnapung iba pang service sa listahan. Kung ayaw mong may third party sa pagitan ng outage at ng iyong telepono, piliin ang built-in na ntfy type at ituro ito sa isang ntfy server na ikaw mismo ang nagpapatakbo, na nagpapadala ng push sa iyong handset sa isang channel na ikaw ang kumokontrol mula simula hanggang dulo.

Magdagdag ng mga monitor, isang uri bawat pagkakataon

I-click ang Add New Monitor, pumili ng uri, at itakda ang Friendly Name, ang Check Interval (makatuwiran ang 60 seconds), ang Retries (magkakasunod na failure bago ituring na “down”; gumamit ng 2 o 3 para hindi magpadala ng alert dahil lang sa isang nawalang packet), at ang mga notification na ipapadala. Ito ang mga uri na gagamitin mo:

  • HTTP(s). Isang buong URL. Itinuturing na up kapag tumanggap ng status code (200-299 bilang default; palawakin ito sa ilalim ng Accepted Status Codes kung normal sa iyo ang 301 o 401). Ito ang pangunahing monitor para sa mga website at API.
  • HTTP(s) - Keyword. Pareho ang request, pero kailangan ding may string sa body para ituring na “up”, o wala ito kapag ginagamit ang Invert. Nakikita nito kapag nagbabalik ang site ng 200 OK habang ipinapakita ang “Error establishing a database connection”, na ituturing na healthy ng simpleng HTTP check. Ito rin ang tamang check para sa browser front end na kumokonekta sa hiwalay na backend, gaya ng Halcyon video-store skin sa ibabaw ng Jellyfin, kung saan maayos na nagbabalik ng 200 ang page shell kahit hindi reachable ang media server sa likod nito.
  • TCP Port. Isang direktang TCP connection sa host at port para sa mga serbisyong hindi HTTP: SSH sa 22, Postgres sa 5432, SMTP server sa 25, o game server.
  • Ping. ICMP echo para sa murang pagsusuri ng reachability at latency. Gayunman, bina-block ng maraming network at cloud firewall ang ICMP, kaya maaaring ang pulang ping monitor ay nangangahulugang “host down” o “binablock ng provider ang ping”; kumpirmahin ito gamit ang TCP monitor.
  • DNS. Nireresolba nito ang isang record (A, AAAA, MX, TXT at iba pa) laban sa resolver na tinukoy mo, at maaaring tiyakin ang sagot. Maaga nitong natutukoy ang outage sa registrar o DNS.
  • Push. Isang inside-out monitor na tatalakayin sa susunod.

Pagsubaybay sa cron job gamit ang push (heartbeat) monitor

Lahat ng monitor sa itaas ay pumapasok sa iyong service mula sa labas. Kabaligtaran nito ang push monitor: naghihintay ang Uptime Kuma, at tinatawagan ito ng iyong job upang sabihing “Tumakbo ako.” Ito lang ang maaasahang paraan para subaybayan ang isang backup o cron: alam ng HTTP check na tumutugon ang isang URL, pero ang job lang ang nakaaalam kung natapos ito.

Gumawa ng monitor na may type na Push. Bumubuo ang Uptime Kuma ng natatanging URL na gaya nito:

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

Itakda ang Heartbeat Interval sa dalas ng pagtakbo ng job, at magdagdag ng kaunting palugit. Pagkatapos, magdagdag ng isang linya sa dulo ng script upang tumakbo lamang ito kapag matagumpay ang job:

#!/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="

Kapag nag-fail ang job, set -e ang nag-a-abort bago umabot sa curl; kung down ang box, hindi rin ito tatakbo. Sa alinmang sitwasyon, hihinto ang heartbeat. Kapag lumampas na ang interval-plus-retries window, itatakda ng Uptime Kuma ang monitor bilang down at magpapadala ito ng alert. Ituring na secret ang push token na ito: maaaring magpanggap na healthy ang heartbeat ang sinumang may hawak nito.

Bumuo ng public status page

Ang status page ang customer-facing na view. Ipinapakita nito kung aling mga serbisyo ang gumagana at ang kamakailang history ng mga ito, nang hindi inilalantad ang iyong dashboard. Pumunta sa Status Pages then New Status Page, maglagay ng pangalan at slug (ang public path, gaya ng /status/main), at i-drag ang mga monitor na gusto mo sa mga grupo gaya ng "Websites" at "APIs". Magdagdag ng logo at maikling description, pagkatapos ay i-click ang Save. Maaari mo ring i-bind ang page sa sarili nitong domain upang direktang ma-serve ito ng status.example.com.

Dalawang paalala: idagdag lamang ang mga monitor na handa mong gawing public, dahil ipinapakita ng status page na umiiral ang isang serbisyo at kung gumagana ito; at nananatiling protektado ng iyong login ang dashboard, samantalang sadyang public ang status page at hindi nito kailangan ng authentication.

Ilagay sa reverse proxy na may TLS, at tiyaking gumagana ang WebSocket

Para sa public instance, maglagay ng reverse proxy sa harap ng loopback-bound container para sa TLS at hostname. Ang detalyeng madalas nakakaligtaan: live Socket.IO app ang UI ng Uptime Kuma, kaya dapat i-upgrade ng proxy ang WebSocket connection. Kapag hindi ito nagawa, naglo-load ang page pero hindi kailanman kumokonekta; nananatili ang dashboard sa “Connecting...”, hindi nag-a-update ang live heartbeats, at ipinapakita ng browser console ang WebSocket connection to 'wss://.../socket.io/...' failed.

I-install ang nginx at certbot, pagkatapos ay isulat ang vhost na nagpo-proxy sa loopback port. Gamitin muna ang port 80 at hayaang idagdag ng certbot ang TLS pagkatapos; saklaw ng pag-isyu ng Let's Encrypt certificates gamit ang certbot at nginx ang challenge, renewal timer, at mga failure mode nito.

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

I-save ito bilang /etc/nginx/sites-available/status.example.com; ang dalawang WebSocket line ang mahalaga:

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;
    }
}

I-enable ang site, i-test ang configuration, pagkatapos ay hayaang baguhin ng certbot ang block para makinig sa 443, ilagay ang certificate, at magdagdag ng HTTP-to-HTTPS redirect:

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

Ang magkaparehang Upgrade at Connection "upgrade" ang mahalagang bahagi, at pinipigilan ng proxy_read_timeout 3600s na putulin ng nginx ang matagalang socket; kokopyahin ng certbot ang dalawang ito sa 443 block na ginagawa nito. Kung nagpapatakbo ka na ng ilang container sa likod ng iisang proxy, ganoon din ang ginagawa ng pag-route sa mga ito sa pamamagitan ng Traefik na may automatic TLS gamit ang container labels, at awtomatiko nitong ipinapasa ang WebSocket upgrades.

Huwag lagyan ng basic auth ang buong vhost, dahil haharangin din nito ang public status page at ang /api/push endpoint. Panatilihin ang built-in login ng Uptime Kuma, at idagdag ang fail2ban na nagmo-monitor ng magkakasunod na nabigong login kung exposed ito sa internet. Kung hindi kailangang maging public ang dashboard, alisin ang proxy at i-access ito gamit ang VPN.

Pagsubaybay sa pag-expire ng certificate, nang tama

Maaari ka ring bigyan ng babala ng isang HTTP(s) monitor bago mag-expire ang TLS certificate: i-check ang Certificate Expiry Notification, at mag-aalert ang Uptime Kuma kapag ilang araw na lang bago ito mag-expire. May dalawang pagkakamali na nagiging sanhi ng maling pagbasa nito. Mag-monitor gamit ang hostname, hindi IP, dahil ang request na walang SNI ay makakakuha ng default certificate ng server at makikita mo ang Hostname/IP does not match certificate's altnames. Huwag ding i-check ang Ignore TLS/SSL Error sa monitor na gagamitin mo para sa mga babala sa pag-expire: para ang toggle na iyon sa mga self-signed na internal host (unable to verify the first certificate, DEPTH_ZERO_SELF_SIGNED_CERT), pero pinipigilan nito ang Uptime Kuma na suriin ang certificate, kabilang ang pag-expire nito.

Mga backup: iisang directory lang ito

Dahil nasa /app/data ang lahat, ang backup ay kopya ng volume na ginawa habang nakahinto ang container. Dahil dito, consistent ang SQLite file:

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

I-confirm muna ang aktuwal na pangalan ng volume gamit ang docker volume ls | grep kuma, dahil nilalagyan ito ng Compose ng prefix batay sa project directory. Pagkatapos, kopyahin ang tarball palabas ng server, dahil ang backup na nasa parehong VPS ay kopya lamang, hindi backup. Kabaligtaran ang proseso ng restore: ihinto ang stack, i-extract sa isang walang lamang /app/data volume, at pagkatapos ay simulan ito.

Mga Upgrade

Ang mga upgrade ay isinasagawa sa pamamagitan ng pag-pull ng image:

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

Isinasagawa ng bagong container ang anumang database migration sa unang pag-start nito; i-monitor ang docker compose logs -f. Gawin ang backup sa itaas bago mag-pull, at manatili sa iisang major tag: one-way migration ang paglipat mula :1 patungo sa :2, kaya mag-backup muna at suriin ang release notes.

Mga failure mode at mga string na makikita mo

Maling "down" sa monitor na nakaturo sa localhost. Nagiging pula ang monitor na may timeout of 48000ms exceeded o connect ETIMEDOUT, pero sumasagot ang serbisyo mula sa iyong laptop. Kung sa parehong host tumatakbo ang Uptime Kuma, maaaring naubusan ng CPU o memory ang check, hindi ang target. Ilipat ang monitor sa hiwalay na VPS at gamitin ang public hostname bilang target.

connect ECONNREFUSED 127.0.0.1:443 (o anumang port). Walang nakikinig sa port na iyon: maaaring down ang serbisyo, o mino-monitor mo ang localhost mula sa loob ng container, kung saan ang 127.0.0.1 ay ang container, hindi ang server mo. I-monitor ang public hostname, hindi ang loopback.

Invalid login: 535-5.7.8 Username and Password not accepted sa email test. Mali ang SMTP credentials, o nangangailangan ang provider ng app-specific password pero account password ang ginamit. Gumawa ng app password at iyon ang ilagay.

connect ETIMEDOUT o queryA ETIMEDOUT <host> sa email test. Mali ang port, o bina-block ng provider ang outbound SMTP. Tiyaking tumutugma ang 465 o 587 sa Secure/STARTTLS setting, at mag-test mula sa host gamit ang nc -vz smtp.example.com 587. Maraming provider ang nagba-block ng outbound 25, at bina-block naman ng ilan ang submission ports hanggang humingi ka ng access.

self signed certificate o unable to verify the first certificate sa email test. Nagpapakita ang iyong SMTP server ng certificate na hindi pinagkakatiwalaan ng Node; ayusin ang certificate ng mail server sa halip na i-bypass ang error.

Naka-stuck ang dashboard sa "Connecting...", at ipinapakita ng console ang WebSocket connection ... failed. Hindi ina-upgrade ng reverse proxy ang WebSocket. Idagdag ang Upgrade at Connection "upgrade" headers sa nginx, o gumamit ng proxy na awtomatikong nagpapasa ng mga ito, gaya ng Traefik o Caddy. Naglo-load ang HTML dahil normal na HTTP GET iyon; ang live socket lamang ang nangangailangan ng upgrade.

Hindi kailanman nagbababala ang cert-expiry monitor, o mali ang babala nito. Maaaring naka-check ang Ignore TLS/SSL Error, kaya naka-disable ang certificate checking, o IP ang target ng monitor at maling certificate ang nababasa nito dahil walang SNI, kaya ipinapakita ang Hostname/IP does not match certificate's altnames. Alisin ang check sa ignore at i-monitor gamit ang hostname.

SQLITE_BUSY o database disk image is malformed sa logs. Ang /app/data volume ay nasa filesystem na walang wastong file locking, karaniwang NFS; ilipat ito sa local Docker volume at i-restore mula sa backup.

FAQ

Saan dapat patakbuhin ang aking uptime monitor?

Sa ibang server ito patakbuhin kaysa sa mga server na sinusubaybayan nito. Mas mainam kung nasa ibang provider o region ito at ina-access ang mga target gamit ang hostname sa public internet, gaya ng ginagawa ng mga user. Kung kapareho ng box ng mga target ang monitor, mawawala rin ang monitor kapag nagka-outage ang server. Kapag overloaded naman ang host, maaari nitong markahang “down” ang mga serbisyong maayos naman. Naiiwasan ang dalawang problemang ito gamit ang isang maliit at hiwalay na VPS.

Paano ako makakakuha ng mga alert sa Telegram o email?

Idagdag ang channel sa ilalim ng Settings then Notifications, at i-attach ito sa bawat monitor. Para sa Telegram, gumawa ng bot gamit ang @BotFather at basahin ang chat.id mula sa https://api.telegram.org/bot<token>/getUpdates. Para sa email, gamitin ang 465 para sa SSL o 587 para sa STARTTLS, kasama ang app password kung gumagamit ng two-factor authentication ang iyong provider. Pindutin ang Test at tiyaking natatanggap ang mensahe bago ito asahan para sa mga alert.

Maaari bang subaybayan ng Uptime Kuma ang isang cron job o backup script?

Oo. Ito ang Push monitor: bibigyan ka ng Uptime Kuma ng URL, at curl mo ito sa dulo ng script upang magpadala lamang ito ng signal kapag matagumpay ang pagtakbo. Kung mabigo ang job o down ang box, hindi darating ang heartbeat at makakatanggap ka ng alert kapag lumampas na ang interval. Ito ang tanging maaasahang paraan upang malaman kung aktuwal na tumakbo ang isang scheduled job, dahil hindi nakikita ng external check ang loob nito.

Uptime Kuma kumpara sa Zabbix, alin ang dapat kong patakbuhin?

Sinasagot ng Uptime Kuma ang tanong na “up ba ito mula sa labas, at naalerto ba ako?” sa loob ng sampung minuto at halos walang ginagamit na resources, bukod pa sa status page. Hindi ito nangongolekta ng malalalim na metric gaya ng mga trend ng CPU, memory, at disk, o mga threshold para sa buong fleet. Para rito, ang isang kumpletong Zabbix monitoring server ang mas mabigat at agent-based na tool, at maraming user ang nagpapatakbo ng pareho. Hindi ka pa rin makapagpasya kung ano ang patatakbuhin? Inilalagay ng aming roundup ng mga maaaring i-self-host sa 2026 ang monitoring sa tamang konteksto.

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