วิธีติดตั้ง Uptime Kuma ด้วย Docker เพื่อเฝ้าดูเซิร์ฟเวอร์
เรียนรู้วิธีติดตั้ง Uptime Kuma ผ่าน Docker เพื่อตรวจสอบสถานะเว็บไซต์ พอร์ต และ DNS พร้อมตั้งค่าแจ้งเตือนผ่าน Telegram และอีเมล โดยเน้นการแยกเซิร์ฟเวอร์เพื่อความแม่นยำ
สิ่งที่คุณกำลังสร้าง
คอนเทนเนอร์ขนาดเล็กหนึ่งตัวที่คอยเฝ้าดูเซิร์ฟเวอร์และเว็บไซต์อื่นๆ ของคุณจากภายนอก และแจ้งเตือนคุณทันทีที่บริการใดบริการหนึ่งหยุดตอบสนอง ผ่านทางอีเมล, Telegram, Discord หรือ webhook โดย Uptime Kuma เป็นโพรเซส Node หนึ่งตัวที่ใช้ SQLite เป็นฐานข้อมูล จึงสามารถทำงานได้อย่างราบรื่นด้วย RAM เพียง 256-512 MB พร้อมมอบแดชบอร์ดแบบเรียลไทม์ กราฟประวัติการทำงาน และหน้าสถานะสาธารณะ การติดตั้งใช้ไฟล์ Compose เพียง 10 บรรทัด ส่วนที่สำคัญจริงๆ คือ ตำแหน่งที่คุณรันมัน และ การทดสอบว่าการแจ้งเตือนของคุณทำงานจริงหรือไม่ เพราะระบบตรวจสอบที่คุณไม่เคยพิสูจน์ว่าสามารถส่งข้อความถึงคุณได้นั้น แย่ยิ่งกว่าการไม่มีระบบใดๆ เลย เนื่องจากมันทำให้คุณรู้สึกอุ่นใจทั้งที่ไม่ได้เฝ้าดูอะไรอยู่จริง
รันระบบตรวจสอบในตำแหน่งที่เหตุขัดข้องเข้าไม่ถึง
การตัดสินใจเพียงข้อเดียวนี้เป็นตัวกำหนดความสำเร็จหรือความล้มเหลวของระบบทั้งหมด จึงต้องให้ความสำคัญเป็นอันดับแรก ห้ามรัน Uptime Kuma บนเครื่องเดียวกับบริการที่ต้องการตรวจสอบ หากระบบตรวจสอบทำงานอยู่บนเซิร์ฟเวอร์ที่มันคอยเฝ้าดู เหตุการณ์ที่คุณกังวล เช่น เซิร์ฟเวอร์ล่มหรือหน่วยความจำเต็ม จะทำให้ระบบตรวจสอบหยุดทำงานไปด้วย ส่งผลให้คุณไม่ได้รับการแจ้งเตือนใดๆ ทั้งสิ้น ซึ่งความเงียบจากระบบตรวจสอบที่ตายไปนั้นดูไม่ต่างจากสถานะ "ทุกอย่างปกติ" นอกจากนี้ยังมีกับดักที่ซ่อนเร้นกว่านั้นแม้ในขณะที่เครื่องยังทำงานอยู่ นั่นคือการที่ระบบตรวจสอบที่ชี้ไปยัง localhost ต้องแย่งทรัพยากร CPU กับภาระงานหลัก ดังนั้นเมื่อเกิดโหลดพุ่งสูงขึ้น (load spike) จะทำให้การตรวจสอบของตัวมันเองหมดเวลา (timeout) และเปลี่ยนสถานะเป้าหมายเป็น down ซึ่งเป็นการแจ้งเตือนที่ผิดพลาด ในขณะที่ผู้ใช้งานจริงยังคงเข้าถึงบริการได้ตามปกติ
ดังนั้น ควรติดตั้ง Uptime Kuma บน VPS คนละเครื่อง กับที่ใช้ตรวจสอบ โดยควรเลือกผู้ให้บริการหรือภูมิภาคที่ต่างกัน และเข้าถึงบริการของคุณในลักษณะเดียวกับที่ผู้ใช้งานทั่วไปทำ คือผ่านอินเทอร์เน็ตสาธารณะโดยใช้ชื่อโฮสต์ (hostname) เพียงแค่ instance ราคาประหยัดก็เพียงพอแล้ว และ VPS สำหรับตรวจสอบขนาดเล็กเพียงเครื่องเดียวก็สามารถเฝ้าดูเซิร์ฟเวอร์ทั้งหมดของคุณได้ การแยกส่วนนี้มีความสำคัญอย่างยิ่งสำหรับแอปพลิเคชันที่ใช้ทรัพยากรสูงที่คุณโฮสต์ไว้ เนื่องจากแอปอย่าง PhotoPrism หรือคลังรูปภาพ Immich อาจใช้ CPU เต็มประสิทธิภาพเป็นเวลาหลายชั่วโมงในระหว่างการทำดัชนีไฟล์ที่นำเข้าใหม่ หากระบบตรวจสอบใช้ฮาร์ดแวร์ร่วมกัน มันจะแจ้งเตือนว่าบริการล่มทั้งที่จริงแล้วบริการนั้นเพียงแค่กำลังทำงานหนักเท่านั้น เพื่อป้องกันกรณีที่ตัว Uptime Kuma เองหยุดทำงาน ให้เพิ่มการส่งสัญญาณ push heartbeat จาก cron ในเครื่องอื่นเข้ามาเสริมด้วย
ข้อกำหนดเบื้องต้นและการจัดสรรทรัพยากร
- VPS ที่ใช้ Ubuntu 24.04 ติดตั้งใหม่ พร้อม Docker Engine และปลั๊กอิน Compose v2 โดยต้องติดตั้งจาก apt repository ของ Docker โดยตรง ไม่ใช่จากแพ็กเกจ
docker.ioของ distro เนื่องจากเวอร์ชันมักจะล้าหลัง - RAM ขนาด 256 MB เพียงพอสำหรับการรันตัวตรวจสอบ (monitors) จำนวนหนึ่ง หากต้องการรันหลายสิบรายการรวมถึง reverse proxy ควรใช้ RAM ขนาด 512 MB ถึง 1 GB โดย CPU จะแทบไม่มีภาระงานระหว่างการตรวจสอบ
- โดเมนและระเบียน DNS
A(เช่นstatus.example.comที่ชี้ไปยัง VPS) จำเป็นเฉพาะในกรณี ที่คุณต้องการใช้งาน TLS และหน้าสถานะแบบสาธารณะ หากเป็น instance ส่วนตัวสามารถข้ามขั้นตอน DNS และใช้ VPN หรือ SSH tunnel แทนได้ - การเชื่อมต่อเครือข่ายขาออกไปยังปลายทางที่ต้องการรับการแจ้งเตือน เช่น SMTP ไปยังผู้ให้บริการอีเมลของคุณ หรือ HTTPS ไปยัง Telegram และ Discord
ไฟล์ 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การเริ่มต้นที่ถูกต้องจะบันทึก log เป็น Listening on 3001 แล้วเงียบไป มีสามสิ่งที่ตั้งใจกำหนดไว้ในไฟล์นั้น
127.0.0.1:3001:3001 ไม่ใช่ 3001:3001 Docker เผยแพร่พอร์ตด้วยกฎ DNAT ซึ่งถูกประเมินผล ก่อน ที่ ufw จะเห็นแพ็กเก็ต ดังนั้นการใช้ 3001:3001 เปล่าๆ จะทำให้แดชบอร์ดของคุณเปิดสู่สาธารณะโดยไม่สนใจไฟร์วอลล์ การผูกไว้กับ loopback จะช่วยให้เป็นส่วนตัว โดยเปิดเผยเฉพาะ reverse proxy เท่านั้น หากเป็น instance ส่วนตัว คุณสามารถข้าม proxy และเข้าถึง 3001 ผ่าน VPN WireGuard ที่โฮสต์เอง ได้
Named volume ที่ /app/data ทุกสิ่งที่ Uptime Kuma จดจำไว้ ไม่ว่าจะเป็นฐานข้อมูล SQLite, มอนิเตอร์ของคุณ, การตั้งค่าการแจ้งเตือน และโลโก้หน้าสถานะ จะถูกเก็บไว้ที่นั่น หากทำไฟล์นี้หาย คุณจะต้องเริ่มใหม่จากหน้าจอผู้ดูแลระบบที่ว่างเปล่า นี่คือสิ่งเดียวที่คุณต้องสำรองข้อมูลไว้
Image ถูกระบุเวอร์ชันไว้ที่แท็กหลัก :2 นี่คือสายการผลิตที่เสถียรในปัจจุบัน ให้ตรวจสอบ Docker Hub เพื่อดูเวอร์ชันหลักล่าสุดก่อนคัดลอก และอย่าใช้แท็กที่เปลี่ยนแปลงตลอดเวลาอย่าง latest ซึ่งทางโปรเจกต์ไม่แนะนำให้ใช้ การข้ามเวอร์ชันหลักของ image นี้เป็นการย้ายฐานข้อมูลแบบทางเดียว ซึ่งคุณควรเลือกทำด้วยตนเอง ไม่ใช่ให้เกิดขึ้นโดยบังเอิญจากการ pull ตามปกติ
ข้อควรระวัง: /app/data ต้องอยู่บนระบบไฟล์ที่รองรับ POSIX file locks การใช้ Docker volume ในเครื่องนั้นไม่มีปัญหา แต่หากใช้บน NFS ฐานข้อมูล SQLite จะเสียหายและคุณจะพบกับ 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 หน้าแรกจะเป็นแบบฟอร์มตั้งค่าชื่อผู้ใช้และรหัสผ่านสำหรับผู้ดูแลระบบ ซึ่งไม่มีการกำหนดรหัสผ่านเริ่มต้นไว้ เลือกใช้รหัสผ่านที่ปลอดภัย เนื่องจากแดชบอร์ดนี้สามารถเข้าถึงที่อยู่ภายในและโทเค็นของทุกบริการที่คุณตรวจสอบ หากลืมรหัสผ่านในภายหลัง ให้รีเซ็ตจากโฮสต์โดยตรงแทนการทำผ่านเบราว์เซอร์:
sudo docker compose exec uptime-kuma npm run reset-passwordเพิ่มช่องทางการแจ้งเตือนของคุณก่อน แล้วจึงทดสอบ
ตั้งค่าการแจ้งเตือนก่อนเพิ่มมอนิเตอร์ เพื่อให้คุณสามารถเลือกช่องทางแจ้งเตือนได้ทันทีที่สร้างมอนิเตอร์แต่ละรายการ ไปที่ Settings แล้วเลือก Notifications จากนั้นเลือก Setup Notification และใช้ปุ่ม Test ของแต่ละช่องทางเพื่อยืนยันว่าข้อความส่งถึงจริง เพราะการแจ้งเตือนที่ไม่ได้ทดสอบเป็นสาเหตุอันดับสองที่พบบ่อยที่สุดที่ทำให้การตั้งค่าล้มเหลวโดยไม่มีการแจ้งเตือนใดๆ
Email (SMTP). กรอก host, port, encryption, username, password, From และ To การตั้งค่าที่ใช้งานได้มีสองรูปแบบคือ 465 โดยตั้งค่า "Secure" เป็น TLS/SSL หรือ 587 โดยใช้ STARTTLS สำหรับ Gmail และผู้ให้บริการส่วนใหญ่ที่ใช้การยืนยันตัวตนสองชั้น คุณต้องสร้าง 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 ไปยัง URL ที่คุณระบุ และการรวม Apprise ที่มาพร้อมกับระบบจะครอบคลุมบริการอื่นๆ อีกกว่าเก้าสิบรายการในรายการ หากคุณไม่ต้องการให้บุคคลที่สามเข้ามาแทรกกลางระหว่างเหตุการณ์ระบบล่มกับการแจ้งเตือนบนโทรศัพท์ของคุณ ให้เลือกประเภท ntfy ที่มีมาให้ในตัว แล้วชี้ไปยัง เซิร์ฟเวอร์ ntfy ที่คุณดูแลเอง ซึ่งจะส่งการแจ้งเตือนไปยังอุปกรณ์ของคุณผ่านช่องทางที่คุณควบคุมได้ตั้งแต่ต้นจนจบ
เพิ่มมอนิเตอร์ทีละประเภท
คลิก Add New Monitor เลือกประเภทที่ต้องการ แล้วตั้งค่า Friendly Name, Check Interval (ค่า 60 วินาทีถือว่าเหมาะสม), Retries (จำนวนครั้งที่ล้มเหลวติดต่อกันก่อนจะถือว่า "down"; แนะนำให้ตั้ง 2 หรือ 3 ครั้ง เพื่อป้องกันการแจ้งเตือนผิดพลาดจากแพ็กเก็ตที่สูญหายเพียงชั่วคราว) และเลือกการแจ้งเตือนที่ต้องการให้ทำงาน ประเภทที่คุณจะได้ใช้งานมีดังนี้:
- HTTP(s). ใช้ URL เต็ม สถานะ "up" หมายถึงได้รับรหัสสถานะที่ยอมรับได้ (โดยปกติคือ 200-299; หาก
301หรือ401เป็นเรื่องปกติสำหรับคุณ สามารถขยายช่วงได้ในส่วน Accepted Status Codes) นี่คือเครื่องมือหลักสำหรับเว็บไซต์และ API - HTTP(s) - Keyword. การร้องขอแบบเดียวกัน แต่สถานะ "up" จะต้องมีข้อความที่กำหนดปรากฏอยู่ในเนื้อหา (หรือไม่มีหากเลือก Invert) วิธีนี้ช่วยตรวจจับกรณีที่เว็บไซต์ส่งรหัส
200 OKแต่แสดงข้อความว่า "Error establishing a database connection" ซึ่งการตรวจสอบแบบ HTTP ปกติจะถือว่าสถานะยังปกติ นอกจากนี้ยังเหมาะสำหรับหน้าเว็บที่ดึงข้อมูลจาก backend แยกต่างหาก เช่น หน้ากากร้านวิดีโอ Halcyon ที่ครอบ Jellyfin ซึ่งหน้าเว็บหลักอาจส่งรหัส200ได้ตามปกติแม้ว่า media server เบื้องหลังจะไม่สามารถเข้าถึงได้ก็ตาม - TCP Port. การเชื่อมต่อ TCP เปล่าไปยังโฮสต์และพอร์ตที่ระบุ สำหรับบริการที่ไม่ใช่ HTTP เช่น SSH บนพอร์ต 22, Postgres บนพอร์ต 5432, เซิร์ฟเวอร์ SMTP บนพอร์ต 25 หรือเซิร์ฟเวอร์เกม
- Ping. การใช้ ICMP echo: เป็นวิธีที่ประหยัดทรัพยากรในการตรวจสอบการเข้าถึงและความหน่วง (latency) อย่างไรก็ตาม เครือข่ายและไฟร์วอลล์บนคลาวด์จำนวนมากมักบล็อก ICMP ดังนั้นหากมอนิเตอร์ Ping ขึ้นสีแดง อาจหมายถึง "โฮสต์ล่ม" หรือ "ผู้ให้บริการบล็อก Ping" ให้ยืนยันผลลัพธ์อีกครั้งด้วยมอนิเตอร์ประเภท TCP
- DNS. ทำการ resolve เรคคอร์ด (เช่น A, AAAA, MX, TXT ฯลฯ) ผ่านตัวแก้ชื่อโดเมน (resolver) ที่คุณระบุ และสามารถตรวจสอบความถูกต้องของคำตอบได้ ช่วยให้ตรวจพบปัญหาจากผู้รับจดทะเบียนโดเมนหรือระบบ DNS ล่มได้รวดเร็ว
- Push. มอนิเตอร์แบบจากภายในสู่ภายนอก ซึ่งจะอธิบายในหัวข้อถัดไป
การตรวจสอบ cron job ด้วย push (heartbeat) monitor
การตรวจสอบทุกรูปแบบที่กล่าวมาข้างต้นเป็นการเข้าถึงบริการของคุณจากภายนอก แต่ push monitor ทำงานในทางกลับกัน คือ Uptime Kuma จะรอรับสัญญาณ และเป็นตัวงาน (job) ของคุณเองที่เรียกเข้ามาเพื่อแจ้งว่า "ฉันทำงานเสร็จแล้ว" นี่เป็นวิธีที่น่าเชื่อถือที่สุดในการตรวจสอบการสำรองข้อมูลหรือ cron job เพราะการตรวจสอบแบบ HTTP เพียงแค่บอกว่า URL ตอบสนองหรือไม่ แต่มีเพียงตัวงานเท่านั้นที่รู้ว่ามันทำงานจนเสร็จสิ้นจริง
ให้สร้าง monitor ประเภท 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 จะหยุดส่ง และเมื่อพ้นระยะเวลาที่กำหนดบวกกับจำนวนครั้งที่ลองใหม่ Uptime Kuma จะเปลี่ยนสถานะ monitor เป็น down และแจ้งเตือนคุณ ให้ถือว่า push token นี้เป็นความลับ เพราะใครก็ตามที่มี token นี้สามารถปลอมแปลงสถานะว่างานทำงานปกติได้
สร้างหน้าสถานะสาธารณะ
หน้าสถานะคือมุมมองสำหรับผู้ใช้งานทั่วไป เพื่อแสดงว่าบริการใดบ้างที่กำลังทำงานอยู่และประวัติการทำงานล่าสุด โดยไม่เปิดเผยข้อมูลในแดชบอร์ดของคุณ ให้ไปที่ Status Pages แล้วเลือก New Status Page จากนั้นตั้งชื่อและกำหนด slug (path สาธารณะ เช่น /status/main) ลาก monitor ที่ต้องการจัดกลุ่มไว้ภายใต้หัวข้อ เช่น "Websites" และ "APIs" เพิ่มโลโก้และคำอธิบายสั้นๆ แล้วกด Save คุณยังสามารถผูกหน้าสถานะเข้ากับโดเมนของตนเองเพื่อให้ status.example.com แสดงผลหน้านั้นโดยตรงได้
ข้อควรระวังสองประการ: เพิ่มเฉพาะ monitor ที่คุณต้องการเปิดเผยต่อสาธารณะเท่านั้น เนื่องจากหน้าสถานะจะเปิดเผยว่ามีบริการนั้นอยู่จริงและสถานะการทำงานของบริการนั้น และแดชบอร์ดจะยังคงอยู่หลังระบบล็อกอินของคุณ ในขณะที่หน้าสถานะถูกออกแบบมาให้เป็นสาธารณะและไม่จำเป็นต้องมีการยืนยันตัวตน
วางไว้หลัง reverse proxy ที่รองรับ TLS และอย่าลืมเรื่อง WebSocket
สำหรับการใช้งานแบบสาธารณะ ให้วาง reverse proxy ไว้หน้าคอนเทนเนอร์ที่รันบน loopback เพื่อจัดการ TLS และชื่อโฮสต์ รายละเอียดที่มักทำให้เกิดปัญหาคือ UI ของ Uptime Kuma เป็นแอป Socket.IO แบบเรียลไทม์ ดังนั้น proxy ต้องรองรับการอัปเกรดการเชื่อมต่อเป็น WebSocket หากพลาดจุดนี้ หน้าเว็บจะโหลดขึ้นมาแต่ไม่สามารถเชื่อมต่อได้ โดย dashboard จะค้างอยู่ที่สถานะ "Connecting...", ข้อมูล heartbeat จะไม่ถูกอัปเดต และใน console ของเบราว์เซอร์จะแสดงข้อความ WebSocket connection to 'wss://.../socket.io/...' failed
ให้ติดตั้ง nginx และ certbot จากนั้นเขียนไฟล์ vhost เพื่อทำ proxy ไปยังพอร์ต loopback โดยให้ตั้งค่าที่พอร์ต 80 ไว้ก่อน แล้วค่อยให้ certbot เพิ่ม TLS ในภายหลัง สำหรับขั้นตอนการตรวจสอบ (challenge), ตัวตั้งเวลาต่ออายุ และรูปแบบความล้มเหลว สามารถดูได้ที่ การออกใบรับรอง Let's Encrypt ด้วย certbot และ 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;
}
}เปิดใช้งานไซต์ ทดสอบการตั้งค่า จากนั้นให้ 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 ที่สร้างขึ้นโดยอัตโนมัติ หากคุณรันหลายคอนเทนเนอร์หลัง proxy ตัวเดียวอยู่แล้ว การ กำหนดเส้นทางผ่าน Traefik พร้อม TLS อัตโนมัติ จะให้ผลลัพธ์แบบเดียวกันโดยใช้ container labels และส่งต่อการอัปเกรด WebSocket เป็นค่าเริ่มต้น
ห้ามทำ basic-auth กับ vhost ทั้งหมด เพราะจะทำให้หน้าสถานะสาธารณะและ endpoint /api/push ถูกล็อกไปด้วย ให้ใช้ระบบล็อกอินในตัวของ Uptime Kuma ต่อไป และเพิ่ม fail2ban เพื่อเฝ้าระวังการล็อกอินล้มเหลวซ้ำๆ หากบริการนี้เปิดให้เข้าถึงจากอินเทอร์เน็ต และหากไม่จำเป็นต้องเปิด dashboard เป็นสาธารณะ ให้ยกเลิกการใช้ proxy แล้วเข้าถึงผ่าน VPN แทน
การตรวจสอบวันหมดอายุของใบรับรองอย่างถูกต้อง
คุณสามารถใช้ HTTP(s) monitor เพื่อแจ้งเตือนก่อนที่ใบรับรอง TLS จะหมดอายุได้ โดยทำเครื่องหมายที่ Certificate Expiry Notification แล้ว Uptime Kuma จะส่งการแจ้งเตือนตามจำนวนวันที่คุณกำหนดไว้ล่วงหน้า มีข้อผิดพลาด 2 ประการที่ทำให้การตรวจสอบนี้อ่านค่าผิดพลาด ประการแรก ให้ตรวจสอบด้วย hostname ไม่ใช่ IP เพราะหากคำขอไม่มี SNI ระบบจะได้รับใบรับรองเริ่มต้นของเซิร์ฟเวอร์และคุณจะพบกับ Hostname/IP does not match certificate's altnames ประการที่สอง อย่าทำเครื่องหมายที่ Ignore TLS/SSL Error ใน monitor ที่คุณต้องการให้แจ้งเตือนวันหมดอายุ เพราะตัวเลือกดังกล่าวมีไว้สำหรับโฮสต์ภายในที่ใช้ใบรับรองแบบ self-signed (unable to verify the first certificate, DEPTH_ZERO_SELF_SIGNED_CERT) ซึ่งจะทำให้ Uptime Kuma หยุดตรวจสอบใบรับรองทั้งหมด รวมถึงวันหมดอายุด้วย
การสำรองข้อมูล: เป็นเพียงไดเรกทอรีเดียว
เนื่องจากทุกอย่างถูกเก็บไว้ใน /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 จะใส่ชื่อไดเรกทอรีโปรเจกต์นำหน้าชื่อ volume เสมอ จากนั้นให้คัดลอกไฟล์ tarball ออกจากเซิร์ฟเวอร์ เพราะการสำรองข้อมูลไว้บน VPS เครื่องเดิมถือเป็นการทำสำเนา ไม่ใช่การสำรองข้อมูล การกู้คืนข้อมูลทำได้โดยการย้อนขั้นตอน: หยุดการทำงานของ stack, แตกไฟล์ลงใน volume /app/data ที่ว่างเปล่า แล้วจึงเริ่มการทำงานใหม่
การอัปเกรด
การอัปเกรดคือการดึง image ใหม่:
cd /srv/uptime-kuma
sudo docker compose pull
sudo docker compose up -dคอนเทนเนอร์ใหม่จะดำเนินการ migration ฐานข้อมูลใดๆ ในการเริ่มทำงานครั้งแรก ให้ตรวจสอบ docker compose logs -f สำรองข้อมูลตามขั้นตอนข้างต้น ก่อน ทำการดึง image และควรอยู่ในช่วงของ major tag เดียวกัน: การย้ายจาก :1 ไปยัง :2 เป็นการ migration แบบทางเดียว ดังนั้นต้องสำรองข้อมูลก่อนและตรวจสอบบันทึกประจำรุ่น (release notes)
รูปแบบความล้มเหลวและข้อความที่คุณจะพบ
สถานะ "down" ปลอมบนมอนิเตอร์ที่ชี้ไปยัง 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 ไม่ถูกต้อง หรือผู้ให้บริการต้องการรหัสผ่านเฉพาะสำหรับแอป (app-specific password) แต่คุณใช้รหัสผ่านบัญชีปกติ ให้สร้างรหัสผ่านสำหรับแอปแล้วนำมาวางแทน
connect ETIMEDOUT หรือ queryA ETIMEDOUT <host> ในการทดสอบอีเมล ใช้พอร์ตผิด หรือผู้ให้บริการบล็อกการส่งอีเมลขาออก ตรวจสอบว่า 465 หรือ 587 ตรงกับการตั้งค่า Secure/STARTTLS และทดสอบจากโฮสต์ด้วย nc -vz smtp.example.com 587 ผู้ให้บริการหลายรายบล็อกพอร์ตขาออก 25 และบางรายบล็อกพอร์ตสำหรับการส่งอีเมลจนกว่าคุณจะแจ้งขอเปิดใช้งาน
self signed certificate หรือ unable to verify the first certificate ในการทดสอบอีเมล เซิร์ฟเวอร์ SMTP ของคุณแสดงใบรับรองที่ Node ไม่เชื่อถือ ให้แก้ไขใบรับรองของเซิร์ฟเวอร์อีเมลแทนการข้ามการตรวจสอบ
แดชบอร์ดค้างที่ "Connecting..." และคอนโซลแสดง WebSocket connection ... failed Reverse proxy ไม่ได้อัปเกรดการเชื่อมต่อเป็น WebSocket ให้เพิ่ม header Upgrade และ Connection "upgrade" ใน nginx หรือใช้พร็อกซีที่ส่งต่อ header เหล่านี้โดยอัตโนมัติ เช่น 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 ใน log วอลุ่ม /app/data อยู่บนระบบไฟล์ที่ไม่รองรับการล็อกไฟล์อย่างถูกต้อง ซึ่งมักเกิดกับ NFS ให้ย้ายไปใช้ local Docker volume และกู้คืนข้อมูลจากสำรอง
FAQ
ฉันควรติดตั้ง uptime monitor ไว้ที่ไหน?
ควรติดตั้งบนเซิร์ฟเวอร์ที่แยกต่างหากจากเซิร์ฟเวอร์ที่ต้องการตรวจสอบ โดยเลือกผู้ให้บริการหรือภูมิภาคที่ต่างกัน และเข้าถึงผ่าน hostname บนอินเทอร์เน็ตสาธารณะเช่นเดียวกับที่ผู้ใช้งานของคุณทำ หาก monitor ทำงานอยู่บนเครื่องเดียวกับเป้าหมาย เมื่อเซิร์ฟเวอร์ล่ม monitor ก็จะล่มไปด้วย และหากโฮสต์มีภาระงานหนักเกินไป ก็อาจทำให้เกิดการแจ้งเตือนว่าบริการ "down" ทั้งที่จริงแล้วบริการยังทำงานปกติ การใช้ VPS ขนาดเล็กแยกต่างหากจะช่วยหลีกเลี่ยงปัญหาทั้งสองประการนี้
ฉันจะรับการแจ้งเตือนผ่าน Telegram หรืออีเมลได้อย่างไร?
เพิ่มช่องทางการแจ้งเตือนที่ Settings แล้วไปที่ Notifications จากนั้นจึงผูกเข้ากับ monitor แต่ละตัว สำหรับ Telegram ให้สร้างบอทด้วย @BotFather และอ่าน chat.id จาก https://api.telegram.org/bot<token>/getUpdates สำหรับอีเมล ให้ใช้ 465 สำหรับ SSL หรือ 587 สำหรับ STARTTLS พร้อมรหัสผ่านแอป (app password) หากผู้ให้บริการของคุณใช้การยืนยันตัวตนแบบสองชั้น (two-factor auth) ให้กด Test และตรวจสอบว่าได้รับข้อความจริงก่อนที่จะเริ่มใช้งานจริง
Uptime Kuma สามารถตรวจสอบ cron job หรือสคริปต์สำรองข้อมูลได้หรือไม่?
ได้ โดยใช้ monitor ประเภท Push ซึ่ง Uptime Kuma จะให้ URL มา และคุณต้อง curl URL นั้นที่ท้ายสคริปต์เพื่อให้ทำงานเฉพาะเมื่อสคริปต์สำเร็จเท่านั้น หากงานล้มเหลวหรือเครื่องล่ม จะไม่มีสัญญาณ heartbeat ส่งไป และคุณจะได้รับการแจ้งเตือนหลังจากผ่านช่วงเวลาที่กำหนด นี่เป็นวิธีเดียวที่เชื่อถือได้ในการยืนยันว่างานที่ตั้งเวลาไว้ทำงานจริง เนื่องจากตัวตรวจสอบภายนอกไม่สามารถมองเห็นการทำงานภายในสคริปต์ได้
ระหว่าง Uptime Kuma กับ Zabbix ควรเลือกใช้อะไร?
Uptime Kuma ตอบโจทย์คำถามที่ว่า "บริการยังออนไลน์อยู่หรือไม่จากมุมมองภายนอก และมีการแจ้งเตือนฉันหรือไม่" ได้ภายในสิบนาทีโดยใช้ทรัพยากรน้อยมาก พร้อมทั้งมีหน้า status page ให้ใช้งาน แต่มันไม่สามารถเก็บข้อมูลเชิงลึก เช่น แนวโน้มการใช้ CPU, หน่วยความจำ, พื้นที่ดิสก์ หรือการตั้งค่า threshold สำหรับระบบขนาดใหญ่ หากต้องการฟังก์ชันเหล่านั้น เซิร์ฟเวอร์ตรวจสอบด้วย Zabbix ซึ่งเป็นเครื่องมือที่ใช้ agent และมีความซับซ้อนกว่าจะเป็นตัวเลือกที่เหมาะสม ซึ่งหลายคนเลือกใช้งานทั้งสองอย่างควบคู่กัน หากยังตัดสินใจไม่ได้ว่าจะเลือกใช้เครื่องมือใด บทสรุปการเลือกซอฟต์แวร์สำหรับ self-host ในปี 2026 ของเราจะช่วยให้คุณเห็นภาพรวมของการเลือกใช้ระบบตรวจสอบได้ชัดเจนขึ้น