VPN·HUB·CRACK Мониторинг ресурсов: увидеть, что нода умирает, до падения · VPN HUB CRACK
Все статьи
Инфраструктура и защита PRO

Мониторинг ресурсов: увидеть, что нода умирает, до падения

Обновлено 11 августа 2026 Проверено

Мониторинг ресурсов: увидеть, что нода умирает, до падения

В Мониторинге и бэкапе мы подняли Uptime Kuma. Она отвечает ровно на один вопрос: отвечает порт или нет. Вопрос важный, но у него есть неприятное свойство: ответ меняется на «нет» одновременно с тем, как клиенты начинают писать в поддержку.

Практически всё, что убивает ноду, убивает её медленно: диск заполняется неделю, память утекает сутки, сосед по гипервизору душит процессор каждый вечер. Всё это время монитор аптайма светится зелёным, потому что порт-то отвечает.

Дальше разберём второй слой: мониторинг ресурсов. Он не заменяет Kuma, он показывает то, чего она не видит в принципе.

📖 Незнакомые слова? Все термины простыми словами есть в Словаре терминов.

Что тихо убивает VPN-ноду

Что происходит Что видит клиент Метрика, которая предупредила бы заранее
Диск забит логами Xray Соединения рвутся, no space left on device Диск, %: растёт линейно днями
Утечка памяти на панели (Postgres + Remnawave) Панель отваливается, OOM-killer убивает контейнер RAM + swap: ползут часами
Оверселл гипервизора (сосед ест CPU) «Вечером тормозит, ночью норм» Load average и steal: пик по расписанию
Выжран месячный трафик Хостер режет канал до 10 Мбит или выставляет счёт Пропускная способность: видно на второй неделе
Кончились inode Место вроде есть, а записать нельзя Диск / inode
Перегрев дедика Троттлинг, скорость просела вдвое Температура

Общее у всех строк: сигнал был за дни до аварии. Его просто некому было увидеть.

Kuma и Beszel решают разные задачи

Соблазн заменить одно другим, и это ошибка. Они смотрят с разных сторон:

  • Uptime Kuma смотрит снаружи. Проверяет то, что видит клиент: маршрут, доступность, сертификат. Только она заметит, что нода жива и здорова, но ТСПУ прикрыл ваш 443, сервер при этом идеален по всем метрикам.
  • Beszel смотрит изнутри. Показывает запас прочности: сколько осталось диска, памяти, процессора. Только он заметит, что до аварии три дня.

Нужны оба. Kuma отвечает «работает ли сервис», Beszel отвечает «надолго ли его хватит».

Почему Beszel

Инструментов много, но большинство несоразмерны задаче «десять нод и панель»:

Чем неудобно для нашей задачи
Zabbix Мощно и правильно, но это отдельный проект на неделю и сервер под него
Prometheus + node_exporter + Grafana Три компонента, свои конфиги и язык запросов ради шести графиков
Netdata Отлично на одном хосте; сведение десяти хостов и история тянут за собой облако

Beszel это минимум, который закрывает 90% потребности: хаб (веб-панель) + лёгкий агент на каждом сервере. История, статистика по Docker-контейнерам отдельно от хоста, алерты в Telegram из коробки. Лицензия MIT, актуальная версия на момент написания: v0.18.7. Образы крошечные: хаб ~12 МБ, агент ~9 МБ в сжатом виде.

Отдельно ценно для нас: он разделяет хост и контейнеры. Видно не просто «память кончается», а «память ест конкретно remnawave-db».

Шаг 1. Хаб

⚠️ Хаб не ставим на ноду. Если он живёт на сервере, за которым следит, то в момент реальной аварии некому будет прислать алерт. Панельный сервер или отдельный дешёвый VPS.

mkdir -p /opt/beszel && cd /opt/beszel
cat > docker-compose.yml <<'EOF'
services:
  beszel:
    image: henrygd/beszel
    container_name: beszel
    restart: unless-stopped
    ports:
      - "127.0.0.1:8090:8090"   # только локально, наружу — через nginx
    volumes:
      - ./beszel_data:/beszel_data
EOF
docker compose up -d

Официальный пример публикует порт как 8090:8090, то есть на все интерфейсы. Мы намеренно вешаем на 127.0.0.1: панель мониторинга со списком всех ваших серверов не должна торчать в интернет голой.

Наружу пускаем через reverse-proxy с сертификатом:

server {
    listen 443 ssl;
    server_name beszel.example.com;
    location / {
        proxy_pass http://127.0.0.1:8090;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;   # обязательно: агенты ходят по WebSocket
        proxy_set_header Connection "upgrade";
    }
}

certbot --nginx -d beszel.example.com, и открываем адрес, создаём аккаунт администратора. Первый, кто откроет свежий хаб, станет админом: не оставляйте его без сертификата и без пароля даже на час.

Шаг 2. Агенты и ни одного открытого порта

Здесь ключевой для нас момент. У агента два режима связи, и выбор между ними это вопрос не удобства, а маскировки ноды.

  • SSH-режим (входящий). Хаб сам стучится к агенту на порт 45876. Значит, на ноде появляется ещё один открытый порт с опознаваемым баннером, на сервере, который мы старательно прячем за self-steal и CDN.
  • WebSocket-режим (исходящий). Агент сам открывает соединение к хабу (HUB_URL + TOKEN). Входящий порт не нужен вообще.

Для VPN-нод берём только второй.

В хабе Settings → Tokens даёт универсальный токен, либо Add System открывает диалог с готовой командой с вашим ключом и токеном. Проще всего скопировать её оттуда; ниже: что означают флаги.

