Release VpnPanel 1.0.0

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
test2
2026-07-25 22:34:22 +03:00
co-authored by Cursor
parent ad7e1db6b7
commit 0b3103bd78
6 changed files with 42 additions and 15 deletions
+20
View File
@@ -0,0 +1,20 @@
# Changelog
## [1.0.0] — 2026-07-25
Первый стабильный релиз VpnPanel.
### Возможности
- Веб-админка на FastAPI + PostgreSQL (Dokploy / Docker Compose)
- Серверы WireGuard и AmneziaWG 2.0 по SSH: проверка, установка VPN, синхронизация конфигов
- Клиенты WG/AWG: создание, QR, скачивание `.conf`
- Подключение панелей **3x-ui** (API v3.5.0): API Token или логин/пароль
- Создание клиентов VLESS и WireGuard в 3x-ui (срок, старт после первого использования, лимиты)
- Учёт клиентов, созданных через сайт
- Выбор inbound’ов на сервере 3x-ui, доступных для пользователей
- Единая страница клиентов: вкладки WireGuard/AWG и 3x-ui
### Деплой
Порт панели: `20000`. Миграции Alembic применяются при старте контейнера.
+13 -14
View File
@@ -1,19 +1,19 @@
# VpnPanel # VpnPanel
Веб‑панель (сайт) для управления **WireGuard** и **AmneziaWG 2.0** на VPS. **Версия 1.0.0**
Веб‑панель (сайт) для управления **WireGuard**, **AmneziaWG 2.0** и панелями **3x-ui** на VPS.
В отличие от BandjuPanel это не десктопное приложение через SSH, а обычный веб‑сайт с админкой, который крутится на сервере (Dokploy / Docker Compose) и хранит данные в PostgreSQL. В отличие от BandjuPanel это не десктопное приложение через SSH, а обычный веб‑сайт с админкой, который крутится на сервере (Dokploy / Docker Compose) и хранит данные в PostgreSQL.
## Что уже есть ## Что есть в 1.0
- Лендинг `/` - Лендинг `/` и админка `/admin` (логин из ENV)
- Админка `/admin` (логин из ENV) - Серверы WireGuard / AWG 2.0: SSH, установка VPN на VPS, синхронизация конфигов
- Серверы WireGuard и AWG 2.0 (создаются при старте) - Клиенты WG/AWG: создать / вкл-выкл / удалить, `.conf` и QR
- Клиенты: создать / вкл-выкл / удалить - Панели **3x-ui**: подключение по API, VLESS / WireGuard клиенты
- Скачивание `.conf` и QR‑код - Выбор inbound’ов, доступных пользователям; клиенты, созданные через сайт
- Запись серверных конфигов в volumes `/data/wireguard` и `/data/amneziawg` - PostgreSQL + Alembic, Docker Compose под Dokploy
- PostgreSQL + Alembic миграции
- Docker Compose под Dokploy
## Docker Compose (Dokploy) ## Docker Compose (Dokploy)
@@ -103,9 +103,8 @@ Dockerfile
alembic/ # миграции alembic/ # миграции
``` ```
## Дальше ## Дальше (после 1.0)
- Редактирование endpoint/DNS сервера из админки
- Подключение XRay / Hysteria2 / MTProto
- Статистика handshake / трафика
- Пользовательский кабинет (не только admin) - Пользовательский кабинет (не только admin)
- Статистика handshake / трафика
- Редактирование endpoint/DNS сервера из админки
+1
View File
@@ -0,0 +1 @@
1.0.0
+1
View File
@@ -5,6 +5,7 @@ class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore") model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
app_name: str = "VpnPanel" app_name: str = "VpnPanel"
app_version: str = "1.0.0"
secret_key: str = "change-me" secret_key: str = "change-me"
debug: bool = False debug: bool = False
+6 -1
View File
@@ -10,11 +10,16 @@ from app.routers import admin, auth, public, xui
def create_app() -> FastAPI: def create_app() -> FastAPI:
app = FastAPI(title=settings.app_name, docs_url="/api/docs" if settings.debug else None) app = FastAPI(
title=settings.app_name,
version=settings.app_version,
docs_url="/api/docs" if settings.debug else None,
)
install_session_middleware(app) install_session_middleware(app)
base = Path(__file__).resolve().parent base = Path(__file__).resolve().parent
templates = Jinja2Templates(directory=str(base / "templates")) templates = Jinja2Templates(directory=str(base / "templates"))
templates.env.globals["app_version"] = settings.app_version
app.state.templates = templates app.state.templates = templates
app.state.settings = settings app.state.settings = settings
+1
View File
@@ -16,6 +16,7 @@
</nav> </nav>
<div class="meta"> <div class="meta">
<div>{{ admin.username }}</div> <div>{{ admin.username }}</div>
<div class="muted" style="margin-top:0.35rem;font-size:0.78rem">v{{ app_version }}</div>
<form class="inline-form" method="post" action="/admin/logout" style="margin-top:0.6rem"> <form class="inline-form" method="post" action="/admin/logout" style="margin-top:0.6rem">
<button class="btn btn-ghost btn-sm" type="submit" style="color:#d7dee5;border-color:#2a343c">Выйти</button> <button class="btn btn-ghost btn-sm" type="submit" style="color:#d7dee5;border-color:#2a343c">Выйти</button>
</form> </form>