javascript

Хватит это терпеть: как я написал Telegram-бота для VPS, который не бесит

  • четверг, 23 октября 2025 г. в 00:00:06
https://habr.com/ru/articles/959122/

Всем привет! Меня, как и многих здесь, в какой-то момент достало. Достало логиниться по SSH, чтобы проверить htop. Достало запускать Termius на телефоне, чтобы сделать sudo reboot зависшему инстансу. Достало ставить тяжелые веб-панели, которые жрут ресурсы и открывают лишний порт, только ради того, чтобы посмотреть загрузку диска.

Я админю VPS. Мне нужен был инструмент, который:

  1. Мгновенно даёт сводку по системе.

  2. Работает легковесно, не отъедая ресурсы.

  3. Безопасен (никаких "запусти_от_рута_в_один_пайп").

  4. Надёжен, как швейцарские часы (и не спамит алертами).

  5. Умеет в администрирование этих кастомных приложений.

Я перепробовал готовые решения. Веб-панели — оверинжиниринг и дыра в безопасности. Готовые боты — либо заброшены, либо требуют root-доступ по дефолту, либо умеют только uptime.

Поэтому я сел и написал своего. Встречайте — tgbotvpscp.

Чем он лучше аналогов? Фокус на безопасности и надёжности

Я сразу решил, что не буду делать "ещё одного" бота. Я делал инструмент для себя, а я параноик в плане безопасности и ненавижу "глючные" скрипты.

1. Установка: Secure vs Root

Первое, что я продумал, — это установка. Мой deploy.sh — это не просто git pull. Это полноценный интерактивный установщик.

