Init
This commit is contained in:
@@ -0,0 +1,67 @@
|
|||||||
|
# Nexuma
|
||||||
|
|
||||||
|
Nexuma is a multi-node VPN and proxy management platform. It lets you deploy VPN servers, manage users and subscriptions, and control everything from a single web interface.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Multi-node** — connect unlimited VPN servers, manage them from one place
|
||||||
|
- **Subscriptions** — per-user links with traffic limits, expiry, and auto-renewal
|
||||||
|
- **Multiple protocols** — VLESS, VMess, Trojan, Shadowsocks, Hysteria2, MTProto
|
||||||
|
- **Balance system** — user balance with deposits, withdrawals, and auto-charge on renewal
|
||||||
|
- **Traffic accounting** — per-subscription usage analytics
|
||||||
|
- **Telegram integration** — OAuth login, user approval flow, admin notifications
|
||||||
|
- **Routing rules** — xray-native rule sets and load balancers per node
|
||||||
|
- **Config builder** — guided wizard for protocol and stream configuration
|
||||||
|
- **Double VPN** — proxy chain support via node outbounds
|
||||||
|
- **External subscriptions** — aggregate external VPN share links into user subscriptions
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌───────────────────────────────────┐
|
||||||
|
│ Panel │
|
||||||
|
│ (Admin Web Interface) │
|
||||||
|
└────────────────┬──────────────────┘
|
||||||
|
│
|
||||||
|
┌────────────────▼──────────────────┐
|
||||||
|
│ Core │
|
||||||
|
│ (Control Plane API) │
|
||||||
|
│ PostgreSQL ◄────────► Redis │
|
||||||
|
└──────┬────────────────────────────┘
|
||||||
|
│
|
||||||
|
┌────┴──────────────┐
|
||||||
|
▼ ▼
|
||||||
|
Node 1 . . . Node N
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Deploy Core and Panel
|
||||||
|
|
||||||
|
Download [`docker-compose.base.yml`](./docker-compose.base.yml), fill in your values, and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.base.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://your-server:3010` — the first registered account becomes admin.
|
||||||
|
|
||||||
|
### 2. Deploy a Node
|
||||||
|
|
||||||
|
On each VPN server, download [`docker-compose.node.yml`](./docker-compose.node.yml).
|
||||||
|
|
||||||
|
1. In the admin panel, open **Nodes** and generate a registration code.
|
||||||
|
2. Set `CORE_URL` and `REGISTRATION_CODE` in the file.
|
||||||
|
3. Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.node.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
The node registers with Core automatically on first start. After that, remove the `REGISTRATION_CODE` line.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [Core](./core.md) — configuration and API reference
|
||||||
|
- [Node](./node.md) — setup and registration
|
||||||
|
- [Panel](./panel.md) — features overview
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Core
|
||||||
|
|
||||||
|
REST API server — the control plane of Nexuma. Manages users, tariffs, subscriptions, nodes, traffic accounting, and generates subscription configs for VPN clients.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Edit the environment variables in [`docker-compose.base.yml`](./docker-compose.base.yml):
|
||||||
|
|
||||||
|
| Variable | Required | Description |
|
||||||
|
|----------|----------|-------------|
|
||||||
|
| `DB_HOST` | Yes | PostgreSQL host |
|
||||||
|
| `DB_PORT` | Yes | PostgreSQL port |
|
||||||
|
| `DB_USER` | Yes | Database user |
|
||||||
|
| `DB_PASSWORD` | Yes | Database password |
|
||||||
|
| `DB_NAME` | Yes | Database name |
|
||||||
|
| `REDIS_HOST` | Yes | Redis host |
|
||||||
|
| `REDIS_PORT` | Yes | Redis port |
|
||||||
|
| `JWT_SECRET` | Yes | Access token secret |
|
||||||
|
| `JWT_REFRESH_SECRET` | Yes | Refresh token secret |
|
||||||
|
| `JWT_EXPIRES_IN` | No | Access token TTL (default: `15m`) |
|
||||||
|
| `JWT_REFRESH_EXPIRES_IN` | No | Refresh token TTL (default: `7d`) |
|
||||||
|
| `TELEGRAM_BOT_TOKEN` | No | Enables Telegram bot and OAuth login |
|
||||||
|
| `CORS_ORIGINS` | No | Allowed CORS origins (default: `*`) |
|
||||||
|
|
||||||
|
## API Overview
|
||||||
|
|
||||||
|
### Public
|
||||||
|
|
||||||
|
- `POST /auth/register` — create account
|
||||||
|
- `POST /auth/login` — login, get JWT tokens
|
||||||
|
- `POST /auth/refresh` — refresh access token
|
||||||
|
- `GET /sub/:uuid` — subscription config for VPN clients (base64 URI list)
|
||||||
|
- `GET /sub/:uuid/info` — subscription info (JSON)
|
||||||
|
- `GET /health`, `GET /metrics`
|
||||||
|
|
||||||
|
### User
|
||||||
|
|
||||||
|
- `GET /me` — profile and balance
|
||||||
|
- `GET /me/subscriptions` — subscriptions and links
|
||||||
|
- `GET /me/balance/transactions` — transaction history
|
||||||
|
|
||||||
|
### Admin
|
||||||
|
|
||||||
|
- **Users** — CRUD, status approval (pending / active / rejected), balance management
|
||||||
|
- **Tariffs** — CRUD
|
||||||
|
- **Nodes** — CRUD, protocol management, xray/MTProto version install, GeoIP update, outbounds
|
||||||
|
- **Subscriptions** — create, manage, auto-renewal toggle
|
||||||
|
- **Routing rule sets** — xray-native rules and balancers
|
||||||
|
- **External subscriptions** — aggregate external VPN share URLs
|
||||||
|
- **Audit logs**
|
||||||
|
|
||||||
|
## Tariff types
|
||||||
|
|
||||||
|
| Type | Expiry | Auto-renews |
|
||||||
|
|------|--------|-------------|
|
||||||
|
| Timed paid | By date | If balance ≥ 0 |
|
||||||
|
| Timed free | By date | Always |
|
||||||
|
| Indefinite paid | When traffic exhausted | If balance ≥ 0 |
|
||||||
|
| Indefinite free | When traffic exhausted | Always |
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
version: '3.9'
|
||||||
|
|
||||||
|
# Core + Panel deployment (main server)
|
||||||
|
# Usage: docker compose -f docker-compose.base.yml up -d
|
||||||
|
|
||||||
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: nexuma-redis
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
networks:
|
||||||
|
- nexuma
|
||||||
|
|
||||||
|
core:
|
||||||
|
image: nexuma/core:latest
|
||||||
|
container_name: nexuma-core
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
PORT: 3000
|
||||||
|
# PostgreSQL — use an external instance or add a postgres service below
|
||||||
|
DB_HOST: your-postgres-host
|
||||||
|
DB_PORT: 5432
|
||||||
|
DB_USER: postgres
|
||||||
|
DB_PASSWORD: change-me
|
||||||
|
DB_NAME: nexuma
|
||||||
|
# Redis
|
||||||
|
REDIS_HOST: redis
|
||||||
|
REDIS_PORT: 6379
|
||||||
|
# JWT — use long random strings
|
||||||
|
JWT_SECRET: change-me
|
||||||
|
JWT_REFRESH_SECRET: change-me
|
||||||
|
JWT_EXPIRES_IN: 15m
|
||||||
|
JWT_REFRESH_EXPIRES_IN: 7d
|
||||||
|
# Optional: Telegram bot (enables OAuth login and notifications)
|
||||||
|
# TELEGRAM_BOT_TOKEN: your-bot-token
|
||||||
|
# CORS_ORIGINS: https://your-domain.com
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
networks:
|
||||||
|
- nexuma
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "wget -qO- http://localhost:3000/health || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
panel:
|
||||||
|
image: nexuma/panel:latest
|
||||||
|
container_name: nexuma-panel
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
NUXT_CORE_URL: http://core:3000
|
||||||
|
ports:
|
||||||
|
- "3010:3000"
|
||||||
|
depends_on:
|
||||||
|
- core
|
||||||
|
networks:
|
||||||
|
- nexuma
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
redis_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
nexuma:
|
||||||
|
driver: bridge
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
version: '3.9'
|
||||||
|
|
||||||
|
# Node agent deployment (each VPN server)
|
||||||
|
# Usage: docker compose -f docker-compose.node.yml up -d
|
||||||
|
|
||||||
|
services:
|
||||||
|
node:
|
||||||
|
image: nexuma/node:latest
|
||||||
|
container_name: nexuma-node
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
PORT: 3001
|
||||||
|
# URL of Core — must be reachable from this server
|
||||||
|
CORE_URL: http://your-core-server:3000
|
||||||
|
# One-time registration code — generate in admin panel → Nodes
|
||||||
|
# Remove this line after the node registers successfully
|
||||||
|
REGISTRATION_CODE: your-one-time-code
|
||||||
|
HEARTBEAT_INTERVAL_SEC: 30
|
||||||
|
volumes:
|
||||||
|
- node_data:/var/lib/vpnnode
|
||||||
|
ports:
|
||||||
|
- "3001:3001"
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "wget -qO- http://localhost:3001/health || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 15s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
node_data:
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Node
|
||||||
|
|
||||||
|
Agent that runs on each VPN server. Connects to Core, receives protocol configuration, manages the xray process, and reports traffic statistics.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Edit the environment variables in [`docker-compose.node.yml`](./docker-compose.node.yml):
|
||||||
|
|
||||||
|
| Variable | Required | Description |
|
||||||
|
|----------|----------|-------------|
|
||||||
|
| `CORE_URL` | Yes | URL of the Core service (e.g. `http://your-core-server:3000`) |
|
||||||
|
| `REGISTRATION_CODE` | Once | One-time code generated in admin panel → Nodes |
|
||||||
|
| `HEARTBEAT_INTERVAL_SEC` | No | Heartbeat interval in seconds (default: `30`) |
|
||||||
|
|
||||||
|
Data directory is `/var/lib/vpnnode` and mounted as a Docker volume — all state (auth key, VPN configs, binaries) persists across container restarts automatically.
|
||||||
|
|
||||||
|
## Registration
|
||||||
|
|
||||||
|
1. In the admin panel, open **Nodes** and generate a registration code.
|
||||||
|
2. Set `CORE_URL` and `REGISTRATION_CODE` in `docker-compose.node.yml`.
|
||||||
|
3. Run `docker compose -f docker-compose.node.yml up -d`.
|
||||||
|
4. Once the node appears as online in the panel, remove the `REGISTRATION_CODE` line.
|
||||||
|
|
||||||
|
## Behaviour
|
||||||
|
|
||||||
|
- Sends a heartbeat to Core every 30 seconds; if Core reports a newer config revision, the node pulls it immediately.
|
||||||
|
- Core can also trigger an instant config pull by calling the node directly (e.g. on admin-initiated sync).
|
||||||
|
- Reports per-subscription traffic to Core every minute.
|
||||||
|
- On first start, automatically installs the latest xray release if not present.
|
||||||
|
- Updates GeoIP/Geosite files automatically every 12 hours.
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Panel
|
||||||
|
|
||||||
|
Admin web interface for Nexuma. Built with Nuxt 3 and Nuxt UI.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
| Variable | Required | Description |
|
||||||
|
|----------|----------|-------------|
|
||||||
|
| `NUXT_CORE_URL` | Yes | Internal URL of Core (e.g. `http://core:3000`) |
|
||||||
|
| `NUXT_PUBLIC_API_BASE` | No | Public API base path (default: `/api`) |
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://your-server:3010`.
|
||||||
|
|
||||||
|
## What you can do
|
||||||
|
|
||||||
|
- **Users** — manage accounts, approve or reject registrations, top up balances
|
||||||
|
- **Tariffs** — create and configure tariff plans (protocols, nodes, traffic limits, price)
|
||||||
|
- **Nodes** — add VPN servers, configure protocols, install xray, manage routing
|
||||||
|
- **Subscriptions** — view and manage all subscriptions, create links, toggle auto-renewal
|
||||||
|
- **Config builder** — guided wizard to set up a new protocol on a node
|
||||||
|
- **Routing rules** — create xray rule sets and assign them to nodes
|
||||||
|
- **External subscriptions** — import external VPN share URLs into user subscriptions
|
||||||
|
- **Logs** — audit log viewer
|
||||||
|
- **User self-service** — users can view their own subscriptions, traffic, and balance
|
||||||
Reference in New Issue
Block a user