התקנת Uptime Kuma ב-Docker למעקב אחר שרתים
למדו איך להריץ Uptime Kuma בתוך Docker כדי לנטר אתרים, DNS ו-cron jobs. למדו מדוע כדאי להריץ את המנטר ב-VPS נפרד כדי למנוע התרעות שווא בזמן עומס CPU.
מה אתם בונים
קונטיינר קטן ויחיד המנטר שרתים ואתרים אחרים מבחוץ. המערכת תתריע ברגע ששרת מפסיק להגיב באמצעות email, Telegram, Discord או webhook. Uptime Kuma הוא תהליך Node אחד המשתמש בקובץ SQLite, ולכן הוא פועל בקלות עם 256-512 MB של RAM. המערכת מספקת לכם לוח בקרה (dashboard) חי, גרפי היסטוריה ודף סטטוס ציבורי. ההתקנה היא קובץ Compose בן עשר שורות; החלק החשוב באמת הוא איפה אתם מריצים אותו ו-האם ההתראות שלכם עובדות בבדיקה, מכיוון שמנטר שלא נבדק מעולם הוא פחות טוב מאפס: הוא יוצר תחושת ביטחון שקרית בזמן שאתם לא מקבלים שום עדכון.
הפעל את המנטר במקום שבו תקלה לא תוכל להגיע אליו
ההחלטה הזו קריטית להצלחת המערכת כולה, לכן היא מופיעה ראשונה. אל תריצו את Uptime Kuma על אותו שרת שעליו רצות השירותים שאתם מנטרים. אם המנטר נמצא על השרת שהוא מנטר, האירוע שאתם רוצים לזהות — קריסת השרת או חוסר בזיכרון — יפיל גם את המנטר. במצב זה לא תקבלו התראה כלל: שתיקה ממנטר שקפץ נראית בדיוק כמו מצב שבו "הכל תקין". קיימת מלכודת עדינה יותר גם כשהשרת פעיל: מנטר המופנה אל localhost חולק את ה-CPU עם עומס העבודה. לכן, עלייה חדה בעומס (load spike) עלולה לגרום לבדיקה עצמה לפוגע בזמן (timeout) ולסמן את היעד כ-down. זוהי התרעה שווא, בעוד שהמשתמשים האמיתיים מקבלים שירות ללא תקלות.
לכן, הריצו את Uptime Kuma על VPS שונה מזה שהוא מנטר. עדיף להשתמש בספק או באזור (region) שונה, כך שהמנטר יגיע לשירותים שלכם בדיוק כפי שהמשתמשים מגיעים אליהם: דרך האינטרנט הציבורי, באמצעות hostname. מכונה (instance) זולה תספיק, ו-VPS ניטור אחד קטן יכול לנטר את כל השרתים שלכם. כדי לזהות אם Kuma עצמו קרס, הוסיפו מנגנון push heartbeat מתוך cron בשרת אחר.
Prerequisites and sizing
- שרת VPS חדש עם Ubuntu 24.04, המצויד ב-Docker Engine וב-Compose v2 plugin. יש להתקין אותם מתוך ה-apt repository של Docker ולא מתוך חבילת ה-
docker.ioשל ההפצה, שכן היא אינה מעודכנת מספיק. - 256 MB RAM מספיקים להרצת מספר קטן של מנטרים; 512 MB עד 1 GB יספקו ביצועים נוחים עבור עשרות מנטרים בתוספת ה-reverse proxy, כאשר ה-CPU נשאר כמעט ללא עומס בין הבדיקות.
- דומיין ורשומת DNS מסוג
A(למשלstatus.example.comהמפנה אל ה-VPS), רק אם ברצונכם להשתמש ב-TLS ובדף סטטוס ציבורי. מופע פרטי יכול לוותר על DNS ולהשתמש ב-VPN או ב-SSH tunnel. - גישת רשתתית (Outbound) ליעד שבו נשלחות ההתראות: SMTP לספק המייל שלכם, או HTTPS ל-Telegram ו-Discord.
The Compose file
שמור זאת ב-/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 ולאחר מכן תפסיק להוציא לוגים. שלושה פרטים בקובץ זה הם מכוונים.
127.0.0.1:3001:3001, לא 3001:3001. Docker מפרסם פורטים באמצעות חוקי DNAT שנבדקים לפני ש-ufw רואה את החבילה. לכן, שימוש ב-3001:3001 בלבד יחשוף את ה-dashboard לאינטרנט הציבורי ללא קשר לחומת האש שלך. קישור ל-loopback שומר על המערכת פרטית, כאשר רק ה-reverse proxy חשוף; מופע פרטי יכול לדלג על ה-proxy ולגשת ל-3001 דרך self-hosted WireGuard VPN במקום זאת.
Volume בשם ב-/app/data. כל מה ש-Uptime Kuma זוכר — מסד הנתונים SQLite, ה-monitors, הגדרות ההתראות ולוגואים של דף המצב — נשמר שם. אם תאבד אותו, תתחיל עם מסך מנהל ריק; זהו הדבר היחיד שעליך לגבות.
ה-image מוגדר ל-tag ראשי, :2. זוהי גרסת ה-stable הנוכחית; בדוק ב-Docker Hub את הגרסה הראשית החדשה ביותר לפני ההעתקה. לעולם אל תשתמש ב-tag משתנה כמו latest, שאינו נתמך על ידי הפרויקט. קפיצה בין גרסאות ראשיות ב-image זה היא מיגרציית מסד נתונים חד-כיוונית; עליך להפעיל אותה בכוונה, ולא בטעות במהלך pull שגרתי.
הערה אחת: /app/data חייב להיות על מערכת קבצים התומכת ב-POSIX file locks. Docker volume מקומי הוא פתרון תקין; ב-NFS מסד הנתונים SQLite עלול להفسר (corrupt) ותקבל את SQLITE_BUSY ו-database disk image is malformed, לכן לעולם אל תשתמש בשיתוף רשת.
הרצה ראשונה: יצירת חשבון מנהל
גלוש אל ה-instance דרך ה-proxy שלך בכתובת https://status.example.com, או באמצעות SSH tunnel: הרץ את ssh -L 3001:127.0.0.1:3001 user@your-vps ופתח את http://localhost:3001. הדף הראשון הוא טופס הגדרה עבור שם המשתמש והסיסמה של המנהל (administrator); אין פרטי התחברות ברירת מחדל. בחר סיסמה אמיתית: ל-dashboard זה יש גישה לכתובות הפנימיות ול-tokens של כל מה שאתה מנטר. שכחת את הסיסמה? בצע reset מה-host, לא דרך ה-browser:
sudo docker compose exec uptime-kuma npm run reset-passwordראשית הוסף את ערוצי ההתראות שלך ובצע להם בדיקה
הגדר התראות לפני הוספת מנטרים (monitors), כדי שתוכל לקשר ערוץ בכל פעם שאתה יוצר מנטר חדש. עבור אל Settings לאחר מכן Notifications ואז Setup Notification, והשתמש בכפתור ה-Test של כל ערוץ כדי לוודא שההודעה מתקבלת. התראה שלא נבדקה היא הסיבה השנייה בשכיחותה לכשל שקט בהגדרה.
Email (SMTP). מלא את פרטי ה-host, port, encryption, username, password, וכן כתובת From ו-To. שתי השילובים שעובדים הם 465 כאשר ה-encryption מוגדר כ-TLS/SSL, או 587 עם STARTTLS. עבור Gmail וספקי שירות מרובים עם אימות דו-שלבי (two-factor auth), עליך ליצור app password; סיסמה רגילה של החשבון תגרום לשגיאת Error: Invalid login: 535-5.7.8 Username and Password not accepted.
Telegram. שלח הודעה ל-@BotFather, שלח /newbot, והעתק את ה-bot token. עבור ה-chat ID שלך, שלח הודעה לבוט החדש פעם אחת, פתח את https://api.telegram.org/bot<token>/getUpdates, וקרא את chat.id מתוך ה-JSON. בוט שלא שלחת לו הודעה מעולם יחזיק ב-getUpdates ריק ולא ניתן לשלוח אליו הודעות.
Discord. בערוץ הרלוונטי, פתח את Edit Channel לאחר מכן Integrations ואז Webhooks ואז New Webhook, העתק את ה-URL, והדבק אותו כהתראת Discord.
Generic webhook. עבור כל שירות אחר, כגון Slack incoming webhook, endpoint מותאם אישית, או hook של בית חכם, סוג ה-Webhook מבצע POST של JSON payload לכתובת URL שתספק. אינטגרציית ה-Apprise המובנית מכסה את רוב תשע-העשרות השירותים האחרים ברשימה.
הוספת מנטרים, סוג אחד בכל פעם
לחץ על Add New Monitor, בחר סוג, והגדר את ה-Friendly Name, את ה-Check Interval (60 seconds הוא ערך מומלץ), את ה-Retries (מספר הכשלונות הרצופים לפני מצב "down"; מומלץ 2 או 3 כדי שחבילה אחת שאבד לא תפעיל התראה), ואת ההתראות שיוצאו. הסוגים שתשתמש בהם:
- HTTP(s). כתובת URL מלאה. מצב "up" פירושו קוד סטטוס תקין (200-299 כברירת מחדל; ניתן להרחיב טווח זה תחת Accepted Status Codes אם
301או401הם תקינים עבורך). כלי העבודה העיקרי עבור אתרים ו-APIs. - HTTP(s) - Keyword. אותה בקשה, אך מצב "up" דורש גם נוכחות של מחרוזת מסוימת בגוף התגובה, אלא אם סומן Invert. זה מזהה מצב שבו האתר מחזיר
200 OKבזמן שהוא מציג את הטקסט "Error establishing a database connection", מצב שבודקת HTTP רגילה תתייחס אליו כבריא. - TCP Port. חיבור TCP פשוט למארח (host) ופורט, עבור שירותים שאינם HTTP: SSH בפורט 22, Postgres בפורט 5432, שרת SMTP בפורט 25, או שרת משחק.
- Ping. ICMP echo: בדיקת זמינות ו-latency זולה. אך רשתות רבות ו-cloud firewalls חוסמים ICMP, לכן מנטר ping אדום יכול להעיד על "host down" או על "provider blocks ping"; יש לוודא זאת באמצעות מנטר TCP.
- DNS. פתרון רשומה (A, AAAA, MX, TXT וכדומה) מול רזולבר (resolver) שתקבע, ויכול לאמת את התשובה. זה מאפשר לזהות שירותי רשם (registrar) או DNS שקẩmו בשלב מוקדם.
- Push. מנטר מסוג "inside-out", שיוסבר בהמשך.
ניטור cron job באמצעות מנטור 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 לתדירות שבה המשימה רצה, בתוספת זמן מרווח קצר. לאחר מכן, הוסף שורה אחת לסוף הסקריפט, כך שהוא יתבצע רק במקרה של הצלחה:
#!/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 ייפסק, וברגע שחלון הזמן של ה-interval-plus-retries ينتهي, Uptime Kuma ישנה את סטטוס המנטור ל-down וישלח התראה. התייחס ל-push token כאל סוד: לכל מי שיש לו את הטוקן, יכול להזייף הודעת heartbeat תקינה.
בניית דף סטטוס ציבורי
דף סטטוס הוא התצוגה המיועדת ללקוחות: הוא מציג אילו שירותים פעילים ואת ההיסטוריה האחרונה שלהם, מבלי לחשוף את לוח הבקרה (dashboard) שלכם. עברו אל Status Pages ולאחר מכן אל New Status Page, תנו לדף שם ו-slug (הנתיב הציבורי, כגון /status/main), גררו את ה-monitors שברצונכם להוסיף לקבוצות כמו "Websites" ו-"APIs", הוסיפו לוגו ותיאור קצר, ולחצו על Save. ניתן גם לקשר את הדף לדומיין משלו כך ש-status.example.com יגיש אותו ישירות.
שתי אזהרות: הוסיפו רק monitors שאתם מוכנים להפוך לציבוריים, מכיוון שדף סטטוס חושף שירות קיים והאם הוא פעיל; ולוודא שדעתכם כי לוח הבקרה נשאר מאחורי ההתחברות שלכם, בעוד שדף הסטטוס הוא ציבורי בכוונה ואינו דורש אימות (auth).
השתמש ב-reverse proxy עם TLS, ושים לב ל-websockets
עבור מופע (instance) ציבורי, יש להציב reverse proxy לפני ה-container המקושר ל-loopback, לצורך TLS ושם מארח (hostname). הפרט שגורם לכולם להיכשל: הממשק של Uptime Kuma הוא אפליקציית Socket.IO חיה, לכן ה-proxy חייב לבצע upgrade לחיבור ה-WebSocket. אם תפספס זאת, הדף ייטען אך לא יתחבר; לוח הבקרה יישאר על המצב "Connecting...", ה-heartbeats החיים לא יתעדכנו, וקונסול הדפדפן יציג את WebSocket connection to 'wss://.../socket.io/...' failed.
התקן את nginx ו-certbot, ולאחר מכן כתוב את ה-vhost שמבצע proxy לפורט ה-loopback. הגדר אותו כרגע על פורט 80 ואפשר ל-certbot להוסיף TLS לאחר מכן; נושאים של אתגרים, timers של חידוש ומצבי כשל מכוסים ב-issuing Let's Encrypt certificates with certbot and nginx.
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;
}
}הפעל את האתר (enable site), בדוק את הקונפיגורציה, ולאחר מכן אפשר ל-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.comהצמד Upgrade ו-Connection "upgrade" הוא קריטי, ו-proxy_read_timeout 3600s מונע מה-nginx לנתק את ה-socket ארוך הטווח; certbot מעתיק את שניהם לתוך הבלוק של 443 שהוא יוצר. אם אתה מריץ כבר מספר containers מאחורי proxy אחד, routing them through Traefik with automatic TLS מבצע פעולה דומה באמצעות container labels ומעביר WebSocket upgrades כברירת מחדל.
אל תשתמש ב-basic-auth על כל ה-vhost, מכיוון שזה גם יחסום את דף הסטטוס הציבורי ואת ה-endpoint של /api/push. השאר את מערכת ההתחברות המובנית של Uptime Kuma, והוסף fail2ban watching for repeated failed logins אם המערכת חשופה לאינטרנט. אם לוח הבקרה אינו חייב להיות ציבורי, וותר על ה-proxy וגש אליו דרך VPN.
ניטור תוקף תעודות בצורה נכונה
גם HTTP(s) monitor יכול להזהיר אתכם לפני שתוקף תעודת TLS פוקע: סמנו את Certificate Expiry Notification ו-Uptime Kuma ישלח התראה מספר ימים מראש. שתי טעויות גורמות לקריאה שגויה:
- נMonitor באמצעות hostname, לא IP. אם תשתמשו בבקשה ללא SNI, תקבלו את תעודת ברירת המחדל של השרת ותראו את
Hostname/IP does not match certificate's altnames. - אל תסמנו Ignore TLS/SSL Error ב-monitor שברצונכם לקבל ממנו התרעות על תוקף תעודה: אפשרות זו מיועדת למארחים פנימיים עם תעודות חתומות עצמית (
unable to verify the first certificate,DEPTH_ZERO_SELF_SIGNED_CERT), אך היא גורמת ל-Uptime Kuma להפסיק לבדוק את התעודה לחלוטין, כולל בדיקת תוקף.
Backups: it is one directory
מכיוון שכל המידע נמצא ב-/app/data, גיבוי הוא עותק של ה-volume שנלקח בזמן שה-container כבוי. פעולה זו מבטיחה שהקובץ של 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ראשית, ודא את השם הממשי של ה-volume באמצעות docker volume ls | grep kuma, מכיוון ש-Compose מוסיף לו את שם ספריית הפרויקט. לאחר מכן, העתק את קובץ ה-tarball אל מחוץ לשרת, כיוון שגיבוי שנשמר על אותו VPS הוא רק עותק ולא גיבוי אמיתי. תהליך השחזור הוא הפוך: עצור את ה-stack, חלץ את הקבצים לתוך /app/data ריק, והפעל מחדש.
Upgrades
עדכון גרסה מתבצע באמצעות משיכת image:
cd /srv/uptime-kuma
sudo docker compose pull
sudo docker compose up -dהקונטיינר החדש מריץ כל database migration בעת ההפעלה הראשונה; יש לעקוב אחר docker compose logs -f. בצע את הגיבוי המצוין לעיל לפני משיכת ה-image, והישאר בתוך major tag: המעבר מ-:1 ל-:2 הוא migration חד-כיווני, לכן בצע גיבוי תחילה ובדוק את ה-release notes.
Failure modes, with the strings you will see
False "down" on a monitor pointed at localhost. The monitor goes red with timeout of 48000ms exceeded or connect ETIMEDOUT, yet the service answers from your laptop. If it targets the same host Uptime Kuma runs on, a CPU or memory spike starved the check, not the target. Move the monitor to a separate VPS and target the public hostname.
connect ECONNREFUSED 127.0.0.1:443 (or any port). Nothing was listening on that port: either the service is down, or you monitored localhost from inside the container, where 127.0.0.1 is the container, not your server. Monitor the public hostname, not loopback.
Invalid login: 535-5.7.8 Username and Password not accepted on an email test. The SMTP credentials are wrong, or the provider wants an app-specific password and got your account password. Generate an app password and paste that.
connect ETIMEDOUT or queryA ETIMEDOUT <host> on an email test. Wrong port, or the provider blocks outbound SMTP. Confirm 465 or 587 matches the Secure/STARTTLS setting, and test from the host with nc -vz smtp.example.com 587. Many providers block outbound 25 and some block submission ports until you ask.
self signed certificate or unable to verify the first certificate on an email test. Your SMTP server presents a certificate Node will not trust; fix the mail server's certificate rather than papering over it.
Dashboard stuck on "Connecting...", console shows WebSocket connection ... failed. The reverse proxy is not upgrading the WebSocket. Add the Upgrade and Connection "upgrade" headers on nginx, or use a proxy that forwards them by default such as Traefik or Caddy. The HTML loads because that is a normal HTTP GET; only the live socket needs the upgrade.
Cert-expiry monitor never warns, or warns wrongly. Either Ignore TLS/SSL Error is ticked, which disables cert checking, or the monitor targets an IP and reads the wrong certificate through missing SNI, showing Hostname/IP does not match certificate's altnames. Untick ignore, monitor by hostname.
SQLITE_BUSY or database disk image is malformed in the logs. The /app/data volume is on a filesystem without proper file locking, usually NFS; move it to a local Docker volume and restore from backup.
FAQ
איפה כדאי להריץ את ה-uptime monitor שלי?
על שרת שונה מהשרתים שהוא עוקב אחריהם. עדיף ספק או אזור (region) אחר, כך שהגישה אליהם תתבצע באמצעות hostname דרך האינטרנט הציבורי, בדיוק כפי שהמשתמשים שלך עושים. אם ה-monitor נמצא על אותו שרת עם היעד, תקלה שתפיל את השרת תפיל גם את ה-monitor. בנוסף, שרת עמוס מדי עלול לשלוח התראה על "down" למרות ששירותים תקינים. שימוש ב-VPS נפרד וקטן ימנע את שתי הבעיות הללו.
איך אני מקבל התראות ב-Telegram או באימייל?
הוסף את הערוץ תחת Settings then Notifications, ולאחר מכן הצמד אותו לכל monitor. עבור Telegram, צור bot באמצעות @BotFather וקרא את chat.id מתוך https://api.telegram.org/bot<token>/getUpdates; עבור אימייל, השתמש ב-465 עבור SSL או ב-587 עבור STARTTLS עם app password אם הספק שלך משתמש באימות דו-שלבי. לחץ על Test וודא שההודעה מגיעה לפני שתסתמך על המערכת.
האם Uptime Kuma יכול לעקוב אחר cron job או סקריפט גיבוי?
כן, זהו תפקיד ה-Push monitor: Uptime Kuma מספק לך URL ואתה מבצע curl בסוף הסקריפט, כך שההתראה תישלח רק במקרה של הצלחה. אם המשימה נכשלת או שהשרת כבוי, ה-heartbeat לא יגיע, ותקבל התראה לאחר סיום פרק הזמן שהוגדר. זו הדרך האמינה היחידה לדעת שמשימה מתוזמנת אכן רצה, מכיוון שבודק חיצוני אינו יכול לראות את התוכן הפנימי שלה.
Uptime Kuma לעומת Zabbix, במה כדאי להשתמש?
Uptime Kuma עונה על השאלה "האם השירות פעיל מבחוץ, והאם התקבלתי התראה" תוך עשר דקות עם כמעט ללא משאבים, בנוסף לדף סטטוס. הוא אינו אוסף מדדים עמוקים כמו מגמות CPU, זיכרון ודיסק או סף (thresholds) עבור פריסה רחבה; עבור כך, שרת ניטור Zabbix מלא הוא כלי כבד יותר המבוסס על agents, ומשתמשים רבים מריצים את שניהם. עדיין לא החלטת מה להריץ? המדריך שלנו על מה כדאי לארח בעצמך ב-2026 נותן הקשר רחב יותר לניטור.