Установка Uptime Kuma в Docker для мониторинга серверов
Разверните Uptime Kuma в Docker для отслеживания доступности сайтов и портов. Узнайте, почему монитор нельзя запускать на одном сервере с целевым хостом и как настроить уведомления.
Что вы создаете
Один компактный контейнер, который отслеживает ваши серверы и веб-сайты извне и мгновенно уведомляет вас о недоступности любого из них по электронной почте, через Telegram, Discord или с помощью webhook. Uptime Kuma представляет собой один процесс Node, использующий базу данных SQLite, поэтому он стабильно работает при 256-512 MB оперативной памяти и предоставляет панель мониторинга в реальном времени, графики истории и публичную страницу статуса. Установка выполняется с помощью файла Compose из десяти строк; самое важное — это место запуска и проверка работоспособности оповещений в тестовом режиме. Монитор, который вы не проверили на возможность отправки уведомлений, хуже полного отсутствия мониторинга: он создает ложное ощущение защищенности, фактически ничего не контролируя.
Запускайте монитор там, где сбой его не затронет
Это решение определяет успех всей системы, поэтому оно стоит на первом месте. Не запускайте Uptime Kuma на том же сервере, который она отслеживает. Если монитор находится на сервере, за которым он следит, то событие, которое вас интересует — выход сервера из строя или нехватка памяти — убьет и сам монитор. В итоге вы не получите никаких уведомлений: тишина от неработающего монитора выглядит так же, как сообщение «все в порядке». Существует и более тонкая ловушка, пока сервер еще жив: монитор, направленный на localhost, делит процессор с рабочей нагрузкой. В результате скачок нагрузки приводит к таймауту проверки и переводит статус цели в down. Это ложная тревога, хотя реальные пользователи продолжают получать доступ к сервису.
Поэтому запускайте Uptime Kuma на другом VPS, отличном от того, который она отслеживает. В идеале используйте другого провайдера или другой регион. Монитор должен обращаться к вашим сервисам так же, как это делают пользователи: через публичный интернет по имени хоста. Достаточно дешевого инстанса, и один небольшой VPS для мониторинга может следить за всеми вашими серверами. Такое разделение критически важно для тяжелых приложений, которые вы хостите. Например, фотобиблиотека PhotoPrism или Immich может загружать процессор на 100% в течение нескольких часов во время индексации новых файлов, и монитор, работающий на том же оборудовании, будет ошибочно сообщать о недоступности сервиса, который просто занят работой. Чтобы отслеживать работоспособность самой Uptime Kuma, добавьте push-сигнал heartbeat из cron-задачи на другом сервере.
Предварительные требования и выбор ресурсов
- Свежий VPS с Ubuntu 24.04, на котором установлены Docker Engine и плагин Compose v2. Используйте официальный репозиторий 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.
The Compose file
Put this in /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:Bring it up and watch the first boot:
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-kumaA correct start logs Listening on 3001 and goes quiet. Three things in that file are deliberate.
127.0.0.1:3001:3001, not 3001:3001. Docker publishes ports with DNAT rules evaluated before ufw ever sees the packet, so a bare 3001:3001 puts your dashboard on the public internet regardless of your firewall. Binding to loopback keeps it private, with only the reverse proxy exposed; a private instance can skip the proxy and reach 3001 over a self-hosted WireGuard VPN instead.
A named volume at /app/data. Everything Uptime Kuma remembers, the SQLite database, your monitors, notification settings and status-page logos, lives there. Lose it and you start from an empty admin screen; it is the only thing you must back up.
The image is pinned to a major tag, :2. That is the current stable line; check Docker Hub for the newest major before copying it, and never track a moving tag like latest, which the project deprecates. A major-version jump on this image is a one-way database migration you want to trigger deliberately, not stumble into on a routine pull.
One caveat: /app/data must sit on a filesystem with POSIX file locks. A local Docker volume is fine; on NFS the SQLite database corrupts and you get SQLITE_BUSY and database disk image is malformed, so never use a network share.
Первый запуск: создание учетной записи администратора
Перейдите к экземпляру через ваш прокси по адресу 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, затем Notifications, затем Setup Notification и используйте кнопку Test для каждого канала, чтобы убедиться, что сообщение доходит. Непроверенное уведомление — вторая по частоте причина, по которой настройка незаметно перестает работать.
Email (SMTP). Укажите хост, порт, шифрование, имя пользователя, пароль, адрес отправителя (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 и скопируйте токен бота. Чтобы узнать свой 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, пользовательский эндпоинт или хук для системы домашней автоматизации, тип 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"; подтверждайте результат с помощью 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, поэтому прокси должен поддерживать обновление (upgrade) WebSocket-соединения. Если этого не сделать, страница загрузится, но соединение не установится: дашборд будет бесконечно показывать «Connecting...», показатели в реальном времени не обновятся, а в консоли браузера появится ошибка WebSocket connection to 'wss://.../socket.io/...' failed.
Установите nginx и certbot, затем создайте конфигурацию виртуального хоста, которая проксирует запросы на локальный порт. Пока настройте работу на 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 для защиты от перебора паролей, если сервис доступен из Интернета. Если публичный доступ к дашборду не требуется, откажитесь от прокси и подключайтесь к сервису через 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 добавляет к нему префикс в виде имени каталога проекта. Затем скопируйте архив за пределы сервера, так как копия, хранящаяся на том же VPS, не является полноценным резервным копированием. Восстановление выполняется в обратном порядке: остановите стек, распакуйте данные в пустой том /app/data и запустите стек снова.
Обновления
Обновление выполняется через загрузку нового образа:
cd /srv/uptime-kuma
sudo docker compose pull
sudo docker compose up -dНовый контейнер выполняет миграцию базы данных при первом запуске; отслеживайте docker compose logs -f. Перед загрузкой образа создайте резервную копию, как описано выше, и оставайтесь в рамках одной мажорной версии: переход с :1 на :2 является необратимой миграцией, поэтому сначала выполните резервное копирование и изучите примечания к выпуску (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 или провайдер требует пароль приложения, а вы ввели основной пароль аккаунта. Создайте пароль приложения и используйте его.
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; обновление требуется только для активного сокета.
Монитор срока действия сертификата не выдает предупреждений или работает некорректно. Либо установлена галочка 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 году поможет определить место мониторинга в вашей инфраструктуре.