Как запустить Telegram бота на сервере
Polling или webhook, где взять токен и как его защитить, как запускать бота через systemd, pm2 или Docker и что делать при сбоях.
Содержание8
Коротко
- Обновления боту приходят двумя способами: polling (бот сам спрашивает Telegram) и webhook (Telegram сам присылает их на ваш HTTPS-адрес). Без особых причин начинайте с polling.
- Токен из BotFather работает как пароль от бота. Храните его в переменных окружения, а не в коде и не в git.
- Запускайте бота как службу (systemd, pm2 или Docker) с автоматическим перезапуском.
- Если токен утёк, выполните
/revokeв BotFather.
Polling или webhook
Polling (метод getUpdates): бот регулярно запрашивает новые сообщения. Домен и HTTPS не нужны, работает даже за NAT, отлаживать проще. С одним токеном должен работать только один экземпляр бота.
Webhook: Telegram отправляет каждое обновление на ваш адрес. Нужны домен с действующим HTTPS-сертификатом и один из портов: 443, 80, 88 или 8443. Если домен проксируется Cloudflare, используйте 443 или 8443. Подходит для бессерверных окружений и нескольких экземпляров за балансировщиком.
Одновременно использовать оба способа нельзя: пока установлен webhook, getUpdates не работает. В руководстве Telegram отдельно сказано, что использовать getUpdates вполне нормально.
Токен и переменные окружения
В @BotFather выполните /newbot, задайте имя и username (он заканчивается на bot). BotFather пришлёт токен, который даёт полный контроль над ботом. Не публикуйте его в репозитории, на скриншотах и в логах.
Положите значения в файл .env рядом с ботом, задайте права chmod 600 .env и добавьте файл в .gitignore.
BOT_TOKEN=PASTE_TOKEN_HERE
ADMIN_IDS=123456789
WEBHOOK_SECRET=PASTE_RANDOM_STRING
Запуск как службы
Создайте для бота отдельного пользователя без sudo и положите код и .env в его каталог (ниже это /home/mybot/app):
sudo adduser --disabled-password --gecos "" mybot
Затем создайте файл /etc/systemd/system/mybot.service:
[Unit]
Description=Telegram bot
After=network-online.target
Wants=network-online.target
[Service]
User=mybot
WorkingDirectory=/home/mybot/app
EnvironmentFile=/home/mybot/app/.env
ExecStart=/home/mybot/app/.venv/bin/python main.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now mybot
sudo journalctl -u mybot -f
Для Node.js в ExecStart нужен абсолютный путь к node, его покажет which node. Вариант на pm2: pm2 start index.js --name mybot, затем pm2 startup и pm2 save. Учтите, что pm2 сам .env не читает: бот должен загружать файл, например библиотекой dotenv. Вариант на Docker: docker run -d --name mybot --restart unless-stopped --env-file .env mybot-image.
Webhook и HTTPS
Поставьте перед ботом Caddy или nginx, который проксирует запросы на локальный порт (пример в статье как развернуть сайт на VPS), и зарегистрируйте адрес. Чтобы токен не попал в историю команд, сначала загрузите значения из .env в оболочку (от имени пользователя, которому принадлежит файл):
set -a; source .env; set +a
curl "https://api.telegram.org/bot${BOT_TOKEN}/setWebhook" \
-d "url=https://bot.example.com/webhook" \
-d "secret_token=${WEBHOOK_SECRET}"
curl "https://api.telegram.org/bot${BOT_TOKEN}/getWebhookInfo"
В secret_token допустимы буквы, цифры, _ и -. Telegram передаёт его в заголовке X-Telegram-Bot-Api-Secret-Token, и бот должен его проверять. Сертификату нужна полная цепочка (fullchain). Метод getWebhookInfo показывает last_error_message и pending_update_count. Про сертификаты читайте в статье SSL сертификат и HTTPS.
Проверка и сбои
- Добавьте адрес
/health, который отвечает кодом 200, и проверяйте его внешним мониторингом по публичному адресу либо локальным скриптом, который пишет вам при сбое. Для бота без HTTP проверяйтеsystemctl is-active mybot. Restart=alwaysперезапускает процесс, а причину ищите вsudo journalctl -u mybot -n 100.- Перехватывайте исключения в обработчиках. Если бот падает на одном сообщении, после перезапуска Telegram может отдать его снова, и бот зациклится.
- При ответе 429 соблюдайте паузу
retry_after.
Безопасность
- Админов определяйте по числовому ID и проверяйте
from.idперед командами. Username меняется, ID нет. - Не пишите в логи токен, полные адреса запросов к API (в них есть токен) и личные данные пользователей.
- Запускайте бота от отдельного пользователя без sudo, а не от root и не от своего администратора.
- Docker публикует порты в обход ufw, поэтому порт webhook открывайте только на localhost:
-p 127.0.0.1:3000:3000. - Если токен утёк, выполните
/revokeу BotFather, обновите значение в.envи перезапустите бота. Старый токен перестанет работать.
Если не получилось
- Ошибка 401 Unauthorized: токен неверный или отозван.
- Ошибка 409 Conflict: запущено два экземпляра с polling либо установлен webhook. Оставьте один экземпляр или вызовите
deleteWebhook. - Webhook не доходит: смотрите
last_error_messageвgetWebhookInfoи проверьте порт, полную цепочку сертификата, DNS, файрвол и правила защиты в Cloudflare. - Бот молчит в группе: включён privacy mode. Отключите его командой
/setprivacyу BotFather, затем удалите бота из группы и добавьте снова, иначе изменение не вступит в силу. Можно и сделать бота админом. - Бот не стартует: прочитайте
sudo journalctl -u mybot -n 100, проверьте путь вExecStartи то, что код и.envлежат в каталоге пользователяmybot. - С сервера нет доступа к Telegram: выполните
curl -I https://api.telegram.org. Любой ответ значит, что связь есть, а зависание или ошибка соединения указывает на проблему. Доступность зависит от страны и провайдера.
Если что-то непонятно, напишите мне в Telegram: @lztcoder
Читайте также
Как выбрать хостинг для сайта или бота
Чем отличаются виртуальный хостинг, VPS, облако и статический хостинг, сколько памяти нужно сайту и боту и что спросить у продавца.
4 мин чтенияКак подготовить бриф для сайта или бота
Что описать заранее, чтобы разработчик дал реалистичную оценку, от цели и аудитории до интеграций, срока и бюджета. Есть шаблон.
3 мин чтенияСпамблок в Telegram: что это и что делать
Что такое ограничения аккаунта Telegram, как проверить статус через @SpamBot, как подать апелляцию и чего делать нельзя.
4 мин чтения