Шхуна не тонет: security, infra и доки на русском.
Безопасность довёл до ума — Cursor-генерацию переписал руками. IDOR закрыл, CSRF задушил, refresh rotation теперь как надо. HSTS на staging, ENABLE_DOCS=false, install.env recovery протестил. Backend: - jwt_denylist + auth_epoch: мгновенный revoke access JWT (logout/block/reset) - auth/admin/users: bump epoch, logout с Bearer, forgot_password skip для blocked - install_secrets: путь всегда apps/api/data/secrets/ (bootstrap из корня не ломает Docker) - seed: SEED_DEMO_USERS=false на prod/staging - тесты: jwt revoke, integration, coverage gate 90% Frontend: - logout шлёт Bearer, обработка TOKEN_REVOKED - guards TypeScript fix - E2E: blocked user → 401 сразу после block Infra: - staging/prod compose, TLS nginx, deploy-скрипты - k6 §17.2, backup/health/smoke scripts Docs: - docs/ на русском: project, security, deploy, release (старые md слили) - README короткий + план ТЗ + стандартные логины dev Код готов к плаванию. Капитан может идти писать фронт.
This commit is contained in:
+196
@@ -0,0 +1,196 @@
|
||||
# Деплой и эксплуатация
|
||||
|
||||
От «запустил на ноуте» до «живёт на 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`.
|
||||
Reference in New Issue
Block a user