# Переменные окружения (.env)

Полный справочник переменных окружения VidConf. Все секреты хранятся **только** в `.env` и никогда не коммитятся в git.

## Соглашение

Значения читаются из файла `.env` (или переменных окружения) при старте приложения. Dev-шаблон см. в `.env.example`.

---

## База данных

### DATABASE_URL
**Тип:** `str` | **Default:** `postgresql+asyncpg://vidconf:vidconf@localhost:5432/vidconf`

**Описание:** Connection string для асинхронного драйвера SQLAlchemy (asyncpg).

**Пример:**
```bash
DATABASE_URL=postgresql+asyncpg://vidconf:vidconf@localhost:5432/vidconf
```

**Проде:** Используйте отдельного пользователя с минимальными привилегиями (только SELECT/INSERT/UPDATE на нужные таблицы).

### POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB
**Для Docker Compose:** переменные инициализации контейнера PostgreSQL.

```bash
POSTGRES_USER=vidconf
POSTGRES_PASSWORD=change-me-secure
POSTGRES_DB=vidconf
```

---

## Redis (очередь Celery)

### REDIS_PASSWORD
**Тип:** `str` | **Обязателен** (нет дефолта — `${REDIS_PASSWORD:?}` в `deploy/docker-compose.yml`)

**Описание:** Пароль Redis (`--requirepass`). Без него `docker compose up` не
стартует — намеренно: инцидент безопасности на этом проекте начался именно
с redis без пароля, опубликованного наружу (см. `.forcc/deploy/SESSION2-FINDINGS.md`
во внутренних заметках сессии деплоя). `install.sh` генерирует случайное
значение при первой установке. Используется backend/worker/livekit/egress —
все читают его через `REDIS_URL`/секцию `redis:` своих конфигов, генерируемых
из `.env` (см. `deploy/render-templates.sh`).

**Пример:**
```bash
REDIS_PASSWORD=a1b2c3...
```

### REDIS_URL
**Тип:** `str` | **Default:** `redis://localhost:6379/0`

**Описание:** URL Redis для брокера Celery (очередь задач) и кэша сеансов.
Значим только при запуске backend/worker НА ХОСТЕ вне docker-сети — внутри
контейнеров `docker-compose.yml` всегда подставляет
`redis://:${REDIS_PASSWORD}@redis:6379/0` сам, это значение игнорируя.

**Пример:**
```bash
REDIS_URL=redis://:password@localhost:6379/0
REDIS_URL=redis://:password@redis.example.com:6379/1  # с паролем, БД 1
```

**Проде:** Redis публикуется только на `127.0.0.1` (loopback) — снаружи
недоступен даже с паролем; удалённый доступ — через ssh-туннель.

---

## Конфигурация приложения

### Бутстрап настроек инстанса (первый старт backend, `BOOTSTRAP_*`)

Три переменные определяют начальное состояние настроек модулей при первом
запуске backend. Используются инсталлятором `install.sh` для синхронизации
пресетов поставки (пресеты 1–5 → матрица `BOOTSTRAP_*`).

#### BOOTSTRAP_CHAT_ENABLED

**Тип:** `bool` (строка: `true` | `false`) | **Default:** `false`

**Описание:** Включить чат в конференциях при первом старте backend.

```bash
BOOTSTRAP_CHAT_ENABLED=false  # пресеты 1, 3
BOOTSTRAP_CHAT_ENABLED=true   # пресеты 2, 4, 5
```

**Применение:** однократно при первом старте (lifespan backend), затем игнорируется
(настройка хранится в БД, `instance_settings.chat.enabled`). Изменение переменной
на живой инсталляции не действует — меняйте через админ-API `PUT /api/v1/admin/settings`.

---

#### BOOTSTRAP_TRANSCRIPTION_ENABLED

**Тип:** `bool` | **Default:** `false`

**Описание:** Включить транскрибацию и суммаризацию при первом старте backend.

```bash
BOOTSTRAP_TRANSCRIPTION_ENABLED=false  # пресеты 1, 2
BOOTSTRAP_TRANSCRIPTION_ENABLED=true   # пресеты 3, 4, 5
```

**Применение:** однократно при первом старте (lifespan backend), затем игнорируется.
Выключение транскрибации = AI-уровень не применяется (см. ниже). На живой
инсталляции меняйте через `PUT /api/v1/admin/settings?transcription_enabled=...`.

