DispelEvilBot/DEPLOY.md

166 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Развёртывание
Клонируем репозиторий и поднимаем контур Compose-ом. Контуры `test` и `prod`
разделяются именем проекта (`-p`) и файлом окружения (`--env-file`) — у каждого
свои БД и volume'ы, на одной машине не пересекаются.
## 1. Клонировать
```bash
git clone ssh://git@<gitea-host>:2222/mpakobecex/DispelEvilBot.git
cd DispelEvilBot
```
## 2. Подготовить окружение
```bash
cp env/test.env.example env/test.env
# заполнить: BOT_TOKEN, DB_PASSWORD, CHAT_ID (основной чат), ALERT_CHAT_ID (опц.),
# ADMIN_IDS (опц.)
# плюс для админки: BOT_USERNAME, ADMIN_PUBLIC_URL (HTTPS-домен),
# ADMIN_SESSION_SECRET (openssl rand -hex 32)
```
Порт админки (`ADMIN_HTTP_PORT`) у контуров должен различаться: `prod` — `8101`,
`test` — `8100` (8000 на VPS занят Portainer). `ADMIN_BIND_IP` по умолчанию `127.0.0.1`;
чтобы nginx-proxy-manager (контейнер) видел админку, ставьте `172.17.0.1`.
## 3. Логин в registry (если пакет приватный)
```bash
docker login git.mpakosrv.ru -u mpakobecex -p <ТОКЕН с read:package>
```
Если пакет сделать публичным — логин не нужен.
## 4. Запуск
```bash
# тестовый контур
docker compose -p test --env-file env/test.env -f docker-compose.prod.yml up -d
# прод (когда понадобится)
cp env/prod.env.example env/prod.env
docker compose -p prod --env-file env/prod.env -f docker-compose.prod.yml up -d
```
Логи:
```bash
docker compose -p test --env-file env/test.env -f docker-compose.prod.yml logs -f
```
## Что происходит при старте
1. `postgres` поднимается и проходит healthcheck;
2. `migrate` (**Flyway**) накатывает миграции из `sql/` — для пустой БД с нуля;
3. `bot` стартует (`Запуск DispelEvilBot v<версия> (APP_ENV=...)`), аналитика и рассылки — в нём же;
4. `admin` стартует и отвечает на `GET /healthz` (порт на loopback хоста).
Проверка контура (сервисы, миграции, Postgres, схема аналитики):
```bash
make check E=test
```
## Аналитика (Postgres)
События и дневные счётчики сообщений пишутся в схему `analytics` той же БД Postgres
(контракт — [`docs/events.md`](docs/events.md)). Отдельного сервиса нет.
```bash
make psql E=test
# пример: события за сегодня по типам
SELECT event_type, count(*) FROM analytics.events
WHERE event_time >= current_date GROUP BY event_type;
# сообщения по дням
SELECT day, sum(count) FROM analytics.messages_daily
WHERE day >= current_date - 7 GROUP BY day ORDER BY day;
```
Если Postgres недоступен, бот продолжает работать: батч аналитики уходит в stdout
(WARNING) и отбрасывается. Полностью выключить можно флагом `ANALYTICS_ENABLED=false`.
Партиции создаются приложением при старте и раз в 6 часов; старые **не удаляются**.
Схема создаётся миграцией `V26__analytics_schema.sql`.
## Админка (FastAPI)
Сервис `admin` — отдельный образ `mpakobecex/dispelevilbot-admin`, общий пакет `common`.
Наружу пока **не публикуется**: по умолчанию только loopback хоста
(`127.0.0.1:${ADMIN_HTTP_PORT}`). Для nginx-proxy-manager (он в контейнере) задайте
`ADMIN_BIND_IP=172.17.0.1` и указывайте в NPM цель `172.17.0.1:8100` (test) /
`172.17.0.1:8101` (prod). Домен и TLS — Блок 4.2.
```bash
# проверка живости
curl -s http://127.0.0.1:8100/healthz # test
curl -s http://127.0.0.1:8101/healthz # prod
```
Локально без Docker: `pip install -r requirements-admin.txt && python -m admin`
(по умолчанию `0.0.0.0:8000`, переопределяется `ADMIN_HOST`/`ADMIN_PORT`).
### Вход через Telegram
Админка закрыта Telegram Login Widget. Что нужно на контуре:
- `BOT_TOKEN` — токен бота этого контура (им же проверяется подпись `hash`);
- `BOT_USERNAME` — username бота без `@` (виджет рисует кнопку);
- `ADMIN_PUBLIC_URL` — публичный HTTPS-адрес (`https://debot-test.mpakosrv.ru`);
- `ADMIN_SESSION_SECRET` — `openssl rand -hex 32`;
- `ADMIN_IDS` — Telegram-ID администраторов: ими засевается `bot.admin_users` при старте
(`ON CONFLICT DO NOTHING`, существующих не трогает).
Домен должен быть привязан к боту в `@BotFather` (`/setdomain`), а TLS — настроен на
reverse proxy. Сессия живёт 12 часов (`ADMIN_SESSION_MAX_AGE`), cookie подписана и
`HttpOnly`; в проде ставится флаг `Secure`. Все POST-формы проверяют CSRF-токен.
Роль администратора перечитывается из БД на каждом запросе — отключение пользователя
(`enabled = false`) или удаление записи сразу закрывает доступ.
## Бэкап
Аналитика теперь лежит в Postgres, поэтому отдельного бэкапа событий больше нет.
Бэкап БД — стандартными средствами Postgres (`pg_dump`/`pg_basebackup`); при росте
истории следите за размером `analytics` и диском.
## Обновление и откат
```bash
# обновление: поменять IMAGE_TAG в env/<контур>.env, затем
docker compose -p <контур> --env-file env/<контур>.env -f docker-compose.prod.yml pull
docker compose -p <контур> --env-file env/<контур>.env -f docker-compose.prod.yml up -d
```
Откат — вернуть предыдущий `IMAGE_TAG` (например, commit-sha) и повторить.
## Контуры
| Контур | env-файл | БД | APP_ENV | Бот |
| --- | --- | --- | --- | --- |
| test | `env/test.env` | `dispel_evil_test` | `dev` | тестовый |
| prod | `env/prod.env` | `dispel_evil` | `prod` | боевой |
## Переменные окружения
См. `env/prod.env.example` / `env/test.env.example` (контуры).
## Дашборд (позже)
Superset поднимается отдельно и читает Postgres (схема `analytics`) с полной историей
событий. Отдельный read-only пользователь Postgres и сам дашборд — финальный этап,
в этот контур не входят.
## Перенос данных на прод (позже, короткое окно простоя)
1. Остановить старого бота.
2. `pg_dump -Fc -f dump.pgc <старая_бд>`.
3. Поднять прод-контур (миграции создадут чистую схему).
4. Загрузить данные: `pg_restore --data-only --disable-triggers -d dispel_evil dump.pgc`.
5. Сверить: число пользователей, `SUM(money.amount)`, число сообщений.
6. Переключить бота, проверить команды.
Бэкап старой БД обязателен. Дубли в `tg_users`/`de_users`/`unsubscribe` при загрузке
нужно устранить до создания PK (миграция `V12` делает дедуп, но при загрузке поверх
миграций дедуп — вручную).