Uptime Kuma у Docker: моніторинг доступності
Запустіть Uptime Kuma у Docker на окремому VPS: перевіряйте сайти, порти, DNS і cron, надсилайте сповіщення через email або Telegram та публікуйте status page.
Що ви створюєте
Один невеликий контейнер, який зовні перевіряє доступність інших серверів і вебсайтів та одразу повідомляє, якщо один із них перестає відповідати. Сповіщення можна надсилати електронною поштою, через Telegram, Discord або webhook. Uptime Kuma — це один процес Node, який у цій конфігурації використовує файл SQLite. Версія v2 також може працювати з вбудованою або зовнішньою MariaDB. Застосунок стабільно працює з 256-512 MB RAM і надає інтерактивну панель, графіки історії та публічну сторінку стану. Інсталяція виконується за допомогою десяти рядків у 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, після чого нових повідомлень немає. У цьому файлі навмисно задано три параметри.
127.0.0.1:3001:3001, а не 3001:3001. Docker публікує порти за допомогою правил DNAT, які обробляються до того, як ufw побачить пакет. Тому звичайний 3001:3001 відкриває вашу панель керування в публічному інтернеті незалежно від правил ufw. Фільтрувати такий трафік можна лише правилами у власному ланцюжку Docker DOCKER-USER. Прив’язка до loopback залишає сервіс приватним і відкриває назовні лише reverse proxy. Це також означає, що лише сам хост може підключатися до 3001. Для приватного екземпляра без проксі використовуйте SSH-тунель, наведений нижче. Щоб підключатися до нього через власний self-hosted WireGuard VPN, потрібно опублікувати порт на WireGuard-адресі сервера, наприклад 10.8.0.1:3001:3001, а не на 127.0.0.1.
Іменований volume у /app/data. У ньому зберігаються всі дані, які пам’ятає Uptime Kuma: база даних SQLite, монітори, параметри сповіщень і логотипи сторінок стану. Якщо втратити цей volume, ви отримаєте порожній екран адміністратора. Це єдине, що потрібно резервно копіювати.
Образ закріплено на major tag :2. Це поточна стабільна гілка. Перед копіюванням перевірте Docker Hub на наявність новішої major-версії. Не використовуйте рухомий tag на кшталт latest, оскільки проєкт виводить його з використання. Перехід на нову major-версію цього образу запускає міграцію бази даних. Її потрібно виконувати навмисно, маючи свіжу резервну копію, а не випадково під час звичайного pull.
Є одна важлива умова: /app/data має розташовуватися у файловій системі з підтримкою POSIX file locks. Локальний Docker volume підходить. У NFS база даних SQLite пошкоджується, і ви отримуєте SQLITE_BUSY та database disk image is malformed. Тому не використовуйте мережеву файлову систему.
Перший запуск: створення облікового запису адміністратора
Відкрийте instance через проксі за адресою https://status.example.com або через SSH-тунель: виконайте ssh -L 3001:127.0.0.1:3001 user@your-vps і відкрийте http://localhost:3001. Під час першого встановлення v2 перший екран запропонує вибрати базу даних; виберіть SQLite. Усі дані зберігатимуться у volume /app/data, і саме на це розраховані наведені нижче кроки резервного копіювання та усунення несправностей. Далі відкриється форма налаштування імені користувача та пароля адміністратора. Облікових даних за замовчуванням немає. Виберіть надійний пароль: ця панель бачить внутрішні адреси й токени всіх об’єктів, які ви моніторите. Якщо пізніше забудете пароль, скиньте його на хості, а не в браузері:
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. Деякі сервери також підтримують STARTTLS на 25, тому використовуйте порт і режим, зазначені у документації вашого провайдера. Для Gmail і більшості провайдерів із двофакторною автентифікацією потрібно створити app password. Звичайний пароль облікового запису спричиняє Error: Invalid login: 535-5.7.8 Username and Password not accepted.
Telegram. Надішліть повідомлення @BotFather і виконайте /newbot, щоб скопіювати токен бота. Щоб отримати 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 для home automation, тип Webhook надсилає JSON payload на вказаний вами URL методом POST. Вбудована інтеграція Apprise підтримує більшість інших приблизно дев’яноста сервісів у списку. Якщо ви не хочете, щоб між інцидентом і телефоном був сторонній сервіс, виберіть вбудований тип ntfy і вкажіть сервер ntfy, яким ви керуєте самостійно. Він надсилатиме повідомлення на ваш телефон через канал, яким ви повністю контролюєте.
Додавайте монітори по одному типу
Натисніть 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-перевірка вважає нормальною. Це також правильний варіант для браузерного фронтенду, який взаємодіє з окремим бекендом, наприклад оболонки Halcyon для відеомагазину поверх Jellyfin, коли оболонка сторінки без проблем повертає200, але сервер медіа за нею недоступний. - TCP Port. Просте TCP-підключення до хоста й порту для сервісів, які не використовують HTTP: SSH на 22, Postgres на 5432, SMTP-сервер на 25, ігровий сервер.
- Ping. ICMP echo-запит для недорогої перевірки доступності та затримки. Але багато мереж і хмарних 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 і врахуйте WebSocket
Для публічного екземпляра розмістіть reverse proxy перед контейнером, прив’язаним до loopback, щоб налаштувати TLS і hostname. Ключова деталь, на якій часто припускаються помилки: інтерфейс Uptime Kuma працює як інтерактивний застосунок Socket.IO, тому proxy має оновлювати WebSocket-з’єднання. Якщо цього не зробити, сторінка завантажиться, але підключення не відбудеться; dashboard залишиться у стані «Connecting...», актуальні heartbeat не оновлюватимуться, а консоль браузера покаже WebSocket connection to 'wss://.../socket.io/...' failed.
Встановіть nginx і certbot, а потім створіть vhost, який проксуватиме запити на 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 дає такий самий результат за допомогою labels контейнерів і за замовчуванням пересилає оновлення WebSocket.
Не захищайте весь vhost за допомогою basic auth, оскільки це також заблокує публічну status page і endpoint /api/push. Залиште вбудований login Uptime Kuma, додайте fail2ban для моніторингу повторних невдалих входів, якщо сервіс доступний з Інтернету. Якщо dashboard не має бути публічним, приберіть proxy та підключайтеся через SSH tunnel або через VPN, опублікувавши порт на VPN-адресі, а не на loopback.
Моніторинг завершення дії сертифіката без помилок
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. Створіть резервну копію, описану вище, до отримання образу та не виходьте за межі одного major-тега: перехід із :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 році допоможе зрозуміти місце моніторингу в загальній схемі.