Files

110 lines
8.3 KiB
Markdown
Raw Permalink 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.
# 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/<N>/` — `Build/`, `TemplateData/`, `index.html`, `ServiceWorker.js` |
| Активная сборка | `/opt/game/current` → симлинк на `releases/<N>` |
| Инструменты | `/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/<N>/` — конкретная сборка (**обязательно со слэшем**);
- `https://smart-updown.binom.pw/<N>/Build/WebGL.data` — ассет конкретной сборки;
- `/api`, `/ws` — **не nginx**: их забирает внешний Traefik (VDS) → куб (ingress `smart-updown-api`).
## Публикация сборки
```bash
# CI fun-game-front2 пушит образ images.binom.pw/fun/game-front2:<N>
# затем на хосте Proxmox:
ssh root@192.168.76.66 "pct exec 152 -- /opt/game/tools/publish-release.sh <N> --activate"
```
Без `--activate` сборка ляжет в `/opt/game/releases/<N>/` и будет доступна по `/<N>/`,
но корень останется прежним. Откат = `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/<N>/
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` каждого слоя и распаковывает по имени файла `<hex>` (не `sha256:...`).
- **Корень — 302 на активную сборку** (`location = / { return 302 /<N>/; }` в
`/etc/nginx/game-active.inc`, пишет `publish-release.sh --activate`). Нужен потому, что
`index.html` Unity зовёт ассеты **относительным** путём (`buildUrl = "Build"`): без редиректа они
запрашивались бы как `/Build/WebGL.wasm` — без номера сборки, а такой URL между релизами НЕ
меняется → `immutable` заставлял браузер неделю отдавать старый билд. С редиректом путь становится
`/29/Build/…` и кэш корректен.
- **`immutable` только для путей с номером сборки** (`~^/[0-9]+/…`). Всё остальное, включая
неверсионированные ассеты, — `no-store` (страховка от отравления кэша).
- ⚠️ Если правишь `game.nginx.conf` — не забудь `include /etc/nginx/game-active.inc;`, иначе корень
снова начнёт раздавать файлы напрямую и мина вернётся.
- **Сборки копятся** (~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. Не тиражировать наружу.
## Именованные сборки (zip от фронтендера) — рядом с номерными
Кроме номерных релизов из CI (`/opt/game/releases/<N>/`) на nginx можно положить **именованную**
сборку — готовый zip от фронтендера, вне релизного цикла:
```bash
# zip сначала доставить на LXC 152 (через хост проксмокса):
scp build.zip root@192.168.76.66:/tmp/build.zip
ssh root@192.168.76.66 "pct push 152 /tmp/build.zip /tmp/build.zip"
# разложить под именем:
ssh root@192.168.76.66 "pct exec 152 -- /opt/game/tools/publish-zip.sh sol /tmp/build.zip"
```
Адрес: **`https://smart-updown.binom.pw/sol/`**. Активную сборку такая публикация **не трогает** —
корень по-прежнему редиректит на текущий номер.
**Питфоллы именованных сборок:**
- Служебные location обязаны иметь **`^~`** (`^~ /api`, `^~ /ws`, `^~ /solana-rpc/`). Regex-локейшн
сборок `^/(?<build>[a-zA-Z0-9][a-zA-Z0-9_-]*)…` иначе перехватит `/api/...` как «сборку с именем
api» — regex в nginx приоритетнее обычного префикса. Без `^~` API ломается (проверено).
- `immutable` — **только для номерных** каталогов (`~^/[0-9]+/…`). Именованную папку могут перезалить
тем же именем → её ассеты кэшировать нельзя.
- Сборки фронтендера бывают на `.unityweb`-ассетах (`Build.wasm.unityweb` и т.п.) — расширение
`unityweb` в маске кэша учтено.
- Имя папки не должно совпадать со служебным путём (`api`, `ws`, `solana-rpc`) — скрипт это проверяет.