SSD Nodes Learn Hosting plans →
Посібники Matt ConnorВід Matt Connor · Оновлено 2026-08-28

Uptime Kuma: моніторинг сайтів на власному VPS

Запустіть Uptime Kuma у Docker на окремому VPS: контролюйте сайти, порти, DNS і cron jobs, отримуйте сповіщення в Telegram та публікуйте status page.

Що ви створюєте

Один невеликий контейнер, який перевіряє інші сервери та вебсайти ззовні й одразу повідомляє, коли один із них перестає відповідати, через email, Telegram, Discord або webhook. Uptime Kuma — це один процес Node, який використовує файл SQLite. Тому він без проблем працює з 256-512 MB RAM і надає live dashboard, графіки історії та публічну status page. Інсталяція — це Compose-файл із десяти рядків. Насправді важливо, де саме ви його запускаєте і чи спрацьовували ваші сповіщення під час тесту. Монітор, який ви жодного разу не перевірили на здатність повідомити вас, гірший за повну відсутність моніторингу: він створює хибне відчуття захищеності, хоча нічого не контролює.

Запускайте моніторинг там, куди не дістанеться збій

Це рішення визначає, чи працюватиме вся схема, тому воно має бути першим. Не запускайте Uptime Kuma на тому самому сервері, на якому розміщені об’єкти моніторингу. Якщо монітор працює на сервері, який він контролює, саме подія, яку потрібно виявити, — відмова сервера або вичерпання пам’яті — також зупинить монітор. У результаті ви не отримаєте сповіщення: мовчання непрацюючого монітора неможливо відрізнити від стану «все працює». Є й менш очевидна проблема, яка виникає навіть тоді, коли сервер ще працює: монітор, налаштований на localhost, використовує той самий CPU, що й робоче навантаження. Стрибок навантаження може призвести до перевищення часу очікування його власної перевірки, і він позначить ціль як недоступну. Це буде хибним сповіщенням, якщо реальні користувачі все ще можуть працювати із сервісом.

Тому запускайте Uptime Kuma на іншому VPS, ніж той, який він контролює. Бажано використовувати іншого провайдера або інший регіон і перевіряти сервіси так, як це роблять користувачі: через публічний інтернет, за hostname. Достатньо недорогого інстансу, а один невеликий VPS для моніторингу може контролювати всі ваші сервери. Це розділення особливо важливе для ресурсоємних застосунків, які ви розміщуєте. Наприклад, фотобібліотека на PhotoPrism або Immich може годинами завантажувати CPU під час індексації нового імпорту. Монітор, який використовує те саме обладнання, позначить сервіс як недоступний, хоча насправді він лише зайнятий. Щоб виявляти відмову самого Kuma, додайте push-heartbeat із cron на іншому сервері.

Передумови та розрахунок ресурсів

  • Чистий VPS з Ubuntu 24.04, Docker Engine і плагіном Compose v2, встановленими з власного apt-репозиторію Docker, а не з дистрибутивного пакета docker.io, який оновлюється із затримкою.
  • 256 MB RAM достатньо для кількох моніторів; 512 MB–1 GB буде достатньо для десятків моніторів разом із reverse proxy, а CPU майже не використовується між перевірками.
  • Домен і DNS-запис типу A (наприклад, status.example.com, що вказує на VPS) — лише якщо потрібні TLS і публічна сторінка стану. Приватний екземпляр може не використовувати DNS, а підключатися через VPN або SSH-тунель.
  • Вихідний мережевий доступ до місця призначення сповіщень: 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

Коректний запуск записує в журнал Listening on 3001, після чого журнал замовкає. У цьому файлі навмисно зроблено 3 речі.

127.0.0.1:3001:3001, а не 3001:3001. Docker публікує порти за допомогою правил DNAT, які обробляються до того, як ufw побачить пакет. Тому звичайний 3001:3001 відкриває вашу панель керування в публічному інтернеті незалежно від налаштувань firewall. Прив’язка до loopback залишає її приватною, а назовні доступним є лише reverse proxy. Приватний екземпляр може не використовувати проксі й підключатися до 3001 через self-hosted VPN WireGuard.

