VPS с самостоятельным администрированием
Сохранение истории Telegram-бота после перезапуска
Перезапуск не должен незаметно обнулять разговор или повторять последний платный запрос. Пример Telegram-бота хранит в SQLite три вида состояния: недавнюю переписку, курсор обновлений и дневной счётчик попыток. Они находятся в Docker volume bot-data, а не во временной файловой системе контейнера.
Что именно сохраняется
| Состояние | Зачем нужно | Что происходит при потере |
|---|---|---|
| Последние сообщения пользователя и модели | Контекст следующего запроса | Разговор продолжается без прежнего контекста |
| Курсор обновлений Telegram | Учёт уже принятых обновлений | Ещё ожидающие обновления могут обработаться повторно |
| Дневной счётчик | Общий лимит запросов | Новый счётчик допускает дополнительные попытки |
По умолчанию сохраняются четыре завершённые пары «вопрос–ответ» на разрешённого пользователя. HISTORY_TURNS=0 отключает историю разговора, но не курсор и дневной лимит. Вход ограничен 2000 символами по умолчанию; ответ обрезается перед отправкой и сохранением. Это ограничения приложения, а не точный расчёт контекста токенизатором выбранной модели.
История хранится открытым текстом и содержит сообщения и Telegram ID. Защищайте её как пользовательские данные. При следующем запросе сохранённая история отправляется модели. Сообщения внутри Telegram существуют отдельно: очистка SQLite не удаляет их и не очищает записи на стороне inference-провайдера.
Контейнер, volume и VPS живут по-разному
Compose подключает bot-data:/data, а DB_PATH по умолчанию равен /data/bot.sqlite. Эти настройки должны согласовываться. База вне подключённого каталога не получает постоянное хранение автоматически. Контейнер работает с read-only корнем и непривилегированным пользователем. Выдавать всем права записи вместо исправления пути не нужно.
Из исходного каталога развёртывания:
docker compose ps
docker volume ls
docker compose exec -T bot python - <<'PYCODE'
from pathlib import Path
p = Path('/data/bot.sqlite')
print({'database_exists': p.is_file(), 'bytes': p.stat().st_size if p.is_file() else 0})
PYCODE
Команды показывают наличие и размер базы, не содержимое переписки. -T позволяет передать heredoc без интерактивного терминала. Пустая новая база тоже может выглядеть исправной: дополнительно проверьте в Telegram сохранение безобидного факта из разговора.
restart, пересборка контейнера и обычный docker compose down сохраняют named volume. down -v его удаляет. При смене имени Compose-проекта или каталога может подключиться другой volume. Сохраняйте идентичность проекта при обновлениях и не подставляйте случайный похожий volume в поисках истории.
Почему после аварии вопрос может остаться без ответа
Бот фиксирует курсор и счётчик до обращения к inference. Если он упадёт сразу после записи, вопрос может потеряться без вызова модели. Если сбой произойдёт после генерации, но до отправки в Telegram, списание возможно без доставленного ответа. При следующем старте платная попытка автоматически не повторяется.
Это политика «не более одной попытки» при обычной работе с сохранным состоянием, а не гарантия доставки ровно один раз. Восстановление старого бэкапа откатывает курсор и счётчик. Вторая копия с тем же токеном и другой базой тоже обходит локальную координацию. Эти случаи требуют отдельных действий: см. бэкап и перенос.
Очистка контекста и отзыв доступа
Команда /reset удаляет сохранённый контекст разрешённого пользователя, не сбрасывая общий бюджет. Чтобы отозвать доступ, удалите ID из ALLOWED_TELEGRAM_USER_IDS и пересоздайте контейнер. При старте он удаляет историю пользователей, которых больше нет в списке. Это не полное удаление данных из Telegram и систем inference-провайдера; старые копии базы также могут содержать прежнюю переписку.
Volume на том же VPS переживает замену контейнера, но не уничтожение сервера. Нужна копия вне VPS и отдельное защищённое хранение .env. Далее: резервное копирование и обновления и мониторинг. Источник: Docker volumes.
Тарифы из текущего каталога
Сейчас не удалось загрузить планы. Смотрите актуальные тарифы на странице цен.