Он сразу предлагает выбор:

  • Secure (Рекомендуемый): Скрипт сам создаёт отдельного системного пользователя tgbot, выдаёт ему права только на нужные директории (/opt/tg-bot), настраивает sudoers только для перезапуска сервиса (для watchdog'а) и запускает всё в изолированном venv. Бот не имеет доступа к root.

  • Root (Для опытных): Если вам нужен полный фарш — reboot сервера, apt update и чтение всех логов прямо из бота — вы можете выбрать этот режим.

90% аналогов просто предлагают запустить всё от рута. Я считаю это порочной практикой.

2. Watchdog, который не плачет

Бот — это сервис. А сервисы падают. Поэтому у меня их два: tg-bot.service и tg-watchdog.service.

watchdog.py — это отдельный, максимально "тупой" и надёжный скрипт. Его задача — раз в 5 секунд проверять статус systemctl status tg-bot.service.

Ключевая фишка: он не просто шлёт алерт "всё упало". Он присылает админу одно сообщение и редактирует его, показывая жизненный цикл:

  • Сервис бота Недоступен 🔴 (и тут же даёт команду systemctl restart)

  • (если сервис стартует) Сервис бота Активируется 🟡

  • (когда сервис поднялся) Сервис бота Активен 🟢

Но главная моя боль — ложные срабатывания. Когда я сам перезапускаю бота (например, через deploy.sh или из админки самого бота), я не хочу получать паническое "ШЕФ, ВСЁ УПАЛО!".

Поэтому bot.py перед плановым рестартом создаёт restart_flag.txt. А watchdog.py, прежде чем бить тревогу, проверяет: "Ага, есть restart_flag.txt. Значит, рестарт плановый. Молчу."

Python

# Кусочек из watchdog.py
# ...
        else:
            logging.warning(f"Сервис бота '{BOT_SERVICE_NAME}' НЕАКТИВЕН. ...")
            
            # Проверка на плановый перезапуск (остается важной!)
            if os.path.exists(RESTART_FLAG_FILE):
                logging.info(f"Обнаружен плановый перезапуск. Alert-система не вмешивается.")
                return 

            # Это настоящий сбой
            if not bot_service_was_down: # Если это *первое* обнаружение сбоя
                state_to_report = "down"
                alert_type = "bot_service_down"
                message_text = f"Сервис бота <b>{BOT_SERVICE_NAME}</b> Недоступен 🔴"
# ...

Это простое, но гениальное решение сэкономило мне кучу нервов.

3. Real-time мониторинг логов через tail -f

Мне мало знать, что CPU 10%. Я хочу знать, кто зашёл на мой сервер прямо сейчас. Поэтому я встроил в bot.py (который крутится в asyncio) фоновые задачи, которые непрерывно слушают tail -f на критичные логи.

Бот асинхронно читает auth.log (или secure) и fail2ban.log. Как только там появляется новая строка Accepted ... for ... from ... или fail2ban.actions.* Ban ..., бот парсит её и мгновенно шлёт мне алерт с флагом страны, IP и юзером.

Это даёт невероятное чувство контроля. Я ещё не успел закрыть дверь, а уже знаю, что кто-то (или что-то) зашло на сервер. И, конечно, эти алерты можно тонко настроить в меню "🔔 Уведомления".

Python

# Кусочек из bot.py - запуск мониторов
# ...
        if ssh_log_file_to_monitor:
            task_logins = asyncio.create_task(reliable_tail_log_monitor(ssh_log_file_to_monitor, "logins", parse_ssh_log_line), name="LoginsMonitor")
            background_tasks.add(task_logins)
        else: logging.warning("Не найден лог SSH. Мониторинг SSH (logins) не запущен.")
            
        task_bans = asyncio.create_task(reliable_tail_log_monitor(f2b_log_file_to_monitor, "bans", parse_f2b_log_line), name="BansMonitor")
        background_tasks.add(task_bans)
# ...

4. Глубокая интеграция: Администрирование Core-сервисов

А вот и та самая "узкая задача". Многие из нас используют VPS для кастомных сетевых приложений, часто работающих на Docker. Они зависят от быстро обновляемых Core-библиотек, которые обеспечивают, скажем так, саму логику транспортировки данных. Обновлять их вручную — та ещё морока.

Бот автоматически определяет (по именам Docker-контейнеров) известные типы панелей управления (например, mar***n или a***ia) и обновляет их ядро до последнего стабильного релиза с GitHub в один клик. Код явно указывает на releases/latest/download, так что мы берём именно свежий стабильный билд, а не nightly-сборку.

Ну и вишенка на торте — генератор конфигураций доступа. Многим часто нужно поделиться доступом к своему сервису. Теперь вы можете просто скинуть боту JSON-файл с настройками. Бот на лету парсит его, генерирует конфигурационную ссылку нужного формата (да, ту самую, vless://...) и QR-код для клиента. Максимально удобно.

Что дальше? (Спойлер: Агент-Нода)

Этот бот решает мои текущие задачи. Но я уже смотрю в будущее. Сейчас это монолит: один бот на один сервер. Это не масштабируется.

Мой road-map выглядит так:

  1. Архитектура "Агент-Нода". Текущий бот станет "Агентом" (или "Центром управления"). На все VPS будут ставиться легковесные "Ноды" — минималистичные скрипты. Агент будет давать им команды, а ноды — рапортовать о состоянии. Это позволит управлять парком серверов из одного бота.

  2. Модульность. Я вынесу специфичные фичи (обновление Core-библиотек, Fail2Ban) в отдельные модули/плагины. Не нужен мониторинг F2B? Просто отключи модуль в конфиге. Хочешь добавить мониторинг Docker? Пишешь свой docker_plugin.py.

  3. Локализация (EN/RU). Проект уже на GitHub, и я вижу к нему интерес. Первое, что нужно сделать — полная английская локализация.

И это только начало.

Заключение

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

Проект полностью open-source (GPL-3.0), написан на современном Python и aiogram 3.x. Если у вас, как и у меня, "чесались руки" сделать удобную админку для своих серверов — добро пожаловать.

Заходите на GitHub, ставьте звезды, предлагайте фичи, форкайте. Давайте сделаем управление VPS удобным, без костылей и дыр в безопасности.

Спасибо за внимание!