Іменований volume у /app/data. Там зберігається все, що запам’ятовує Uptime Kuma: база даних SQLite, ваші монітори, налаштування сповіщень і логотипи status page. Якщо втратити цей volume, ви побачите порожній екран адміністратора. Це єдині дані, які потрібно резервно копіювати.

Образ зафіксовано на major tag :2. Це поточна стабільна гілка. Перед копіюванням перевірте на Docker Hub найновішу major-версію. Не використовуйте змінний tag на кшталт latest, який проєкт виводить з експлуатації. Перехід на нову major-версію цього образу є односторонньою міграцією бази даних. Її потрібно запускати навмисно, а не виконувати випадково під час звичайного pull.

Є один нюанс: /app/data має розташовуватися у файловій системі з POSIX-блокуванням файлів. Локальний Docker volume підходить. На NFS база даних SQLite пошкоджується, і ви отримуєте SQLITE_BUSY та database disk image is malformed. Тому ніколи не використовуйте мережеву спільну папку.

Перший запуск: створення облікового запису адміністратора

Відкрийте екземпляр через проксі за адресою https://status.example.com або через SSH-тунель: виконайте 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 then Notifications then 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 then Integrations then Webhooks then New Webhook, скопіюйте URL і вставте його як сповіщення Discord.

Generic webhook. Для інших варіантів, зокрема Slack incoming webhook, власної кінцевої точки або hook для домашньої автоматизації, тип Webhook надсилає JSON payload на вказаний вами URL. Вбудована інтеграція Apprise підтримує більшість із приблизно дев’яноста інших сервісів у списку. Якщо ви не хочете, щоб між збоєм і вашим телефоном був сторонній сервіс, виберіть вбудований тип ntfy і вкажіть власний ntfy server, який надсилатиме push-сповіщення на ваш телефон через канал, що повністю контролюється вами.

Додавайте монітори по одному типу

Натисніть Add New Monitor, виберіть тип і задайте Friendly Name, Check Interval (60 секунд — оптимальне значення), Retries (кількість послідовних збоїв перед переходом у стан «down»; установіть 2 або 3, щоб одна втрачена відповідь не спричиняла сповіщення), а також сповіщення, які потрібно надсилати. Ви використовуватимете такі типи:

  • HTTP(s). Повна URL-адреса. Стан «up» означає отримання прийнятного коду відповіді (типово 200-299; розширте діапазон у Accepted Status Codes, якщо 301 або 401 є для вас штатною відповіддю). Основний тип перевірки для вебсайтів і API.
  • HTTP(s) - Keyword. Той самий запит, але стан «up» також вимагає наявності вмісту в тілі відповіді або, якщо ввімкнено Invert, його відсутності. Це виявляє випадок, коли сайт повертає 200 OK, але відображає повідомлення «Error establishing a database connection», яке звичайна HTTP-перевірка вважає ознакою справної роботи. Це також правильна перевірка для браузерного frontend, який взаємодіє з окремим backend, наприклад оболонки відеомагазину Halcyon поверх Jellyfin, коли оболонка сторінки без проблем повертає 200, але доступ до медіасервера за нею втрачено.
  • TCP Port. Звичайне TCP-підключення до хоста й порту для протоколів, які не використовують HTTP: SSH на 22, Postgres на 5432, SMTP-сервер на 25, ігровий сервер.
  • Ping. ICMP echo-запит: недорога перевірка доступності та затримки. Проте багато мереж і cloud firewall блокують ICMP, тому червоний монітор ping може означати «хост недоступний» або «провайдер блокує ping». Підтвердьте результат за допомогою TCP-монітора.
  • DNS. Виконує пошук запису (A, AAAA, MX, TXT тощо) через указаний вами resolver і може перевіряти отриману відповідь. Це допомагає рано виявити збій у registrar або DNS.
  • Push. Монітор із перевіркою зсередини назовні. Його опис наведено далі.

Моніторинг cron job за допомогою push-монітора (heartbeat)

