Перейти до вмісту
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