Сайт тормозил ночью, а утром снова работает нормально. Вы заходите на VPS, открываете top — процессор почти свободен, память есть. Что произошло: закончилась RAM, завис контейнер, резервное копирование перегрузило диск? Без истории нагрузки приходится гадать.
Beszel сохраняет показатели сервера и Docker-контейнеров, показывает их на графиках и отправляет уведомления. С его помощью можно увидеть, когда началась проблема и с чем она совпала. Ниже разберём установку Beszel на VPS, подключение Docker, уведомления в Telegram и проверку, что тревоги действительно доходят.
Примеры рассчитаны на Beszel 0.19.0 и Linux VPS с Docker Engine и плагином Docker Compose. Для уведомлений о состоянии контейнеров потребуется настроенный Docker healthcheck.
Что показывает Beszel и какие сбои он помогает заметить
Beszel состоит из двух частей. Hub — это веб-панель с историей показателей и настройками уведомлений. Agent работает на сервере, за которым нужно следить, и собирает его метрики. К одному Hub можно подключить несколько VPS.
| Что отслеживать | Для чего это нужно |
|---|---|
| CPU и load average | Найти периоды высокой нагрузки и сопоставить их с замедлением приложения. |
| Память и swap | Заметить рост потребления памяти и проверить, хватает ли ресурсов приложению. |
| Заполнение дисков и дисковый ввод-вывод | Увидеть, что заканчивается место или меняется характер работы с диском. |
| Docker-контейнеры | Сравнить потребление CPU, памяти и сети разными сервисами. |
| Доступность агента | Получить сигнал, если Hub потерял связь с наблюдаемым сервером. |
| Состояние Docker healthcheck | Узнать, что контейнер перешёл в unhealthy — его внутренняя проверка работоспособности не проходит. |
При этом доступный VPS может отдавать посетителям ошибку 502. А запущенный контейнер — содержать зависшее приложение. Поэтому для сайта стоит добавить внешнюю HTTP-проверку, например через Uptime Kuma: проверять адрес сайта, ожидаемый код ответа и, при необходимости, содержимое страницы.
Где разместить панель, чтобы получить сообщение о падении VPS
Для знакомства Hub и Agent можно установить на один сервер. Но если этот VPS выключится, вместе с приложением остановится и панель, которая должна отправить уведомление.
Для рабочего проекта лучше использовать такую схему:
- VPS с приложением: сайт, база данных, Docker-контейнеры и Beszel Agent.
- Отдельный сервер мониторинга: Beszel Hub, история метрик и отправка уведомлений.
- Внешняя проверка: контролирует доступность сайта и работу самого мониторинга.
Два VPS на одном физическом узле остаются зависимыми от его отказа. Размещение на разных узлах нужно уточнить у провайдера; другая площадка дополнительно уменьшает зависимость от общей сети.
Если для панели нужен отдельный сервер, можно подобрать VPS Hostyrex. При выборе смотрите на запас памяти для ОС и Docker, место под историю метрик и условия размещения относительно основного проекта.
Шаг 1. Установите Beszel Hub
Ниже панель открывается через SSH-туннель. Домен и настройка HTTPS для первого запуска не понадобятся. Hub будет получать метрики удалённого агента по встроенному SSH-протоколу Beszel.
На сервере мониторинга проверьте Docker:
sudo docker version
sudo docker compose version
Обе команды должны завершиться без ошибок подключения. Если Docker ещё не установлен, используйте инструкцию для своей ОС из официальной документации Docker. Не переустанавливайте работающий Docker на сервере с приложениями ради установки мониторинга.
Создайте каталог и файл конфигурации:
mkdir -p ~/beszel-hub
cd ~/beszel-hub
nano compose.yaml
Вставьте:
services:
beszel:
image: henrygd/beszel:0.19.0
container_name: beszel
restart: unless-stopped
ports:
- "127.0.0.1:8090:8090"
environment:
APP_URL: "http://localhost:8090"
volumes:
- ./beszel_data:/beszel_data
Запустите Hub:
sudo docker compose up -d
sudo docker compose ps
Контейнер должен находиться в состоянии Up. Каталог beszel_data хранит базу панели и её настройки: он должен сохраняться при обновлении контейнера.
Теперь на своём компьютере откройте отдельный терминал и выполните:
ssh -N -L 8090:127.0.0.1:8090 USER@MONITOR_IP
Замените USER на SSH-пользователя, MONITOR_IP — на адрес сервера мониторинга. Пока команда работает, откройте в браузере http://localhost:8090 и создайте учётную запись администратора.
Привязка 127.0.0.1 в Compose ограничивает доступ к порту панели самим сервером. Если нужен постоянный доступ по домену, настройте HTTPS через reverse proxy и измените APP_URL на внешний адрес панели.
Шаг 2. Подключите VPS с Docker-контейнерами
В панели нажмите Add System. Укажите понятное имя, например production-web, IP наблюдаемого VPS и порт 45876. Скопируйте публичный ключ KEY и токен TOKEN из предложенной конфигурации.
На VPS с приложением сначала посмотрите названия дисков:
lsblk -o NAME,KNAME,SIZE,TYPE,MOUNTPOINT
Найдите раздел, смонтированный в /, и запомните его KNAME. В примере ниже это vda1. На вашем сервере значение может быть другим, например sda1 или dm-0.
Создайте отдельный Compose-проект агента:
mkdir -p ~/beszel-agent
cd ~/beszel-agent
nano compose.yaml
services:
beszel-agent:
image: henrygd/beszel-agent:0.19.0
container_name: beszel-agent
restart: unless-stopped
network_mode: host
volumes:
- ./beszel_agent_data:/var/lib/beszel-agent
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
LISTEN: "45876"
KEY: "PUBLIC_KEY_FROM_HUB"
TOKEN: "TOKEN_FROM_HUB"
FILESYSTEM: "vda1"
Замените KEY и TOKEN значениями из своей панели, а FILESYSTEM — названием своего раздела. Для KEY нужен именно ключ Beszel, а не ключ, которым вы заходите на VPS.
В этой конфигурации HUB_URL не задан: соединение инициирует Hub и подключается к агенту на TCP-порт 45876. Это отдельный служебный порт Beszel, обычный SSH-доступ к серверу он не заменяет.
В межсетевом экране VPS разрешите входящие подключения к TCP 45876 только с адреса сервера мониторинга. Проверьте также сетевой firewall в панели провайдера. Если вы уже используете UFW с запретом входящих подключений по умолчанию, правило выглядит так:
sudo ufw allow from MONITOR_IP to any port 45876 proto tcp
Подставьте реальный адрес Hub и убедитесь, что другого правила, открывающего этот порт всем, нет. Включать или сбрасывать firewall для установки Beszel не требуется.
Запустите агент:
chmod 600 compose.yaml
sudo docker compose up -d
sudo docker compose logs --tail=50 beszel-agent
Завершите добавление системы в Hub. Дождитесь статуса Up и появления показателей. Проверьте, что в списке контейнеров видны ваши сервисы, а объём диска соответствует ожидаемому.
Монтирование docker.sock даёт агенту доступ к Docker API. Суффикс :ro не превращает этот API в интерфейс только для чтения. На серверах с повышенными требованиями к изоляции используйте Docker socket proxy с разрешением только необходимых запросов.
Как понять по графикам, почему тормозит сервер
Начинайте с времени жалобы или сбоя. Откройте этот промежуток в Beszel и сравните показатели сервера с графиками контейнеров. Текущее состояние утром не объясняет, что случилось ночью.
Выросла загрузка CPU
Посмотрите, какой контейнер увеличил потребление процессора. Затем сопоставьте время с обновлением приложения, заданиями по расписанию, обработкой очереди или наплывом запросов.
Для проверки текущего состояния на VPS:
sudo docker stats --no-stream
top
Если общая загрузка высокая, а контейнеры почти не используют CPU, ищите процесс вне Docker. Краткий пик во время сборки или бэкапа сам по себе не означает нехватку ресурсов. Важнее, совпадает ли он с задержками для пользователей.
Load average высокий, а CPU занят умеренно
Load average учитывает не только задачи, которым нужен процессор, но и задачи в непрерываемом ожидании, часто связанном с вводом-выводом. Поэтому load 4 на VPS с двумя vCPU нельзя автоматически переводить в «процессор загружен на 200%».
Проверьте дисковую нагрузку:
iostat -xz -y 1 10
Команда входит в пакет sysstat. Рост r_await и w_await означает увеличение времени выполнения операций чтения и записи с учётом очереди. Сопоставляйте его с задержками приложения и нагрузкой базы данных. Одно значение %util, даже близкое к 100%, не доказывает достижение предела современного SSD.
Память постепенно заканчивается
free -h
sudo docker stats --no-stream
В free смотрите на available: это оценка памяти, доступной приложениям без перехода к swap. Маленькое значение free ещё не означает проблему — Linux использует свободную RAM для кэша.
Если память одного контейнера растёт часами и заметно освобождается после его перезапуска, это повод проверить приложение на утечку или неограниченный кэш. Увеличение RAM даст запас времени, но не устранит причину.
Если контейнер завершился, проверьте, был ли он убит из-за нехватки памяти:
sudo docker inspect -f '{{.State.OOMKilled}}' CONTAINER_NAME
Замените CONTAINER_NAME его именем. Значение true подтверждает OOM-завершение для состояния, которое показывает Docker. При этом память могла закончиться в пределах лимита контейнера, даже если на самом VPS ещё оставался запас.
Заканчивается место на диске
df -h
df -i
sudo docker system df
Первая команда показывает свободное место, вторая — использование inode, третья — объём данных Docker. Если гигабайты ещё есть, но inode закончились, новые файлы всё равно не будут создаваться.
Сначала выясните, что растёт: журналы, база, резервные копии, образы или build cache. Не запускайте очистку Docker с удалением volumes вслепую: в них могут находиться данные приложения.
Как получать уведомления о проблемах внутри Docker-контейнера
В Beszel 0.19.0 есть тревога Container Health. Она реагирует на состояние unhealthy, которое сообщает Docker. Для этого у приложения должен быть healthcheck — команда, проверяющая его работоспособность внутри контейнера.
Например, если приложение отвечает на порту 8080 и имеет маршрут /health, добавьте в описание его сервиса:
healthcheck:
test: ["CMD", "curl", "-fsS", "--max-time", "4", "http://127.0.0.1:8080/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 60s
Этот блок нужно добавить внутрь существующего сервиса приложения, на одном уровне с image и environment. Адрес и порт замените своими. curl должен присутствовать в образе; иначе проверка будет падать из-за отсутствующей команды.
Сам маршрут /health тоже должен что-то проверять. Если он всегда возвращает 200, даже при потере соединения с базой, такой healthcheck не обнаружит отказ базы.
Примените изменение в каталоге приложения:
sudo docker compose up -d APP_SERVICE
APP_SERVICE — имя сервиса в Compose. Изменение конфигурации может пересоздать контейнер, поэтому для рабочего приложения выберите подходящее время.
Container Health не является универсальной проверкой «контейнер исчез или остановился». Его условие — именно unhealthy. Кроме того, обычная политика restart не перезапускает контейнер только из-за этого статуса. Beszel сообщает о проблеме; порядок восстановления приложения нужно продумать отдельно.
Как настроить уведомления Beszel в Telegram
Уведомления настраиваются в два этапа: сначала добавляется канал доставки, затем включаются тревоги нужного сервера. Если выполнить только первый этап, сообщения о сбоях не появятся.
- Создайте отдельного бота через @BotFather командой /newbot и сохраните его токен.
- Откройте чат с новым ботом и нажмите Start.
- Получите chat_id нужного чата.
- В Beszel откройте Settings → Notifications и добавьте адрес уведомлений.
- Отправьте тестовое сообщение из панели и убедитесь, что оно пришло в нужный чат.
Для нового бота, который ещё не подключён к другим приложениям, chat_id можно посмотреть через Telegram Bot API. После сообщения боту откройте адрес, подставив свой токен вместо BOT_TOKEN:
https://api.telegram.org/botBOT_TOKEN/getUpdates
В ответе найдите объект message → chat → id. Если result пустой, отправьте боту новое сообщение и повторите запрос. Для бота с настроенным webhook этот способ не работает; отдельный бот для мониторинга избавляет от конфликта с существующей интеграцией.
Адрес для Beszel:
telegram://BOT_TOKEN@telegram?chats=CHAT_ID
Для группового чата сохраните знак минус в chat_id, если он есть, и добавьте бота в группу. Токен и полный адрес уведомлений не публикуйте в скриншотах и тикетах. Сообщения Container Health могут включать фрагменты журналов приложения, поэтому выбирайте чат с подходящим составом участников.
Какие тревоги включить сначала
В таблице систем откройте настройки уведомлений нужного VPS через значок колокольчика. Для начала можно использовать следующие значения:
| Тревога | Стартовая настройка | Что проверить после сообщения |
|---|---|---|
| Status | Down, 2 минуты | Работают ли VPS, агент и соединение между агентом и Hub. |
| CPU Usage | 85%, окно 5 минут | Какой контейнер или процесс создаёт нагрузку и влияет ли она на ответы приложения. |
| Memory Usage | 90%, окно 5 минут | Available RAM, использование swap, лимиты контейнеров и признаки OOM. |
| Disk Usage | 80%, окно 5 минут | Сколько места осталось в гигабайтах и как быстро оно расходуется. |
| Container Health | Unhealthy, 2 минуты | Результат healthcheck и журналы проблемного контейнера. |
Это отправная точка, а не универсальные нормы. Для числовых метрик Beszel учитывает значения за выбранное окно; такие настройки не гарантируют обнаружение каждого короткого пика. Для диска порог подбирайте по времени, которое остаётся до заполнения: 20% свободного места на маленьком VPS могут закончиться быстро.
После изменения настроек снова откройте их и проверьте сохранённые значения. Если тревоги постоянно приходят во время штатного бэкапа, сначала сопоставьте их с реальным влиянием на проект, затем корректируйте порог или период.
Проверьте уведомления до настоящего сбоя
Тестовое сообщение подтверждает доставку в Telegram. Отдельно нужно проверить, что срабатывает сама тревога.
Проверка потери связи с сервером
На наблюдаемом VPS остановите только агент Beszel:
sudo docker stop beszel-agent
Дождитесь перехода системы в Down и уведомления с учётом заданной задержки. Приложения при этом продолжают работать. После проверки обязательно запустите агент обратно:
sudo docker start beszel-agent
Убедитесь, что метрики снова поступают и пришло сообщение о восстановлении. Если тревоги не было, проверьте настройки, но агент всё равно сначала верните в работу.
Проверка unhealthy без остановки приложения
Создайте отдельный тестовый контейнер на наблюдаемом VPS:
sudo docker run -d --name beszel-health-test \
--health-cmd='test -f /tmp/ok' \
--health-interval=10s \
--health-timeout=2s \
--health-retries=2 \
alpine:3 sh -c 'touch /tmp/ok; sleep 86400'
Дождитесь состояния healthy в Docker и появления контейнера в Beszel. Затем удалите файл, который проверяет healthcheck:
sudo docker exec beszel-health-test rm /tmp/ok
Контейнер перейдёт в unhealthy. После задержки Container Health должно прийти уведомление. Для восстановления создайте файл снова:
sudo docker exec beszel-health-test touch /tmp/ok
Дождитесь healthy и сообщения о восстановлении, затем удалите только тестовый контейнер:
sudo docker rm -f beszel-health-test
Почему Beszel не показывает данные или не присылает сообщения
Система остаётся Down
Проверьте логи на обоих серверах:
sudo docker logs --tail=100 beszel
Команда выше выполняется на Hub. На наблюдаемом VPS:
sudo docker logs --tail=100 beszel-agent
sudo ss -lntp 'sport = :45876'
Если агент слушает порт, проверьте IP системы в панели, публичный ключ и правила firewall. В нашей схеме Hub подключается к агенту, поэтому доступность самой веб-панели ничего не говорит о доступности TCP 45876.
Учитывайте и сеть Docker на сервере Hub: строгие правила пересылки пакетов могут блокировать исходящее соединение контейнера. Если такой доступ организовать неудобно, Beszel поддерживает обратную схему — агент подключается к Hub по WebSocket через HUB_URL. Для неё нужен доступный агенту адрес панели и корректно настроенный reverse proxy.
Метрики VPS есть, а контейнеров нет
Проверьте, что на наблюдаемом сервере работает Docker, в конфигурации агента смонтирован правильный docker.sock и в логах нет ошибок доступа. В rootless Docker путь к сокету отличается от /var/run/docker.sock.
Не исправляйте ошибку доступа командой chmod 777 для сокета. Сначала выясните, какой Docker используется и под каким пользователем работает агент.
Диск отображается неправильно
Сравните график с df -h и повторно проверьте FILESYSTEM. Если база или Docker хранят данные на отдельном диске, его нужно добавить в мониторинг отдельно. Для Docker-агента это делается монтированием каталога с нужного раздела в /extra-filesystems.
Контроль одного корневого раздела не предупредит о заполнении другого диска, на котором лежит база.
Тестовое сообщение приходит, а тревога — нет
Проверьте, включено ли правило для нужного сервера, не действует ли период тишины и действительно ли выполнено условие. Для Container Health нужен unhealthy: отсутствие healthcheck не считается ошибкой приложения.
Если не приходит даже тест, начните с токена, chat_id, запуска диалога с ботом и исходящего доступа Hub к api.telegram.org по HTTPS.
Кто сообщит, если остановится сам Beszel
В Beszel есть heartbeat: Hub регулярно отправляет запрос на внешний адрес. Если запросы перестают поступать, внешний сервис сообщает о проблеме.
Создайте проверку в сервисе, который умеет ожидать периодические сигналы, и добавьте её адрес в environment сервиса beszel:
HEARTBEAT_URL: "YOUR_EXTERNAL_HEARTBEAT_URL"
HEARTBEAT_INTERVAL: "60"
HEARTBEAT_METHOD: "GET"
Используйте GET, если его поддерживает выбранный сервис. Настройте на принимающей стороне ожидаемый интервал и допустимую задержку, затем примените изменения через docker compose up -d.
Получатель heartbeat должен работать независимо от VPS с Hub. Иначе при общем отказе остановятся обе стороны проверки.
Частые вопросы
Можно ли закрыть SSH после настройки?
Да. Туннель нужен только для доступа к веб-панели. Сбор метрик и отправка уведомлений продолжаются без открытого браузера. Для просмотра панели снова запустите туннель.
Можно ли поставить Hub и Agent на один VPS?
Да. В Docker для локального соединения документация Beszel рекомендует общий Unix-сокет. Адрес localhost внутри контейнера Hub не указывает автоматически на агент. Такая установка удобна для истории нагрузки, но требует независимой внешней проверки на случай отказа всего VPS.
Beszel заменяет Uptime Kuma?
Они решают разные задачи. Beszel помогает разобраться в состоянии сервера и контейнеров. Uptime Kuma может проверять доступность сайта снаружи. Для рабочего веб-проекта полезны оба вида контроля.
Нужно ли сразу увеличивать VPS после тревоги о нагрузке?
Сначала найдите причину. Если ресурсы регулярно заканчиваются при нормальной работе приложения, увеличение тарифа может помочь. Если память утекает, журнал бесконтрольно растёт или запрос к базе выполняется слишком долго, дополнительный ресурс лишь отложит следующий сбой.
Что сохранять перед обновлением Beszel?
Сохраните конфигурацию и резервную копию данных Hub из beszel_data. Копию файлов базы делайте при остановленном Hub либо используйте штатный механизм резервного копирования PocketBase. Храните резерв отдельно от сервера мониторинга.
После обновления проверьте подключение агентов, появление новых точек на графиках и доставку тестового уведомления. Рабочий мониторинг — это возможность получить сигнал вовремя и понять, какое действие требуется от вас.