Files
fin-tracker/docs/ai/ops.md
T
Dmitry 4a0b4e0532 feat(deploy): healthcheck api и worker, отдельный migrate-сервис, лимит загрузки отчёта
Миграции вынесены из команды api в one-shot сервис migrate, api и worker стартуют после него. /health отвечает 503 при недоступной БД. Отчёт больше MAX_UPLOAD_BYTES (25 МиБ) получает 413, Caddy режет на 30 МБ раньше. Том uploads убран, секреты env_file передаются сервисам явно. В CI добавлена сборка образа бэкенда без push, test_migrations сверяет модели с историей Alembic.
2026-09-19 21:55:33 +03:00

44 lines
3.6 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.
# Эксплуатация
## VPS (Docker Compose)
```bash
cp .env.example .env # заполнить POSTGRES_PASSWORD, JWT_SECRET (openssl rand -hex 32), DOMAIN, токены
just up # docker compose up -d --build: db, migrate (one-shot `alembic upgrade head`), api, worker, caddy, pg-backup
docker compose exec api fintracker create-user you@example.com
```
- Caddy: авто-TLS на `DOMAIN`, `/api/*` → api:8000, остальное — Flutter web из `app/build/web`.
- Worker — единственный экземпляр планировщика; ручной синк через `POST /api/v1/sync/{source}`
ставит задачу в `sync_job`, worker забирает её раз в 5 с.
- Расписание — `worker/jobs.default_schedule()`: zenmoney каждые 30 мин, cbr 13:45 и 18:00 МСК,
tinvest каждые 3 ч с 8:10, moex в 10:20/14:20/19:20/23:20, tinvest_events и moex_payouts раз в
сутки утром. tinvest* без `TINVEST_TOKEN` в расписание не берутся (в логе worker'а — warning).
- Healthcheck: `api` ходит на `/api/v1/health` (503, если БД недоступна), `worker` пишет файл
`/tmp/fintracker-worker-heartbeat` каждые 10 с, проверка смотрит на его возраст (< 60 с).
Compose сам не перезапускает unhealthy-контейнер — статус виден в `docker compose ps`.
- `pg-backup` делает `pg_dump -Fc` раз в сутки в `./backups`, хранит 14 дней; off-site копию
настраивает хост (rclone/cron), см. открытый вопрос в плане.
## Восстановление
```bash
docker compose up -d db
docker compose exec -T db pg_restore -U $POSTGRES_USER -d $POSTGRES_DB --clean < backups/fintracker_<ts>.dump
docker compose up -d
```
Метрики пересчитываются из raw/core: `docker compose exec worker fintracker metrics refresh`.
## Секреты
Только `.env` на сервере. В чат и в git не попадают. T-Invest токен — read-only.
В compose секреты раздаются по потребности: `api`/`worker` читают весь `.env`, `migrate` получает только `DATABASE_URL`, `db` и `pg-backup``POSTGRES_*`, `caddy``DOMAIN`.
## Проверено с podman (2026-09-17)
- `podman 5.8` + `podman-compose 1.6`: стек `db api worker` поднимается, `depends_on.condition: service_healthy` работает.
- Имена образов в `docker-compose.yml` и `Dockerfile` полностью квалифицированы (`docker.io/library/...`) — podman без `unqualified-search-registries` короткие имена не резолвит.
- **Прокси хоста впекается в образ** при `podman build`/`compose --build` (`HTTP_PROXY` попадает в `Config.Env`), после чего запросы к `localhost` внутри контейнера идут в недостижимый прокси. Поэтому `just up` собирает с `env -u …proxy…`. На VPS без прокси это ни на что не влияет.
- `env_file: .env` в compose — буквальный путь; `--env-file` меняет только подстановку `${…}` в самом compose-файле.
- Миграции идут в one-shot сервисе `migrate`; `api` и `worker` ждут его `service_completed_successfully`. Для podman-compose это условие не проверялось.