# ZernProxy Manager (Py-3XUI-multiserver) Объединение нескольких серверов 3x-UI в единую VPN-подписку. Soft-tariff система с веб-панелью, донатной оплатой, Happ и WDTT совместимостью. ## Architecture ``` servers.conf ──→ 3x-UI сервера (API + sub URL + status URL) settings.conf ──→ тарифы, платежи, админка, auto-propagate users.db ───────→ пользователи (SQLite) ↓ aggregator.py ──→ FastAPI сервер ↓ /sub/{id} ────→ подписка для клиента (VLESS / Trojan / VMess / Shadowsocks) /admin/* ─────→ веб-панель управления /admin/api/propagate/{server} → синхронизация пользователей между серверами / ────────────→ статус-пейдж с health-check серверов ``` **Soft-tariff**: пользователь создаётся на всех inbounds один раз, tier (free/test/paid) меняется локально в БД, без дёргания 3x-UI API. ## Features - **Multi-server**: объединение любого количества 3x-UI серверов - **Multi-inbound**: поддержка нескольких inbound на сервере (разные протоколы) - **Soft-tariff**: free / test / paid tier без пересоздания клиентов - **Propagate**: синхронизация пользователей между серверами по strict majority (>50%) - **Auto-propagate**: фоновая синхронизация по расписанию (по умолчанию 30 мин) - **DonationAlerts**: приём платежей с поиском донатера по ID/username - **Веб-панель**: дашборд со статистикой, CRUD пользователей, просмотр трафика, QR-коды - **Статус-пейдж**: публичная страница с health-check серверов (CPU/RAM/Disk/Net/I/O) - **Happ.su / WDTT совместимость**: заголовки profile-title, sub-expire, announce, hide-settings - **Абсолютный expire**: `tariff_end_at` (Unix timestamp) — дни считаются динамически, автопонижение tier при истечении - **In-memory кеш**: ссылки кешируются на 7 дней, трафик — на 2 минуты - **ShortID ротация**: автоматическая смена shortId на серверах каждые N часов - **MOTD**: объявления из motd.txt или settings - **Health scoring**: взвешенная оценка здоровья сервера (CPU 30%, RAM 25%, Disk 20%, Net 15%, I/O 10%) - **Trojan support**: создание клиентов на Trojan инбаундах (password вместо uuid) ## wdtt (Zern-BlackOut) Compatibility Проект полностью совместим с клиентом **Zern-BlackOut** (форк wdtt), доступным по адресу: [https://git.swe.zernmc.ru/sasheg/Zern-BlackOut](https://git.swe.zernmc.ru/sasheg/Zern-BlackOut) > **Важно:** Клиент wdtt был модифицирован для совместимости с данным агрегатором. > Использование оригинального wdtt без модификаций может привести к некорректной работе. > Репозиторий Zern-BlackOut находится в активной разработке для полной интеграции. Поддерживаемые возможности: - VLESS + XTLS Vision / Reality - Trojan + HTTP + Reality - Автообновление подписки - Отображение expire-даты и лимитов трафика - Hide-settings, announce, support-url через subscription-заголовки ## Quick Start ```bash pip install fastapi uvicorn httpx py3xui qrcode[pil] Pillow git clone ssh://git@git.swe.zernmc.ru:2222/sasheg/Py-3XUI-multiserver.git cd Py-3XUI-multiserver # настроить servers.conf, settings.conf (см. ниже) python3 aggregator.py ``` Для production: `screen -S aggregator python3 aggregator.py` ## Configuration ### servers.conf ```json { "servers": [ { "name": "ru-1", "subscription_url": "http://panel.domain.com:2096", "sub_path": "/sub/{sub_id}", "country": "RU", "status_url": "http://domain.com:18765/status?secret=...", "inbounds": [ { "id": 1, "name": "Reality", "api_host": "http://panel.domain.com:22881/PATH", "api_user": "admin", "api_pass": "password", "is_free": true }, { "id": 2, "name": "Trojan-Inbound", "protocol": "trojan", "api_host": "http://panel.domain.com:22881/PATH", "api_user": "admin", "api_pass": "password", "is_free": false } ] } ] } ``` | Field | Type | Description | |-------|------|-------------| | `name` | string | Unique server name | | `subscription_url` | string | Base URL for subscription links | | `sub_path` | string | Sub endpoint path (`/sub/{sub_id}`) | | `country` | string | 2-letter country code (RU, DE, PL, SE...) | | `status_url` | string | URL for server health data (3x-UI status endpoint) | | `inbounds[].id` | int | Inbound ID in 3x-UI | | `inbounds[].name` | string | Display name | | `inbounds[].protocol` | string | *(optional)* protocol type (`trojan`) | | `inbounds[].api_host` | string | 3x-UI API URL for this inbound | | `inbounds[].api_user` | string | API login | | `inbounds[].api_pass` | string | API password | | `inbounds[].is_free` | bool | Доступен ли inbound для free-тарифа | ### settings.conf ```json { "general": { "title": "MyVPN", "host": "conn.example.com", "support_url": "https://t.me/support" }, "announcement": "base64 enc or plain text", "shortid_rotation_hours": 11, "tiers": { "free": { "name": "Free", "traffic_limit_gb": 0 }, "test": { "name": "Test", "traffic_limit_gb": 5, "prices": { "test": 50 }, "days": { "test": 7 } }, "paid": { "name": "Premium", "traffic_limit_gb": 0, "prices": { "monthly": 150, "yearly": 990 }, "days": { "monthly": 30, "yearly": 365 } } }, "payments": { "donationalerts": { "enabled": true, "api_token": "...", "webhook_secret": "...", "url": "https://www.donationalerts.com/r/you" } }, "admin": { "username": "admin", "password": "secure_password" }, "auto_propagate": { "enabled": true, "interval_minutes": 30 } } ``` ### Tiers | Tier | Servers | Traffic | Price | Duration | |------|---------|---------|-------|----------| | free | inbounds with `is_free: true` | unlimited (0 = ∞) | free | forever | | test | all inbounds | 5 GB | 50₽ | 7 days | | paid | all inbounds | unlimited | 150₽/30d, 990₽/365d | configurable | ### Propagate При добавлении нового сервера или инбаунда пользователи НЕ создаются автоматически на нём. Для синхронизации используется **strict majority**: пользователь добавляется на целевой сервер только если он существует на >50% других активных серверов. ```bash curl -X POST http://localhost:8000/admin/api/propagate/{server_name} -b "admin_token=..." ``` В админ-панели кнопка 🔄 на каждом сервере. Auto-propagate запускается фоном каждые N минут. ## Endpoints | Path | Method | Description | |------|--------|-------------| | `/sub/{id}` | GET | Subscription (format: base64/json/raw) | | `/sub/{id}` | GET (HTML) | Web page with QR and info | | `/admin/login` | GET/POST | Admin auth | | `/admin/users` | GET | User management panel | | `/admin/dashboard` | GET | Stats dashboard with server health | | `/admin/api/users` | POST | Create user | | `/admin/api/users/update` | POST | Update user | | `/admin/api/users/delete` | POST | Delete user (with 3x-UI) | | `/admin/api/reload` | POST | Reload configs + clear cache | | `/admin/api/propagate/{server}` | POST | Sync users to server | | `/admin/api/rotate-shortids` | GET | Rotate short IDs on all servers | | `/` | GET | Landing page with server status | ## DonationAlerts Polling-based (every ~2 seconds). Amount mapping from `settings.conf → tiers → prices`: - Any configured amount → corresponding tier + days - Donor identified by `id` or `username` from donation message - `tariff_end_at` extends dynamically (MAX of current end, now + days) ## Happ.su / WDTT Support Subscription response includes compatible headers: - `Profile-Title`, `Profile-Update-Interval`, `Profile-Web-Page-Url` - `Subscription-Userinfo` (upload/download/total/expire) - `Announce`, `Support-Url`, `Hide-Settings` - `Sub-Expire`, `Sub-Expire-Button-Link` ## Tech - **FastAPI** + uvicorn - **SQLite** (users only) - **py3xui** — 3x-UI API client - **httpx** — async HTTP for sub links - **qrcode** — QR generation - **Plus Jakarta Sans / JetBrains Mono** — UI typography - **Glassmorphism** — design system