Чтобы Telegram-бот продолжал работать после закрытия терминала и перезагрузки VPS, запустите его как системную службу: под отдельным пользователем, с токеном вне кода, фиксированной рабочей папкой, автоматическим стартом и журналом. Перед созданием службы бот должен уверенно запускаться вручную в той же среде — иначе systemd будет лишь многократно повторять неизвестную ошибку.

Запуск Telegram-бота на VPS как постоянной systemd-службы

Ниже разобран вариант для небольшого бота, который получает обновления через long polling. Пример службы использует Python, но тот же порядок подходит для Node.js и других сред: меняются путь к интерпретатору и команда запуска. Для webhook дополнительно нужны публичный HTTPS-адрес, reverse proxy и проверка входящих запросов.

Что выбрать: long polling или webhook

Telegram передаёт боту новые события двумя взаимоисключающими способами. При long polling процесс сам регулярно запрашивает обновления методом getUpdates. При webhook Telegram отправляет HTTPS POST на заранее зарегистрированный публичный адрес. Одновременно использовать оба способа для одного токена нельзя.

Для первого небольшого бота на одном VPS long polling обычно проще: не нужен отдельный домен, TLS-сертификат и публичный HTTP-маршрут. Процессу достаточно исходящего доступа к Telegram Bot API. Webhook подходит, когда приложение уже имеет защищённый веб-сервер, нужен входящий HTTP-поток или архитектура рассчитана на обработку запросов через публичный endpoint.

Официальное описание метода getUpdates называет его long polling и указывает, что он не работает, пока для бота установлен webhook. Метод setWebhook требует HTTPS URL и позволяет передавать secret_token, который Telegram добавляет в заголовок запроса.

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

КритерийLong pollingWebhook
Входящий публичный портНе требуется для получения обновленийТребуется HTTPS endpoint
Первый запускПроще для одного процессаНужны домен, TLS и reverse proxy
ПроверкаСтатус процесса, журнал и ответ ботаДополнительно состояние webhook и HTTP-ответ
КонфликтНе работает при активном webhookИсключает получение через getUpdates

Как подготовить пользователя, каталог и среду

Не запускайте рабочего бота от root. Создайте отдельного системного пользователя без административных прав и интерактивного входа. Он должен читать код и нужные секреты, записывать только в заранее выбранные каталоги и не иметь доступа к чужим проектам на сервере.

Разделите файлы по назначению. Код приложения можно хранить в /opt/mybot или другом документированном каталоге. Изменяемые данные — базу SQLite, загруженные файлы, кэш, сформированные документы — вынесите в отдельный постоянный каталог. Журналы при работе через systemd обычно читает journald, поэтому не создавайте второй бесконтрольный лог-файл без ротации.

Состав службы Telegram-бота на VPS: пользователь, проект, секреты и systemd
У процесса есть понятный пользователь, рабочая папка, закрытые секреты и единая точка управления

Установите только нужную версию языка и зависимостей. Для Python создайте виртуальное окружение внутри каталога проекта или рядом с ним и установите зависимости из зафиксированного файла. Для Node.js используйте версию, под которую проверен проект, и воспроизводимую установку по lock-файлу. Обновление всех пакетов до последних версий во время первого деплоя добавляет отдельный риск.

Проверьте владельцев и права. Пользователь службы должен читать исполняемые файлы и записывать только туда, где бот хранит рабочие данные. Репозиторий, архив деплоя и временные файлы не должны находиться в публичном каталоге сайта. Базовые меры для нового сервера перечислены в статье что настроить на VPS после покупки.

Где хранить токен и другие секреты

Токен Telegram-бота даёт возможность выполнять запросы от имени бота. Не записывайте его в исходный код, README, systemd unit, команду в истории терминала или публичную ссылку. В документации Telegram каждый запрос к Bot API содержит токен в адресе, поэтому такой адрес нельзя отправлять в чат или вставлять в браузер на чужом компьютере.

Для небольшой службы удобно использовать отдельный файл окружения вне каталога репозитория, например /etc/mybot/mybot.env. Сам каталог принадлежит root, а файл доступен на чтение только root и группе службы. Значение устанавливают непосредственно на сервере безопасным способом; в примерах и документации оставляют только имя переменной:

BOT_TOKEN=<set-on-server>
OWNER_CHAT_ID=<set-on-server>

