Образ собран с `uv sync --frozen --no-dev`, но `uv run` перед каждым запуском заново синхронизирует venv и подтягивает dev-группу. В логах старта vidconf-backend-1 и vidconf-worker-1 на проде это видно как «Downloading ruff / mypy / pygments» и «Installed 12 packages». Хуже всего healthcheck'и: они выполняют ту же синхронизацию каждые 15 секунд всю жизнь контейнера. Проверено на локально собранном образе, одна и та же команда: uv run — качает 12 пакетов, venv 456 → 574 МБ uv run --no-sync — не качает ничего, venv остаётся 456 МБ Флаг добавлен во все вызовы в прод-путях: CMD образа, command/entrypoint/ healthcheck всех сервисов compose, миграции и seed в install.sh, те же команды в docs/deploy. Локальная разработка (dev-setup.md, backend/README.md, CI) не затронута — там dev-зависимости нужны. Заодно убрано устаревшее объяснение ретрая `up -d --wait`: первый старт больше не синхронизирует окружение. Версия uv в образе — 0.11.33, `--no-sync` поддерживается.
142 lines
11 KiB
Markdown
142 lines
11 KiB
Markdown
# Инсталлятор (`install.sh`, релиз v0.0.1)
|
||
|
||
Один скрипт в корне репозитория — автодетект железа, опросник из 5
|
||
пресетов поставки, идемпотентная запись `.env`, сборка образов, миграции и
|
||
seed, подъём стека. По завершении `http://localhost/` отдаёт рабочий
|
||
фронтенд-SPA (React + Vite; статика вкомпилирована в образ nginx,
|
||
`frontend/Dockerfile`) — во ВСЕХ пресетах. Источник истины по
|
||
моделям/квантам/требованиям железа — ADR-004
|
||
(`docs/architecture/adr/004-ai-tier-matrix.md`); по пресетам поставки —
|
||
сам `install.sh` (см. таблицу ниже).
|
||
|
||
## Пресеты
|
||
|
||
| # | Состав | Профили compose | Модели |
|
||
|---|---|---|---|
|
||
| 1 | MVP-ядро (лобби, конференции, календарь, закреплённые, гости) | `media` | — |
|
||
| 2 | 1 + чат | `media` | — |
|
||
| 3 | 2 + AI «мин» (CPU) | `media,transcribe,llm` | faster-whisper `small` + Qwen3.5-4B |
|
||
| 4 | 2 + AI «средний» (CPU) | `media,transcribe,llm` | faster-whisper `medium` + Qwen3.5-9B |
|
||
| 5 | 2 + AI «макс» (GPU обязателен) | `media,transcribe-gpu,llm-gpu` | faster-whisper `large-v3` + Qwen3.5-35B-A3B |
|
||
|
||
Чат (2) и уровень AI (3/4/5) — переключатели плагинов в админке
|
||
(`instance_settings`, БД); `install.sh` поднимает НЕОБХОДИМЫЕ для
|
||
выбранного пресета контейнеры/модели И синхронизирует настройки инстанса
|
||
в соответствии с матрицей пресета (см. раздел «Синхронизация настроек
|
||
модулей»). Уровень `medium` в текущей матрице (`backend/services/ai_tiers.py`)
|
||
CPU-only — отдельного GPU-варианта профилей для пресета 4 нет (GPU для
|
||
`medium` — ручная настройка администратора вне детекта).
|
||
|
||
Запись конференций НЕ входит в пресеты (появится в v0.1.0) — вопрос
|
||
про неё инсталлятор не задаёт.
|
||
|
||
## Синхронизация настроек модулей (бутстрап)
|
||
|
||
При **первом старте** backend (lifespan) применяет пресет настроек через
|
||
три env-переменные `BOOTSTRAP_*`:
|
||
|
||
- `BOOTSTRAP_CHAT_ENABLED` (`true` | `false`) — включить чат в конференциях
|
||
- `BOOTSTRAP_TRANSCRIPTION_ENABLED` (`true` | `false`) — включить транскрибацию и суммаризацию
|
||
- `BOOTSTRAP_AI_LEVEL` (`min` | `medium` | `max`) — уровень AI (игнорируется, если транскрибация выключена)
|
||
|
||
**Матрица пресет → настройки модулей:**
|
||
|
||
| Пресет | Чат | AI | Уровень | `BOOTSTRAP_CHAT_ENABLED` | `BOOTSTRAP_TRANSCRIPTION_ENABLED` | `BOOTSTRAP_AI_LEVEL` |
|
||
|--------|-----|-----|---------|:---:|:---:|---|
|
||
| 1 (MVP-ядро) | — | — | — | `false` | `false` | `min` |
|
||
| 2 (+чат) | ✓ | — | — | `true` | `false` | `min` |
|
||
| 3 (+AI мин) | ✓ | ✓ | мин | `true` | `true` | `min` |
|
||
| 4 (+AI средний) | ✓ | ✓ | средний | `true` | `true` | `medium` |
|
||
| 5 (+AI макс) | ✓ | ✓ | макс | `true` | `true` | `max` |
|
||
|
||
Бутстрап **идемпотентен** при первом старте: дефолты из `config/plugins.yaml`
|
||
(всё `enabled: true`) переопределяются переменными `BOOTSTRAP_*` только если
|
||
БД ещё не содержит ключи настроек инстанса (проверка `INSERT ... ON CONFLICT DO NOTHING`).
|
||
Повторное включение контейнера backend не перетирает существующие настройки.
|
||
|
||
**При повторном запуске** инсталлятора на живой инсталляции:
|
||
|
||
```bash
|
||
./install.sh --preset 3 # спросит: обновить настройки? [Y/n]
|
||
./install.sh --preset 3 --yes # без подтверждения, применит пресет 3
|
||
```
|
||
|
||
Поведение:
|
||
- **Дефолт (Enter):** применяет матрицу выбранного пресета к настройкам БД
|
||
(defs: `docker compose exec -T backend uv run --no-sync python -m scripts.apply_preset_settings --force`)
|
||
- **Отказ (`n`):** сохраняет ручные правки админа; переменные `BOOTSTRAP_*` в `.env`
|
||
обновляются, но скрипт применения настроек НЕ запускается
|
||
- **Флаг `--yes`:** автоматически применяет пресет без вопроса (для CI/CD)
|
||
|
||
Скрипт обновления: upsert четырёх ключей в `instance_settings` БД:
|
||
`chat` (`enabled`), `transcriber` (`enabled`), `summarizer` (`enabled`), `ai_level`.
|
||
|
||
## Использование
|
||
|
||
```bash
|
||
./install.sh # интерактивный опросник + рекомендация по железу
|
||
./install.sh --preset 3 # неинтерактивно
|
||
./install.sh --preset 3 --yes # без подтверждений (скрипты/CI, пресет 5 без GPU)
|
||
./install.sh --preset 2 --monitoring --yes # + профиль monitoring (Grafana/Prometheus)
|
||
```
|
||
|
||
Флаг `--monitoring` дописывает профиль `monitoring` к `COMPOSE_PROFILES` (иначе
|
||
`set_env_var` при выборе пресета перезаписывает это значение целиком и
|
||
Grafana/Prometheus не поднимаются автоматически — см.
|
||
`.forcc/deploy/SESSION4-FINDINGS.md`, ГРАБЛИ 2, во внутренних заметках сессии
|
||
деплоя). Без флага мониторинг поднимается отдельной командой — см.
|
||
[docs/deploy/monitoring.md](monitoring.md).
|
||
|
||
Повторный запуск с другим `--preset` — апгрейд/даунгрейд на месте: модели
|
||
уровня докачиваются (старые с диска не удаляются — занимают место, но не
|
||
мешают), `COMPOSE_PROFILES`/`WHISPER_MODEL`/`LLM_MODEL_*` в `.env`
|
||
обновляются точечно, секреты (JWT/БД/TURN/LiveKit/Grafana) и любые
|
||
пользовательские правки `.env` — сохраняются (генерация только при полном
|
||
отсутствии значения, см. `ensure_secret` в `install.sh`).
|
||
|
||
## Что делает скрипт
|
||
|
||
1. Автодетект `nproc`/`free -m` (или `sysctl` на macOS)/`nvidia-smi` →
|
||
пишет `HW_CPUS`/`HW_RAM_MB`/`HW_GPU_NAME`/`HW_VRAM_MB` в `.env` — их
|
||
читает `backend/services/ai_levels.py` (детект доступности уровней AI в
|
||
админке, причины недоступности).
|
||
2. Точечно обновляет `.env` (создаёт из `.env.example` при первом запуске,
|
||
на первом запуске сразу генерирует РЕАЛЬНЫЕ секреты вместо
|
||
плейсхолдеров `change-me...` из шаблона в git).
|
||
3. Собирает флаги `--profile` из `COMPOSE_PROFILES` в `.env` (эта версия
|
||
docker compose НЕ подхватывает `COMPOSE_PROFILES` автоматически при `up`,
|
||
поэтому профили media/transcribe/llm передаются командам явно) и собирает
|
||
образы: `docker compose pull --ignore-buildable` (best-effort) →
|
||
`docker compose build` (backend, worker и nginx — образ nginx multi-stage
|
||
собирает фронтенд-SPA и вкомпилирует статику, `frontend/Dockerfile`).
|
||
4. Поднимает `postgres`/`redis` (`up -d --wait`) и применяет **до старта
|
||
backend** миграции и seed одноразовыми контейнерами:
|
||
`docker compose run --rm backend uv run --no-sync alembic upgrade head` +
|
||
`... python -m scripts.seed`. Порядок критичен: `backend.lifespan`
|
||
бутстрапит `instance_settings` при каждом старте приложения, поэтому на
|
||
чистой БД таблицы обязаны существовать до первого запуска backend — иначе
|
||
healthcheck (`--wait`) никогда не проходит. Seed идемпотентен (админ;
|
||
справочник `teams` и ключи `instance_settings`, включая
|
||
`registration_team_choice`/`registration_email_domain`, бутстрапятся
|
||
backend'ом при старте, `INSERT ... ON CONFLICT DO NOTHING` — существующие
|
||
настройки инстанса не перетираются).
|
||
5. Поднимает остальной стек: `docker compose <--profile ...> up -d --wait`
|
||
(backend, worker, nginx с фронтом + сервисы активных профилей). Команда
|
||
идемпотентна и обёрнута в ретрай (до 3 попыток): на слабой/загруженной
|
||
машине healthcheck может не успеть за отведённые
|
||
retries — повтор лишь дожидается уже стартующих контейнеров.
|
||
6. Печатает сводку: URL фронтенда/бэкенда, учётные данные администратора,
|
||
команда для `--profile monitoring`.
|
||
|
||
## Проверка
|
||
|
||
- Чистая установка (пресеты 1 и 3) на пустом `.env`/чистых volume.
|
||
- Апгрейд 1 → 3 (повторный запуск с другим `--preset`, секреты сохранены).
|
||
- Рекомендация детекта соответствует реальному железу текущей машины.
|
||
- `bash -n install.sh`, `docker compose -f deploy/docker-compose.yml --env-file .env config -q`
|
||
для всех сочетаний профилей — минимальная валидация без реального подъёма.
|
||
|
||
Полную установку на чистой машине/VM гоняют вручную (использование сети
|
||
для скачивания GGUF-моделей ~2,6–20,5 ГБ, GPU-хост для пресета 5) — вне
|
||
рамок автоматической проверки.
|