VPN сервис на основе Hysteria 2 с разделением ролей, управлением пользователями и серверами, генерацией клиентских URL и сбором статистики трафика.
Проект состоит из:
backend— FastAPI + PostgreSQL API для аутентификации, админки и сбора трафикаfrontend— React 19 + Vite + TypeScript интерфейс для администратора и пользователейhysteria— локальная конфигурация Hysteria 2 для разработкиprod— production-compose конфиги для инфраструктуры и серверов
- аутентификация через JWT access token + refresh cookie
- роли
adminиuser - управление VPN-пользователями: создание, регистрация, блокировка, активация, смена пароля, регенерация
hyPassword - управление серверами Hysteria 2: добавление, редактирование, деактивация, удаление
- генерация
hysteria2://URL для подключения клиента - дашборд администратора: пользователи, онлайн, серверы, истекающие подписки
- профиль пользователя: статус аккаунта, трафик, срок действия, выбор сервера
- сбор и агрегация трафика по 5-минутным бакетам
- rate limiting для чувствительных endpoints
- healthcheck и базовые security headers
- Python 3.11
- FastAPI
- PostgreSQL
- psycopg2
- bcrypt
- PyJWT
- httpx
- React 19
- TypeScript
- Vite
- TanStack Query
- Zustand
- React Hook Form + Zod
- Tailwind CSS v4
- Radix UI
- Recharts
Frontend (Vite, :5173)
|
| /api
v
Backend (FastAPI, :8000)
|
+--> PostgreSQL (:5432)
|
+--> Hysteria management API (:8080)
В dev-режиме frontend проксирует /api/* в backend через frontend/vite.config.ts.
.
├── backend/
│ ├── source/
│ │ ├── main.py
│ │ ├── config.py
│ │ ├── database.py
│ │ └── routers/
│ ├── Dockerfile
│ └── requirements.txt
├── frontend/
│ ├── src/
│ │ ├── api/
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── pages/
│ │ ├── stores/
│ │ └── styles/
│ ├── Dockerfile
│ └── package.json
├── hysteria/
├── prod/
├── docker-compose.yaml
└── .env
Это основной и самый простой способ поднять проект локально.
В корне проекта нужен .env. Минимально важные переменные:
ADMIN_USERNAME=admin
ADMIN_PASSWORD=change_me
JWT_SECRET=replace_with_long_random_secret_at_least_32_chars
HYSTERIA_AUTH=Bearer change_me
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=htrbox
ALLOWED_ORIGINS=http://localhost:5173
COOKIE_SECURE=false
DOCS_ENABLED=trueПолный список переменных и значений по умолчанию смотрите в backend/source/config.py.
Не храните реальные production-секреты в репозитории.
Для локального Hysteria также используются:
hysteria/.envhysteria/config.yaml- сертификаты в
hysteria/certs/
docker compose up --buildПоднимутся:
postgres— база данныхbackend— FastAPI API наhttp://localhost:8000frontend— Vite dev server наhttp://localhost:5173hysteria— локальный Hysteria server
- frontend:
http://localhost:5173 - backend healthcheck:
http://localhost:8000/health - Swagger UI:
http://localhost:8000/docsприDOCS_ENABLED=true
Возможен, но менее удобен, чем Compose.
cd backend
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cd source
uvicorn main:app --reload --host 0.0.0.0 --port 8000cd frontend
npm ci
npm run devВажно: текущий frontend/vite.config.ts проксирует API на хост backend, то есть на имя docker-сервиса. Если запускать frontend вне Docker, прокси для /api нужно либо адаптировать под localhost:8000, либо запускать frontend внутри Compose.
/admin— дашборд/users— управление пользователями/servers— управление серверами/settings— настройки аккаунта
/profile— профиль, статус, трафик, сервер, ссылка подключения/manual— инструкция/онбординг/chekavo— дополнительная пользовательская страница/settings— настройки аккаунта
/login/register
/auth— логин, refresh, logout, Hysteria auth callback/users— пользователи и self-service сценарии/servers— список и управление серверами/traffic— трафик по пользователям и серверам/kick,/online,/generate-url/{username}— Hysteria-интеграция/health— healthcheck
При запуске приложение:
- инициализирует PostgreSQL connection pool
- создаёт таблицы, если они отсутствуют
- создаёт первого администратора из
ADMIN_USERNAMEиADMIN_PASSWORD - запускает cleanup rate limiter
- запускает traffic collector
- запускает maintenance worker
- access token хранится на клиенте в памяти
- refresh token хранится в
HttpOnlycookie - роль пользователя читается из базы на каждом запросе, поэтому смена роли применяется сразу
- для production рекомендуется
COOKIE_SECURE=true /docsи/redocвыключены по умолчанию и открываются черезDOCS_ENABLED=true- в
backend/source/database.pyотдельно задокументировано, почемуhyPasswordхранится в открытом виде: это отдельный VPN-секрет, а не пароль аккаунта
В репозитории есть отдельные compose-файлы для production-развёртывания:
prod/infra/docker-compose.yamlprod/servers/docker-compose.*.yaml
Они отделены от локального docker-compose.yaml, который предназначен именно для разработки.
backend/source/routers— HTTP endpointsbackend/source/schemas.py— Pydantic-схемы APIfrontend/src/pages— страницы приложенияfrontend/src/components— UI и бизнес-компонентыfrontend/src/api— клиентские API-обёрткиfrontend/src/hooks— data-fetching и прикладные хукиfrontend/src/stores— Zustand storesfrontend/src/styles— централизованные токены и стили
cd frontend
npm run dev
npm run buildcd backend/source
uvicorn main:app --reload --host 0.0.0.0 --port 8000Если вы только знакомитесь с проектом, безопасный порядок такой:
- Поднять стек через
docker compose up --build - Проверить
http://localhost:8000/health - Открыть
http://localhost:5173 - Войти под администратором из
.env - Добавить первый сервер через
/servers - Создать тестового пользователя и проверить генерацию URL







