diff --git a/README.md b/README.md index 201f1bf..9836cc1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Proxmox VPS Panel -Минимальная self-hosted панель для мульти-тенантного управления VPS (VM и LXC) на вашем +Self-hosted панель для мульти-тенантного управления VPS (VM и LXC) на вашем Proxmox VE через API. Backend — FastAPI (Python), frontend — React (Vite), хранилище — Postgres. Клиенты регистрируются, выбирают шаблон и разворачивают себе VM или LXC-контейнер одной кнопкой; @@ -8,22 +8,26 @@ Proxmox VE через API. Backend — FastAPI (Python), frontend — React (Vit Первый зарегистрированный пользователь автоматически становится администратором и управляет шаблонами и списком пользователей. -## Возможности MVP +## Возможности - Регистрация/логин (JWT), роли admin / client - Шаблоны VPS: админ создаёт тарифы, привязанные к VM-шаблону (клонирование) или CT-шаблону LXC - Клиент создаёт инстанс из шаблона — панель сама берёт свободный VMID и вызывает Proxmox API - Действия: start / stop / shutdown / reboot / delete -- Веб-консоль через noVNC (websocket-прокси на backend) +- Веб-консоль через noVNC (websocket-прокси на backend, noVNC устанавливается из npm) +- Проверка владельца во всех эндпоинтах — клиент не может управлять чужими VM - Всё через docker-compose, разворачивается как Custom App в TrueNAS SCALE +- Healthcheck-эндпоинты (`/health`, `/health/ready`) и Docker-healthcheck у всех сервисов +- Backend работает от непривилегированного пользователя (non-root) -## Чего нет в MVP (сознательно, чтобы не раздувать первую версию) +## Чего нет (сознательно, чтобы не раздувать первую версию) - Поддержки нескольких Proxmox-нод/кластеров одновременно (сейчас один `PVE_NODE` в конфиге) - Биллинга и лимитов по ресурсам на пользователя - Очереди задач (Celery/Redis) — создание VPS идёт в фоне через `BackgroundTasks` FastAPI, для нескольких одновременных заявок этого достаточно, для десятков в секунду — уже нет - Управления сетью/IP-пулами (LXC получает адрес по DHCP, для VM выдаётся из клонированного шаблона) +- Alembic-миграций (сейчас `create_all()` — для прода рекомендуется добавить) ## 1. Подготовка Proxmox @@ -52,23 +56,45 @@ Datacenter → Permissions → API Tokens → добавить токен для Скопируйте `backend/.env.example` в `backend/.env` и заполните: ``` +SECRET_KEY=<случайная строка> # обязательно смените! PVE_HOST=https://:8006 PVE_NODE=pve PVE_TOKEN_NAME=root@pam!panel PVE_TOKEN_VALUE=<значение токена> -SECRET_KEY=<случайная строка> ``` -## 3. Запуск +Пароль Postgres задаётся через переменную окружения `POSTGRES_PASSWORD` в shell +или через `.env` рядом с `docker-compose.yml` (compose читает оба файла). + +## 3. Настройка CORS + +В `backend/.env` укажите `ALLOW_ORIGINS` — список доменов через запятую, с которых +фронтенд будет обращаться к API. По умолчанию это `http://localhost:5173,http://127.0.0.1:5173`. +Для прода обязательно укажите конкретный домен: + +``` +ALLOW_ORIGINS=https://panel.example.com +``` + +## 4. Запуск ```bash +# Установите обязательные переменные: +export POSTGRES_PASSWORD=$(openssl rand -hex 16) +# (опционально) задайте порог логирования: +# export LOG_LEVEL=DEBUG + docker compose up -d --build ``` -Frontend будет на `http://:5173`, backend API — на `http://:8000`. +Frontend будет на `http://:5173`. Backend API наружу **не пробрасывается** — +все запросы идут через nginx фронтенда по пути `/api/*`. Если нужен прямой доступ +для отладки — раскомментируйте `ports` у сервиса `backend` в `docker-compose.yml` +(только `127.0.0.1:8000:8000`). + Первый, кто зарегистрируется на `/register`, станет администратором — заходите первым сами. -## 4. Установка на TrueNAS SCALE +## 5. Установка на TrueNAS SCALE TrueNAS SCALE умеет запускать произвольные Docker-приложения ("Apps → Discover Apps → Custom App" либо через "Launch Docker Compose", если версия TrueNAS это поддерживает). Проще всего: @@ -84,8 +110,9 @@ TrueNAS SCALE умеет запускать произвольные Docker-пр ## Консоль VNC — важное примечание Веб-консоль реализована как websocket-прокси: backend получает от Proxmox тикет -(`vncproxy`) и порт, затем проксирует бинарный поток на `/console/ws`, а фронтенд рисует -экран через noVNC (`@novnc/novnc`, подключается с CDN). +(`vncproxy`) и порт, затем проксирует бинарный поток на `/api/console/ws`, а фронтенд +рисует экран через **noVNC, установленный как npm-пакет** (`@novnc/novnc`, копируется +в `/novnc/` внутри nginx-контейнера на этапе сборки). Proxmox исторически ожидает на `vncwebsocket` либо cookie-тикет (`PVEAuthCookie`) из обычной браузерной сессии, либо (в более новых версиях) заголовок `Authorization: PVEAPIToken=...` — @@ -97,31 +124,57 @@ Proxmox консоль не подключается, скорее всего п ## Безопасность перед продакшеном -- Смените `SECRET_KEY` и пароль Postgres по умолчанию -- Ограничьте `allow_origins` в `backend/app/main.py` конкретным доменом фронтенда -- Закройте порт 8000 (backend) наружу, оставьте доступ только через nginx фронтенда +- Смените `SECRET_KEY` и задайте сильный `POSTGRES_PASSWORD` +- Укажите конкретный домен в `ALLOW_ORIGINS` (а не `*`) +- Backend-порт 8000 не должен торчать наружу — закрыт по умолчанию, используйте nginx - Используйте отдельного Proxmox-пользователя с минимально необходимыми правами для токена панели, а не `root@pam` +- Не публикуйте `backend/.env` (он в `.gitignore`) ## Структура проекта ``` backend/ app/ - main.py — точка входа FastAPI - config.py — переменные окружения - models.py — таблицы: User, Template, Instance - proxmox_client.py — вся логика вызовов Proxmox API (proxmoxer) + main.py — точка входа FastAPI + config.py — переменные окружения (Pydantic v2 Settings) + database.py — SQLAlchemy engine и сессии + security.py — bcrypt + JWT + deps.py — Depends(get_current_user, require_admin) + models.py — таблицы: User, Template, Instance + schemas.py — Pydantic-схемы запросов/ответов + proxmox_client.py — вся логика вызовов Proxmox API (proxmoxer) routers/ - auth.py — регистрация / логин - templates.py — CRUD шаблонов (admin) - instances.py — создание/список/действия/удаление VPS - admin.py — управление пользователями - console.py — websocket-прокси для VNC-консоли + auth.py — регистрация / логин / /me + templates.py — CRUD шаблонов (admin) + импорт из Proxmox + instances.py — создание/список/действия/удаление VPS + admin.py — управление пользователями + console.py — websocket-прокси для VNC-консоли frontend/ src/ - pages/ — Login, Register, Dashboard, InstanceDetail, AdminTemplates, AdminUsers - components/ — InstanceCard, ConsoleViewer - api.js — обёртка над fetch к backend + pages/ — Login, Register, Dashboard, InstanceDetail, AdminTemplates, AdminUsers + components/ — InstanceCard, ConsoleViewer + api.js — обёртка над fetch к backend + styles.css — UI-стили docker-compose.yml +.gitignore +.dockerignore — для backend и frontend ``` + +## Changelog + +### 0.2.0 +- 🔒 Удалён закоммиченный `backend/.env` с реальными секретами. **Смените SECRET_KEY и PVE_TOKEN_VALUE!** +- 🔒 Добавлена проверка владельца во всех рутерах `instances.py` +- 🔒 CORS теперь читается из `ALLOW_ORIGINS` (по умолчанию только localhost) +- 🔒 Backend-порт 8000 закрыт снаружи по умолчанию +- 🔒 Postgres-пароль обязателен через `POSTGRES_PASSWORD` (нет дефолта `panel:panel`) +- 🔒 Добавлены security-заголовки и CSP в `nginx.conf` +- 🛠 Заменён `passlib` на прямой `bcrypt` (passlib несовместим с bcrypt 4.x) +- 🛠 Pydantic v2: `SettingsConfigDict` вместо устаревшего `class Config` +- 🛠 Удалены дубли функций/эндпоинтов в `proxmox_client.py` и `instances.py` +- 🛠 Backend запускается от non-root пользователя +- 🛠 Multi-stage Dockerfile для backend (меньше размер образа) +- 🛠 noVNC устанавливается из npm вместо загрузки с CDN +- 🛠 Добавлены healthcheck'и у всех сервисов в docker-compose +- 🛠 Структурированное логирование через `logging`