Установка Uptime Kuma в Docker для мониторинга серверов
Разверните Uptime Kuma в Docker для отслеживания сайтов, портов и DNS. Настройте уведомления в Telegram и email. Важно запускать мониторинг на отдельном VPS для надежности.
Что вы создаете
Один небольшой контейнер, который отслеживает ваши серверы и веб-сайты извне и мгновенно уведомляет вас о сбоях в работе по электронной почте, через Telegram, Discord или вебхуки. Uptime Kuma представляет собой один процесс Node, использующий в данной конфигурации файл SQLite (версия 2 также может работать с встроенной или внешней MariaDB). Он потребляет от 256 до 512 МБ оперативной памяти и предоставляет панель мониторинга в реальном времени, графики истории и публичную страницу статуса. Установка выполняется с помощью Compose-файла из десяти строк. Самое важное — это то, где вы его запускаете и проверяли ли вы работу оповещений в тестовом режиме. Мониторинг, работоспособность которого не подтверждена, хуже полного отсутствия мониторинга: он создает ложное ощущение безопасности, не выполняя свою задачу.
Запускайте монитор там, где сбой не сможет его достать
Это решение определяет успех всей затеи, поэтому оно стоит на первом месте. Не запускайте Uptime Kuma на том же сервере, который он отслеживает. Если монитор находится на сервере, за которым он следит, то событие, которое вас интересует — выход сервера из строя или нехватка оперативной памяти — убьет и сам монитор. В итоге вы не получите никакого оповещения: тишина от неработающего монитора выглядит так же, как и сообщение «всё в порядке». Существует и более тонкая ловушка, даже когда сервер работает: монитор, направленный на localhost, делит ресурсы процессора с рабочей нагрузкой. В результате скачок нагрузки приводит к тому, что проверка монитора завершается по таймауту, а целевой сервис помечается как down (недоступен). Это ложная тревога, хотя реальные пользователи продолжают получать доступ к сервису.
Поэтому запускайте Uptime Kuma на другом VPS, отличном от того, который он отслеживает. Идеально, если это будет другой провайдер или регион. Монитор должен обращаться к вашим сервисам так же, как и пользователи: через публичный интернет, по имени хоста. Для этого достаточно дешевого инстанса, и один небольшой VPS для мониторинга может следить за всеми вашими серверами. Такое разделение критически важно для тяжелых приложений, которые вы хостите, поскольку, например, фотобиблиотека PhotoPrism или Immich может занимать процессор на долгое время во время индексации новых файлов. Монитор, использующий то же оборудование, будет сообщать о сбое сервиса, который на самом деле просто занят работой. Чтобы отслеживать состояние самого Kuma, добавьте push-сигнал heartbeat из cron-задачи на другом сервере.
Предварительные требования и выбор ресурсов
- Свежая установка Ubuntu 24.04 на VPS с 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-туннель, описанный ниже, а для доступа через собственный WireGuard VPN необходимо опубликовать порт на WireGuard-адресе сервера (например, 10.8.0.1:3001:3001), а не на 127.0.0.1.
Именованный том в /app/data. Здесь хранятся все данные Uptime Kuma: база данных SQLite, мониторы, настройки уведомлений и логотипы страниц статуса. Если потерять этот том, вы получите пустую панель администратора; это единственный объект, который необходимо резервировать.
Образ зафиксирован на мажорной версии, :2. Это текущая стабильная ветка; перед копированием проверьте Docker Hub на наличие более новой мажорной версии. Никогда не используйте «плавающие» теги вроде latest, которые проект не рекомендует. Переход на новую мажорную версию образа запускает миграцию базы данных, которую нужно выполнять осознанно, имея на руках свежую резервную копию, а не случайно при обычном обновлении.
Важное замечание: /app/data должен находиться на файловой системе с поддержкой POSIX-блокировок. Локальный том Docker подходит; при использовании 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. При чистой установке v2 на первом экране будет предложено выбрать базу данных; выберите SQLite. Она хранит все данные в томе /app/data, и именно этот вариант подразумевается в приведенных ниже инструкциях по резервному копированию и устранению неполадок. Далее появится форма настройки имени пользователя и пароля администратора; учетных данных по умолчанию не существует. Выберите надежный пароль: эта панель управления имеет доступ к внутренним адресам и токенам всех отслеживаемых вами систем. Забыли пароль? Сбросьте его на хосте, а не через браузер:
sudo docker compose exec uptime-kuma npm run reset-passwordСначала добавьте каналы уведомлений и протестируйте их
Настройте оповещения до добавления мониторов, чтобы вы могли привязать канал при создании каждого из них. Перейдите в Settings, затем Notifications, затем Setup Notification и используйте кнопку Test для каждого канала, чтобы убедиться, что сообщение доходит. Непроверенное уведомление — вторая по частоте причина, по которой настройка незаметно выходит из строя.
Email (SMTP). Укажите хост, порт, шифрование, имя пользователя, пароль, адрес отправителя (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, затем Integrations, Webhooks, New Webhook, скопируйте URL и вставьте его как уведомление типа Discord.
Generic webhook. Для всего остального, например, входящего вебхука Slack, пользовательской конечной точки или хука для домашней автоматизации, используйте тип Webhook. Он отправляет JSON-полезную нагрузку методом POST на указанный вами URL. Встроенная интеграция Apprise охватывает большинство из девяноста с лишним других сервисов из списка. Если вы не хотите, чтобы сторонние сервисы находились между сбоем и вашим телефоном, выберите встроенный тип ntfy и укажите его на собственный сервер ntfy, который отправляет 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-проверка посчитала бы корректным. Это также подходящая проверка для фронтенда, который взаимодействует с отдельным бэкендом, например, оболочка Halcyon для видеомагазина поверх Jellyfin, чья страница успешно возвращает200, даже если медиасервер за ней недоступен. - TCP Port. Прямое TCP-соединение с хостом и портом для сервисов, не использующих HTTP: SSH на 22, Postgres на 5432, SMTP-сервер на 25 или игровой сервер.
- Ping. ICMP echo: простой способ проверки доступности и задержки. Однако многие сети и облачные файрволы блокируют ICMP, поэтому красный статус монитора ping может означать как "хост недоступен", так и "провайдер блокирует ping"; подтверждайте результат с помощью TCP-монитора.
- DNS. Выполняет разрешение записи (A, AAAA, MX, TXT и т.д.) через указанный вами резолвер и может проверять полученный ответ, что позволяет оперативно обнаружить проблемы у регистратора или сбой DNS.
- Push. Монитор, работающий по принципу "изнутри наружу", будет рассмотрен далее.
Мониторинг cron-задачи с помощью 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 прекратится, и по истечении интервала с учетом попыток Uptime Kuma переведет монитор в состояние down и отправит уведомление. Относитесь к push-токену как к секретному ключу: любой, у кого он есть, может имитировать успешное выполнение задачи.
Создание публичной страницы статуса
Страница статуса — это интерфейс для пользователей, отображающий доступность сервисов и историю их работы без предоставления доступа к панели управления. Перейдите в Status Pages, затем New Status Page, укажите название и slug (публичный путь, например /status/main), перетащите нужные мониторы в группы, такие как "Websites" и "APIs", добавьте логотип и краткое описание, после чего нажмите Save. Вы также можете привязать страницу к собственному домену, чтобы status.example.com обслуживал её напрямую.
Два предостережения: добавляйте только те мониторы, которые вы готовы сделать публичными, так как страница статуса раскрывает факт существования сервиса и его текущее состояние; панель управления остаётся защищённой вашими учётными данными, в то время как страница статуса является намеренно публичной и не требует аутентификации.
Разместите сервис за обратным прокси с TLS и не забудьте про WebSocket
Для публичного экземпляра установите обратный прокси перед контейнером, привязанным к loopback, чтобы обеспечить TLS и работу по доменному имени. Деталь, на которой все спотыкаются: интерфейс Uptime Kuma — это приложение на базе Socket.IO, поэтому прокси должен поддерживать обновление соединения до WebSocket. Если этого не сделать, страница загрузится, но не установит связь: дашборд будет бесконечно показывать «Connecting...», показатели в реальном времени не обновятся, а в консоли браузера появится ошибка WebSocket connection to 'wss://.../socket.io/...' failed.
Установите nginx и certbot, затем создайте конфигурацию виртуального хоста, которая проксирует запросы на порт loopback. Настройте его на 80 порт, а после добавьте TLS с помощью certbot; процесс получения сертификатов, таймер обновления и возможные ошибки описаны в выпуске сертификатов 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 долгоживущих сокетов; certbot автоматически скопирует обе настройки в создаваемый блок 443 порта. Если вы уже используете несколько контейнеров за одним прокси, маршрутизация через Traefik с автоматическим TLS выполняет те же действия с помощью меток контейнеров и по умолчанию корректно обрабатывает обновление WebSocket.
Не устанавливайте basic auth на весь виртуальный хост, так как это заблокирует доступ к публичной странице статуса и эндпоинту /api/push. Используйте встроенную систему авторизации Uptime Kuma, добавьте fail2ban для отслеживания повторных неудачных попыток входа, если сервис доступен из Интернета. Если дашборд не должен быть публичным, откажитесь от прокси и подключайтесь через SSH-туннель или 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 добавляет к нему префикс в виде имени каталога проекта. Затем скопируйте архив за пределы сервера, так как копия, хранящаяся на том же VPS, не является полноценным резервным копированием. Восстановление выполняется в обратном порядке: остановите стек, распакуйте данные в пустой том /app/data и запустите стек снова.
Обновления
Обновления выполняются через загрузку образа (image pull):
cd /srv/uptime-kuma
sudo docker compose pull
sudo docker compose up -dНовый контейнер выполняет миграцию базы данных при первом запуске; следите за docker compose logs -f. Перед загрузкой образа создайте резервную копию, как описано выше, и оставайтесь в рамках одной мажорной версии: переход с :1 на :2 инициирует миграцию базы данных. В руководстве по миграции проекта указано, что прерывание процесса миграции требует восстановления из резервной копии и повторной попытки. Поэтому сначала создайте бэкап, а затем изучите руководство и примечания к релизу.
Режимы сбоев и соответствующие сообщения
Ложное состояние «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, или провайдер требует пароль приложения, а вы ввели пароль от учетной записи. Создайте пароль приложения и используйте его.
connect ETIMEDOUT или queryA ETIMEDOUT <host> при проверке электронной почты. Указан неверный порт или провайдер блокирует исходящий SMTP-трафик. Убедитесь, что 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 не выполняет upgrade соединения до WebSocket. Добавьте заголовки Upgrade и Connection "upgrade" в nginx или используйте прокси, который пересылает их по умолчанию, например Traefik или Caddy. HTML-страница загружается, так как это обычный HTTP GET; upgrade требуется только для активного сокета.
Монитор срока действия сертификата не отправляет предупреждения или работает некорректно. Либо установлена галочка 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-том и восстановите данные из резервной копии.
FAQ
Где следует запускать монитор доступности?
На сервере, отличном от тех, которые он отслеживает; желательно у другого провайдера или в другом регионе. Монитор должен обращаться к ним по имени хоста через публичный интернет, так же, как это делают ваши пользователи. Если монитор находится на одном сервере с целевыми сервисами, сбой, который выведет из строя сервер, остановит и сам монитор, а перегрузка хоста заставит его сообщать о «падении» сервисов, которые на самом деле работают нормально. Небольшой отдельный VPS позволяет избежать обеих проблем.
Как настроить оповещения в Telegram или по электронной почте?
Добавьте канал в разделе Settings (Настройки), затем Notifications (Уведомления), а после привяжите его к каждому монитору. Для Telegram создайте бота через @BotFather и получите chat.id из https://api.telegram.org/bot<token>/getUpdates; для электронной почты используйте 465 для SSL или 587 для STARTTLS с паролем приложения, если ваш провайдер использует двухфакторную аутентификацию. Нажмите Test (Тест) и убедитесь, что сообщение доставлено, прежде чем полагаться на этот канал связи.
Может ли Uptime Kuma отслеживать cron-задачи или скрипты резервного копирования?
Да, для этого предназначен монитор типа Push: Uptime Kuma предоставляет URL, который нужно curl в конце скрипта, чтобы запрос отправлялся только при успешном выполнении. Если задача завершится с ошибкой или сервер будет недоступен, сигнал не поступит, и вы получите оповещение по истечении заданного интервала. Это единственный надежный способ узнать, что запланированная задача действительно выполнилась, так как внешняя проверка не может заглянуть внутрь процесса.
Uptime Kuma или Zabbix: что выбрать?
Uptime Kuma отвечает на вопрос «работает ли сервис, доступен ли он снаружи и получил ли я оповещение» за десять минут и практически не потребляет ресурсов, дополнительно предоставляя страницу статуса. Она не собирает глубокие метрики, такие как тенденции использования CPU, памяти, диска или пороговые значения для всего парка серверов. Для этих целей существует полноценный сервер мониторинга Zabbix — более тяжелый инструмент, работающий на основе агентов; многие администраторы используют оба решения одновременно. Еще не решили, что именно развернуть? Наш обзор решений для self-hosting в 2026 году поможет определить место мониторинга в вашей инфраструктуре.