ADR-011: статика игры вынесена из куба на nginx (LXC 152 game-web), версии каталогами
- корень smart-updown.binom.pw -> nginx на Proxmox (LXC 152, 192.168.76.152) - /api,/ws -> куб (router PathPrefix на внешнем Traefik VDS), куб не менялся - версионирование: /opt/game/releases/<N>/, активная = симлинк /opt/game/current - tools/proxmox-nginx: unpack-release.sh, publish-release.sh, game.nginx.conf, smart-updown.traefik.yaml, README - приёмка живьём: корень 200 nginx/1.24.0 (Ubuntu), /27/ /28/ 200, /api/state 200 JSON, /api/ws цена, autoclose-check 9/9 - питфоллы: OCI-manifest в skopeo dir-дампе, слэш в конце версии, /solana-rpc мимо PathPrefix /api
This commit is contained in:
@@ -80,8 +80,10 @@ binance-market — это **не часть игры**, а **общий инфр
|
||||
| **k3s-кластер** | VM `192.168.76.120`, ns `game` | — |
|
||||
| **Игровой бэк (боевой)** | TS-шлюз `updown-relayer`, сервис `testfront-gateway-smart-updown-relayer:8895` | оба домена: `/api`, `/ws` |
|
||||
| **Домены** | `smart-updown.binom.pw` (Unity-игра), `testfront.binom.pw` (тех-дашборд) | один и тот же бэк |
|
||||
| **Фронт игры** | deployment `fun-game-front2` (nginx + Unity WebGL) | образ `images.binom.pw/fun/game-front2:<тег>` |
|
||||
| **Ingress-пути** | **`smart-updown-api`** — `/api`,`/ws` (ВНЕ helm); `fun-game-front2-…` — только `/` | ADR-010 |
|
||||
| **Статика игры (корень `smart-updown.binom.pw`)** | **nginx на Proxmox, LXC 152 `game-web` (192.168.76.152)** | `/opt/game/releases/<N>/`, активная — `/opt/game/current` (ADR-011) |
|
||||
| **Фронт игры (сборка)** | репозиторий `fun-game-front2` → образ `images.binom.pw/fun/game-front2:<тег>` | из образа извлекается статика и кладётся на nginx (`tools/proxmox-nginx/`) |
|
||||
| **Ingress-пути (куб)** | **`smart-updown-api`** — `/api`,`/ws` (ВНЕ helm); `fun-game-front2-…` — только `/` (уже не обслуживает домен) | ADR-010 |
|
||||
| **Маршрутизация корня** | внешний Traefik VDS: `/api`,`/ws` → куб `192.168.76.120`; всё остальное → nginx `192.168.76.152` | ADR-011 |
|
||||
| **Solana localnet** | LXC 151 на Proxmox `192.168.76.66` | RPC `192.168.76.181:8899` |
|
||||
| **Контракт (в цепи)** | `9ALs…S1fCpf` (фантики, 4 инструкции) | прод-игра работает тут |
|
||||
| **Реестр образов** | `images.binom.pw` | — |
|
||||
|
||||
@@ -156,3 +156,40 @@ helm upgrade fun-game-front2 binom/fun-game-front2 -n game \
|
||||
## Ссылки (дополнено 2026-09-13)
|
||||
- Цена: `docs/PRICE-NATS.md`, диаграмма `docs/diagrams/price-flow.puml`
|
||||
- **Безопасность: `docs/SECURITY.md` — чек-лист `SEC-1…SEC-15` (аудит живого стенда 2026-09-13)**
|
||||
|
||||
## ⭐ 2026-09-15 (2) — статика игры ушла из куба на nginx (LXC 152), версии каталогами
|
||||
|
||||
**Где мы:** корень `smart-updown.binom.pw` раздаёт **nginx на Proxmox (LXC 152 `game-web`,
|
||||
192.168.76.152)** со версионированием по каталогам; `/api` и `/ws` по-прежнему идут в куб
|
||||
на TS-шлюз отдельным router'ом внешнего Traefik. Решение и разбор — **ADR-011** в `docs/DECISIONS.md`.
|
||||
|
||||
**Как выпустить новую сборку игры (памятка — вместо helm upgrade фронта):**
|
||||
```bash
|
||||
# 1. CI репозитория fun-game-front2 собирает Unity WebGL и пушит образ
|
||||
# images.binom.pw/fun/game-front2:<N> (тег = номер релиза, как раньше)
|
||||
# 2. раскладываем на nginx и включаем как активную:
|
||||
ssh root@192.168.76.66 "pct exec 152 -- /opt/game/tools/publish-release.sh <N> --activate"
|
||||
# 3. проверяем ДОМЕН (не helm):
|
||||
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>/Build/WebGL.framework.js
|
||||
```
|
||||
Без `--activate` сборка просто ложится в `/opt/game/releases/<N>/` и доступна по `/<N>/` —
|
||||
корень не меняется. Откат версии = `publish-release.sh <старый N> --activate` (каталоги не удаляются).
|
||||
|
||||
**Инструменты:** `tools/proxmox-nginx/` — `unpack-release.sh` (распаковать dir-дамп образа),
|
||||
`publish-release.sh` (тянуть образ + разложить + переключить), `game.nginx.conf`,
|
||||
`smart-updown.traefik.yaml` (боевой конфиг внешнего Traefik). Скопированы в LXC 152
|
||||
в `/opt/game/tools/` и `/etc/nginx/sites-available/game`.
|
||||
|
||||
**Проверено живьём:** `/` → 200 `nginx/1.24.0 (Ubuntu)`; `/27/`,`/28/` → 200, ассеты версий
|
||||
различаются; `/api/state` → 200 JSON; `/api/ws` → цена идёт; сквозной `autoclose-check.cjs` — **9/9**.
|
||||
|
||||
**Задачи на будущее по этой схеме:**
|
||||
- [ ] **TODO** `[pump.meta]` Ссылки на версии — **только со слэшем** (`/28/`): голый `/28` даёт 301.
|
||||
Если понадобится бесслэшевый вид — добавить в nginx `return 301 /$build/`.
|
||||
- [ ] **TODO** `[pump.meta]` Чистка старых сборок на 152: каталоги `releases/<N>` не удаляются сами
|
||||
(~68 МБ на сборку). Политика ретеншена (сколько версий держим) — за владельцем.
|
||||
- [ ] **TODO** `[pump.meta]` Автоматизировать шаг публикации в CI `fun-game-front2`: после push образа
|
||||
дёргать `publish-release.sh` на 152 (сейчас — ручной вызов одной командой).
|
||||
- [ ] **TODO** `[pump.meta]` Уточнить, нужен ли под `fun-game-front2` в кубе вообще (домен он больше
|
||||
не обслуживает) — либо оставить как «предыдущая схема на откат», либо выключить.
|
||||
|
||||
@@ -203,3 +203,58 @@
|
||||
(отдать фронтендеру, см. `TASKS.md`).
|
||||
|
||||
---
|
||||
|
||||
## ADR-011 — Статика игры вынесена из куба на nginx (LXC 152), версии — каталогами (2026-09-15)
|
||||
|
||||
**Контекст.** До этого и корень, и `/api`,`/ws` жили в кубе: внешний Traefik (VDS) вёл весь домен
|
||||
`smart-updown.binom.pw` на k3s `192.168.76.120`, статику отдавал под `fun-game-front2`
|
||||
(nginx внутри образа), API — отдельный ingress `smart-updown-api` → TS-шлюз `:8895`.
|
||||
Владелец решил **разделить плоскости**: бэк честно деплоится в куб, а сама игра (статика)
|
||||
раздаётся с nginx, развёрнутого на Proxmox — со **версионированием по каталогам** (`/<номер>/`).
|
||||
|
||||
**Решение:**
|
||||
1. **nginx на Proxmox** — новый LXC **152** (`game-web`, 192.168.76.152, Ubuntu 24.04, 2 ядра,
|
||||
1 ГБ RAM, диск 8 GB на `local-lvm`, `onboot=1`, unprivileged). Отдельный LXC потому, что
|
||||
статика игры — «10 строк конфига и каталог», держать её в кубе рядом с бэком смысла нет.
|
||||
2. **Версионирование каталогами:**
|
||||
- `/opt/game/releases/<N>/` — файлы сборки N (`Build/`, `TemplateData/`, `index.html`);
|
||||
- `/opt/game/current` — симлинк на активную сборку;
|
||||
- `https://smart-updown.binom.pw/` → активная сборка, `/28/…` → конкретная сборка.
|
||||
3. **Маршрутизация на внешнем Traefik (VDS)** — два router'а на один host, вместо одного:
|
||||
- `smart-updown-api-router`: `Host(...) && (PathPrefix('/api') || PathPrefix('/ws'))` → `192.168.76.120` (куб);
|
||||
- `smart-updown-router`: `Host(...)` → `192.168.76.152` (nginx на проксмоксе).
|
||||
PathPrefix-роутер специфичнее Host-роутера, поэтому `/api`,`/ws` **не перехватываются статикой**.
|
||||
IP LXC 152 достижим с VDS через wg-туннель (192.168.76.0/22 dev wg0).
|
||||
4. **В кубе ничего не менялось**: `ingress smart-updown-api` (`/api`,`/ws` → шлюз) как был, вне helm.
|
||||
Под `fun-game-front2` остался жив, но домен он больше не обслуживает (статика ушла на nginx) —
|
||||
в куб его релизить больше не обязательно; релизы — только доставка статики на nginx.
|
||||
5. **Инструменты** (`tools/proxmox-nginx/`): `unpack-release.sh` (распаковка dir-дампа образа в
|
||||
`releases/<N>`), `publish-release.sh` (тянет образ из реестра, раскладывает, по `--activate`
|
||||
переключает `current`), `game.nginx.conf`, `smart-updown.traefik.yaml`.
|
||||
|
||||
**Питфоллы, пойманные живьём:**
|
||||
- `skopeo copy docker://… dir:` кладёт слои по **sha256-digest**, а `manifest.json` — это **OCI-манифест**
|
||||
(словарь `layers[].digest`, не список строк как в docker-archiv). Парсить `json['layers'][i]['digest']`,
|
||||
а не печатать элемент целиком (иначе `tar: Cannot connect to {'mediaType': ...}`).
|
||||
- Голый шаблон `/28` (без слэша) отдаёт **301** — это `try_files ... /$build$subpath/`, т.е. редирект
|
||||
на `/28/`. Для относительных путей Unity (`src="Build/WebGL.loader.js"`) важно, чтобы **браузерный
|
||||
URL заканчивался слэшем**; иначе `Build/...` уедет в `/Build/...` и вернётся 404. Ссылаться на
|
||||
версии только со слэшем (`/28/`), либо ставить редирект в nginx (`return 301 /$build/`).
|
||||
- `/solana-rpc/` **не** перехватывается PathPrefix `/api` — это отдельный path, и на VDS он уходит
|
||||
в корневой router (nginx). Поэтому страховочный `location /solana-rpc/` в nginx нужен: старые сборки
|
||||
игры стучатся именно туда (проверено: `getHealth` → `ok` через домен).
|
||||
- Имена ассетов Unity внутри сборки не меняются (`WebGL.data`/`.wasm`/`.framework.js`), но теперь
|
||||
URL содержит номер сборки → `immutable`-кэш больше не «прилипает» между релизами (закрыт остаточный
|
||||
риск из ADR-010). Внутри одной версии ассеты неизменяемы, т.к. каталог версии не перезаписывается.
|
||||
|
||||
**Приёмка (живой домен, 2026-09-15):** корень `/` → 200 от `nginx/1.24.0 (Ubuntu)` (LXC 152);
|
||||
`/27/`,`/28/` → 200, ассеты версий различаются (md5 `WebGL.data`: `76b6f3…` vs `47453d…`);
|
||||
`/api/state` → 200 JSON (куб), `/api/ws` → `[open]` + `{"type":"price"}`; сквозной
|
||||
`tools/autoclose-check.cjs` на `BASE=https://smart-updown.binom.pw/api` — **9/9**; `testfront` не задет.
|
||||
Откат: вернуть `/opt/traefik/static/smart-updown.yaml` из бэкапа VDS
|
||||
(`/root/bak-smart-updown-nginx-2026-09-15/`) — домен снова целиком уйдёт в куб.
|
||||
|
||||
**Альтернативы:** (а) оставить статику в кубе и версионировать каталогами внутри образа — тянет
|
||||
пересборку образа на каждый билд игры и не решает вопрос кэша; (б) поднять в LXC не nginx, а
|
||||
podman-контейнер с nginx — лишний слой на 10 строках конфига; (в) отдавать статику прямо с k3s-Traefik
|
||||
по PVC — не то, о чём просил владелец (он хотел nginx на проксмоксе).
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 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:...`).
|
||||
- **Кэш больше не прилипает между релизами**: URL содержит номер сборки → `immutable` корректен.
|
||||
Внутри версии каталог не перезаписывается, поэтому ассеты действительно неизменяемы.
|
||||
- **Сборки копятся** (~68 МБ на версию) — ретеншен пока ручной, см. `TASKS.md`.
|
||||
- **Откат схемы целиком**: вернуть `/opt/traefik/static/smart-updown.yaml` из
|
||||
`/root/bak-smart-updown-nginx-2026-09-15/` на VDS — домен снова пойдёт целиком в куб.
|
||||
@@ -0,0 +1,98 @@
|
||||
# nginx для раздачи Unity-сборок «Бинарной ракеты» — LXC 152 (game-web, 192.168.76.152)
|
||||
# Файл: /etc/nginx/sites-available/game
|
||||
#
|
||||
# Модель версионирования:
|
||||
# /opt/game/releases/<N>/ — файлы сборки N (Build/, TemplateData/, index.html)
|
||||
# /opt/game/current -> releases/<N> — активная сборка (симлинк, переключает publish-release.sh)
|
||||
#
|
||||
# https://smart-updown.binom.pw/ -> активная сборка (current)
|
||||
# https://smart-updown.binom.pw/28/ -> конкретная сборка 28
|
||||
# https://smart-updown.binom.pw/28/Build/WebGL.data -> ассет сборки 28
|
||||
#
|
||||
# API и WebSocket nginx НЕ обслуживает: их забирает Traefik на VDS
|
||||
# (router smart-updown-api: PathPrefix /api,/ws -> куб 192.168.76.120).
|
||||
# Локальные location /api, /ws, /solana-rpc — страховка для запросов,
|
||||
# которые всё же дойдут до nginx (прямой заход по IP, старые сборки).
|
||||
|
||||
# Ассеты Unity внутри каталога версии неизменяемы -> immutable.
|
||||
# index.html и всё остальное -> no-store.
|
||||
map $uri $game_cache_control {
|
||||
default "no-store";
|
||||
~^/[0-9]+/.+\.(js|wasm|data|mem|symbols|css|png|jpg|jpeg|gif|svg|woff2?)$ "public, max-age=604800, immutable";
|
||||
~^/.+\.(js|wasm|data|mem|symbols|css|png|jpg|jpeg|gif|svg|woff2?)$ "public, max-age=604800, immutable";
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
server_name _;
|
||||
|
||||
root /opt/game/current;
|
||||
index index.html;
|
||||
|
||||
access_log /var/log/nginx/game-access.log;
|
||||
error_log /var/log/nginx/game-error.log warn;
|
||||
|
||||
gzip on;
|
||||
gzip_min_length 512;
|
||||
gzip_types application/javascript application/wasm application/json text/css application/octet-stream;
|
||||
|
||||
add_header Cache-Control $game_cache_control;
|
||||
|
||||
# --- версионированные сборки: /<число>/... -------------------------------
|
||||
# /28/index.html -> /opt/game/releases/28/index.html
|
||||
location ~ ^/(?<build>[0-9]+)(?<subpath>/.*)?$ {
|
||||
root /opt/game/releases;
|
||||
try_files /$build$subpath /$build$subpath/ =404;
|
||||
}
|
||||
|
||||
# --- ассеты активной сборки ----------------------------------------------
|
||||
location ~* \.(js|wasm|data|mem|symbols|json|css|png|jpg|jpeg|gif|svg|woff2?)$ {
|
||||
root /opt/game/current;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# --- страховка: API -------------------------------------------------------
|
||||
# Нормальный /api идёт мимо nginx (Traefik VDS -> куб). Если запрос всё же
|
||||
# пришёл сюда — уходим в куб на k3s-Traefik с правильным Host, дальше
|
||||
# ingress smart-updown-api ведёт в шлюз :8895.
|
||||
location /api {
|
||||
proxy_pass http://192.168.76.120;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host smart-updown.binom.pw;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_connect_timeout 10s;
|
||||
proxy_read_timeout 90s;
|
||||
}
|
||||
|
||||
# страховка: WebSocket шлюза
|
||||
location /ws {
|
||||
proxy_pass http://192.168.76.120;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host smart-updown.binom.pw;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 3600s;
|
||||
}
|
||||
|
||||
# страховка: тонкий CORS-прокси до Solana RPC (старые сборки игры)
|
||||
location /solana-rpc/ {
|
||||
proxy_pass http://192.168.76.181:8899/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host 192.168.76.181:8899;
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_read_timeout 30s;
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header Access-Control-Allow-Headers "content-type" always;
|
||||
add_header Access-Control-Allow-Methods "POST, OPTIONS" always;
|
||||
if ($request_method = OPTIONS) { return 204; }
|
||||
}
|
||||
|
||||
# --- корень = активная сборка --------------------------------------------
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/bin/bash
|
||||
# Публикация сборки игры на nginx (LXC 152, game-web).
|
||||
#
|
||||
# publish-release.sh <тег> [--activate]
|
||||
#
|
||||
# Что делает:
|
||||
# 1. тянет образ images.binom.pw/fun/game-front2:<тег> из реестра (skopeo copy в dir);
|
||||
# 2. распаковывает статику в /opt/game/releases/<тег>/;
|
||||
# 3. без --activate оставляет активной текущую сборку (корень не меняется);
|
||||
# с --activate переключает симлинк /opt/game/current на новую версию;
|
||||
# 4. печатает проверку.
|
||||
#
|
||||
# Итог: https://smart-updown.binom.pw/ -> активная сборка
|
||||
# https://smart-updown.binom.pw/<тег>/ -> конкретная сборка
|
||||
set -euo pipefail
|
||||
|
||||
TAG="${1:?использование: publish-release.sh <тег> [--activate]}"
|
||||
ACTIVATE="${2:-}"
|
||||
REG="images.binom.pw/fun/game-front2"
|
||||
CREDS="subochev:Drovosek319"
|
||||
IMG="/tmp/gameimg-${TAG}"
|
||||
|
||||
echo "=== 1/4 тяну образ ${REG}:${TAG} ==="
|
||||
rm -rf "$IMG"
|
||||
skopeo copy --src-creds "$CREDS" "docker://${REG}:${TAG}" "dir:${IMG}"
|
||||
# креды не нужны при распаковке
|
||||
chmod -R a+rX "$IMG"
|
||||
|
||||
echo "=== 2/4 распаковываю статику в /opt/game/releases/${TAG} ==="
|
||||
/opt/game/tools/unpack-release.sh "$TAG" "$IMG"
|
||||
|
||||
if [ "$ACTIVATE" = "--activate" ]; then
|
||||
echo "=== 3/4 переключаю активную сборку на ${TAG} ==="
|
||||
PREV="$(readlink -f /opt/game/current || echo none)"
|
||||
rm -f /opt/game/current
|
||||
ln -s "/opt/game/releases/${TAG}" /opt/game/current
|
||||
echo "было: $PREV"
|
||||
echo "стало: $(readlink -f /opt/game/current)"
|
||||
else
|
||||
echo "=== 3/4 активную сборку НЕ трогаю (нет --activate) ==="
|
||||
echo "активна: $(readlink -f /opt/game/current)"
|
||||
fi
|
||||
|
||||
echo "=== 4/4 проверка ==="
|
||||
systemctl reload nginx
|
||||
for u in "/" "/${TAG}/" "/${TAG}/index.html" "/${TAG}/Build/WebGL.framework.js"; do
|
||||
printf ' %-42s %s\n' "$u" "$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1${u}")"
|
||||
done
|
||||
echo "готово: сборка ${TAG}"
|
||||
rm -rf "$IMG"
|
||||
@@ -0,0 +1,62 @@
|
||||
http:
|
||||
# ── middlewares ─────────────────────────────────────────────────────────
|
||||
middlewares:
|
||||
# Подмена Host на входе в куб — k3s-Traefik роутит именно по Host,
|
||||
# а ingress `smart-updown-api` объявлен на smart-updown.binom.pw.
|
||||
smart-updown-host:
|
||||
headers:
|
||||
customRequestHeaders:
|
||||
Host: "smart-updown.binom.pw"
|
||||
smart-updown-redirect-https:
|
||||
redirectScheme:
|
||||
scheme: https
|
||||
permanent: true
|
||||
|
||||
# ── routers ─────────────────────────────────────────────────────────────
|
||||
routers:
|
||||
# API и WebSocket игры: уходят в k3s (192.168.76.120) на ingress
|
||||
# `smart-updown-api` (ns game), дальше в TS-шлюз :8895.
|
||||
# Отдельный router потому, что PathPrefix специфичнее Host:
|
||||
# так /api и /ws не перехватываются статикой nginx.
|
||||
smart-updown-api-router:
|
||||
rule: "Host(`smart-updown.binom.pw`) && (PathPrefix(`/api`) || PathPrefix(`/ws`))"
|
||||
service: smart-updown-api
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: mycloudflare
|
||||
|
||||
# Корень: статика игры. Раздаёт nginx на LXC 152 (game-web, 192.168.76.152)
|
||||
# в домашней сети через wg-туннель. Версии — каталогами (/28/, /29/, ...),
|
||||
# корень — активная сборка (симлинк /opt/game/current).
|
||||
smart-updown-router:
|
||||
rule: Host(`smart-updown.binom.pw`)
|
||||
service: smart-updown
|
||||
entryPoints:
|
||||
- websecure
|
||||
tls:
|
||||
certResolver: mycloudflare
|
||||
|
||||
# http -> https
|
||||
smart-updown-http-redirect:
|
||||
rule: Host(`smart-updown.binom.pw`)
|
||||
entryPoints:
|
||||
- web
|
||||
service: noop
|
||||
middlewares:
|
||||
- smart-updown-redirect-https
|
||||
|
||||
# ── services ────────────────────────────────────────────────────────────
|
||||
services:
|
||||
smart-updown-api:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://192.168.76.120"
|
||||
smart-updown:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://192.168.76.152"
|
||||
noop:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://127.0.0.1:9"
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
# Распаковка образа игры из dir-дампа skopeo в версионированный каталог nginx.
|
||||
# Использование: unpack-release.sh <тег> <dir-дамп образа>
|
||||
set -euo pipefail
|
||||
|
||||
TAG="$1"
|
||||
IMG="$2"
|
||||
DEST="/opt/game/releases/${TAG}"
|
||||
|
||||
[ -d "$IMG" ] || { echo "нет дампа $IMG"; exit 1; }
|
||||
|
||||
rm -rf /tmp/rootfs-${TAG}
|
||||
mkdir -p /tmp/rootfs-${TAG}
|
||||
|
||||
cd "$IMG"
|
||||
# слои из manifest.json в правильном порядке
|
||||
/usr/bin/python3 - <<'PY' > /tmp/layers-${TAG}.txt
|
||||
import json
|
||||
m = json.load(open('manifest.json'))
|
||||
for l in m['layers']:
|
||||
print(l['digest'].split(':', 1)[1])
|
||||
PY
|
||||
|
||||
while read -r layer; do
|
||||
[ -z "$layer" ] && continue
|
||||
case "$layer" in
|
||||
*tar.gz|*tgz) tar -xzf "$layer" -C /tmp/rootfs-${TAG} ;;
|
||||
*tar.zst) tar --zstd -xf "$layer" -C /tmp/rootfs-${TAG} ;;
|
||||
*) tar -xf "$layer" -C /tmp/rootfs-${TAG} ;;
|
||||
esac
|
||||
done < /tmp/layers-${TAG}.txt
|
||||
|
||||
SRC="/tmp/rootfs-${TAG}/usr/share/nginx/html"
|
||||
[ -d "$SRC" ] || { echo "нет $SRC в образе"; ls /tmp/rootfs-${TAG}/usr/share/nginx 2>/dev/null; exit 1; }
|
||||
|
||||
mkdir -p "$DEST"
|
||||
cp -a "$SRC/." "$DEST/"
|
||||
chmod -R a+rX /opt/game/releases
|
||||
rm -rf /tmp/rootfs-${TAG} /tmp/layers-${TAG}.txt
|
||||
|
||||
echo "=== релиз ${TAG} разложен в ${DEST} ==="
|
||||
ls -la "$DEST"
|
||||
du -sh "$DEST"
|
||||
Reference in New Issue
Block a user