Назад в блог/VPS для Telegram-бота: минимальный тариф, Docker и автозапуск

VPS для Telegram-бота: минимальный тариф, Docker и автозапуск

Как запустить Telegram-бота на минимальном VPS: polling или webhook, Docker Compose с автозапуском, секреты, firewall и когда хватит посуточного тарифа для тестов.

Telegram-бот редко нуждается в «тяжёлом» сервере. Ему важнее другое: стабильный исходящий доступ к Bot API, предсказуемый автозапуск после ребута и чтобы токен не уехал в git. Ниже — узкий сценарий: как выбрать минимальный тариф, поднять бота в Docker Compose, закрыть лишнее firewall’ом и не пропустить падение. Без общего курса по Ubuntu и Docker — только то, что реально нужно боту на VPS.

Если сервер ещё не подготовлен (SSH-ключи, обновления, базовый firewall), начните с настройки Ubuntu: безопасность, Docker, firewall. Подключиться с любой ОС поможет гайд по SSH. Здесь же — от выбора polling/webhook до мониторинга и посуточного теста.

схема
Telegram-бот на VPS: polling/webhook, Docker Compose, автозапуск и firewall

Polling или webhook — что выбрать на VPS

Telegram отдаёт обновления двумя способами. Long polling: ваш процесс сам ходит в getUpdates и ждёт события. Webhook: Telegram стучится на ваш HTTPS-endpoint, когда приходит сообщение.

Для большинства ботов на одном VPS polling проще:

  • не нужен домен и TLS-сертификат;
  • не нужно открывать 443 наружу под webhook;
  • меньше точек отказа на старте (DNS, Certbot, reverse proxy).

Webhook оправдан, когда:

  • нагрузка высокая и вы хотите мгновенную доставку без постоянного опроса;
  • бот уже стоит за reverse proxy с нормальным HTTPS;
  • несколько инстансов и вы осознанно проектируете входящий трафик.

На минимальном тарифе под личный или небольшой рабочий бот polling почти всегда выигрывает по простоте. Webhook добавьте позже, когда появятся домен, nginx/caddy и понятный health-check. Не смешивайте оба режима на одном токене: Telegram принимает либо polling, либо webhook.

Практичный порядок: сначала polling в Docker с restart: unless-stopped, убедиться, что бот отвечает, логи чистые. Потом — если нужно — вынести webhook за HTTPS и закрыть лишние порты.

Минимальные ресурсы под бота

Типичный бот на Python (aiogram/python-telegram-bot) или Node — это лёгкий процесс: сеть к api.telegram.org, иногда SQLite или маленький Redis, редко тяжёлая БД на той же машине.

Ориентиры для одного бота без тяжёлой аналитики:

  • 1 vCPU — достаточно, пока нет CPU-bound задач (видео, OCR, массовая генерация);
  • 1 ГБ RAM — комфортный минимум под Docker + один контейнер бота; 512 МБ тоже живут, но запас на пики и обновления тоньше;
  • 10–20 ГБ диска — хватает ОС, образа и логов, если не копить том логирования без ротации;
  • исходящий HTTPS к Bot API — критичнее «сырых» ядер.

Когда ресурсов мало не хватает:

  • в контейнере крутятся ещё Postgres, Elasticsearch, тяжёлый браузерный headless;
  • бот шлёт медиа потоком и пишет на диск без очистки;
  • вы держите несколько ботов на одной машине без лимитов памяти.

Если бот только отвечает на команды и пишет в SQLite — младший тариф с запасом. Если рядом полноценный бэкенд сайта — считайте ресурсы сайта отдельно и не «натягивайте» всё на одну виртуалку «для экономии», пока не измерите нагрузку.

Выдача VPS у AZERTA — до 120 секунд после оплаты, тарифы от 360₽, поддержка 24/7. Для постоянной работы смотрите линейку на /vps/, для тестов удобнее посуточная аренда.

Скелет Docker Compose

Идея простая: один сервис бота, переменные окружения из файла вне git, политика перезапуска, ограничение логов. Ниже — универсальный каркас под Python или Node: меняете образ и команду, логика та же.

Структура каталога:

TEXT
bot/
  docker-compose.yml
  .env                 # не в git
  .env.example
  Dockerfile           # или готовый образ
  app/                 # код

Пример docker-compose.yml:

YAML
services:
  bot:
    build: .
    # image: ghcr.io/your-org/telegram-bot:latest
    container_name: tg-bot
    restart: unless-stopped
    env_file:
      - .env
    environment:
      TZ: Europe/Moscow
    # Для webhook раскомментируйте и пробросьте порт:
    # ports:
    #   - "127.0.0.1:8080:8080"
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
    # Опционально: лимит памяти, чтобы один утекающий процесс не уронил весь VPS
    mem_limit: 512m

Минимальный .env (пример, не копируйте токены в чаты):

BASH
BOT_TOKEN=123456:ABC-DEF...
# DATABASE_URL=sqlite:////data/bot.db