В unit-файле указывают EnvironmentFile=/etc/mybot/mybot.env. Это отделяет код от конфигурации, но не превращает файл в защищённое хранилище автоматически. Проверьте права, резервное копирование и круг администраторов. Если приложение запускается в контейнере или через менеджер секретов, используйте штатный механизм выбранной среды.

Не выводите все переменные окружения при диагностике. Журнал с токеном опаснее временной ошибки запуска. Исключите секреты из сообщений об исключениях, команд отладки и уведомлений мониторинга. При подозрении на утечку токен нужно отозвать через BotFather, выдать новый и заменить его на сервере; простого удаления строки из git недостаточно.

Если токен уже попал в репозиторий, считайте его раскрытым даже после удаления текущего файла: значение могло остаться в истории и копиях. Сначала замените токен, затем очистите источник утечки и проверьте, где ещё использовалось старое значение.

Как проверить бота до создания службы

Systemd не исправляет ошибку импорта, отсутствующую библиотеку или неправильный путь к базе. Сначала запустите приложение вручную от имени будущего пользователя службы и из будущей рабочей папки. Оно должно прочитать переменные, установить соединение и обработать хотя бы одно контрольное сообщение.

Проверка включает больше, чем команду /start. Пройдите основной сценарий: нажмите кнопку, отправьте текст или файл, проверьте запись данных и уведомление владельцу. Убедитесь, что после остановки процесса и повторного запуска бот не теряет нужные настройки и не обрабатывает старое событие дважды.

Если используется long polling, проверьте, что второй экземпляр бота не запущен на ноутбуке, другом VPS или в старом контейнере. Два процесса с одним токеном будут конкурировать за обновления. Для webhook получите состояние через getWebhookInfo и проверьте URL, количество ожидающих событий и последнее сообщение об ошибке; поля ответа описаны в официальной документации Telegram.

Запишите точную команду, которая успешно запускает приложение. Используйте абсолютные пути к интерпретатору и файлу программы. Команда python bot.py может работать в интерактивной оболочке за счёт активированного окружения, но не найти нужный Python при запуске systemd.

Остановите ручной процесс штатным сигналом и убедитесь, что бот закрывает соединения и сохраняет данные. Только после этого переносите ту же команду в unit. Если для корректного завершения нужны минуты, это следует учесть в настройках остановки, а не заменять процесс принудительным уничтожением при каждом обновлении.

Как создать службу systemd для Telegram-бота

Unit-файл описывает, от чьего имени, из какой папки и какой командой запускается бот. Его размещают в системном каталоге units, затем systemd перечитывает конфигурацию. Ниже — пример для Python-проекта; имена пользователя и пути нужно заменить на фактические.

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

[Service]
Type=simple
User=botuser
Group=botuser
WorkingDirectory=/opt/mybot
EnvironmentFile=/etc/mybot/mybot.env
ExecStart=/opt/mybot/venv/bin/python /opt/mybot/bot.py
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

User и Group ограничивают права процесса. WorkingDirectory задаёт рабочую папку, EnvironmentFile подключает конфигурацию, а ExecStart содержит фактическую команду. Параметры запуска служб описаны в официальном руководстве systemd.service, а среда выполнения и ограничения — в systemd.exec.

Для Node.js строка ExecStart может указывать на абсолютный путь к node и главному файлу. Если проект собирается заранее, запускайте готовый рабочий артефакт, а не dev-сервер и не watcher. Команды установки зависимостей не помещают в ExecStart: сборка и запуск являются разными этапами.

Restart=on-failure помогает восстановить процесс после ошибки, но не должен скрывать постоянный сбой. Если приложение завершается сразу, systemd будет повторять запуск. Смотрите первичную ошибку в журнале, исправляйте причину и ограничивайте частоту повторов, если приложение способно создать нагрузку на внешний API.

После сохранения unit выполните последовательность:

sudo systemctl daemon-reload
sudo systemctl enable --now mybot.service
sudo systemctl status mybot.service
sudo journalctl -u mybot.service -n 100 --no-pager

enable добавляет запуск при загрузке в соответствии с секцией Install, а --now одновременно запускает службу. Точные действия и различие между включением и запуском приведены в официальном справочнике systemctl.

Как проверить автозапуск, журналы и восстановление

Статус active подтверждает наличие процесса, но не работу пользовательского сценария. Отправьте боту контрольное сообщение и дождитесь ожидаемого ответа. Если бот записывает данные или уведомляет владельца, проверьте и этот шаг. Затем сопоставьте время сообщения с журналом службы.

