TelegramPythonДеплой

Где разместить Telegram-бота на Python: варианты хостинга и деплой

6 мин чтения

Telegram-бот на Python готов и работает локально: запущен python bot.py, отвечает на сообщения. Но локальный запуск живёт ровно до закрытия терминала или выключения ноутбука. Чтобы бот отвечал круглосуточно, его нужно разместить там, где процесс работает постоянно. Разберём, какие есть варианты хостинга, как подготовить бот к деплою и как развернуть его, ничего не потеряв.

Long-polling или webhook

Это первое решение, и от него зависит, какой хостинг подойдёт.

Long-polling — бот сам постоянно опрашивает Telegram методом getUpdates. Ему не нужен публичный домен, SSL или открытый входящий порт — достаточно исходящего соединения в интернет. Это самый простой режим, и для большинства ботов его более чем достаточно.

Webhook — наоборот: Telegram сам присылает обновления на HTTPS-эндпоинт бота. Нужны публичный домен, валидный SSL-сертификат и открытый порт (Telegram принимает только 443, 80, 88 или 8443). Webhook эффективнее под высокой нагрузкой и удобнее, когда нужно несколько инстансов за балансировщиком.

Практический вывод: начинать стоит с long-polling, а переходить на webhook — когда нагрузка реально этого требует. Важная деталь: одновременно работает либо одно, либо другое. Если установлен webhook, getUpdates вернёт ошибку, а два параллельных long-polling-процесса с одним токеном дадут 409 Conflict: terminated by other getUpdates request.

Куда размещать: три варианта

VPS (Beget, Timeweb, Hetzner). Полный контроль над сервером. Минус — всё придётся настроить и обслуживать самому: установить Python, поднять supervisor для автозапуска, развернуть базу, настроить бэкапы и SSL для webhook. Дёшево по деньгам, дорого по времени.

Managed-платформа (PaaS). Деплой по git push: платформа сама собирает проект, держит процесс запущенным и перезапускает его после сбоя, рядом — managed-база. Меньше ручной работы ценой меньшей гибкости в настройке ОС.

Serverless (облачные функции). Для ботов обычно не подходит. Long-polling требует постоянно живущего процесса, которого в serverless нет; webhook-функции возможны, но страдают от cold start и лимитов времени выполнения. Для бота, который должен быть онлайн всегда, это неудобная модель.

Подготовка бота к деплою

Эти шаги нужны при любом хостинге.

Зафиксировать зависимости. Список библиотек должен ехать вместе с кодом:

pip freeze > requirements.txt

Вынести токен и секреты из кода. Токен бота нельзя держать в исходниках и тем более коммитить в Git — его читают из переменных окружения:

import os

TOKEN = os.environ["BOT_TOKEN"]  # явная ошибка, если переменная не задана

Локально переменные удобно держать в файле .env, добавленном в .gitignore. На сервере те же переменные задаются в окружении процесса. Если токен всё же попал в публичный репозиторий — его нужно немедленно отозвать через @BotFather и выпустить новый.

Не хранить состояние в памяти. Данные пользователей, FSM-состояния и очереди при хранении в обычных переменных Python теряются при каждом рестарте и редеплое. Под состояние нужна внешняя база — Postgres или Redis. О резервных копиях такой базы — в отдельной статье про бэкапы PostgreSQL.

Деплой на VPS

Кратко: забрать код, собрать окружение, запустить под супервизором.

git clone https://github.com/user/mybot.git /opt/mybot
cd /opt/mybot
python -m venv .venv
.venv/bin/pip install -r requirements.txt

Запускать python bot.py руками нельзя — процесс умрёт с закрытием сессии. Нужен супервизор, который держит бот запущенным и поднимает после сбоя и перезагрузки. Минимальный systemd-сервис с загрузкой переменных из файла:

[Service]
WorkingDirectory=/opt/mybot
ExecStart=/opt/mybot/.venv/bin/python bot.py
EnvironmentFile=/opt/mybot/.env
Restart=always

Здесь есть тонкость: EnvironmentFile в systemd читает строки KEY=value буквально, без шелл-синтаксиса — export и кавычки в нём работают не так, как в .env для bash. Полная настройка systemd, pm2 и Docker restart — в статье как держать процесс запущенным 24/7.

Деплой на managed-платформе

Сценарий короче: подключить репозиторий, задать переменные окружения (включая BOT_TOKEN) в панели и сделать git push. Платформа определит, что это Python-проект, установит зависимости из requirements.txt, запустит процесс и будет держать его живым — без отдельной настройки supervisor. Managed-база, а для webhook домен с SSL, поднимаются рядом и не требуют ручной возни.

Проверка после деплоя

Бот задеплоен — но «задеплоен» не значит «работает». Стоит убедиться явно:

  • посмотреть логи процесса: при старте не должно быть исключений, а long-polling-бот сообщает, что начал получать обновления;
  • отправить боту /start в Telegram и дождаться ответа;
  • проверить, что токен виден процессу — метод getMe возвращает данные бота, а не ошибку 401 Unauthorized:
curl https://api.telegram.org/bot<BOT_TOKEN>/getMe

Если бот молчит, причина почти всегда одна из двух: не задан BOT_TOKEN или запущен второй инстанс, перехвативший long-polling.

Частые грабли

  • Два запущенных инстанса. Старый процесс на VPS плюс новый редеплой — и оба зовут getUpdates, в ответ 409 Conflict. Long-polling-консьюмер должен быть один.
  • Состояние в памяти. После редеплоя «бот всё забыл» — данные жили в переменных, а не в базе.
  • Токен в репозитории. Любой, кто видит код, видит токен. Отзывать через @BotFather.
  • Free-tier, который усыпляет процесс. Бот «иногда не отвечает», потому что хостинг остановил неактивный процесс. Боту нужен постоянно живущий процесс.
  • Часовой пояс сервера. Расписания и datetime на сервере по UTC ведут себя не так, как на локальной машине.

Чеклист

  • Выбран режим: long-polling по умолчанию или webhook под нагрузку.
  • Зависимости зафиксированы в requirements.txt.
  • Токен и секреты — в переменных окружения, не в коде и не в Git.
  • Состояние хранится в Postgres или Redis, а не в памяти.
  • Процесс запущен под супервизором с автоперезапуском, а не python bot.py.
  • Запущен ровно один long-polling-инстанс.
  • Настроены бэкапы базы.

Managed-платформа закрывает большую часть этого списка по умолчанию: процесс держится сам, managed Postgres идёт с ежедневными бэкапами, а для webhook домен и SSL поднимаются автоматически. На Hostim Python-бот разворачивается по git push и работает 24/7 без serverless-засыпания — переменные окружения задаются в панели, база подключается рядом.

Читать дальше