.env.example без секретов кладите в репозиторий. Сам .env — в .gitignore.

Запуск:

BASH
cd bot
docker compose up -d --build
docker compose ps
docker compose logs -f --tail=100

Dockerfile оставляем минимальным: multi-stage не обязателен на старте, важнее не запускать от root без нужды и не класть .env в образ через COPY. Секреты — только runtime (env_file / secrets Docker).

Если нужен reverse proxy под webhook — это уже отдельный сервис в том же compose или на хосте. Базовая установка Docker и firewall описана в статье по Ubuntu; здесь не дублируем полный гайд.

Для черновика бота удобен VPS под разработку: подняли стенд, прогнали compose, снесли или оставили. Когда стабилизируется — тот же compose переносится на постоянный тариф без смены подхода.

Автозапуск и логи

restart: unless-stopped в Compose — база: контейнер поднимется после ребута VPS и после падения процесса, пока вы сами его не остановили (docker compose stop).

Проверка после reboot:

BASH
sudo reboot
# после входа:
docker compose -f /path/to/bot/docker-compose.yml ps
docker compose logs --tail=50

Если Docker установлен штатно, сервис docker обычно в автозагрузке. Имеет смысл один раз проверить:

BASH
systemctl is-enabled docker
systemctl status docker --no-pager

Логи:

  • docker compose logs -f — основной инструмент в повседневке;
  • docker logs tg-bot --since 1h — если смотрите по имени контейнера;
  • ротация через logging.options в compose (см. выше) — иначе json-логи съедят диск.

На хосте journald тоже растёт. Если крутите unit’ы вне Docker, смотрите journalctl -u your-bot -f. Для контейнерного сценария чаще хватает docker logs + лимиты размера.

Не путайте «контейнер Up» и «бот реально отвечает». После деплоя отправьте тестовое сообщение в Telegram и убедитесь, что в логах нет бесконечных reconnect/timeout к API.

Секреты и firewall

Токен не в git и не в образе

Token BotFather — полный доступ к боту. Утечка = чужой спам от вашего имени, кража данных пользователей, отзыв токена в спешке.

Правила:

  • BOT_TOKEN только в .env или Docker/ Swarm/ CI secrets;
  • .env в .gitignore; в CI — секреты пайплайна, не переменные в открытом YAML;
  • не коммитьте скриншоты с токеном и не светите его в issue;
  • при утечке — сразу /revoke в BotFather и новый токен в .env, затем docker compose up -d.

Права на файл:

BASH
chmod 600 .env
chown "$USER":"$USER" .env

Firewall: только нужное

Для бота на polling снаружи обычно нужен только SSH (лучше по ключу, не паролем). HTTPS наружу — если webhook или свой веб-интерфейс.

Минимальный UFW:

BASH
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
# только если webhook / свой сайт на этой машине:
# sudo ufw allow 80/tcp
# sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Исходящий HTTPS к Telegram не блокируйте: боту нужен доступ к api.telegram.org. Входящий 443 без webhook открывать незачем.

Дополнительно к SSH имеет смысл Fail2ban, если оставляете 22/tcp в мир. Ключи вместо пароля — обязательный минимум из гайда по настройке VPS.

Не публикуйте порт приложения бота в 0.0.0.0, если webhook идёт через локальный reverse proxy: в compose достаточно 127.0.0.1:8080:8080.

Москва или Германия для Bot API

Bot API Telegram — глобальный сервис. Для бота важнее стабильный маршрут и отсутствие блокировок исходящего HTTPS, чем «магический» выбор города в панели.

Практично:

  • Москва (ДЦ Нагатинский) — удобно, если вы и пользователи в РФ, проще совмещать бота с другими сервисами на той же площадке, привычный TZ в логах (Europe/Moscow).
  • Германия (DE) — нормальный вариант, когда нужен европейский сегмент или вы уже держите там остальные сервисы. Точный адрес ЦОД для выбора «пинга до Telegram» обычно не критичен: важнее измерить именно ваш канал.

Не опирайтесь на чужие скриншоты ping. С вашего VPS после выдачи проверьте сами:

BASH
curl -o /dev/null -s -w "%{http_code} time=%{time_total}\n" https://api.telegram.org
# или несколько раз:
for i in 1 2 3 4 5; do
  curl -s -o /dev/null -w "%{time_connect} %{time_total}\n" https://api.telegram.org
done

Смотрите не «идеальные миллисекунды», а стабильность: нет ли таймаутов, обрывов TLS, долгих зависаний getUpdates. Если polling стабилен часами — локация для вашего кейса подходит. Если есть странные обрывы — смените площадку или проверьте firewall/MTU, а не увеличивайте тариф «на всякий случай».

Пользователи бота общаются с Telegram-клиентами; ваш VPS общается с API. Latency «Москва vs DE» редко решает UX чата — чаще решают баги обработчиков и рестарты без restart-политики.

Мониторинг падений

