Files
sleep-guard/docs/architecture.md
Vadim Sobinin 719afa8533 fix(proxy): harden security and add UpSnap debug logging
- XSS: escape serviceName in waking page HTML
- Session TTL: 24h expiration with periodic cleanup
- Rate limit: 5 login attempts / 15 min per IP
- CORS: restrict to same-origin + localhost
- SSRF: block localhost/metadata in service targets
- UpSnap: log response bodies on auth/wake failures

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-15 00:57:38 +03:00

80 lines
3.9 KiB
Markdown
Raw 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.
# SleepGuard Architecture
## Обзор
Wake-on-demand система из двух компонентов:
- **Proxy** (n150, 192.168.50.199) — reverse proxy + state machine + dashboard
- **Agent** (PC, 192.168.1.50) — мониторинг нагрузки + lock manager
## State Machine
```
REQUEST_RECEIVED
OFFLINE ─────────────────────► WAKING
▲ │
│ SHUTDOWN_COMPLETE │ HEALTH_CHECK_PASSED
│ ▼
SHUTTING_DOWN ◄──── IDLE_CHECK ◄── ONLINE
AGENT_IDLE IDLE_TIMEOUT ▲
│ │
│ AGENT_BUSY / REQUEST
└────────┘
```
- `OFFLINE` → запрос → wake через UpSnap → `WAKING`
- `WAKING` → health check passed → `ONLINE`
- `ONLINE` → idle timeout → `IDLE_CHECK`
- `IDLE_CHECK` → agent busy → `ONLINE`, agent idle → `SHUTTING_DOWN`
- `SHUTTING_DOWN` → agent offline → `OFFLINE`
## Shutdown Policy (Agent)
Три уровня проверки (все должны быть пройдены):
1. **Locks** — если есть активные локи, выключение блокируется
2. **Processes** — hashcat, ffmpeg, whisper, python3, ollama
3. **Metrics** — CPU >15%, GPU >10%, RAM >50%, Disk I/O active
## Проксирование
Proxy матчит сервисы по `Host` заголовку. Если PC online — http-proxy проксирует запрос. Если offline — показывает "Waking up" страницу с автополлом.
## Service Management
Сервисы хранятся в `${DATA_DIR}/services.json` (по умолчанию `./data/services.json`). При первом запуске берутся из env var `SERVICES`, затем управляются через CRUD API:
- `GET /api/services` — список
- `POST /api/services` — создание
- `PUT /api/services/:host` — обновление (host неизменяем)
- `DELETE /api/services/:host` — удаление
`ServiceManager` (`packages/proxy/src/services/serviceManager.ts`) — in-memory + атомарная запись (tmp + rename). Изменения уведомляют dashboard через WebSocket (`service_list_changed`).
В Docker volume монтируется: `./data/proxy:/app/data`.
## Аутентификация
Опциональная auth по логину/паролю через env-переменные `AUTH_USERNAME` и `AUTH_PASSWORD`. Если не заданы — auth отключена.
- `POST /api/auth/login` — возвращает `{ token }` (UUID v4)
- `POST /api/auth/logout` — удаляет сессию
- `GET /api/auth/check` — проверяет, нужна ли auth и валиден ли токен
- Сессии in-memory (`Map`), TTL 24 часа, теряются при рестарте
- Rate limiting: 5 попыток / 15 мин на IP для `/api/auth/login`
- Auth middleware защищает `/api/*` кроме `/api/auth/*`
- WebSocket: токен через query `?token=...`
- Сервис-прокси (по Host) — без auth
- CORS: только same-origin + localhost (для dev)
- SSRF защита: service target не может указывать на localhost, metadata endpoints
- XSS защита: HTML-экранирование в waking page
## Деплой
Два приложения в Dokploy из одного git repo:
- `sleepguard-proxy`: Dockerfile `packages/proxy/Dockerfile`, build context `.`
- `sleepguard-agent`: Dockerfile `packages/agent/Dockerfile`, build context `.`
Agent деплоится на PC как remote server в Dokploy с NVIDIA GPU passthrough.
## Env переменные
См. `.env.example` в корне репозитория.