# Быстрый запуск

Примеры команд для **PowerShell**. Репозиторий: корень `EvoBGP`, Docker Compose лежит в `deploy\compose`.

## Требования

- **Docker** с поддержкой Compose v2 — для готового стека.
- **Go 1.22+** (версию см. в `go.mod`) — для локального запуска бинарников из исходников.
- **Node.js** и npm — для разработки веб-интерфейса в `web/`.
- **PostgreSQL** — если запускаете API вне Compose; строка подключения в `EVOBGP_DATABASE_URL`.

## Готовые образы без сборки (Container Registry Gitea)

После успешного CI (push в `main` или `master`) образы публикуются в **Container Registry** вашего Gitea. В workflow зафиксирован хост реестра **`git.shts.su`**; имя владельца в пути образа — **в нижнем регистре**, как у `github.repository_owner` в CI (например, пользователь `Denozord` → префикс `denozord`).

### Шаблон имени и теги

```text
git.shts.su/<owner>/<имя_образа>:<тег>
```

**Теги:** `latest`, короткий SHA коммита (7 символов), `sha-<полный_sha>` — см. [.gitea/README.md](../.gitea/README.md).

**Платформа образов из CI:** `linux/amd64` (на другой архитектуре pull пройдёт, но запуск может быть невозможен без своей сборки).

### Вход в реестр (если пакеты не публичные)

На сервере или в PowerShell перед `docker pull`:

```powershell
docker login git.shts.su
```

Укажите учётную запись Gitea и **PAT / пароль приложения** с правом чтения пакетов (или токен, который принимает ваш реестр).

### Ссылки и команды `docker pull`

