Telegram-бот редко ломается из-за одной большой ошибки. Чаще всё начинается с мелочей: файл сохранился не туда, лог вырос до нескольких гигабайт, токен лежит прямо в коде, после перезапуска бот забыл настройки, а администратор не помнит, где именно находится рабочая папка.
На тестовом запуске это почти не мешает. Запустили скрипт, отправили команду, получили ответ. Но как только бот принимает заявки, фотографии, документы или команды от клиентов, хаотичное хранение быстро превращается в проблему.
Я бы смотрел на Telegram-бота как на небольшое серверное приложение. У него должны быть отдельные каталоги, понятные права, управляемые логи, конфигурация вне кода и резервная копия. Без лишней архитектуры. Просто аккуратно.
Что именно хранит Telegram-бот
У простого бота может быть один файл с кодом и токеном. У рабочего бота обычно больше сущностей:
- исходный код приложения;
- настройки подключения к Telegram API;
- переменные окружения и секреты;
- загруженные пользователями файлы;
- временные файлы обработки;
- логи ошибок и действий;
- локальная база данных или кеш;
- файлы systemd, supervisor или другого менеджера процессов.
Если всё лежит в одной директории, разобраться можно только пока проект маленький. Потом появляются вопросы: что удалить, что бэкапить, где искать ошибку, почему диск заполнен и почему после обновления пропали документы.
Не храните всё рядом с кодом
Самая частая ошибка — складывать код, настройки, загруженные файлы и логи в одну папку:
/root/bot/
├── bot.py
├── config.json
├── users.db
├── photo_123.jpg
├── error.log
└── temp.zip
Пока бот один, это выглядит терпимо. Но такая структура плохо переживает обновления. Разработчик заменил папку проекта через git pull или rsync — и случайно задел базу, конфиг или файлы пользователей. Логи разрослись — и уже непонятно, можно ли их удалить без вреда.
Лучше сразу разделить код, постоянные данные, временные файлы и логи. Тогда обслуживание перестаёт быть угадайкой.
Рабочая структура каталогов
Для небольшого Telegram-бота на Linux удобна такая схема:
/opt/mybot/ # код приложения
/etc/mybot/ # настройки и файл окружения
/var/lib/mybot/ # постоянные данные
/var/lib/mybot/uploads/ # файлы пользователей
/var/lib/mybot/tmp/ # временная обработка
/var/log/mybot/ # текстовые логи, если они нужны
Имяmybotлучше заменить на короткое имя проекта. Если ботов несколько, пусть каждый живёт отдельно:/opt/orderbot,/var/lib/orderbot,/var/log/orderbot.
Код можно заменить при обновлении, а данные останутся на месте. При бэкапе тоже легче: код обычно лежит в репозитории, а вот/var/lib/mybotнужно сохранять регулярно.
Где держать настройки и секреты
Настройки бывают двух типов. Первые можно спокойно хранить в обычном конфиге: режим работы, путь к каталогу uploads, уровень логирования, адрес базы данных. Вторые нельзя показывать лишним людям: токен Telegram-бота, пароль базы, ключ API, webhook secret.
Не кладите секреты прямо в код:
BOT_TOKEN = "123456:ABC..."
Так удобно только до первого копирования проекта. Потом токен уезжает в архив, репозиторий или чат с разработчиком. Безопаснее читать секреты из переменных окружения или отдельного файла с ограниченными правами.
Пример файла окружения:
/etc/mybot/mybot.env
BOT_TOKEN=123456:ABC...
WEBHOOK_SECRET=long-random-string
DB_PATH=/var/lib/mybot/bot.sqlite3
UPLOAD_DIR=/var/lib/mybot/uploads
LOG_LEVEL=INFO
Права на такой файл должны быть строгими:
chown root:mybot /etc/mybot/mybot.env
chmod 640 /etc/mybot/mybot.env
Пользовательmybotсможет прочитать настройки, а случайный пользователь сервера — нет.
Зачем отдельный пользователь для бота
Запускать Telegram-бота от root удобно, но опасно. Если в коде появится ошибка или кто-то найдёт уязвимость, процесс получит слишком много прав. Для бота почти всегда хватает отдельного системного пользователя.
useradd --system --home /var/lib/mybot --shell /usr/sbin/nologin mybot
После этого можно назначить владельца рабочих каталогов:
mkdir -p /opt/mybot /etc/mybot /var/lib/mybot/uploads /var/lib/mybot/tmp /var/log/mybot
chown -R mybot:mybot /var/lib/mybot /var/log/mybot
chown -R root:root /opt/mybot /etc/mybot
Код лучше оставить под root или под пользователем деплоя, чтобы сам бот не мог случайно переписать свои файлы. А папки с загрузками и временными материалами отдать пользователюmybot.
Как хранить файлы, которые присылают пользователи
Telegram не присылает файл прямо в ваш каталог. Бот получает описание файла, затем запрашивает путь через метод getFile и скачивает файл по ссылке. У обычного Bot API такая ссылка живёт ограниченное время, поэтому её не стоит сохранять как постоянный адрес.
Правильный подход: сохранить метаданные в базе, скачать файл на сервер, дать ему безопасное имя и записать связь между пользователем, сообщением и локальным путём.
Не используйте оригинальное имя файла как основу для пути. Пользователь может прислать файл с одинаковым названием, странными символами или очень длинным именем. Лучше сохранить оригинальное имя отдельно, а файл положить под внутренним идентификатором.
/var/lib/mybot/uploads/2026/07/02/
├── 9f4c2a7b-document.pdf
├── 1b8e934d-photo.jpg
└── c7a12ff0-report.xlsx
Разбивка по датам помогает, когда файлов становится много. Старые материалы проще архивировать или удалять по правилам хранения.
В базе по каждому файлу лучше хранить внутренний id, telegram file_id и file_unique_id, id пользователя или чата, id сообщения, оригинальное имя, MIME-тип, размер, локальный путь, дату загрузки и статус обработки.file_idудобен для повторной отправки через Telegram, а локальный путь нужен для собственной обработки документа.
Временные файлы не должны жить вечно
У Telegram-ботов часто появляются временные материалы: распакованные архивы, уменьшенные изображения, PDF после конвертации, промежуточные JSON. Если их не чистить, они незаметно занимают диск.
Для временных файлов лучше выделить отдельный каталог:
/var/lib/mybot/tmp
И добавить простую очистку. Например, удалять файлы старше семи дней:
find /var/lib/mybot/tmp -type f -mtime +7 -delete
Эту команду можно запускать через cron или systemd timer. Перед автоматическим удалением полезно убедиться, что бот не хранит там постоянные материалы.
Логи: куда писать и сколько хранить
Логи нужны не для красоты. Они отвечают на простые вопросы: бот запустился или нет, почему не принял webhook, какой пользователь отправил слишком большой файл, какая команда упала, когда закончилась память.
Если бот запускается через systemd, самый простой вариант — писать логи в stdout и stderr. systemd передаст их в журнал. Смотреть можно так:
journalctl -u mybot.service -n 100
journalctl -u mybot.service -f
journalctl -u mybot.service --since "1 hour ago"
Это удобно: не нужно вручную создавать log-файл, следить за правами и думать, куда попал вывод после перезапуска.
Но иногда нужны отдельные текстовые логи: например, чтобы сторонняя система читала/var/log/mybot/app.logили чтобы разработчик забирал файл без доступа к journalctl. Тогда логируйте в/var/log/mybot/и обязательно настройте ротацию.
Пример logrotate для Telegram-бота
/etc/logrotate.d/mybot
/var/log/mybot/*.log {
daily
rotate 14
compress
missingok
notifempty
copytruncate
create 0640 mybot mybot
}
dailyвключает ежедневную ротацию,rotate 14хранит две недели,compressсжимает старые файлы. Параметрcopytruncateполезен, если приложение не умеет переоткрывать лог после ротации. Для небольшого бота такой вариант часто спасает диск от переполнения.
Что нельзя писать в логи
- токен Telegram-бота;
- пароли и API-ключи;
- полный текст приватных сообщений, если он не нужен для диагностики;
- персональные документы пользователей;
- платёжные данные;
- ссылки на скачивание файлов с секретными параметрами.
Для отладки можно включать более подробный режим, но ненадолго. После исправления ошибки уровень логирования лучше вернуть наINFOилиWARNING.
База данных: SQLite или отдельный сервер
Для небольшого Telegram-бота SQLite часто подходит лучше, чем кажется. Один файл, простой бэкап, минимум зависимостей. Его можно положить сюда:
/var/lib/mybot/bot.sqlite3
Главное — не хранить базу в папке с кодом и не удалять её при обновлении. Если бот обрабатывает много событий параллельно, работает с очередями и несколькими процессами, стоит перейти на PostgreSQL или MySQL.
Systemd-сервис с аккуратными путями
Пример unit-файла:
/etc/systemd/system/mybot.service
[Unit]
Description=Telegram bot mybot
After=network-online.target
Wants=network-online.target
[Service]
User=mybot
Group=mybot
WorkingDirectory=/opt/mybot
EnvironmentFile=/etc/mybot/mybot.env
ExecStart=/opt/mybot/venv/bin/python /opt/mybot/bot.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Здесь важны не только строки запуска.User=mybotне даёт процессу лишних прав.EnvironmentFileотделяет секреты от кода.Restart=on-failureпомогает пережить случайный сбой.WorkingDirectoryфиксирует рабочую папку.
systemctl daemon-reload
systemctl enable --now mybot.service
systemctl status mybot.service
Права доступа к загруженным файлам
Папка uploads не должна быть доступна через веб-сервер как обычная публичная директория. Пользователь прислал документ боту — это не значит, что документ можно открыть по прямой ссылке.
Лучше хранить файлы вне корня сайта. Если файл нужно отдать пользователю, приложение само проверяет права и отправляет его через Telegram или выдаёт временную ссылку с авторизацией.
chown -R mybot:mybot /var/lib/mybot/uploads
chmod -R 750 /var/lib/mybot/uploads
Если к файлам должен обращаться ещё один сервис, добавьте его в общую группу, а не открывайте каталог всем черезchmod 777.
Как понять, что место на диске заканчивается
Telegram-бот может месяцами работать тихо, а потом внезапно остановиться из-за заполненного диска. Причина часто простая: логи, временные файлы или загрузки пользователей.
df -h
du -sh /var/lib/mybot/*
du -sh /var/log/mybot/*
journalctl --disk-usage
Если быстро растёт/var/lib/mybot/uploads, нужна политика хранения файлов. Если растёт/var/log/mybot, проверьте ротацию. Если много места занимает journal, уменьшите шум в логах приложения.
Что включать в бэкап
/var/lib/mybot— база, загрузки, кеши, рабочие файлы;/etc/mybot— конфиги и файл окружения;/etc/systemd/system/mybot.service— правила автозапуска;/var/log/mybot— история ошибок, если она нужна для расследований;/opt/mybot— код, если нет нормального репозитория.
Секреты в бэкапе нужно сохранять, иначе восстановление затянется. Но архив с секретами должен храниться защищённо: без публичных ссылок, без отправки в общий чат, без доступа для случайных людей.
Как хранить несколько ботов на одном сервере
Если на одном VPS работают два-три бота, не смешивайте их каталоги. У каждого должны быть свои пользователь Linux, директория кода, каталог данных, файл окружения, systemd unit, политика логов и правила бэкапа.
/opt/orderbot
/opt/supportbot
/var/lib/orderbot
/var/lib/supportbot
/etc/orderbot/orderbot.env
/etc/supportbot/supportbot.env
Так один бот не перезапишет файлы другого, а при проверке нагрузки будет видно, кто именно забил диск или начал часто падать.
Если бот должен работать постоянно, лучше запускать его не на домашнем компьютере, а на сервере с круглосуточной сетью и автозапуском. На странице хостинга для Telegram-ботов UkrLine можно посмотреть пример такого подхода.
Типичные ошибки, которые потом долго искать
- бот запускается из
/root, а потом никто не может понять, какие права ему нужны; - токен Telegram хранится в репозитории;
- uploads лежит внутри папки сайта и открывается по прямому URL;
- логи пишутся в один файл без ротации;
- временные файлы не удаляются;
- SQLite-база лежит рядом с кодом и пропадает при обновлении;
- несколько ботов используют один каталог;
- бэкап сохраняет код, но не сохраняет
/var/lib/mybot; - после перезагрузки бот не стартует, потому что его запускали вручную;
- в логах остаются полные сообщения пользователей и секретные ссылки.
Простая схема, с которой удобно жить
Хорошая серверная организация Telegram-бота не требует сложной платформы. Достаточно отделить постоянное от временного, код от данных, секреты от репозитория, а логи от пользовательских файлов.
- код лежит в
/opt/mybot; - данные и загрузки — в
/var/lib/mybot; - секреты — в
/etc/mybot/mybot.envс правами 640; - бот запускается от отдельного пользователя;
- systemd отвечает за автозапуск и перезапуск;
- логи идут в journalctl или в
/var/log/mybotс ротацией; - временные файлы чистятся автоматически;
- бэкап сохраняет данные, конфиги и сервисный файл.
После такой настройки Telegram-бот перестаёт быть скриптом, который «где-то запущен». Его можно обновлять, переносить, проверять, восстанавливать и спокойно сопровождать.
