Telegram-бот на Python через systemd

systemd · надёжность · логи

Самый простой и предсказуемый способ держать Telegram-бота на VDS — это обычный Python-процесс под systemd. Никаких лишних слоёв, никаких «менеджеров процессов ради менеджеров». Бот падает — systemd его поднимает. Сервер перезагрузился — бот стартует сам. Логи смотрятся одной командой. Для большинства ботов этого более чем достаточно.

Структура проекта

Я обычно кладу ботов в /opt/ под отдельным пользователем. Пример:

/opt/mybot/
├── venv/
├── bot.py
├── requirements.txt
├── .env
└── data/          # если нужно хранить состояние

Создаём пользователя без лишних прав:

useradd --system --create-home --home-dir /opt/mybot --shell /usr/sbin/nologin botuser
# или если нужен shell для отладки — обычный пользователь

Виртуальное окружение и зависимости:

cd /opt/mybot
python3 -m venv venv
./venv/bin/pip install -r requirements.txt

Токен и другие секреты — только в .env, файл с правами 600 и владельцем botuser. В коде читаем через python-dotenv или просто os.environ.

systemd-юнит

Файл /etc/systemd/system/mybot.service:

[Unit]
Description=My Telegram Bot
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=botuser
Group=botuser
WorkingDirectory=/opt/mybot
EnvironmentFile=/opt/mybot/.env
ExecStart=/opt/mybot/venv/bin/python bot.py
Restart=always
RestartSec=5
# Ограничения по ресурсам (по желанию)
# MemoryMax=512M
# CPUQuota=50%

[Install]
WantedBy=multi-user.target

Применяем:

systemctl daemon-reload
systemctl enable --now mybot
systemctl status mybot

Restart=always и RestartSec=5 — ключевые строки. Бот может упасть из-за временной ошибки сети, необработанного исключения или обновления библиотеки — systemd поднимет его снова. Пять секунд задержки не дают бесконечному циклу рестартов при серьёзной проблеме.

Логи

Всё, что бот пишет в stdout/stderr, попадает в journald:

journalctl -u mybot -f          # в реальном времени
journalctl -u mybot -n 100     # последние 100 строк
journalctl -u mybot --since "1 hour ago"

Этого хватает в 90% случаев. Если нужно ротировать отдельно или отправлять логи куда-то ещё — можно настроить rsyslog или просто писать в файл из самого бота, но для начала journald удобнее: он уже ротирует, не занимает место бесконечно и доступен без дополнительных настроек.

Полезный приём: в коде бота логировать через стандартный logging с уровнем INFO для обычных событий и ERROR для проблем. Тогда в journalctl легко фильтровать.

Обновление бота

Обычный процесс:

systemctl stop mybot
# обновить код (git pull или скопировать файлы)
./venv/bin/pip install -r requirements.txt   # если зависимости изменились
systemctl start mybot
journalctl -u mybot -f   # убедиться, что стартовал нормально

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

Типичные проблемы

Бот не стартует, в статусе failed. Смотрим journalctl -u mybot -n 50. Чаще всего: неправильный путь к python, нет прав на .env, отсутствует зависимость, синтаксическая ошибка в коде, или токен не подхватился.

Работает, но после ребута не поднимается. Забыли enable. Проверка: systemctl is-enabled mybot.

Падает каждые несколько минут. Либо необработанное исключение в основном цикле (нужно ловить и логировать), либо внешний сервис (API Telegram, база) временно недоступен и код не умеет ждать. В таких случаях полезно добавить retry с экспоненциальной задержкой внутри бота, а не надеяться только на RestartSec.

Съедает слишком много памяти. Смотрим systemctl status mybot или ps. Можно добавить MemoryMax= в юнит — тогда systemd убьёт процесс при превышении, и он перезапустится. Это лучше, чем когда бот тихо раздувается и кладёт весь сервер.

Нужно несколько ботов. Просто несколько юнитов. Можно сделать шаблон ([email protected]) и запускать mybot@bot1, mybot@bot2, но для 2–3 ботов отдельные файлы проще и понятнее.

Почему не PM2 / Docker / supervisor

PM2 хорош для Node.js, особенно когда процессов много и хочется веб-интерфейс. Для одного-двух Python-ботов он добавляет лишний слой. Docker имеет смысл, если вы уже всё контейнеризируете и хотите одинаковое окружение везде. Для простого бота на VDS контейнер часто избыточен: дольше собирать, сложнее смотреть логи, больше места. Supervisor — рабочий вариант, но systemd уже есть в системе и решает ту же задачу.

Я использую Docker для ботов только когда там сложные зависимости (например, нужна конкретная версия системной библиотеки) или когда бот — часть большего compose-стека. В остальных случаях — systemd.

Дополнительные практики

Отдельный пользователь без sudo — обязательно. Не запускайте бота от root.

Если бот ходит во внешние API — имейте в виду rate limits и возможные блокировки. Логируйте неудачные запросы.

Для ботов с состоянием (диалоги, очереди) лучше сразу думать, где оно хранится: файл, SQLite, Redis, Postgres. Файл проще всего, но при рестарте можно потерять данные в памяти — поэтому важное состояние пишите на диск или в базу сразу.

Мониторинг: достаточно следить, что юнит в состоянии active. Можно добавить простой healthcheck или просто смотреть journalctl по крону и слать уведомление, если бот слишком часто рестартится.

В итоге схема получается очень скучная и надёжная: код в /opt, venv, .env, systemd-юнит с Restart=always, логи через journalctl. Именно поэтому она работает годами без присмотра. Если нужно поднять бота по этой схеме под конкретный проект — это стандартная задача.

Работа с длинными задачами и очередями

Если бот делает что-то долгое (генерация отчёта, обработка файла, запрос к медленному API), не блокируйте основной цикл обработки апдейтов. Иначе Telegram начнёт считать бота зависшим, а пользователь не получит даже промежуточного ответа. Простые варианты: threading, asyncio (если используете aiogram или python-telegram-bot в async-режиме), или вынос тяжёлой работы в отдельную очередь (Redis + RQ, Celery, или даже просто отдельный процесс).

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

Безопасность и секреты

Токен бота — это полный доступ к нему. Храните его только в .env или в systemd EnvironmentFile с правильными правами. Не коммитьте в git, не пишите в логи. Если токен утёк — сразу перевыпускайте через BotFather.

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

Регулярно обновляйте зависимости. Уязвимости в библиотеках для работы с Telegram случаются нечасто, но обновления библиотек и самого Python лучше не откладывать на годы.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

После настройки проверяю автозапуск, доступность логов одной командой и наличие короткой заметки с основными командами. Бэкапы, если используются, должны восстанавливаться. Обновления делаю при возможности проверить результат. Минимальная рабочая конфигурация обычно достаточна для небольших задач и проще в поддержке.

← Все статьи