5087c67201
- index.html: buildUrl="Build" -> без редиректа ассеты шли как /Build/WebGL.wasm (без номера сборки) под immutable 7д -> браузер неделю отдавал старую сборку - publish-release.sh --activate пишет /etc/nginx/game-active.inc: return 302 /<N>/ - immutable сужен до путей с номером сборки; остальное no-store - приёмка: / -> 302 /29/, браузер тянет /29/Build/* (все 200), autoclose-check 9/9, testfront цел - сборка 29 (fix webgl: дым падения и PC URP) опубликована на nginx
84 lines
6.3 KiB
Markdown
84 lines
6.3 KiB
Markdown
# 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. Не тиражировать наружу.
|