# Деплой и эксплуатация

От «запустил на ноуте» до «живёт на VPS и не стыдно показать security.md».

## Среды

```mermaid
flowchart LR
  Dev[docker-compose.yml] --> St[staging]
  St --> QA[k6 + ZAP + E2E]
  QA --> Prod[production]
```

| Среда | Compose | APP_ENV | Docs | Demo users |
|-------|---------|---------|------|------------|
| Dev | `docker-compose.yml` | development | ✅ | ✅ |
| CI/E2E | `docker-compose.test.yml` | test | ✅ | ✅ |
| Staging | `infra/docker/docker-compose.staging.yml` | staging | ❌ | ❌ |
| Production | `infra/docker/docker-compose.prod.yml` | production | ❌ | ❌ |

## Локальная разработка

```bash
# 1. venv + зависимости backend (один раз)
python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -r apps/api/requirements-dev.txt

# 2. Секреты установки (один раз, до первого docker compose up)
python apps/api/scripts/bootstrap_install.py

# 3. Полный стек в Docker (API + БД + web)
docker compose --profile docker-web up -d --build

# 4. Проверка
curl http://localhost:8000/api/v1/health
```

| Сервис | URL |
|--------|-----|
| Web | http://localhost:5173 |
| API | http://localhost:8000 |
| PG/Redis/MinIO на хост | `docker-compose.dev-ports.yml` → 5432, 6379, 9000/9001 |

> Bootstrap и локальные тесты (`pytest`, `mypy`) — через активированный `.venv`. Docker API использует свой образ; venv нужен для скриптов и разработки на хосте.

**Гибрид** (инфра в Docker, frontend локально):

```bash
source .venv/bin/activate
docker compose up -d
pnpm install
pnpm --filter web dev
```

**Install secrets на хост** (DBeaver): Admin → Security → Install Secrets → Reveal DB password.

### Стандартные логины (dev)

Создаются при seed на старте API. Пароли по умолчанию — из `apps/api/.env.example` (или дефолты в `config.py`).

| Email | Пароль | Env | Роль | Superuser | Куда заходит |
|-------|--------|-----|------|:---------:|--------------|
| `admin@compton.example` | `Admin1234` | `ADMIN_INITIAL_PASSWORD` | admin | да | `/admin` — Users, Content, Security, Diagnostics, secrets |
| `ops@compton.example` | `OpsAdmin1234` | `DEMO_OPS_PASSWORD` | admin | нет | `/admin` — Users, Content, Activity (без Security) |
| `user@compton.example` | `User1234` | `DEMO_USER_PASSWORD` | user | — | `/profile` |

**CMS-страницы (seed):** `about`, `privacy`, `terms` → `/pages/about` и т.д.

> **Staging/production:** `SEED_DEMO_USERS=false` — demo `user@` и `ops@` **не создаются**, только admin + CMS. Пароль admin задаётся через `ADMIN_INITIAL_PASSWORD` **до первого seed**, потом — сменить в UI.

## Staging

**Нужно:** VPS, DNS, TLS certs в `infra/docker/certs/`, SMTP.

```bash
git clone https://git.groupkomton.ru/Matvey/site.git && cd site
python3 apps/api/scripts/bootstrap_install.py
cp infra/docker/.env.staging.example infra/docker/.env.staging
# правим: домен, CORS, SMTP, ADMIN_INITIAL_PASSWORD
./infra/docker/deploy-staging.sh
```

Проверка:

```bash
curl -fsS https://STAGING/api/v1/health
curl -fsS -o /dev/null -w "%{http_code}" https://STAGING/api/v1/docs   # 404
./infra/scripts/health-check.sh https://STAGING
```

Nginx: `default.tls.conf` — 80→443, HSTS.

## Production

```bash
python3 apps/api/scripts/bootstrap_install.py
cp infra/docker/.env.production.example infra/docker/.env.production
./infra/docker/deploy-prod.sh infra/docker/.env.production
```

**Сразу после bootstrap:**
1. Бэкап `install.env` off-server (зашифровать)
2. Сменить пароль admin

| Сервис | Host ports |
|--------|------------|
| nginx | 80, 443 |
| api, web, pg, redis, minio | internal only |

```bash
./infra/scripts/smoke-prod.sh https://YOUR_DOMAIN
```

### Rollback

```bash
docker compose -f infra/docker/docker-compose.prod.yml down
git checkout PREVIOUS_TAG
./infra/docker/deploy-prod.sh infra/docker/.env.production
```

## Бэкапы и мониторинг

| Что | Команда / как |
|-----|---------------|
| PostgreSQL | `./infra/scripts/backup-postgres.sh` → `backups/postgres-*.sql.gz` |
| install.env | `cp …/install.env backups/install.env.$(date +%F).enc` + gpg |
| Uptime | `./infra/scripts/health-check.sh URL` или UptimeRobot на `/api/v1/health` + `/` |
| Логи | logrotate для `server.log`, `admin-audit.jsonl` |

## Восстановление секретов

`install.env` — единственный источник runtime-секретов. Потеряли — не генерируйте новый вслепую.

### Симптомы

- `password authentication failed for user "compton_app"`
- bootstrap после того, как Postgres volume уже создан

### Fix (есть бэкап)

```bash
docker compose down
# восстановить apps/api/data/secrets/install.env
docker compose up -d --build
```

### Fix (нет бэкапа)

| Вариант | Данные |
|---------|--------|
| Reveal из другой среды | сохраняются |
| `down -v` + bootstrap (**только dev**) | **удаляются все** |

```bash
docker compose --profile docker-web down -v
python apps/api/scripts/bootstrap_install.py
docker compose --profile docker-web up -d --build
```

## SMTP

Staging/prod: `EMAIL_DELIVERY_MODE=smtp`. Dev: `memory` (письма в RAM, SMTP не нужен).

| Env | Назначение |
|-----|------------|
| `SMTP_HOST`, `SMTP_PORT`, `SMTP_FROM` | сервер |
| `FRONTEND_URL` | ссылки в письмах |

## Troubleshooting

| Проблема | Решение |
|----------|---------|
| `install.env missing` | `python apps/api/scripts/bootstrap_install.py` |
| `password authentication failed` | [восстановление секретов](#восстановление-секретов) |
| Login failed | `curl …/health`, проверить `.env`, restart web |
| 401 refresh в консоли (гость) | норма на публичных страницах |
| Logout после F5 на `/admin` | rebuild web, перелогиниться |
| «На сайт» ведёт на login | должно быть `href="/"`, rebuild |
| Port 5173 busy | stop Docker web **или** local Vite |
| CORS | `VITE_USE_API_PROXY=true`, не бить напрямую :8000 |
| Нет Security/Diagnostics | логин `admin@`, не `ops@` |
| Docker web: missing modules | `docker compose … up -d --build web` |

## Compose-справочник

| Файл | Назначение |
|------|------------|
| `docker-compose.yml` | dev |
| `docker-compose.dev-ports.yml` | порты на хост |
| `docker-compose.test.yml` | CI/E2E |
| `infra/docker/docker-compose.staging.yml` | staging |
| `infra/docker/docker-compose.prod.yml` | production |

Deploy: `infra/docker/deploy-staging.sh`, `deploy-prod.sh`.