Бинарём (рекомендую для нод):

curl -sL https://get.beszel.dev -o /tmp/install-agent.sh && chmod +x /tmp/install-agent.sh
/tmp/install-agent.sh -t <ТОКЕН> -url https://beszel.example.com --auto-update

Флаги: -t = токен, -url = адрес хаба, -k = публичный ключ (если ставите не по универсальному токену), -p = порт прослушивания, --auto-update = ежедневное автообновление, --china-mirrors = зеркала, если GitHub недоступен с сервера.

Скрипт заведёт пользователя beszel и сервис beszel-agent.service.

Закрываем порт прослушивания. Даже в WebSocket-режиме агент поднимает локальный слушатель на 45876. На скрытой ноде он не нужен снаружи:

ufw deny 45876/tcp        # либо nft/iptables — как у вас заведено
ss -tlnp | grep 45876      # убедиться, что не виден с внешнего интерфейса

Заодно ограничим агенту аппетит, правим /etc/systemd/system/beszel-agent.service, секция [Service]:

MemoryMax=128M

systemctl daemon-reload && systemctl restart beszel-agent.

Docker-вариант (удобно там, где уже всё в контейнерах, например, на панельном сервере):

services:
  beszel-agent:
    image: henrygd/beszel-agent
    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: 127.0.0.1:45876
      HUB_URL: "https://beszel.example.com"
      TOKEN: "<токен>"
      KEY: "<публичный ключ>"

🔒 Проброс docker.sock это то, что даёт статистику по каждому контейнеру отдельно. Он смонтирован :ro, но помните: доступ к сокету Docker равносилен root на хосте. Ставьте агента только из официального образа и только на свои серверы.

Шаг 3. Пороги именно под VPN-ноду

Дефолтные пороги «CPU > 80%» бесполезны: у ноды под нагрузкой это норма. Что реально стоит сторожить:

Метрика Порог Почему так Что делать по алерту
Диск > 75% Главный убийца нод. Растёт медленно: 75% даёт дни на реакцию Разобрать логи (ниже)
Память > 90%, держится 10 мин На панели: Postgres; на ноде: утечка Xray Проверить, кто ест; перезапуск как временная мера
Load average > числа ядер, держится 15 мин Отличает реальную нагрузку от всплеска Если растёт без роста клиентов: подозрение на оверселл
Пропускная способность ~70% месячного лимита хостера Чтобы узнать до счёта, а не после См. Лимиты трафика
Температура > 75 °C Только для дедиков Троттлинг → жалобы на скорость
Статус агент пропал Дублирует Kuma другим маршрутом Проверить, жив ли сервер вообще

Ставьте пороги с выдержкой по времени, иначе телефон будет звенеть на каждом всплеске, вы отключите уведомления, и весь мониторинг превратится в тыкву.

Диск: почти всегда это логи

Девять из десяти переполнений на ноде это логи Xray внутри Docker. Найти:

du -sh /var/lib/docker/containers/*/*.log | sort -h | tail
du -sh /var/lib/docker/volumes/* | sort -h | tail

Лечится не удалением, а ограничением на будущее. В docker-compose.yml ноды каждому сервису:

    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

docker compose up -d, и файл лога физически не сможет вырасти больше 30 МБ. Плюс убавьте многословность самого Xray: в конфиге ноды уровень логирования выше warning на проде не нужен, а access-лог на живой ноде это ещё и лишние данные о клиентах, которые вам незачем хранить.

Шаг 4. Алерты в Telegram

Settings → Notifications, добавить URL в формате shoutrrr:

telegram://<BOT_TOKEN>@telegram?chats=<CHAT_ID>
  • BOT_TOKEN: от @BotFather, без префикса bot.
  • CHAT_ID: ваш id или id группы (у групп он с минусом). Для группы бота нужно сначала в неё добавить.

Дальше алерты включаются по каждой системе в таблице на главной. Доступные типы: CPU, память, диск, пропускная способность, температура, load average и статус.

Заведите под это отдельную группу, а не личку. Когда нод десяток, алерты в личке смешиваются с рабочей перепиской и теряются, проверено многими.

Чего Beszel не покажет

Честно про границы, чтобы не было ложного спокойствия:

  • Блокировку. Нода идеальна по всем метрикам, а из России не открывается. Это ловит Kuma снаружи и живая проверка с РФ-адреса.
  • Качество маршрута до клиента. Потери и джиттер по пути не про ресурсы сервера.
  • Что творится у хостера. Steal time намекнёт на оверселл, но подтверждать диагноз придётся отдельно.
  • Прикладные ошибки. Xray может отдавать ошибки при нулевой нагрузке, смотрите логи и Диагностику «не работает».

Чек-лист

  1. Хаб не на ноде, порт на 127.0.0.1, наружу через nginx с сертификатом.
  2. Админ-аккаунт создан сразу, пароль сильный.
  3. Агенты в WebSocket-режиме, порт 45876 закрыт фаерволом.
  4. MemoryMax агенту прописан.
  5. Пороги: диск 75%, память 90% с выдержкой, LA по числу ядер, трафик 70% лимита.
  6. Логи Docker ограничены max-size на всех нодах, не только на проблемной.
  7. Алерты в отдельную группу Telegram, проверены тестовым срабатыванием.
  8. Uptime Kuma оставлена работать: она про другое.

Полчаса на настройку. Окупается первым же алертом «диск 75%» в среду днём вместо «всё легло» в субботу ночью.