Files
netrunner-backend/DEPLOYMENT.md
T
nineap 1a26403afb Переключить dev Caddy на порт 443 вместо 8443
Telegram Login Widget в браузере требует именно порт 443 — его CSP
frame-ancestors от oauth.telegram.org не учитывает порт домена и всегда
подразумевает дефолтный порт схемы, поэтому на 8443 виджет рендерился, но
iframe блокировался как cross-origin. VPN-нода, ранее занимавшая 443 на
dev VPS, перенесена на другой порт, так что конфликта больше нет.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 20:00:09 +07:00

107 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Netrunner Control Plane — разработка и деплой
## Локальная разработка (fully-dockerized, hot-reload)
Весь стек поднимается одной командой — Postgres, Redis и приложение с
автоперекомпиляцией (`cargo-watch`). Локальный хостовый Rust не нужен.
```bash
make dev # db + redis + app (http://localhost:8080)
make dev-logs # логи приложения
make dev-down # остановить (тома/кеши сохраняются)
make clean # снести стек вместе с БД и кешем компиляции
```
- Конфиг — `.env.dev` (бот выключен: `BOT_ENABLED=false`, реальный токен Telegram не нужен).
- Миграции накатываются автоматически при старте `app` (`cargo run -- --migrate`).
- Healthcheck: `GET /health` (liveness), `GET /health/ready` (readiness, пингует БД).
- Первый запуск компилирует всё (несколько минут); дальше — инкрементально через тома `target_cache` / `cargo_registry`.
Качество кода (то же, что гоняет CI):
```bash
make fmt # форматирование
make lint # clippy -D warnings
make test # тесты (нужен Postgres + DATABASE_URL)
```
## Пайплайн (CI/CD)
Три воркфлоу в `.github/workflows/`:
| Workflow | Триггер | Что делает |
|----------|---------|------------|
| `ci.yml` | PR, push в `main` | `fmt --check`, `clippy -D warnings`, тесты на эфемерном Postgres |
| `build.yml` | push в `main`, тег `v*`, вручную | Собирает Docker-образ (cargo-chef + GHA-кеш слоёв) и пушит в GHCR |
| `deploy.yml``deploy-dev` | **авто**, сразу после успешного `build.yml` на `main` | SSH на dev VPS: pull образа `latest` → миграции → перезапуск (`docker-compose.dev-remote.yml`) |
| `deploy.yml``deploy-prod` | **только вручную** (Actions → Run workflow) | SSH на прод VPS: pull образа → миграции → перезапуск (`docker-compose.prod.yml`) |
Компиляция Rust происходит **в GitHub Actions**, а не на машине разработчика и
не на VPS. Сервер только тянет готовый образ — деплой занимает секунды.
Сборка не требует доступа к БД (sqlx работает в offline-режиме).
### Ручной деплой (прод)
GitHub → **Actions****Deploy****Run workflow**
(можно указать тег образа, по умолчанию `latest`).
Dev-окружение отдельного ручного шага не требует — обновляется само после каждого
успешного билда `main`.
### Секреты GitHub (Settings → Secrets → Actions)
- `VPS_IP` / `SSH_PRIVATE_KEY` — прод-сервер
- `DEV_VPS_IP` / `DEV_SSH_PRIVATE_KEY` — dev-сервер (`45.76.161.137`, DNS
`dev.netrunner-vpn.com`; на нём же по аналогии деплоится dev-версия
`netrunner-landing`, см. её `DEPLOYMENT`/README). Домен, а не голый IP,
используется во всех browser-facing URL (`WEB_APP_BASE_URL`,
`CORS_ALLOWED_ORIGINS` и т.п.) — Telegram Login Widget не работает на IP
(`/setdomain` в BotFather принимает только доменное имя).
- `GHCR_TOKEN` — токен GHCR с правом `read:packages` (для pull на VPS, обоих)
`GITHUB_TOKEN` для push в GHCR выдаётся автоматически.
Отдельно на самом dev VPS (не GitHub-секрет, а переменная в `.env` рядом с
`docker-compose.dev-remote.yml`) — `CF_API_TOKEN`: Cloudflare-токен для Caddy
(DNS-01 challenge, см. ниже), шаблон "Edit zone DNS", ограниченный зоной
`netrunner-vpn.com`. Не Global API Key.
### Что должно лежать на VPS (`/root/netrunner-core`)
- `docker-compose.prod.yml`
- `.env` (прод-секреты; `APP_ENV=production`, `BOT_ENABLED=true`, реальные токены)
- `keys/netrunner_master_ed25519[.pub]` — мастер-ключ для провижининга нод
- конфиги мониторинга: `prometheus.yml`, `loki-config.yml`, `promtail-config.yml`, `grafana-datasources.yml`
Прод-стек (`docker-compose.prod.yml`) поднимает: `migrate` (one-shot миграции) →
`app` (с healthcheck) + `db` + `redis` + Prometheus/Loki/Promtail/Grafana.
### Что должно лежать на dev VPS (`/root/netrunner-core`)
- `docker-compose.dev-remote.yml`, `Dockerfile.caddy`, `Caddyfile.dev` (все три
синкает CI при каждом `deploy-dev`, руками копировать не нужно)
- `.env` (см. [`.env.dev-remote.example`](.env.dev-remote.example) — свои
`JWT_SECRET`/`ARGON_SALT`/`DB_PASSWORD`, `CF_API_TOKEN`,
`CORS_ALLOWED_ORIGINS`/`CSRF_ALLOWED_ORIGINS` включают origin dev-лендинга и
Caddy-порта на этом же хосте)
- `keys/netrunner_master_ed25519[.pub]` — свой мастер-ключ, отдельный от прода
Dev-стек: `migrate``app` (порт `8080`, обычный HTTP, без TLS) + `db` + `redis`
+ `caddy` (порт `443`, реальный TLS через DNS-01/Cloudflare — см.
[`Caddyfile.dev`](Caddyfile.dev)). Caddy здесь нужен по двум причинам: Telegram
Web Apps (кнопки бота "Личный Кабинет"/"Тарифы"/"Синдикат") требуют `https://`
URL, а Telegram Login Widget в обычном браузере требует именно порт 443 (его
CSP `frame-ancestors` не учитывает порт и всегда подразумевает дефолтный порт
схемы). Порт 80 на этом VPS закрыт — обычный HTTP-01 challenge не проходит,
поэтому DNS-01. Все браузерные auth-флоу (бот, лендинг) должны идти через
Caddy на 443, не напрямую в `:8080``COOKIE_SECURE=true` (как в проде), и
Secure-cookie по голому HTTP на `:8080` браузер по-прежнему отбросит.
### Локальная сборка образа (фолбэк, обычно не нужно)
```bash
make build-image # docker build -t $IMAGE .
make push-image # docker push $IMAGE
# или ./deploy.sh — собрать и запушить разом
```