«Контейнер Up» в docker ps не равен «бот отвечает в Telegram». Нужен хотя бы один внешний сигнал.

Минимальный набор:

  1. Health внутри кода — периодический успешный getMe / свой heartbeat в лог.
  2. Внешний uptime — HTTP health, если есть webhook/веб; для чистого polling — отдельная проверка «процесс жив» + алерт по отсутствию логов/метрик.
  3. Диск и память — бот молчит, когда диск 100% или OOM убил процесс.

Краткая проверка с хоста:

BASH
docker compose ps
docker compose logs --tail=20
df -h /
free -h

Для системного взгляда (uptime снаружи, диск, CPU) — мониторинг VPS: uptime, диск, CPU. Имеет смысл повесить алерт в Telegram… другим ботом или через канал уведомлений: ирония в том, что один бот может сообщить о смерти другого, если крутятся на разных машинах или хотя бы внешний SaaS пингует health.

Простой cron-heartbeat (идея): раз в 5 минут скрипт дергает API или смотрит docker inspect на Status и OOMKilled, при сбое пишет в запасной канал. Не усложняйте до Prometheus в первый день — сначала стабильный restart и один алерт.

Когда хватит младшего тарифа и посуточно для тестов

Младшего тарифа обычно хватает, если:

  • один бот, polling, без тяжёлой БД на той же VM;
  • нет массовой рассылки на десятки тысяч чатов с медиа;
  • логи ротируются, диск не забит бэкапами «на всякий»;
  • нет параллельного «ещё и интернет-магазин на этом же VPS».

Имеет смысл апгрейд, когда стабильно упираетесь в RAM (OOM), CPU на обработчиках или диск из‑за данных — не когда «вдруг завтра хайп».

Посуточно ([/vps/daily/](/vps/daily/)) отлично подходит, чтобы:

  • проверить Docker Compose и автозапуск «с нуля» за один вечер;
  • сравнить Москву и DE на своём коде без обязательства на месяц;
  • отдать стенд подрядчику на пару дней.

Под разработку ([/vps/development/](/vps/development/)) — когда бот ещё пишется: частые пересборки образа, эксперименты с webhook, временные домены. Когда пайплайн устоялся — тот же compose на постоянный /vps/.

Напоминание по продукту AZERTA (без выдуманных опций): выдача до 120 секунд после оплаты, тарифы от 360₽, работа 24/7, площадки — Москва (Нагатинский) и Германия. После 3 ТБ трафика действует шейпинг 1 Мбит/с — для обычного текстового бота это обычно далеко за горизонтом; упираются чаще те, кто гоняет крупные файлы или зеркала.

FAQ

Нужен ли домен для Telegram-бота на VPS?

Для polling — нет. Для webhook — да (или хотя бы валидный HTTPS на IP с сертификатом, что на практике неудобнее домена). На старте проще polling без домена.

Сколько RAM нужно боту в Docker?

Часто хватает 512 МБ–1 ГБ на лёгкий Python/Node-бот плюс ОС. Держите запас: обновления пакетов, пик при деплое, утечки. Лимит mem_limit в compose защищает хост от одного «поехавшего» процесса.

Polling безопаснее webhook?

Разные модели угроз. Polling не открывает входящий HTTP под бота — меньше поверхность. Webhook требует TLS и аккуратного firewall. Безопасность токена и SSH важнее выбора режима.

Что делать, если бот «молчит», а контейнер Up?

Смотрите docker compose logs, проверьте токен и доступ к api.telegram.org, нет ли webhook, забытого на старом URL (deleteWebhook), не упёрлись ли в диск/OOM. Отправьте тестовое сообщение и сверьте latency запросов к API.

Можно ли держать несколько ботов на одном VPS?

Да: отдельные сервисы в compose или отдельные compose-проекты, разные .env, лимиты памяти. Следите за суммарной RAM и за тем, чтобы логи не писались без ротации. Изоляция секретов — по боту, не один общий .env на всех.

Посуточный VPS подойдёт для продакшена?

Для продакшена удобнее постоянный тариф с предсказуемым биллингом. Посуточно — стенды, тесты, сравнение локаций, демо клиенту. Рабочий бот лучше перенести на обычный /vps/, сохранив тот же Docker-стек.


Итоговый путь короткий: polling на минимальном тарифе → Compose с restart и .env вне git → UFW только под SSH (и 443, если webhook) → простой мониторинг падений → посуточный стенд для проверки, постоянный VPS для боя. Когда базовая ОС и Docker ещё не настроены, вернитесь к гайду по Ubuntu и SSH; когда бот уже крутится — к мониторингу, чтобы узнавать о падении раньше пользователей в чате.

Нужен быстрый сервер под ваш проект?

Арендуйте производительный KVM VPS в Москве или Германии на скоростных NVMe дисках от 405 ₽/мес. Автовыдача за 60 секунд, выделенный IPv4 и защита от DDoS.

Выбрать тариф