Усі наведені вище монітори звертаються до вашого сервісу ззовні. Push-монітор працює навпаки: Uptime Kuma очікує сигнал, а ваш job викликає його й повідомляє: «Я виконався». Це єдиний надійний спосіб контролювати backup або cron: HTTP-перевірка знає лише, що URL відповідає, але тільки сам job знає, що він завершився.

Створіть монітор типу Push. Uptime Kuma згенерує унікальний URL, наприклад:

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

Установіть Heartbeat Interval відповідно до періодичності запуску 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="

Якщо job завершується з помилкою, set -e перериває виконання до curl. Якщо сервер недоступний, job також не запускається. У будь-якому разі heartbeat припиняється, і після завершення інтервалу з урахуванням повторних спроб Uptime Kuma переводить монітор у стан down та надсилає сповіщення. Вважайте цей push-токен секретом: маючи його, будь-хто може підробити коректний heartbeat.

Створіть публічну сторінку стану

Сторінка стану — це інтерфейс для клієнтів: він показує, які сервіси працюють, і їхню нещодавню історію, не відкриваючи панель моніторингу. Перейдіть до Status Pages, потім New Status Page, укажіть назву та slug (публічний шлях, наприклад /status/main), перетягніть потрібні монітори до груп на кшталт "Websites" і "APIs", додайте логотип і короткий опис, а потім натисніть Save. Також можна прив’язати сторінку до окремого домену, щоб status.example.com безпосередньо обслуговував її.

Зверніть увагу на два моменти: додавайте лише ті монітори, які готові зробити публічними, оскільки сторінка стану показує, що сервіс існує і чи працює він; панель моніторингу залишається захищеною вашим входом, тоді як сторінка стану навмисно є публічною і не потребує автентифікації.

Розмістіть його за reverse proxy із TLS і не забудьте про websockets

Для публічного екземпляра розмістіть reverse proxy перед контейнером, прив’язаним до loopback, щоб налаштувати TLS і hostname. Важлива деталь, на якій часто помиляються: інтерфейс Uptime Kuma працює як live-застосунок Socket.IO, тому proxy має оновлювати WebSocket-з’єднання. Якщо цього не зробити, сторінка завантажиться, але з’єднання не встановиться; dashboard залишиться у стані «Connecting...», live heartbeats не оновлюватимуться, а консоль браузера покаже WebSocket connection to 'wss://.../socket.io/...' failed.

Встановіть nginx і certbot, а потім створіть vhost, який проксуватиме запити на loopback-порт. Поки що розмістіть його на порту 80, а згодом дозвольте certbot додати TLS; challenge, timer поновлення та способи діагностики його помилок описано в видачі сертифікатів 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 дає такий самий результат за допомогою labels контейнерів і за замовчуванням передає оновлення WebSocket.

Не захищайте весь vhost за допомогою basic auth, оскільки це також заблокує публічну сторінку стану та endpoint /api/push. Залиште вбудований login Uptime Kuma, додайте моніторинг повторних невдалих входів за допомогою fail2ban, якщо сервіс доступний з Інтернету, а якщо dashboard не має бути публічним, приберіть proxy і підключайтеся до нього через VPN.

Моніторинг завершення дії сертифіката без помилок

HTTP(s)-монітор також може попереджати про завершення дії TLS-сертифіката: увімкніть Certificate Expiry Notification, і Uptime Kuma сповістить вас за вказану кількість днів до завершення його дії. Дві помилки призводять до неправильного результату. Використовуйте для моніторингу ім’я хоста, а не IP-адресу, інакше запит без SNI отримає сертифікат сервера за замовчуванням, а ви побачите Hostname/IP does not match certificate's altnames. Не вмикайте Ignore TLS/SSL Error для монітора, від якого очікуєте сповіщення про завершення дії сертифіката: цей параметр призначений для внутрішніх хостів із самопідписаними сертифікатами (unable to verify the first certificate, DEPTH_ZERO_SELF_SIGNED_CERT), але він повністю припиняє перевірку сертифіката в Uptime Kuma, зокрема перевірку строку його дії.

Резервні копії: усе зберігається в одному каталозі