**Guard:** если транскрибация включена в настройках (`transcription_enabled=true`),
но ни один Celery-воркер `transcriber` не обслуживает очередь, в админке
отображается предупреждение (поле `transcription_queue_served` в ответе
`GET /api/v1/admin/settings`).

---

#### BOOTSTRAP_AI_LEVEL

**Тип:** `str` | **Default:** `min` | **Допустимые:** `min`, `medium`, `max`

**Описание:** Уровень качества AI-обработки при первом старте backend
(требует `BOOTSTRAP_TRANSCRIPTION_ENABLED=true`).

```bash
BOOTSTRAP_AI_LEVEL=min      # пресеты 1–3
BOOTSTRAP_AI_LEVEL=medium   # пресет 4
BOOTSTRAP_AI_LEVEL=max      # пресет 5
```

**Матрица инсталлятора (пресет → `BOOTSTRAP_*`):**

| Пресет | `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` |

**Применение:** однократно при первом старте, затем игнорируется
(настройка в `instance_settings.ai_level`). На живой инсталляции меняйте
через `PUT /api/v1/admin/settings?ai_level=...` (проверяется доступность уровня,
недоступный уровень → 400).

---

### PLUGINS_CONFIG_PATH
**Тип:** `str` | **Default:** `config/plugins.yaml`

**Описание:** Путь к конфигурационному файлу плагинов (от корня проекта или абсолютный).

```bash
PLUGINS_CONFIG_PATH=config/plugins.yaml
```

Содержит профили AI: transcriber (faster-whisper small/medium/large-v3), summarizer (Qwen3.5 4B/9B/35B-A3B), chat (отключён/включён).

---

## Пользователь seed (начальный администратор)

### SEED_ADMIN_EMAIL
**Тип:** `str` | **Default:** `admin@vidconf.example`

**Описание:** Email администратора, создаваемого при инициализации БД (`uv run python -m scripts.seed`, см. [backend/README.md](../../backend/README.md)).

```bash
SEED_ADMIN_EMAIL=admin@example.com
```

### SEED_ADMIN_PASSWORD
**Тип:** `str` | **Default:** `change-me`

**Описание:** Пароль администратора. **Измените на боевом инстансе сразу после развёртывания!**

```bash
SEED_ADMIN_PASSWORD=SuperSecurePassword123!
```

---

## Аутентификация и сессии (JWT)

### JWT_SECRET
**Тип:** `str` | **Default:** `dev-only-insecure-secret-change-me`

**Описание:** Секретный ключ для подписи JWT токенов (HS256).

**Требование:** Минимум 32 символа случайных данных для проде.

```bash
# Генерировать:
# python -c "import secrets; print(secrets.token_urlsafe(32))"
JWT_SECRET=your-long-random-secret-generated-above
```

### ACCESS_TOKEN_TTL_MINUTES
**Тип:** `int` | **Default:** `15`

**Описание:** Срок действия access-токена в минутах.

```bash
ACCESS_TOKEN_TTL_MINUTES=15
```

### REFRESH_TOKEN_TTL_DAYS
**Тип:** `int` | **Default:** `14`

**Описание:** Срок действия refresh-токена в днях. При истечении пользователь должен перелогиниться.

```bash
REFRESH_TOKEN_TTL_DAYS=14
```

### EMAIL_VERIFICATION_TTL_HOURS
**Тип:** `int` | **Default:** `24`

**Описание:** Срок действия email-верификационного токена в часах (при регистрации).

```bash
EMAIL_VERIFICATION_TTL_HOURS=24
```

### AUTH_COOKIE_SECURE
**Тип:** `bool` | **Default:** `true`

**Описание:** Флаг `Secure` для cookies, содержащих refresh-токены.

- **true** (проде) — cookies отправляются только по HTTPS
- **false** (dev на localhost) — cookies отправляются и по HTTP (необходимо для Safari на localhost без HTTPS)

```bash
AUTH_COOKIE_SECURE=false    # только для dev
AUTH_COOKIE_SECURE=true     # проде обязательно
```

### FRONTEND_URL
**Тип:** `str` | **Default:** `http://localhost:5173`

**Описание:** URL фронтенда. Используется для формирования ссылок в email'ах подтверждения (обычно не требуется, фронтенд за nginx'ом).

```bash
FRONTEND_URL=http://localhost:5173
FRONTEND_URL=https://vidconf.example.com
```

---

## LiveKit SFU

### LIVEKIT_URL
**Тип:** `str` | **Default:** `ws://localhost:7880`

