# nginx для раздачи Unity-сборок «Бинарной ракеты» — LXC 152 (game-web, 192.168.76.152) # Файл: /etc/nginx/sites-available/game # # Модель версионирования (два вида сборок, живут рядом): # /opt/game/releases// — номерные релизы (1, 2, 3, … 29) из CI/реестра # /opt/game/releases/<имя>/ — именованные сборки (например `sol`), присланные zip'ом # /opt/game/current -> releases/ — активная сборка (симлинк, переключает publish-release.sh) # # https://smart-updown.binom.pw/ -> 302 на активную сборку (/29/) # https://smart-updown.binom.pw/29/ -> номерная сборка 29 # https://smart-updown.binom.pw/sol/ -> именованная сборка `sol` # https://smart-updown.binom.pw/29/Build/WebGL.data -> ассет сборки 29 # # ⚠️ ПОЧЕМУ КОРЕНЬ РЕДИРЕКТИТ, А НЕ ОТДАЁТ ФАЙЛЫ: # index.html сборки ссылается на ассеты ОТНОСИТЕЛЬНЫМ путём (`buildUrl = "Build"`). # Если отдавать его прямо с корня, ассеты запрашиваются как /Build/WebGL.wasm — БЕЗ номера # сборки. Такой URL между релизами НЕ меняется, а мы отдаём его `immutable` на 7 суток → # браузер игрока неделю держит ассеты старой сборки и игнорирует новый билд (мина из ADR-010). # При редиректе на // все ассеты получают версионированный URL (/29/Build/...), старый URL # просто перестаёт использоваться, и `immutable` становится корректным. # Номер активной сборки пишет publish-release.sh в отдельный include-файл /etc/nginx/game-active.inc. # # ⚠️ ПОРЯДОК LOCATION. Служебные пути (/api, /ws, /solana-rpc) объявлены с префиксом `^~`, # потому что regex-локейшн сборок `^/(?…)` иначе перехватил бы их (regex в nginx # приоритетнее обычного префикса). `^~` подавляет проверку regex для этого префикса. # # 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. # Всё остальное (включая именованные сборки: их папку могут перезалить) -> no-store. map $uri $game_cache_control { default "no-store"; ~^/[0-9]+/.+\.(js|wasm|data|mem|symbols|css|png|jpg|jpeg|gif|svg|woff2?|unityweb)$ "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; # --- корень: 302 на активную сборку --------------------------------------- # Файл переписывает publish-release.sh при --activate. include /etc/nginx/game-active.inc; # --- страховка: API (^~ — приоритетнее regex-локейшна сборок) ------------- # Нормальный /api идёт мимо nginx (Traefik VDS -> куб). Если запрос всё же # пришёл сюда — уходим в куб на k3s-Traefik с правильным Host, дальше # ingress smart-updown-api ведёт в шлюз :8895. location ^~ /api { proxy_pass http://192.168.76.120; 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 X-Forwarded-Proto https; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; proxy_buffering off; } # --- страховка: WebSocket ------------------------------------------------- location ^~ /ws { proxy_pass http://192.168.76.120; 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 X-Forwarded-Proto https; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; proxy_buffering off; } # --- страховка: Solana RPC ------------------------------------------------- # /solana-rpc/ НЕ ловится PathPrefix /api на VDS, поэтому уходит в корневой # router, т.е. сюда. Старые сборки игры стучатся именно в этот путь. location ^~ /solana-rpc/ { proxy_pass http://192.168.76.181:8899/; proxy_set_header Host $host; proxy_http_version 1.1; proxy_read_timeout 300s; } # --- сборки: //... и /<имя>/... --------------------------------------- # /29/index.html -> /opt/game/releases/29/index.html # /sol/index.html -> /opt/game/releases/sol/index.html # /29/Build/WebGL.data -> /opt/game/releases/29/Build/WebGL.data location ~ ^/(?[a-zA-Z0-9][a-zA-Z0-9_-]*)(?/.*)?$ { root /opt/game/releases; try_files /$build$subpath /$build$subpath/ =404; } }