# Инсталлятор (`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) — вне рамок автоматической проверки.