**Описание:** Внутренний server-to-server URL LiveKit (для Celery задач, вызовы RoomService). Не проксируется через Nginx.

```bash
LIVEKIT_URL=ws://localhost:7880
LIVEKIT_URL=http://livekit:7880  # docker-сеть
```

### LIVEKIT_PUBLIC_URL
**Тип:** `str` | **Default:** `ws://localhost:7880`

**Описание:** Публичный URL LiveKit (браузер клиента). Обычно за nginx'ом с TLS.

```bash
LIVEKIT_PUBLIC_URL=ws://localhost:7880      # dev
LIVEKIT_PUBLIC_URL=wss://livekit.example.com # проде (WSS)
```

### LIVEKIT_API_KEY
**Тип:** `str` | **Default:** `devkey`

**Описание:** API ключ LiveKit (для генерации токенов комнат).

```bash
LIVEKIT_API_KEY=your-api-key
```

### LIVEKIT_API_SECRET
**Тип:** `str` | **Default:** `change-me-livekit-secret`

**Описание:** API секрет LiveKit (для подписи токенов).

```bash
LIVEKIT_API_SECRET=your-secret-key
```

Оба найдите в конфигурации LiveKit сервера (`livekit.conf`).

---

## TURN (Coturn)

### TURN_REALM
**Тип:** `str` | **Default:** `vidconf.local`

**Описание:** Realm для TURN сервера (Coturn). Испльзуется в credentials для WebRTC NAT traversal.

```bash
TURN_REALM=vidconf.example.com
```

### TURN_STATIC_AUTH_SECRET
**Тип:** `str` | **Default:** `change-me-turn-secret`

**Описание:** Секрет для TURN сервера (для временных credentials).

```bash
TURN_STATIC_AUTH_SECRET=your-secret-auth-key
```

---

## Аватары

### MEDIA_ROOT
**Тип:** `str` | **Default:** `/app/media`

**Описание:** Абсолютный путь к каталогу хранения загруженных аватаров пользователей.

```bash
MEDIA_ROOT=/app/media           # Docker Compose (по умолчанию)
MEDIA_ROOT=/var/lib/vidconf/media  # альтернативный путь на сервере
```

**Структура:**
```
MEDIA_ROOT/
└── avatars/
    ├── 550e8400-e29b-41d4-a716-446655440000.jpg
    ├── 6ba7b811-9dad-11d1-80b4-00c04fd430c8.png
    └── ...
```

**Docker Compose:** том `media` монтируется в backend и nginx. Nginx раздаёт файлы напрямую по `location /media/` в обход backend'а (для performance).

---

## Транскрибация

### RECORDINGS_DIR
**Тип:** `str` | **Default:** `/recordings`

**Описание:** Абсолютный путь к тому с записями (LiveKit Egress пишет .ogg треки сюда, Celery воркер их читает).

```bash
RECORDINGS_DIR=/recordings
RECORDINGS_DIR=/mnt/recordings  # альтернативный путь
```

**Docker Compose:** том `recordings` монтируется в обе сервиса (egress, transcriber). Менять путь внутри контейнера обычно не нужно (он совпадает с точкой монтирования).

---

## Email

Все SMTP-реквизиты — **только в `.env`, никогда не попадают в БД или API**.

### EMAIL_BACKEND
**Тип:** `str` | **Default:** `console`

**Допустимые значения:**
- `console` — dev: письма только логируются в stdout, ссылки берутся из логов
- `smtp` — реальная отправка через aiosmtplib

```bash
EMAIL_BACKEND=console  # dev
EMAIL_BACKEND=smtp     # проде
```

### SMTP_HOST
**Тип:** `str` | **Default:** `localhost`

**Описание:** Хост SMTP сервера (для `EMAIL_BACKEND=smtp`).

```bash
SMTP_HOST=smtp.gmail.com
SMTP_HOST=mail.example.com
```

### SMTP_PORT
**Тип:** `int` | **Default:** `587`

**Описание:** Порт SMTP (обычно 587 для TLS, 465 для SSL, 25 без шифрования).

```bash
SMTP_PORT=587   # TLS (STARTTLS)
SMTP_PORT=465   # SSL
SMTP_PORT=25    # plain
```

### SMTP_USERNAME
**Тип:** `str | None` | **Default:** `None`

**Описание:** Логин SMTP (если требуется аутентификация).

```bash
SMTP_USERNAME=noreply@vidconf.example.com
SMTP_USERNAME=
```

