# nginx на Proxmox — раздача статики игры (LXC 152) Боевой веб-слой игры «Бинарная ракета»: **корень `smart-updown.binom.pw` раздаётся nginx'ом на LXC 152 с версионированием по каталогам**. Бэк (API/WS) остаётся в кубе — см. ADR-011. ## Что где живёт | Что | Где | |---|---| | LXC | **152 `game-web`**, 192.168.76.152 (Server3, `pct exec 152` через `root@192.168.76.66`) | | nginx-конфиг | `/etc/nginx/sites-available/game` (симлинк в `sites-enabled/`) | | Сборки | `/opt/game/releases//` — `Build/`, `TemplateData/`, `index.html`, `ServiceWorker.js` | | Активная сборка | `/opt/game/current` → симлинк на `releases/` | | Инструменты | `/opt/game/tools/` (`unpack-release.sh`, `publish-release.sh`) | | Логи | `/var/log/nginx/game-access.log`, `game-error.log` | ## Адреса - `https://smart-updown.binom.pw/` — активная сборка; - `https://smart-updown.binom.pw//` — конкретная сборка (**обязательно со слэшем**); - `https://smart-updown.binom.pw//Build/WebGL.data` — ассет конкретной сборки; - `/api`, `/ws` — **не nginx**: их забирает внешний Traefik (VDS) → куб (ingress `smart-updown-api`). ## Публикация сборки ```bash # CI fun-game-front2 пушит образ images.binom.pw/fun/game-front2: # затем на хосте Proxmox: ssh root@192.168.76.66 "pct exec 152 -- /opt/game/tools/publish-release.sh --activate" ``` Без `--activate` сборка ляжет в `/opt/game/releases//` и будет доступна по `//`, но корень останется прежним. Откат = `publish-release.sh <старый N> --activate`. ## Проверка ```bash curl -sI https://smart-updown.binom.pw/ | grep -iE 'server|last-modified' # nginx/1.24.0 (Ubuntu) curl -s -o /dev/null -w '%{http_code}\n' https://smart-updown.binom.pw// curl -s https://smart-updown.binom.pw/api/state | head -c 80 # JSON от шлюза в кубе # сквозная живая приёмка (ставит реальную ставку): cd ~/WORK/games/pump-game-ops && BASE=https://smart-updown.binom.pw/api \ WS_URL=wss://smart-updown.binom.pw/api/ws node tools/autoclose-check.cjs # ждём 9/9 ``` ## Питфоллы - **Слэш в конце обязателен** для версии: `/28` → 301 (редирект на `/28/`). Unity грузит ассеты относительным путём (`Build/WebGL.loader.js`), поэтому без слэша `Build/...` уедет в корень → 404. - **`skopeo ... dir:` пишет OCI-манифест**, где `layers` — словари. `unpack-release.sh` берёт `digest` каждого слоя и распаковывает по имени файла `` (не `sha256:...`). - **Кэш больше не прилипает между релизами**: URL содержит номер сборки → `immutable` корректен. Внутри версии каталог не перезаписывается, поэтому ассеты действительно неизменяемы. - **Сборки копятся** (~68 МБ на версию) — ретеншен пока ручной, см. `TASKS.md`. - **Откат схемы целиком**: вернуть `/opt/traefik/static/smart-updown.yaml` из `/root/bak-smart-updown-nginx-2026-09-15/` на VDS — домен снова пойдёт целиком в куб. ## ⚠️ Приёмка визуально: ошибки шейдеров в headless-браузере — НЕ наш дефект Проверка игры живым браузером (Browserbase/headless, без GPU) показывает: прогресс замирает на 90%, в консоли `ERROR: Shader Hidden/CoreSRP/CoreCopy shader is not supported on this GPU` и Unity-исключение из wasm. **Это артефакт headless-окружения без аппаратного GPU.** Доказательство (контрольный опыт 15.09.2026): тот же образ `game-front2:28` открыт через **старый путь** (`kubectl port-forward` на под в кубе, `http://127.0.0.1:18080/`) — **ровно те же** ошибки шейдеров, ровно те же 90%, те же 11 ресурсов. Значит миграция на nginx тут ни при чём. Что реально проверяемо в headless: заголовки, коды, содержимое, инициализация движка (`Creating WebGL 2.0 context`, `Initialize engine version: 6000.3.16f1`), факт загрузки **всех** ассетов (`/Build/WebGL.wasm` 52 234 795 б, `.data` 18 437 188 б, `.framework.js` 489 223 б — по 200). Отрисовку сцены проверять только на реальном железе с GPU (принятие на железе — за владельцем). ⚠️ `publish-release.sh` содержит креды реестра (`subochev:…`) в открытом виде — файл живёт только внутри LXC 152 как root (`/opt/game/tools/`), в git лежит шаблон из репы ops. Не тиражировать наружу.