Ниже пример для владельца **`denozord`** — замените сегмент пути на своего владельца репозитория в нижнем регистре. В веб-интерфейсе все контейнерные пакеты можно открыть разом: [список пакетов `denozord` на git.shts.su](https://git.shts.su/denozord/-/packages). Если прямая ссылка на версию `latest` не открывается (зависит от версии Gitea), откройте общий список пакетов и выберите нужный образ по имени.

| Образ | Назначение | Страница пакета (пример) | Pull |
|--------|------------|--------------------------|------|
| `evobgp-api` | HTTP API (с `birdc` в образе) | [packages/…/evobgp-api](https://git.shts.su/denozord/-/packages/container/evobgp-api/latest) | `docker pull git.shts.su/denozord/evobgp-api:latest` |
| `evobgp-all` | Монолит microVPS: API + in-process воркеры scheduler/ingest/render/deploy | [packages/…/evobgp-all](https://git.shts.su/denozord/-/packages/container/evobgp-all/latest) | `docker pull git.shts.su/denozord/evobgp-all:latest` |
| `evobgp-scheduler` | Планировщик (reference) | [packages/…/evobgp-scheduler](https://git.shts.su/denozord/-/packages/container/evobgp-scheduler/latest) | `docker pull git.shts.su/denozord/evobgp-scheduler:latest` |
| `evobgp-ingest` | Ingest CDN / ETag | [packages/…/evobgp-ingest](https://git.shts.su/denozord/-/packages/container/evobgp-ingest/latest) | `docker pull git.shts.su/denozord/evobgp-ingest:latest` |
| `evobgp-render` | Render | [packages/…/evobgp-render](https://git.shts.su/denozord/-/packages/container/evobgp-render/latest) | `docker pull git.shts.su/denozord/evobgp-render:latest` |
| `evobgp-deploy` | Deploy | [packages/…/evobgp-deploy](https://git.shts.su/denozord/-/packages/container/evobgp-deploy/latest) | `docker pull git.shts.su/denozord/evobgp-deploy:latest` |
| `evobgp-node` | Нода на площадке | [packages/…/evobgp-node](https://git.shts.su/denozord/-/packages/container/evobgp-node/latest) | `docker pull git.shts.su/denozord/evobgp-node:latest` |
| `evobgp-web` | Статика UI + nginx (прокси на **evobgp-api**) | [packages/…/evobgp-web](https://git.shts.su/denozord/-/packages/container/evobgp-web/latest) | `docker pull git.shts.su/denozord/evobgp-web:latest` |
| `evobgp-web-all` | Тот же UI, прокси на **evobgp-all** (профиль `microvps-full`) | [packages/…/evobgp-web-all](https://git.shts.su/denozord/-/packages/container/evobgp-web-all/latest) | `docker pull git.shts.su/denozord/evobgp-web-all:latest` |
| `evobgp-agent` | Агент (bird2 в образе) | [packages/…/evobgp-agent](https://git.shts.su/denozord/-/packages/container/evobgp-agent/latest) | `docker pull git.shts.su/denozord/evobgp-agent:latest` |
| `evobgp-bird2` | Только BIRD2 | [packages/…/evobgp-bird2](https://git.shts.su/denozord/-/packages/container/evobgp-bird2/latest) | `docker pull git.shts.su/denozord/evobgp-bird2:latest` |

На **Linux-сервере** команды `docker pull` и `docker login` такие же (выполняйте в обычном shell).

### Запуск контейнера с готового образа (минимум)

После pull, например только API (порты и переменные подставьте свои):

```powershell
docker run --rm -p 8080:8080 `
  -e EVOBGP_DATABASE_URL="postgres://user:pass@host:5432/evobgp?sslmode=disable" `
  -e EVOBGP_HTTP_ADDR=":8080" `
  git.shts.su/denozord/evobgp-api:latest
```

**Compose** в `deploy/compose` поднимает стек **только из образов реестра** (`image:`, без локальной сборки). Префикс и тег задаются через **`.env`** рядом с compose-файлами (шаблон — [deploy/compose/.env.example](../deploy/compose/.env.example)): `EVOBGP_REGISTRY=git.shts.su/<owner>` (владелец в **нижнем регистре**), `EVOBGP_IMAGE_TAG=latest` или SHA. Перед первым запуском: `docker login git.shts.su`, затем `docker compose pull` и `docker compose ... up -d`. Имена пакетов и CI — [.gitea/README.md](../.gitea/README.md).

## Вариант 1: Docker, профиль microvps

Один процесс `evobgp-all` (HTTP API + in-process воркеры scheduler, ingest, render, deploy), PostgreSQL, BIRD2, `evobgp-agent`.

```powershell
cd deploy\compose
Copy-Item .env.example .env -Force   # или создайте .env вручную; укажите EVOBGP_REGISTRY / EVOBGP_IMAGE_TAG
docker login git.shts.su
docker compose --profile microvps pull
docker compose --profile microvps up -d
```

Ожидаемые сервисы:

- **API:** `http://localhost:8080` (внутри контейнера `EVOBGP_HTTP_ADDR=:8080`).
- **BGP:** порт **179/tcp** проброшен с контейнера BIRD (для отладки; в проде часто нужен `network_mode: host` или отдельная сеть — см. комментарии в `docker-compose.yaml`).

Проверка живости (без ключа):

```powershell
Invoke-RestMethod -Uri "http://localhost:8080/v1/health"
```

Остановка:

```powershell
docker compose --profile microvps down
```

Полная очистка томов (осторожно, удалит данные БД):

```powershell
docker compose --profile microvps down -v
```

## Вариант 1b: microVPS ~1 ГиБ RAM — полный набор + Web UI

Один монолит **`evobgp-all`** (те же in-process воркеры, что и в варианте 1), плюс **статическая панель** за nginx (`evobgp-web-microvps`), **NATS JetStream** (как в reference, для `EVOBGP_BROKER_URL` и будущей интеграции) и **Prometheus** со скрейпом метрик с `evobgp-all`. Отдельные контейнеры `evobgp-scheduler` / `evobgp-ingest` / … не нужны — это не дублирование логики, а тот же код в одном процессе.

**Рекомендация:** на хосте с ровно **1 ГиБ** включите **swap** (1–2 ГиБ), иначе при пиках возможен OOM. На **2+ ГиБ** можно поднять тот же профиль **без** второго файла — останутся более мягкие лимиты из основного `docker-compose.yaml`.

Из каталога `deploy\compose` (как в варианте 1: `.env` из `.env.example`, при необходимости `docker login git.shts.su`):

1. Подготовьте отдельный файл параметров защищенного UI:

```powershell
Copy-Item .env.web-sec.example .env.web-sec -Force
```

2. Заполните в `.env.web-sec`:
- `WEBUI_DOMAIN` — домен панели;
- `WEBUI_IP_WHITELIST` — список разрешенных IP/CIDR через запятую;
- `LETSENCRYPT_EMAIL` — email для ACME;
- `CF_DNS_API_TOKEN` — Cloudflare token для `DNS challenge` (минимальные права `Zone:DNS:Edit` на нужной зоне).

3. В Cloudflare для `WEBUI_DOMAIN` используйте запись в режиме **DNS only** (серый облачок), указывающую на публичный IP VPS.

4. Запускайте compose с двумя env-файлами:

```powershell
# С ужатыми лимитами и EVOBGP_BROKER_URL=nats://… (ориентир под ~1 ГиБ RAM на хосте)
docker compose --env-file .env --env-file .env.web-sec -f docker-compose.yaml -f docker-compose.microvps-full.yaml --profile microvps-full pull
docker compose --env-file .env --env-file .env.web-sec -f docker-compose.yaml -f docker-compose.microvps-full.yaml --profile microvps-full up -d
```

Только профиль `microvps-full` и **без** файла `docker-compose.microvps-full.yaml` (лимиты как в базовом compose, без принудительной подстановки брокера в `evobgp-all`):

```powershell
docker compose --env-file .env --env-file .env.web-sec --profile microvps-full pull
docker compose --env-file .env --env-file .env.web-sec --profile microvps-full up -d
```

При необходимости задайте брокер вручную для `evobgp-all` (override или `.env` рядом с compose): `EVOBGP_BROKER_URL=nats://nats:4222`.

| Порт | Назначение |
|------|------------|
| **80** | HTTP вход (редирект на HTTPS через Traefik) |
| **443** | HTTPS Web UI (Traefik + Let's Encrypt) |
| **8080** | Прямой HTTP API (`evobgp-all`) |
| **9090** | Prometheus (`prometheus-microvps`) |
| **4222** | NATS |
| **179** | BGP (BIRD2), как в варианте 1 |

Проверка UI:
- `http://<WEBUI_DOMAIN>` должен редиректить на `https://<WEBUI_DOMAIN>`;
- с IP из `WEBUI_IP_WHITELIST` UI доступен по HTTPS;
- с неразрешенного IP Traefik вернет `403`.
- исключение: `GET /v1/firewall/install.sh`, `GET /v1/firewall/sync-script`, `POST /v1/firewall/enroll` — публичные, без whitelist (см. [firewall.md](firewall.md)).

Health API: `http://<IP>:8080/v1/health`.

### Файловые runtime-логи (API `/v1/runtime-logs/*`)

В профиле **microvps-full** и в standalone `stack.microvps-full.yaml` sidecar **`stack-runtime-logs`** пишет `docker logs` каждого сервиса в `*.log` на хосте. Каталог по умолчанию — **`./runtime-logs`** рядом с compose-файлами; на production-хосте задайте **`EVOBGP_RUNTIME_LOGS_HOST_DIR=/opt/evobgp/runtime-logs`** (см. `deploy/compose/.env.stack.microvps-full.example`).

Контейнер **`evobgp-all`** монтирует тот же каталог в **`/opt/evobgp/runtime-logs`** и включает FS API при `EVOBGP_SERVICE=evobgp-all` и `EVOBGP_RUNTIME_LOGS_DIR=/opt/evobgp/runtime-logs` (уже в compose). Просмотр и очистка — в Web UI (Monitoring → «Файловые логи») или через REST; детали — [docs/access.md](access.md).

На **`evobgp-api`** (профиль reference) volume не монтируется — эндпоинты отвечают **503** (`runtime_logs_unavailable`).

### Auto-updater для standalone stack (без рестарта BIRD2)

Для `stack.microvps-full.yaml` можно включить автообновление только выбранных сервисов (например, `evobgp-all,evobgp-web`) по digest образов в registry.

В файле `deploy\compose\.env.stack.microvps-full`:

- `AUTO_UPDATE_ENABLED=1` — включить updater;
- `AUTO_UPDATE_INTERVAL_SEC=300` — период проверки;
- `AUTO_UPDATE_SERVICES=evobgp-all,evobgp-web` — allowlist сервисов;
- `AUTO_UPDATE_PROTECTED_SERVICES=bird2` — список защищённых сервисов (по умолчанию `bird2`).

Updater делает `pull` и при изменении образа выполняет `up -d --no-deps` только для сервиса из allowlist. `bird2` в обновление не попадает, пока явно указан в protected-списке.

Важно: updater использует доступ к `docker.sock` (высокие привилегии), включайте осознанно.

Остановка (если поднимали с двумя `-f`):

```powershell
docker compose --env-file .env --env-file .env.web-sec -f docker-compose.yaml -f docker-compose.microvps-full.yaml --profile microvps-full down
```

## Вариант 2: Docker, профиль reference

Эталонное разбиение: отдельные контейнеры `evobgp-api`, `evobgp-scheduler`, `evobgp-ingest`, `evobgp-render`, `evobgp-deploy`, сервис **NATS JetStream** (в compose; привязка очереди задач к брокеру — следующая итерация), веб UI за nginx, опционально Prometheus.

```powershell
cd deploy\compose
Copy-Item .env.example .env -Force
docker login git.shts.su
docker compose --profile reference pull
docker compose --profile reference up -d
```

Полезные порты:

| Порт | Назначение |
|------|------------|
| 8080 | HTTP API (`evobgp-api`) |
| 3000 | Веб UI (`evobgp-web` → nginx, прокси на API) |
| 4222 | NATS |
| 9090 | Prometheus (в compose) |
| 179 | BGP (BIRD2) |

**Воркеры reference:** `evobgp-scheduler` ходит в API по HTTP (`EVOBGP_CONTROL_PLANE_URL`, `EVOBGP_SCHEDULER_BEARER`); в [docker-compose.yaml](../deploy/compose/docker-compose.yaml) для локального запуска включены `EVOBGP_DEV_INSECURE=1` на API и токен `dev` у планировщика. `evobgp-ingest` обновляет ETag CDN-источников; `evobgp-render` по умолчанию не трогает `published_revision` (включите `EVOBGP_RENDER_AUTOPUBLISH=1` осознанно); `evobgp-deploy` пишет в лог расхождение applied vs published. Очередь `jobs` остаётся in-process у **evobgp-api**; общий брокер — в планах.

В **evobgp-all** (microvps) те же пакеты крутятся в одном процессе и используют общий `jobs.Registry` без HTTP.

## Удалённые BGP-спикеры

Реплики на отдельных VPS (bird2 + agent + Traefik): см. **[remote-speakers.md](remote-speakers.md)**. На CP включите `EVOBGP_NODE_DISPATCH_ENABLED=1` и зафиксируйте `EVOBGP_BUNDLE_SEED_HEX`. Compose: `deploy/compose/docker-compose.remote-speaker.yaml`.

## Вариант 3: Локально без Docker (только API)

1. Поднимите PostgreSQL и создайте БД (или используйте существующую).
2. Установите переменные окружения в текущей сессии PowerShell:

```powershell
$env:EVOBGP_DATABASE_URL = "postgres://user:pass@localhost:5432/evobgp?sslmode=disable"
$env:EVOBGP_HTTP_ADDR = ":8080"
# Ключи обязательны для защищённых маршрутов (пример формата см. access.md)
$env:EVOBGP_API_KEYS = "op|YOUR_TENANT_ID|operator"
```

3. Запуск только HTTP API:

```powershell
cd <корень-клона-репозитория>
go run .\cmd\evobgp-api
```

Или монолит **microVPS** (тот же API плюс горутины тех же воркеров scheduler/ingest/render/deploy):

```powershell
go run .\cmd\evobgp-all
```

При старте в лог выводится **публичный ключ бандла** (base64) — его нужно передать на сторону `evobgp-node` для проверки подписи. При включённом демо-сиде (`EVOBGP_SEED_DEMO` не равен `0`, поведение по умолчанию) сервер также печатает подсказку с примером `EVOBGP_API_KEYS`.

Для разработки без настройки ключей (только демо-данные):

```powershell
$env:EVOBGP_DEV_INSECURE = "1"
go run .\cmd\evobgp-api
```

Запросы с заголовком `Authorization: Bearer dev` получают роль operator в демо-tenant. **Не включайте в продакшене.**

## Вариант 4: Веб-интерфейс (разработка)

```powershell
cd web
npm install
npm run dev
```

Укажите в окружении API список разрешённых origin для CORS (пример для Vite на порту 5173):

```powershell
$env:EVOBGP_CORS_ORIGINS = "http://localhost:5173,http://127.0.0.1:5173"
```

В эталонном Compose для `evobgp-api` уже заданы origin для 5173 и 3000 — см. `deploy/compose/docker-compose.yaml`.

## Пересборка HTML из OpenAPI

После правок `docs/openapi.yaml`:

```powershell
.\scripts\build-openapi-html.ps1
```

Подробности — [OPENAPI-GITEA.md](OPENAPI-GITEA.md).

## Дальше

- [access.md](access.md) — как выдать ключи и настроить ноду.
- [architecture.md](architecture.md) — состав сервисов и пакетов.