Оскільки все зберігається в /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 додає до неї префікс із назви каталогу проєкту. Потім скопіюйте tar-архів на інший сервер або локальний комп’ютер, оскільки резервна копія на тому самому VPS є лише копією, а не повноцінною резервною копією. Відновлення виконується у зворотному порядку: зупиніть стек, розпакуйте архів у порожній том /app/data і запустіть його.

Оновлення

Оновлення виконуються через завантаження образу:

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

Новий контейнер під час першого запуску виконує міграцію бази даних; моніторте docker compose logs -f. Створіть резервну копію, описану вище, до завантаження образу та використовуйте тег у межах тієї самої основної версії: перехід із :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 під час перевірки email. Облікові дані SMTP неправильні, або провайдер вимагає пароль для застосунку, а ви вказали пароль облікового запису. Створіть пароль для застосунку та вставте його.

connect ETIMEDOUT або queryA ETIMEDOUT <host> під час перевірки email. Неправильний порт або провайдер блокує вихідний SMTP-трафік. Переконайтеся, що 465 або 587 відповідає параметру Secure/STARTTLS, і виконайте перевірку з хоста за допомогою nc -vz smtp.example.com 587. Багато провайдерів блокують вихідний 25, а деякі блокують порти для надсилання пошти, доки ви не попросите зняти блокування.

self signed certificate або unable to verify the first certificate під час перевірки email. Ваш SMTP-сервер надає сертифікат, якому Node не довіряє. Виправте сертифікат поштового сервера, а не обходьте цю перевірку.

Панель керування зависла на «Connecting...», у консолі відображається WebSocket connection ... failed. Reverse proxy не перемикає з’єднання на WebSocket. Додайте заголовки Upgrade і Connection "upgrade" у nginx або використайте proxy, який передає їх за замовчуванням, наприклад 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 розміщено у файловій системі без належного блокування файлів, зазвичай NFS. Перемістіть його до локального Docker volume і відновіть дані з резервної копії.

FAQ

Де слід запускати моніторинг доступності?

На іншому сервері, ніж ті, за якими він стежить, бажано в іншого провайдера або в іншому регіоні. Монітор має звертатися до них за іменем хоста через публічний інтернет, так само як це роблять користувачі. Якщо монітор працює на одному сервері з цільовими сервісами, збій цього сервера виведе з ладу і монітор. Перевантажений хост також може показувати статус «недоступний» для сервісів, які насправді працюють. Невеликий окремий VPS усуває обидві проблеми.

Як налаштувати сповіщення в Telegram або електронною поштою?

Додайте канал у розділі Settings then Notifications, а потім призначте його кожному монітору. Для Telegram створіть бота за допомогою @BotFather і отримайте chat.id з https://api.telegram.org/bot<token>/getUpdates. Для електронної пошти використовуйте 465 для SSL або 587 для STARTTLS, а якщо ваш провайдер використовує двофакторну автентифікацію — пароль застосунку. Натисніть Test і переконайтеся, що повідомлення надійшло, перш ніж покладатися на цей канал.

Чи може Uptime Kuma контролювати cron job або backup script?

Так. Для цього використовуйте монітор Push: Uptime Kuma надає URL, а ви curl його наприкінці скрипту, щоб сигнал надсилався лише після успішного виконання. Якщо завдання завершується з помилкою або сервер недоступний, сигнал не надходить, і після завершення заданого інтервалу ви отримуєте сповіщення. Це єдиний надійний спосіб перевірити, що заплановане завдання справді виконалося, оскільки зовнішня перевірка не бачить його внутрішній стан.

Uptime Kuma чи Zabbix: що слід використовувати?

Uptime Kuma за десять хвилин і майже без використання ресурсів відповідає на запитання: «Чи працює сервіс ззовні та чи отримав я сповіщення?». Він також надає status page. Uptime Kuma не збирає детальні метрики, як-от тренди CPU, пам’яті та дискового простору, і не підтримує порогові значення для всього парку серверів. Для цього повноцінний сервер моніторингу Zabbix є потужнішим інструментом на основі агентів, тому багато хто використовує обидва рішення. Ще не вирішили, що саме запускати? наш огляд того, що можна розмістити на власній інфраструктурі у 2026 році допоможе зрозуміти місце моніторингу в загальній схемі.

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