EQVPS

Telegram-бот 24/7 на VPS: aiogram, systemd, polling проти webhook

Jul 4, 2026 · 5 min read · EQVPS Team

Ви написали Telegram-бота на aiogram, погоняли локально — працює. Тепер йому треба жити там, де не засинають при закритті ноутбука. Невеликий VPS — природний дім, але між python bot.py у SSH-сесії та ботом, який реально тримається через падіння, перезавантаження й обриви зв'язку, є прірва.

Це бойова версія: virtualenv, токен поза кодом, systemd-сервіс, що воскрешає бота сам, і тверезу відповідь на питання, яке рано чи пізно ставить кожен — polling чи webhook?

Чому не лишити на ноутбуці

Боту потрібне стійке вихідне з'єднання з Telegram. Ноутбук засинає, перезавантажується заради оновлень, стрибає між мережами — щоразу бот відпадає, і користувачі впираються в тишу. VPS тримає це з'єднання цілодобово. У цьому весь сенс переїзду з особистої машини — з тієї ж причини і Discord-боту місце на сервері.

Якщо потрібен найшвидший шлях «просто підніми бота» з мінімальним прикладом — це розібрано в гайді з хостингу Telegram-бота. Тут — на рівень глибше: aiogram, безпечний токен і розуміння, коли масштабуватися.

Бот у virtualenv

Заходимо по SSH і тримаємо бота ізольованим у своєму venv — не ставте пакети системно, потім намучаєтесь з оновленнями та чищенням:

sudo apt update && sudo apt install -y python3-venv
mkdir ~/tgbot && cd ~/tgbot
python3 -m venv venv && source venv/bin/activate
pip install -U aiogram

Мінімальний бот на aiogram 3, який читає токен з оточення, а не із зашитого рядка:

# bot.py
import asyncio, logging, os
from aiogram import Bot, Dispatcher
from aiogram.types import Message
from aiogram.filters import CommandStart

logging.basicConfig(level=logging.INFO)
dp = Dispatcher()

@dp.message(CommandStart())
async def start(m: Message):
    await m.answer("Живий, працюю на VPS.")

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

if __name__ == "__main__":
    asyncio.run(main())

Токен — поза кодом

Ніколи не вставляйте токен від BotFather прямо в bot.py: один пуш у публічний репозиторій — і він витік. Покладіть його в env-файл, який читає лише root:

sudo tee /etc/tgbot.env >/dev/null <<'EOF'
BOT_TOKEN=123456:ваш-токен-від-botfather
EOF
sudo chmod 600 /etc/tgbot.env

Витеклий токен лагодиться одним /revoke у BotFather — а от витік чого завгодно ще на спільній машині значно гірший. Окремий VPS під бота, чесно кажучи, безпечніший для токена, ніж ваш робочий ноутбук: якщо щось витече, ви міняєте один токен, а не всю свою систему.

Те, що тримає бота живим: systemd

Саме це відділяє бота, який «запускається», від бота, який «тримається». Створюємо сервіс:

# /etc/systemd/system/tgbot.service
[Unit]
Description=Telegram bot (aiogram)
After=network-online.target
Wants=network-online.target

[Service]
User=botuser
WorkingDirectory=/home/botuser/tgbot
EnvironmentFile=/etc/tgbot.env
ExecStart=/home/botuser/tgbot/venv/bin/python bot.py
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

Запускайте від звичайного користувача (botuser вище), не від root — якщо бота колись скомпрометують, хай він буде замкнений у пісочниці. Далі:

sudo systemctl daemon-reload
sudo systemctl enable --now tgbot

Restart=always з RestartSec=3 означає, що падіння — кривий відповідь Telegram, необроблений виняток, OOM — поверне бота за три секунди, а не лишить лежати, поки ви не помітите. Дивимось логи в реальному часі:

journalctl -u tgbot -f

Ось і все налаштування логування. Жодних файлів логів для ротації, жодних зайвих інструментів — journald уже все пише.

Оновлення без драми з даунтаймом

Коли міняєте код або оновлюєте aiogram:

cd ~/tgbot && source venv/bin/activate
pip install -U aiogram          # якщо оновлюєте бібліотеку
sudo systemctl restart tgbot
journalctl -u tgbot -n 30 --no-pager   # переконатися, що піднявся чисто

Рестарт мигає ботом на секунду-дві. Для polling-бота це невидимо користувачам — Telegram накопичує апдейти й віддає їх, щойно бот перепідключиться.

Polling проти webhook — чесна версія

Це рішення зазвичай переускладнюють. Ось як є:

Polling (start_polling, як у коді вище) — бот сам питає Telegram «є нове?» довгоживучим з'єднанням. Йому не потрібно нічого, крім вихідного інтернету — ні домену, ні TLS, ні відкритих вхідних портів. Чудово працює за NAT. Для переважної більшості ботів це правильний вибір, і на цьому можна спинитися.

Webhook — Telegram сам шле апдейти вам, а отже треба виставити назовні публічний HTTPS-ендпоінт. Для цього потрібен домен і доступний вхідний порт — тобто або виділений публічний IP, або reverse-proxy попереду. Більше налаштувань, більше того, що може зламатися. Виграш — менша затримка й менше накладних витрат на великому масштабі: тисячі одночасних користувачів, високий потік апдейтів.

Практичне правило: починайте з polling на NAT-тарифі. Переходьте на webhook, лише коли реально переросли polling — і ось тоді виділений IP виправдовує себе, бо вам потрібен цей вхідний HTTPS-ендпоінт.

Скільки це коштує

Polling-бот легкий. Він висить на long-poll Telegram і реагує на повідомлення, тож сервер здебільшого чекає:

Реєстрація за одним email, оплата в USDC або USDT на Base чи Ethereum — без картки, без документів. Картка теж працює, але в онрампу мінімум ~$27, тож для тарифу за $3 зручніше один раз поповнити баланс і списувати продовження з нього. Лише CPU, один дата-центр у Німеччині — для бота неважливо, але варто знати, якщо потрібен був GPU або конкретний регіон.

Чесний підсумок

Telegram-бот — одна з найдешевших речей для самостійного хостингу: сервер за $3, юніт systemd і polling дають бота, який онлайн через падіння й перезавантаження без няньки. За webhook і тариф побільше беріться, лише коли до цього реально примушує масштаб, — а не тому що туторіал сказав, ніби webhook «кращий». Візьміть маленький сервер, тримайте токен в env-файлі, довірте аптайм systemd і — насамперед — проженіть чек-лист безпеки нового VPS, щоб сам сервер був закритий.

FAQ

Polling чи webhook — що обрати?

Починайте з polling. Він працює з будь-якого сервера, де є вихідний інтернет — без домену, без відкритих портів, без TLS — і цього вистачає більшості ботів. Webhook потрібен лише за великого масштабу (тисячі користувачів) або коли критична мінімальна затримка; для нього потрібен публічний HTTPS-ендпоінт, а отже домен і доступний вхідний порт (виділений IP або reverse-proxy) — більше рухомих частин. Для 95% ботів правильна відповідь — polling на невеликому VPS.

Чи потрібен виділений IP або домен для Telegram-бота?

Для polling — ні. Бот лише вихідно стукає до Telegram, тож вистачає NAT-тарифу з проброшеним SSH. Публічний HTTPS-ендпоінт (домен + вхідний порт, тобто виділений IP або reverse-proxy) потрібен лише при переході на webhook. Більшості ботів він не потрібен ніколи.

Який розмір VPS потрібен aiogram-боту?

Найменший. Polling-бот здебільшого чекає на відповідь від long-poll Telegram, тож 1 vCPU / 1 ГБ (Nano за $3) спокійно тягне більшість ботів. Апгрейд потрібен, лише коли важку роботу робить сам бот — база даних, обробка медіа, локальна модель — тоді беруть 2 ГБ ($5) і вище.

Як лишити бота працювати після виходу з SSH?

Запустити як systemd-сервіс з Restart=always. Запущений у терміналі бот помирає при закритті SSH; під systemd він переживає вихід, перезапускається при падінні й піднімається після ребуту. Це межа між демкою і тим, на що можна покластися.

← Back to blogSee plans & pricing →