Команда journalctl -u mybot.service показывает сообщения конкретной службы. Фильтруйте по времени, следите за повторными запусками и не публикуйте полный журнал без проверки секретов и личных данных. Параметры фильтрации и вывода описаны в официальном руководстве journalctl.

Проверьте управляемое восстановление: остановите процесс штатным способом или вызовите безопасную тестовую ошибку в отдельной среде, затем убедитесь, что политика restart сработала ожидаемо. Не перезагружайте рабочий сервер только ради первой проверки, если на нём есть другие сервисы. Автозапуск можно подтвердить в согласованное окно обслуживания.

Добавьте внешний контроль, который проверяет не только наличие процесса. Для polling-бота это может быть служебный показатель свежести полученных обновлений и периодический безопасный сценарий. Для webhook контролируйте HTTPS endpoint, коды ответа, очередь ожидающих обновлений и сообщения getWebhookInfo.

Уведомление должно назвать бота, сервер, время сбоя и первый шаг диагностики. Не отправляйте токен, весь env-файл или содержимое пользовательских сообщений. Общий порядок метрик и оповещений разобран в статье как настроить мониторинг VPS.

Как безопасно обновлять и откатывать бота

Обновление должно быть повторяемым: резервная копия данных, проверенная версия кода, установка зависимостей, контролируемый перезапуск, просмотр журнала и реальное сообщение боту. Не редактируйте рабочие файлы вручную в процессе выполнения, если можете подготовить новую версию в отдельном каталоге.

Порядок обновления Telegram-бота на VPS: копия, новая версия, перезапуск и проверка
Релиз заканчивается проверкой сообщения, а не только успешной командой перезапуска

Перед релизом сохраните базу, пользовательские файлы и рабочую конфигурацию. Код лучше идентифицировать коммитом или номером версии, чтобы возврат не зависел от памяти. Если новая версия меняет структуру данных, подготовьте отдельный план миграции и обратной совместимости.

Остановите службу только на необходимое время. Загрузите код, установите зависимости в нужной среде, выполните проверку конфигурации и запустите службу. Сразу посмотрите статус и последние записи журнала. После этого отправьте контрольное сообщение и проверьте основной сценарий.

Если проверка не пройдена, остановите новую версию, верните предыдущий код и совместимую копию данных, затем снова проверьте ответ бота. Откат должен быть описан до изменения базы. Простая замена кода не поможет, если новая версия уже необратимо изменила данные.

Не храните единственную копию в соседней папке на том же диске. Отказ VPS или удаление каталога затронет обе версии. Состав копий и тест восстановления подробно разобраны в статье о резервном копировании VPS.

Интерактивный чек-лист

Пошаговый чек-лист запуска бота на VPS

Отмечайте выполненные шаги. Прогресс сохранится в этом браузере, поэтому к настройке можно вернуться позже.

0 из 11 пунктов отмечено

Если VPS ещё не подготовлен, начните с безопасной настройки SSH и базового чек-листа сервера. Все материалы направления находятся в разделе «Серверы и инфраструктура».

Частые вопросы

Почему бот останавливается после закрытия SSH

Процесс запущен внутри интерактивной оболочки и завершается вместе с сеансом либо не имеет механизма восстановления. Оформите его как systemd-службу и проверьте запуск от отдельного пользователя.

Что выбрать для небольшого бота: polling или webhook

Long polling обычно проще, если бот работает одним процессом и ему не нужен публичный HTTP endpoint. Webhook требует HTTPS-адреса, но подходит приложению с уже настроенным веб-контуром. Код должен поддерживать выбранный режим.

Можно ли записать токен прямо в unit-файл

Не стоит. Unit могут читать администраторы и средства диагностики, а секрет легко попадёт в копии и историю. Храните токен в отдельном защищённом файле окружения или штатном менеджере секретов.

Почему systemd постоянно перезапускает бота

Приложение завершается с ошибкой, а политика Restart запускает его снова. Посмотрите первые сообщения после старта через journalctl, проверьте путь, зависимости, пользователя, переменные окружения и права на данные.

Нужно ли открывать порт в firewall для polling-бота

Для получения обновлений через getUpdates входящий порт обычно не нужен: бот сам обращается к Telegram Bot API. Webhook требует публичного HTTPS-маршрута и правильно настроенного reverse proxy.

Как проверить, что бот запустится после перезагрузки

Убедитесь, что служба enabled, зависимости и данные находятся в постоянных каталогах, а секрет доступен пользователю службы. Подтвердите автозапуск в согласованное окно и после загрузки проверьте status, журнал и реальное сообщение.