diff --git a/deploy/dev-stand.md b/deploy/dev-stand.md new file mode 100644 index 0000000..175025e --- /dev/null +++ b/deploy/dev-stand.md @@ -0,0 +1,108 @@ +# dev/staging стенд awg-dash — runbook + +Задача **#21** (эпик **#15**). Стенд для локальной разработки и проверки +acceptance criteria до появления staging-окружения. + +* Docker-хост: **192.168.1.147** (`ssh root@192.168.1.147`), Docker 29.4.x + compose v5. +* Каталог состояния: **`/opt/awg-dash-dev/{config,data}`** (bind mount → `/config`, `/data`). +* Compose project: **`awg-dash-dev`** (изолирован от PoC-контейнеров `amneziawg-client`). +* Хост-порт приложения: **8180** (`AWG_DASH_PORT`), внутри контейнера — **8080**. + Порт 8080 на dev-хосте занят другим сервисом (drawio), поэтому проброс нестандартный. + +## Быстрый старт + +```bash +# на Docker-хосте, из корня репозитория +export AWG_DASH_HOST_DIR=/opt/awg-dash-dev +make dev-up # docker compose up -d --build (проект awg-dash-dev) +make dev-verify # проверка AC: health 200 + состояние переживает restart +curl -fsS http://127.0.0.1:8180/api/v1/health +make dev-logs # логи контейнера +make dev-down # остановить (каталоги состояния сохраняются) +``` + +До реализации FastAPI-каркаса (**#31**) `/api/v1/health` не отвечает — контейнер +работает как агент и помечается `unhealthy`. Чтобы проверить плумбинг стенда +(порт, healthcheck, тома, restart) **до** #31, используйте health-заглушку: + +```bash +make dev-up-stub # + deploy/docker-compose.stub.yml (DEV-ONLY, api_stub.py) +make dev-verify-stub # AC-1 проходит на заглушке, в отчёте api=stub +``` + +Заглушка отвечает `{"status":"ok","stub":true,...}` только на `/api/v1/health` и +никогда не должна использоваться в staging/prod. + +## Проверка AC (#21) + +| AC | Команда | Ожидание | +|---|---|---| +| AC-1: health 200 | `curl -fsS -o /dev/null -w '%{http_code}' http://127.0.0.1:8180/api/v1/health` | `200` (после мержа #31; до него — заглушка через `dev-verify-stub`) | +| AC-2: состояние переживает restart | `make dev-verify` | маркеры в `/config` и `/data` совпадают до и после `docker compose restart` и `--force-recreate` | +| AC-3: netns + мок-endpoint | `make test-netns` | 8/8 тестов, netns `awgt21-{client,gw,uplink}` создаются и сносятся | + +`deploy/verify-dev-stand.sh` (за `make dev-verify`) печатает отчёт и возвращает: + +| Код | Значение | +|---|---| +| 0 | AC-1 и AC-2 выполнены | +| 1 | регрессия стенда (health не 200 с заглушкой, состояние не сохранилось) | +| 2 | AC-1 заблокирован: API (#31) ещё не реализован, стенд при этом поднят | +| 3 | заблокировано окружением: нет docker/compose или compose-файлов | + +## Состав стенда + +| Файл | Назначение | +|---|---| +| `docker-compose.dev.yml` | приложение: порт 8080 (наружу `${AWG_DASH_PORT:-8180}`), bind mount `/config` `/data`, healthcheck, NET_ADMIN/NET_RAW/SYS_MODULE, `/dev/net/tun` | +| `docker-compose.stub.yml` | DEV-ONLY оверрайд: health-заглушка до #31 (`api_stub.py`) | +| `docker-compose.test.yml` | тестовый стенд: привилегированный `netns`-раннер + `app` для API-тестов | +| `api_stub.py` | минимальный HTTP-сервер `/api/v1/health` (только dev) | +| `verify-dev-stand.sh` | проверка AC на Docker-хосте + JSON-отчёт | +| `../tests/netns/` | netns-харнесс: топология client/gw/uplink + мок WireGuard-endpoint | + +## Переменные окружения + +| Переменная | По умолчанию | Назначение | +|---|---|---| +| `AWG_DASH_PORT` | `8180` | хост-порт приложения | +| `AWG_DASH_HOST_DIR` | `/opt/awg-dash-dev` | каталог состояния на хосте | +| `AWG_DASH_IMAGE` | `awg-dash:dev` | имя образа (build или pull) | +| `AWG_DASH_DOCKERFILE` | `deploy/Dockerfile` | путь к Dockerfile для build | +| `COMPOSE_PROJECT_NAME` | `awg-dash-dev` | изоляция от других стендов | +| `AWG_LOG_LEVEL` | `info` | уровень логирования приложения | + +## Зависимости + +| Зависимость | Состояние | Влияние на стенд | +|---|---|---| +| #16 (каркас репо, Makefile) | PR #47 | нужен `Makefile`, `requirements.txt`, `deploy/` | +| #18 (образ, entrypoint) | PR #49 | нужен `deploy/Dockerfile` для `--build` | +| #31 (каркас FastAPI, `/api/v1/health`) | Sprint 2 | без него AC-1 выполняется только с заглушкой | +| #17 (CI-пайплайн) | Sprint 0 | `make test-netns-ci`, `make test-manifests` — готовые гейты для пайплайна | + +## Откат и уборка + +```bash +make dev-down # остановить контейнеры проекта awg-dash-dev +make dev-reset # down --remove-orphans (состояние сохраняется) +docker image rm awg-dash:dev # откатить образ (пересобрать из предыдущего коммита) +du -sh /opt/awg-dash-dev # состояние стенда +``` + +Перед откатом образа проверьте проект: `docker compose -p awg-dash-dev ls`. +Состояние (`/opt/awg-dash-dev`) не удаляется автоматически — это осознанно: там +конфиги туннеля (`/config/awg0.conf`). Удаляйте вручную и только после бэкапа. + +## Pitfalls + +* **Порт 8080 занят** на dev-хосте — наружу публикуется 8180. Меняйте `AWG_DASH_PORT`. +* **`/dev/net/tun` обязателен**: без него entrypoint падает (`fail '/dev/net/tun не проброшен'`). +* **Права на каталоги состояния**: entrypoint делает `chown awg:awg /config /data`; + каталоги создаются на хосте от root — не меняйте владельца на хосте вручную. +* **`docker compose restart` сохраняет тома**; `down -v` — нет. Никогда не используйте + `down -v` на этом стенде: это удалит `/config` и `/data`. +* **Заглушка `api_stub.py`** — только dev: она отвечает 200 на `/api/v1/health` и + маскирует отсутствие API. Не включайте `docker-compose.stub.yml` в staging. +* **netns-стенд вне Docker** требует root: `make test-netns` вернёт код 3, если нет + CAP_NET_ADMIN/CAP_SYS_ADMIN (например, в непривилегированном CI-раннере).