# cactoz.su Личный сайт-визитка на `cactoz.su` в Matrix-стилистике: резюме, проекты и браузерные игры. Три страницы статики + мультиплеерный сервер для `./tanks`. Исходный замысел и игровой протокол — в [TZ.md](TZ.md) (⚠️ местами устарел). ## Архитектура ``` ┌────────── homelab (cacto-homelab) ──────────┐ push в main │ │ в Gitea ────────────► │ gitea-actions runner (docker.sock хоста) │ git.cactoz.su │ │ клонирует, синкает, собирает │ │ ▼ │ │ /data/docker/compose/cactoz │ │ docker compose -f docker-compose.prod.yml │ │ ├── nginx (статика + прокси /ws) │ │ └── gameserver (C++/uWebSockets, :9001) │ │ │ │ │ ▼ (external docker-сеть proxy) │ │ Caddy-стек (TLS-терминация 80/443) │ └──────────────────────────────────────────────┘ ``` - **Деплой**: push в `main` → workflow `.gitea/workflows/deploy.yml` → build + `up -d` + smoke-проверка по healthcheck'ам. Отката нет: если сборка/подъём падают, шлётся уведомление, старые контейнеры продолжают работать. - **TLS** терминирует отдельный Caddy-стек, сеть `proxy` создаётся там (`external: true`) — на этом хосте только подключаемся. - Gameserver изнутри доступен только по docker-сети `internal`; наружу смотрит только nginx (через Caddy). ## Локальный запуск ```bash docker compose up --build # http://localhost, /ws на ws://localhost/ws ``` Сборка gameserver тянет зависимости через CMake FetchContent (uWebSockets, uSockets, nlohmann/json) — первый билд долгий, дальше кэшируется слоями Docker. ## Структура ``` frontend/ чистый HTML/CSS/JS, без сборки vendor/fonts/ self-hosted JetBrains Mono (OFL), 4 сабсета × 4 насыщенности js/game/ клиент ./tanks: network (WS + ping 25с), lobby, battle js/blocks.js, js/invaders.js одиночные мини-игры (canvas, без сервера) gameserver/ src/main.cpp uWS::App, /ws, лимиты фреймов/таймауты src/Lobby.* лобби: комнаты, broadcast, ping/pong, события в stdout src/Game.* авторитетная симуляция (20 Гц), pvp и coop с AI nginx/ статика + проксирование /ws (rate-limit на соединения) ``` ## Runbook ```bash # на homelab: cd /data/docker/compose/cactoz docker compose -f docker-compose.prod.yml ps # статус + healthcheck'и docker logs -f cactoz-gameserver-... 2>&1 | less # события лобби/игр docker compose -f docker-compose.prod.yml up -d --build # ручной перезапуск ``` - Логи ротируются (`max-size 10m × 3`), лимиты ресурсов: nginx 128M/0.5cpu, gameserver 256M/1cpu. - Gameserver не умеет graceful shutdown — при рестарте активные матчи обрываются (комнаты сами поднимаются заново). - Статика без хешей в именах: js/css отдаются с `no-cache`, `/assets/` — час. ## Доступ и безопасность - SSH на homelab: ключи, вход только с доверенных сетей; sudo — по необходимости. - Gitea (`git.cactoz.su`) — источник истины для кода; секретов в репо нет. - За пределами compose на хосте живут Caddy-стек, Gitea и её runner — их конфиги не входят в этот репозиторий и бэкапятся отдельно.