Системная архитектура
┌─────────────────────────────────┐ │ Пользователь │ └────────────┬────────────────────┘ │ HTTPS ┌────────────▼────────────────────┐ │ Traefik (TLS) │ └──┬──────────────────────────┬───┘ │ │ ┌────────────▼───────────┐ ┌──────────▼──────────┐ │ Frontend (React SPA) │ │ Backend API (Go) │ │ / │ │ /api/v1/... │ │ /dashboard │ │ │ │ /admin │ │ Fiber HTTP Server │ └───────────────────────┘ │ JWT Auth │ │ WebSocket (metrics) │ └──┬───────────────────┘ │ ┌─────────────────┼─────────────────┐ │ │ │ ┌────────▼──────┐ ┌───────▼───────┐ ┌─────▼──────┐ │ PostgreSQL │ │ Redis │ │ Asynq │ │ (основная │ │ (кэш, │ │ Worker │ │ БД) │ │ pub/sub) │ │ │ └───────────────┘ └───────────────┘ └─────┬──────┘ │ gRPC ┌───────────────────┼──────────────┐ │ │ │ ┌────────▼──────┐ ┌─────────▼─────┐ │ │ Node 1 │ │ Node 2 │ ... │ │ (NL / DE) │ │ (US / NYC) │ │ │ │ │ │ │ │ Xray-core │ │ Xray-core │ │ │ Агент (Go) │ │ Агент (Go) │ │ └───────────────┘ └───────────────┘ │Компоненты
Section titled “Компоненты”Frontend (React SPA)
Section titled “Frontend (React SPA)”Статические файлы, отдаются Traefik / nginx. Три зоны:
- Лендинг (
/) — публичная, описание сервиса, тарифы, FAQ - Личный кабинет (
/dashboard) — статус подписки, subscription link, устройства - Админ-панель (
/admin) — управление нодами, пользователями, тарифами, статистика
Backend API (Go)
Section titled “Backend API (Go)”Единый сервис. Отвечает за:
- REST API для фронтенда
- WebSocket endpoint для realtime-метрик в админке
- HTTP endpoint для subscription link (отдаёт конфиг для VPN-клиентов)
- Запуск Asynq воркеров
Asynq Worker
Section titled “Asynq Worker”Запускается внутри того же Go-процесса (отдельная горутина). Обрабатывает задачи:
sync:user— синхронизировать пользователя на все его ноды через gRPCsync:node— синхронизировать всех активных пользователей на новую нодуcheck:expired— крон, проверяет истёкшие подписки и отзывает доступ
Агент на ноде (Go)
Section titled “Агент на ноде (Go)”Лёгкий gRPC-сервер на каждой ноде. Умеет:
- Добавить / удалить / изменить клиента в Xray inbound
- Вернуть статистику трафика по тегу
- Вернуть метрики системы (CPU, RAM, connections)
- Применить новый конфиг инбаунда
Потоки данных
Section titled “Потоки данных”Регистрация + первый вход
Section titled “Регистрация + первый вход”Пользователь → POST /api/v1/auth/register→ Создаётся users + user_credentials (генерируется UUID)→ Создаётся subscription_links токен→ Если есть активная подписка (промокод/триал) → enqueue sync:user→ Агент на нодах получает gRPC вызов → Xray добавляет UUID в inboundПодписка истекает
Section titled “Подписка истекает”Крон check:expired (каждые 5 минут)→ Находит subscriptions WHERE expires_at < NOW() AND status = 'active'→ UPDATE status = 'expired'→ enqueue sync:user для каждого→ Агент удаляет UUID из всех inbound-ов → трафик блокируетсяСбор статистики трафика
Section titled “Сбор статистики трафика”Крон collect:traffic (каждые 5 минут)→ gRPC GetStats к каждой ноде→ INSERT INTO traffic_snapshots→ UPSERT daily_traffic (UPDATE bytes += delta)→ UPDATE subscriptions SET traffic_used_bytesМасштабирование
Section titled “Масштабирование”На начальном этапе всё работает в одном docker-compose на одном VPS. При росте:
- Бэкенд горизонтально масштабируется (stateless, сессии в Redis)
- Воркеры можно вынести в отдельный процесс
- PostgreSQL → managed (RDS, Supabase) или read replica
- Ноды добавляются через админку без downtime