### SMTP_PASSWORD
**Тип:** `str | None` | **Default:** `None`

**Описание:** Пароль SMTP.

```bash
SMTP_PASSWORD=your-app-password
SMTP_PASSWORD=
```

### SMTP_START_TLS
**Тип:** `bool` | **Default:** `true`

**Описание:** Использовать STARTTLS (команда TLS после SMTP HELLO). Обычно для порта 587.

```bash
SMTP_START_TLS=true    # порт 587
SMTP_START_TLS=false   # если уже SSL или plain
```

### SMTP_USE_TLS
**Тип:** `bool` | **Default:** `false`

**Описание:** Использовать implicit TLS (сразу шифрованное соединение). Обычно для порта 465.

```bash
SMTP_USE_TLS=false  # для STARTTLS (587)
SMTP_USE_TLS=true   # для implicit TLS (465)
```

### SMTP_FROM
**Тип:** `str` | **Default:** `VidConf <no-reply@vidconf.example>`

**Описание:** From адрес в письмах (имя + email).

```bash
SMTP_FROM=VidConf <no-reply@vidconf.example>
SMTP_FROM=noreply@example.com
```

### SMTP_TIMEOUT_S
**Тип:** `int` | **Default:** `30`

**Описание:** Таймаут SMTP операций в секундах.

```bash
SMTP_TIMEOUT_S=30
```

---

## Примеры конфигурации

### Dev (console backend)
```bash
# Database & Redis
DATABASE_URL=postgresql+asyncpg://vidconf:vidconf@localhost:5432/vidconf
REDIS_PASSWORD=change-me-redis-secret
REDIS_URL=redis://:change-me-redis-secret@localhost:6379/0

# App
PLUGINS_CONFIG_PATH=config/plugins.yaml
JWT_SECRET=dev-only-secret-change-me
FRONTEND_URL=http://localhost:5173

# LiveKit
LIVEKIT_URL=ws://localhost:7880
LIVEKIT_PUBLIC_URL=ws://localhost:7880
LIVEKIT_API_KEY=devkey
LIVEKIT_API_SECRET=...

# Seed
SEED_ADMIN_EMAIL=admin@vidconf.example
SEED_ADMIN_PASSWORD=change-me

# Email (только логирование)
EMAIL_BACKEND=console

# Media (аватары)
MEDIA_ROOT=/app/media
```

### Проде (SMTP, TLS)
```bash
# Database & Redis
DATABASE_URL=postgresql+asyncpg://vidconf:secure-pass@db.example.com:5432/vidconf
REDIS_PASSWORD=redis-password
REDIS_URL=redis://:redis-password@redis.example.com:6379/0

# App
PLUGINS_CONFIG_PATH=config/plugins.yaml
JWT_SECRET=<generated-long-random-key>
ACCESS_TOKEN_TTL_MINUTES=15
REFRESH_TOKEN_TTL_DAYS=14
AUTH_COOKIE_SECURE=true
FRONTEND_URL=https://vidconf.example.com

# LiveKit
LIVEKIT_URL=http://livekit:7880
LIVEKIT_PUBLIC_URL=wss://livekit.example.com
LIVEKIT_API_KEY=your-key
LIVEKIT_API_SECRET=your-secret

# Seed
SEED_ADMIN_EMAIL=admin@vidconf.example
SEED_ADMIN_PASSWORD=<strong-password>

# Email
EMAIL_BACKEND=smtp
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USERNAME=apikey
SMTP_PASSWORD=SG.xxxxx...
SMTP_START_TLS=true
SMTP_USE_TLS=false
SMTP_FROM=VidConf <noreply@vidconf.example>
SMTP_TIMEOUT_S=30

# Media (аватары)
MEDIA_ROOT=/var/lib/vidconf/media

# Recordings
RECORDINGS_DIR=/mnt/recordings

# Transcription
```

---

## Безопасность

1. **Никогда не коммитьте `.env` в git** — используйте `.gitignore`
2. **Регулярно ротируйте JWT_SECRET** (потребует переlogin'ования пользователей)
3. **Используйте окружение для production credentials** (никогда не hardcod'ьте)
4. **Проверьте SMTP_PASSWORD в логах** — их быть не должно (логирование маскирует пароли)
5. **Для SMTP используйте app passwords** (не основной пароль аккаунта)

---

## Ссылки

- [.env.example](../../.env.example) — шаблон переменных для dev
- [backend/core/config.py](../../backend/core/config.py) — парсинг Settings в коде
