Перейти к содержимому
VPS и серверы · 6 мин

Telegram-бот на VPS: чтобы работал круглые сутки

Бот на ноутбуке умирает каждый раз, когда закрывается крышка. На VPS он работает без перерывов и сам поднимается после сбоя или перезагрузки. Ниже — минимальный бот на Python, служба systemd, которая держит его живым, и логи, которые реально удобно читать.

Что понадобится

  • VPS с Ubuntu 24.04 или Debian 12. Обычному боту с запасом хватит самого младшего тарифа: у Pulse 2 vCPU и 2 ГБ памяти за $10 в месяц, а бот на aiogram занимает из этого 60–100 МБ — останется место ещё для нескольких ботов или небольшой базы.
  • Токен бота от @BotFather.
  • Доступ к серверу по SSH (см. Подключение по SSH).

С тяжёлыми ботами история другая. Если ваш режет видео через ffmpeg, гоняет локальную ML-модель или держит большую базу — начинайте с Pulse или Drive.

1. Отдельный пользователь и виртуальное окружение

Не запускайте бота от root. Лишний пользователь ничего не стоит, зато если в коде бота найдётся дыра, ущерб будет ограничен.

apt update && apt install -y python3-venv
useradd -r -m -d /opt/bot -s /usr/sbin/nologin bot
sudo -u bot python3 -m venv /opt/bot/venv
sudo -u bot /opt/bot/venv/bin/pip install aiogram

2. Сам бот

/opt/bot/bot.py отвечает на /start и повторяет сообщения. Обработчики замените своей логикой.

import asyncio, os
from aiogram import Bot, Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message

dp = Dispatcher()

@dp.message(CommandStart())
async def start(m: Message):
    await m.answer("Привет! Я работаю на VPS.")

@dp.message()
async def echo(m: Message):
    await m.answer(m.text or "…")

async def main():
    await dp.start_polling(Bot(os.environ["BOT_TOKEN"]))

asyncio.run(main())

Токен держите не в коде, а в файле, который может читать только пользователь бота:

echo 'BOT_TOKEN=123456:ABC...' > /opt/bot/.env
chown bot:bot /opt/bot/.env /opt/bot/bot.py && chmod 600 /opt/bot/.env

3. systemd следит, чтобы бот работал

/etc/systemd/system/bot.service:

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

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

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now bot
systemctl status bot

Restart=always поднимает бота через пять секунд после любого падения, а enable запускает его после перезагрузки сервера.

4. Логи и обновления

journalctl -u bot -f            # лог в реальном времени
journalctl -u bot --since today # всё за сегодня

Новая версия — скопировать файл и выполнить systemctl restart bot. Если код лежит в git, большинству ботов за всю жизнь не понадобится ничего сложнее git pull в /opt/bot и того же перезапуска.

Polling или webhook?

В примере polling: бот сам спрашивает у Telegram новые сообщения. Ему не нужны домен, сертификат и открытые порты, поэтому я бы начинал с него. Webhook имеет смысл, когда у бота много трафика или он и так живёт рядом с веб-приложением на HTTPS. Тогда Telegram сам присылает обновления на ваш адрес, но понадобятся домен и сертификат (хватит nginx и Let's Encrypt).

Одна честная оговорка: при polling бот держит долгое соединение с Telegram. Это нормально и почти не тратит трафик, а он на всех VPS dedisrv и так без ограничений.

Telegram-бот на VPS: чтобы работал круглые сутки · dedisrv