Uptime Kuma: самый простой self-hosted мониторинг доступности за 10 минут
За восемь лет мы поставили Zabbix десяткам инфраструктур — от корпоративного Active Directory до кластеров 1С. Это правильный инструмент для сотен хостов с SNMP, агентами и триггерами. Но когда директору компании из 20-40 рабочих мест нужно ровно одно: узнать о падении сайта, 1С-сервера или почты раньше, чем позвонит клиент, — Zabbix избыточен. Для таких задач мы последние полтора года ставим Uptime Kuma: один Docker-контейнер, веб-интерфейс с зелёным/красным светофором и push-уведомление в Telegram за считанные секунды после сбоя. Ниже — наша методология внедрения: от docker compose up до порогов ложных срабатываний и публичной страницы статуса для клиента.
Когда Uptime Kuma, а когда полноценный Zabbix
Первый вопрос, который я задаю себе на объекте клиента: сколько узлов реально нужно наблюдать и нужны ли метрики внутри системы (загрузка CPU, очереди, логи) или достаточно бинарного ответа «жив/не жив». Если у клиента серверная с доменом, десятками рабочих станций, SNMP-принтерами и требованием триггеров с зависимостями между узлами — это зона Zabbix (мы разворачивали его в проектах Genesis и Zabbix для zb-genesis, там счёт узлов идёт на сотни). Если задача — приглядеть за 5-15 внешними точками: сайт-визитка, сервер 1С, почтовый релей, VPN-шлюз, роутер — Zabbix превращается в артиллерию по воробьям: агенты, шаблоны, отдельная СУБД, недели настройки.
Есть и промежуточный сценарий, с которым мы регулярно встречаемся у клиентов с 30-50 рабочими местами: инфраструктура сама по себе несложная (один сервер 1С, один почтовый релей, десяток рабочих станций), но директор хочет видеть не просто «жив/не жив», а ещё и историю по времени — сколько минут в этом месяце сайт был недоступен, когда именно упал 1С-сервер в прошлый четверг. Именно эту историю Uptime Kuma хранит по умолчанию: каждый heartbeat пишется в базу, из него строится график аптайма за 24 часа, 30 дней и год, а также процент доступности — без отдельной настройки графиков и дашбордов, как это потребовалось бы в Zabbix или Grafana.
Uptime Kuma (проект louislam/uptime-kuma на GitHub, актуальная стабильная линейка 2.x, образ louislam/uptime-kuma:2) — это Node.js-приложение с встроенной SQLite-базой (в 2.x опционально можно подключить внешнюю БД, но для 90% наших клиентов достаточно дефолтной SQLite прямо в volume контейнера). Никаких агентов на стороне клиента ставить не нужно: сервер мониторинга сам стучится наружу по HTTP, TCP, ICMP, DNS. Разворачивается один контейнер — и через 10 минут на экране уже видно светофор.
Мы также сознательно не используем внешние SaaS вроде UptimeRobot или Pingdom для клиентских инфраструктур: данные о графике доступности внутренних сервисов (в том числе 1С-серверов, которые светятся наружу только портом кластера) уходят на сторонний сервис, бесплатный тариф режет интервал проверки до 5 минут, а платный — это ежемесячный счёт за то, что можно развернуть один раз на своей же VPS рядом с сайтом.
Ещё один довод в пользу self-hosted решения именно для нас как аутсорсера, который ведёт не одного клиента, а десятки объектов одновременно: внутри одного инстанса мониторы группируются через Tags — цветные метки с произвольным именем и значением, например «Клиент: ТСЖ Рогожский Вал» или «Клиент: Дентекс». Это даёт быстрый визуальный фильтр на дашборде, когда в одной панели живёт полсотни точек проверки по нескольким объектам, а не превращает экран в нечитаемую простыню одинаковых зелёных кружков. В Settings → Monitor History отдельно настраивается срок хранения истории heartbeat в днях — на объектах с коротким интервалом проверки (20-30 секунд) мы сознательно урезаем retention, чтобы файл SQLite не разрастался бесконтрольно на диске VPS за месяцы работы.
Установка: Docker Compose и первый запуск
Требования по факту эксплуатации у нас на нескольких объектах: Docker Engine 24+, Docker Compose plugin v2, и по ресурсам — 1 vCPU и 512 МБ RAM с большим запасом (по нашей практике простаивающий контейнер с 10-15 мониторами держит потребление около 150-250 МБ RAM — это оценка по эксплуатации, не официальная цифра проекта). Диск — от 1 ГБ, дальше растёт от глубины хранения истории heartbeat.
Разворачиваем в отдельной директории через compose-файл, который мы держим единым для всех клиентских инсталляций:
mkdir -p /opt/uptime-kuma && cd /opt/uptime-kuma
cat > compose.yaml << 'EOF'
services:
uptime-kuma:
image: louislam/uptime-kuma:2
container_name: uptime-kuma
volumes:
- ./data:/app/data
ports:
- "127.0.0.1:3001:3001"
restart: always
EOF
docker compose up -dПорт 3001 мы намеренно публикуем только на localhost (127.0.0.1:3001:3001), а наружу отдаём через реверс-прокси с TLS — об этом отдельно ниже. Так панель управления мониторингом никогда не торчит в интернет голым HTTP.
При первом заходе на http://127.0.0.1:3001 (через SSH-туннель или уже настроенный прокси) мастер настройки просит создать учётную запись администратора — логин и пароль задаём сразу по нашей парольной политике для клиентских панелей, и сразу включаем двухфакторную аутентификацию (TOTP) в Settings → Security → Two Factor Authentication: панель мониторинга — это и карта того, что у клиента вообще есть в инфраструктуре, отдавать доступ к ней без 2FA мы считаем недопустимым.
Флаг restart: always в compose-файле мы ставим намеренно, а не unless-stopped: сервер мониторинга должен пережить перезагрузку хоста и сам подняться без нашего участия, иначе получится абсурдная ситуация — упал не сайт клиента, а сам инструмент, который должен был об этом сообщить. По той же причине после первого запуска мы сразу проверяем, что контейнер действительно поднимается после reboot хоста, а не полагаемся на предположение о работе restart-политики Docker.
Мониторы: какие типы закрывают задачу клиента до 50 РМ
Uptime Kuma из коробки поддерживает больше десятка типов мониторов (HTTP(s), TCP Port, Ping, DNS, Docker Container, Push, gRPC Keyword, а также готовые проверки для MySQL/PostgreSQL/MongoDB/Redis/RabbitMQ и других сервисов). На практике для клиента-юрлица до 50 рабочих мест нам хватает пяти типов из таблицы ниже.
| Тип монитора | Что проверяет | Наш типовой пример у клиента | Ключевой параметр |
|---|---|---|---|
| HTTP(s) | код ответа сайта, опционально — наличие ключевого слова в теле ответа | сайт-визитка/лендинг клиента, интернет-магазин | поле Keyword + флаг Upside Down для инвертирования логики |
| TCP Port | открыт ли и отвечает ли TCP-порт | сервер 1С:Предприятие — порт менеджера кластера 1541, порт агента 1540, диапазон рабочих процессов 1560-1591 (по регламенту ИТС); почтовый релей — 25/465/587/993 | Hostname + Port |
| Ping (ICMP) | базовая доступность узла на сетевом уровне | WAN-интерфейс шлюза клиента (Keenetic/pfSense), внутренний контроллер домена | Packet Size, интервал |
| DNS | резолвится ли домен в ожидаемую A/AAAA-запись | контроль после миграции DNS (у нас были инциденты именно с забытым TTL при переезде почты) | Resolver Server + Expected Value |
| Push (пассивный, dead man's switch) | сервис сам обязан «стукнуться» по URL Kuma за интервал — если тишина, монитор уходит в DOWN | ночной cron-бэкап клиента, регламентный скрипт выгрузки в банк | уникальный Push URL, который скрипт дергает curl'ом в конце своей работы |
Отдельно стоит монитор Docker Container — он актуален, когда у клиента часть сервисов уже в контейнерах (например, тот же почтовый стек или внутренний портал): Kuma подключается к /var/run/docker.sock и следит за статусом контейнера напрямую, без сетевого запроса.
Ещё одна вещь, которую мы включаем на каждом HTTP(s)-мониторе с HTTPS — это встроенная проверка срока действия TLS-сертификата (галка «уведомить о скором истечении сертификата» с полем количества дней до окончания). Она не заменяет отдельный монитор, а работает как побочный эффект обычной HTTPS-проверки: при приближении даты окончания сертификата (мы ставим порог за 14-20 дней) в тот же Telegram-канал уходит отдельное предупреждение. Для нас это подстраховка на случай, если автопродление Let's Encrypt на хосте клиента почему-то не сработало — узнаём об этом заранее, а не когда браузер посетителя показывает предупреждение о недоверенном сертификате.
Пороги: как не устроить клиенту 200 сообщений при обрыве интернета
Самая частая ошибка при внедрении Uptime Kuma — оставить настройки по умолчанию и получить шквал уведомлений на каждый секундный сетевой всплеск. У каждого монитора есть три ключевых параметра, и мы их всегда пересчитываем под конкретный сервис: Heartbeat Interval (частота проверки), Retries (сколько неудачных проверок подряд нужно, прежде чем монитор реально уйдёт в статус DOWN и полетит алерт), и Heartbeat Retry Interval (интервал между повторными попытками во время серии неудач, отдельный от обычного интервала).
Логика состояний простая: PENDING (первая неудача, алерт ещё не шлётся) → серия повторов с интервалом Retry Interval → DOWN только после исчерпания Retries. То есть при Retries=3 и Retry Interval=20 c монитор подтвердит падение и пришлёт нотификацию только через 40-60 секунд устойчивой недоступности — одиночный сетевой хвост в это окно не попадёт.
| Сервис | Heartbeat Interval | Retries | Retry Interval | Комментарий (наша практика) |
|---|---|---|---|---|
| Сайт/лендинг (HTTP) | 60 c | 3 | 20 c | жёстче для интернет-магазина: 30 c / 2 / 15 c |
| Сервер 1С (TCP 1541) | 60 c | 2 | 30 c | ночью можно ослаблять через Maintenance-окно на время регламентных работ |
| Почтовый релей (TCP 587/993) | 120 c | 2 | 30 c | реже, почта переживает короткие всплески без вреда для бизнеса |
| WAN-шлюз клиента (Ping) | 20 c | 5 | 10 c | ICMP на «домашних» роутерах шумит чаще всего, отсюда больше повторов |
| Push cron-бэкапа | интервал = периодичности задачи + запас 20-30% | 1 | — | если скрипт не стукнулся вовремя — это уже реальная проблема, повторы тут не нужны |
Дополнительно включаем в настройках уведомления опцию «важные события» (шлёт алерт только на смену статуса UP↔DOWN, а не на каждый heartbeat), а на время плановых работ заводим окно в разделе Maintenance — на это время монитор помечается как «под обслуживанием» и не генерирует ложный инцидент в истории и на публичной странице статуса.
Хотите такой же светофор доступности для своей инфраструктуры?
Мы развернём Uptime Kuma под ваши сервисы — сайт, 1С-сервер, почту, VPN-шлюз — настроим пороги под реальное поведение вашего канала связи, подключим Telegram-алерты и отдадим публичную страницу статуса. Итог: о падении вы узнаете раньше клиента, а не после его звонка.
Уведомления: Telegram — основной канал, e-mail — резервный
Telegram мы выбираем основным каналом по той же причине, по которой у нас на нём уже висят алерты Zabbix, Veeam-монитора и marzban: сообщение долетает за 1-2 секунды, не требует проверки почты, работает с телефона в любой точке. Настройка занимает пять минут: создаём бота через @BotFather командой /newbot, получаем токен вида 123456789:AA..., добавляем бота в нужный чат (или используем личный чат с ним), узнаём chat_id через https://api.telegram.org/bot<TOKEN>/getUpdates после любого сообщения в чат.
Дальше в Uptime Kuma: Settings → Notifications → Setup Notification, тип Telegram, вставляем Bot Token и Chat ID, жмём Test — бот должен прислать тестовое сообщение немедленно. Обязательно включаем флаг Default enabled, чтобы все новые мониторы автоматически получали этот канал — иначе рано или поздно кто-то заведёт монитор без уведомлений и падение сервиса заметят только по звонку клиента.
Второй канал — email через SMTP-нотификацию (у нас чаще всего через собственный релей mail24x7.net), настраивается как резерв: если Telegram недоступен (блокировка API, разрыв VPN) — критичное падение всё равно долетит на почту ответственного инженера. На каждый монитор можно повесить несколько нотификаций одновременно — мы обычно вешаем Telegram+email на «боевые» сервисы (сайт, 1С, почта) и только Telegram — на второстепенные (Ping шлюза).
Из полусотни встроенных провайдеров нотификаций отдельно выделю тип Webhook — универсальный POST-запрос с JSON-телом при смене статуса монитора. Мы используем его точечно там, где падение сервиса у клиента должно не просто прилететь алертом, а сразу породить задачу на инженера: webhook уходит на небольшой промежуточный обработчик, который через REST API создаёт задачу в Планфиксе на дежурного — по той же схеме, по которой у нас уже работает мост между СБИС и Планфиксом для налоговых требований. Ручной перенос алерта из Telegram в таск-трекер — это лишняя минута реакции и человеческий фактор «увидел, но забыл завести задачу»; прямой webhook эту минуту убирает.
Публичная Status Page для клиента
Отдельная фишка Uptime Kuma, которую мы обязательно предлагаем клиенту — публичная страница статуса (Settings → Status Pages → New Status Page). Она собирается из тех же мониторов, но группируется в логические блоки (например, «Сайт», «1С-сервер», «Почта») и публикуется по собственному короткому адресу вида /status/<slug>. Клиент получает ссылку — и вместо звонка «у меня что, всё упало?» сам смотрит на страницу: зелёная плашка — работает, красная — авария с указанием, с какого момента.
Для страницы можно привязать собственный домен клиента через CNAME (например, status.клиент.ru), отключить бейдж «Powered by Uptime Kuma» в настройках отображения, и вручную (или через API) публиковать инцидент-баннер сверху страницы на время плановых работ — это снимает часть входящих обращений в поддержку именно в момент, когда мы сами что-то обновляем на стороне клиента.
Практический эффект мы видим сразу после внедрения: количество звонков «а у вас там всё работает?» в момент любых наших регламентных работ падает почти до нуля — достаточно один раз отправить клиенту ссылку на страницу статуса и приучить открывать её вместо звонка. Отдельно рекомендуем директору компании-клиента держать эту ссылку в закладках телефона — так решение «звонить в поддержку или подождать» принимается за пять секунд, а не в состоянии раздражения от недоступного сайта.
Публикация через реверс-прокси, TLS и защита входа
Панель управления мы никогда не выставляем в интернет напрямую портом 3001 — контейнер публикует его только на 127.0.0.1, а наружу отдаёт уже связка с TLS-терминацией. На хостах с HestiaCP используем встроенный Nginx-темплейт с проксированием на localhost:3001 и Let's Encrypt; на отдельных VPS — легковесный Caddy с автоматическим TLS:
status.client-domain.ru {
reverse_proxy 127.0.0.1:3001
encode gzip
}После публикации закрываем два момента безопасности: во-первых, 2FA (TOTP) для админ-аккаунта, о которой уже писал выше, во-вторых — если у клиента есть статичный внешний IP офиса, ограничиваем доступ к /dashboard и /manage-status-page правилом на файрволе (pfSense alias или Keenetic ACL), оставляя публичный Status Page открытым для всех, а панель управления — только для наших IP и IP клиента. Для внешних интеграций (если клиенту нужно вытянуть статус в свою CRM) в Uptime Kuma есть API Key (Settings → API Keys) — используем его вместо логина/пароля для любых скриптовых обращений.
Отдельно проговариваю с клиентом один нюанс: реверс-прокси перед Uptime Kuma должен поддерживать проксирование WebSocket-соединений (интерфейс общается с бэкендом через Socket.IO, обновляя статусы мониторов в реальном времени без перезагрузки страницы). В Caddy это работает из коробки без дополнительных директив, а вот в классическом Nginx-конфиге нужно явно прописать заголовки Upgrade и Connection в блоке location — если этого не сделать, страница будет открываться, но статусы перестанут обновляться «вживую» и потребуют ручного F5.
Эксплуатация: бэкапы, обновления, ресурсы
Вся конфигурация и история живут в SQLite-файле внутри смонтированного volume ./data — бэкап сводится к копированию этой директории (мы включаем её в общий регламент бэкапа VPS, который уже описан в наших скиллах по инфраструктуре). Отдельно в интерфейсе есть Settings → Backup — экспорт конфигурации мониторов и нотификаций в JSON (без истории heartbeat), удобно как быстрый снапшот перед экспериментами с настройками.
Обновление контейнера — стандартный docker-паттерн:
cd /opt/uptime-kuma
docker compose pull
docker compose up -d --force-recreateПеред крупными обновлениями (переход между мажорными версиями линейки) сверяемся с разделом «How to Update» вики проекта на предмет breaking changes — были случаи, когда менялась схема хранения нотификаций. На нескольких объектах мы дополнительно держим отдельный тестовый инстанс на localhost перед обновлением боевого — поднимаем ту же версию образа на копии volume, проверяем, что все мониторы и нотификации пережили миграцию схемы, и только после этого катим обновление на прод; на объектах с 3-5 мониторами это, конечно, избыточно, но там, где Uptime Kuma уже разросся до полусотни точек проверки по нескольким клиентам — оправдано. По ресурсам на объекте с 10-20 мониторами и интервалами 30-120 секунд контейнер стабильно укладывается в 1 vCPU и до 300 МБ RAM (оценка по нашей эксплуатации, не гарантия вендора) — то есть спокойно живёт на минимальном тарифе VPS рядом с сайтом клиента, отдельного сервера под мониторинг заводить не нужно.
Наш чек-лист внедрения на объекте клиента за 10 минут
- Разворачиваем
compose.yamlс образом louislam/uptime-kuma:2, volume./data:/app/data, порт только на127.0.0.1:3001, поднимаемdocker compose up -d. - Создаём администратора, сразу включаем 2FA (TOTP).
- Заводим 3-5 базовых мониторов: HTTP(s) на сайт, TCP на 1С-сервер и почтовый релей, Ping на WAN шлюза.
- Выставляем пороги под тип сервиса (таблица из раздела про Heartbeat/Retries) — не оставляем дефолт.
- Подключаем Telegram-нотификацию через @BotFather, ставим её по умолчанию для новых мониторов, добавляем email-нотификацию как резерв.
- Публикуем через реверс-прокси с TLS, закрываем панель управления по IP, оставляем Status Page открытой.
- Собираем публичную Status Page с группировкой по сервисам, отдаём ссылку клиенту.
- Заводим первый Push-монитор на ключевой ночной cron (бэкап/выгрузка) как dead man's switch.
- Фиксируем регламент бэкапа volume
./dataи план обновлений раз в квартал.
Именно в таком порядке мы это делаем на объектах клиентов — от первой команды в терминале до рабочей ссылки на Status Page в почте директора укладывается в 10-15 минут, дальше время уходит только на подбор порогов под конкретную нервозность канала связи клиента.
Частые вопросы
- Uptime Kuma заменяет Zabbix или полноценный SIEM?
- Нет. Uptime Kuma решает узкую задачу — бинарный контроль доступности внешних и сетевых точек (HTTP, TCP, Ping, DNS). Для контроля метрик внутри системы (загрузка CPU, очереди, журналы событий, SNMP-парк из сотен устройств) мы по-прежнему ставим Zabbix — это разные весовые категории инструмента, и подменять один другим не стоит.
- Сколько это стоит и есть ли ограничения по числу мониторов?
- Сам проект Uptime Kuma — бесплатный self-hosted софт с открытым кодом, без лимита на число мониторов или пользователей. Стоимость для клиента — это по факту стоимость небольшой VPS (можно разместить рядом с уже существующим сайтом) и время на настройку порогов под конкретную инфраструктуру.
- А кто мониторит сам сервер с Uptime Kuma, если он упадёт?
- Разумный вопрос «quis custodiet ipsos custodes». Мы либо ставим сторонний бесплатный внешний пинг-чек с низкой частотой именно на сам сервер мониторинга (простая HTTP-проверка от внешнего сервиса раз в 5-10 минут), либо, если у клиента уже используется Zabbix для инфраструктуры, заводим туда один узел — сам хост с Uptime Kuma. Дублировать полноценный мониторинг мониторинга избыточно, но одна внешняя проверка «жив ли хост» обязательна.
- Можно ли мониторить 1С-сервер, если у него нет белого IP?
- Да, если сервер Uptime Kuma и 1С-сервер находятся в одной сети или связаны VPN/site-to-site туннелем (мы так делаем в нескольких инфраструктурах с pfSense и Keenetic) — TCP-монитор обращается по внутреннему IP и порту кластера 1С без необходимости выставлять что-либо в интернет.
- Подходит ли Uptime Kuma для мониторинга сразу нескольких клиентов из одной панели?
- Технически — да, через теги (Tags) и отдельные Status Page на каждого клиента внутри одного инстанса. На практике для аутсорсинговой модели мы всё же разносим клиентов по отдельным легковесным инстансам (или минимум по отдельным Status Page с ограничением доступа) — это упрощает выдачу отдельного логина клиенту без риска, что он увидит чужую инфраструктуру.