Добавлена подробная инструкция INSTALL.md (Docker + VPS Panel)
This commit is contained in:
+487
@@ -0,0 +1,487 @@
|
||||
# Установка Docker и развёртывание Proxmox VPS Panel
|
||||
|
||||
Полная пошаговая инструкция: от чистого Linux-сервера до работающей панели
|
||||
управления VPS на базе Proxmox VE.
|
||||
|
||||
Документ рассчитан на Debian 12 / Ubuntu 22.04+ (это самый частый вариант
|
||||
для Proxmox-хоста и для отдельной VM/LXC под панель). Для других дистрибутивов
|
||||
есть отдельный раздел ниже.
|
||||
|
||||
---
|
||||
|
||||
## 1. Требования
|
||||
|
||||
### Аппаратные (для VM/LXC, где будет крутиться панель)
|
||||
|
||||
| Ресурс | Минимум | Рекомендуется |
|
||||
|---|---|---|
|
||||
| CPU | 1 vCPU | 2 vCPU |
|
||||
| RAM | 1 ГБ | 2 ГБ |
|
||||
| Диск | 8 ГБ | 20 ГБ (с запасом под бэкапы Postgres) |
|
||||
| Сеть | Доступ до API Proxmox по TCP 8006 | то же |
|
||||
|
||||
### Программные
|
||||
|
||||
- Linux с ядром ≥ 3.10 (для Docker Engine)
|
||||
- Права `root` или пользователь из группы `sudo`
|
||||
- Открытый порт `5173` (frontend, nginx) — если панель должна быть доступна извне
|
||||
- Доступ до Proxmox VE по HTTPS (порт 8006)
|
||||
|
||||
### Сетевые
|
||||
|
||||
- Сервер панели должен «видеть» Proxmox API (`https://<pve-ip>:8006/api2/json`)
|
||||
- Proxmox в свою очередь должен «видеть» сеть, в которой будут создаваться VM/CT
|
||||
(обычно это один и тот же `vmbr0` / bridge)
|
||||
|
||||
---
|
||||
|
||||
## 2. Установка Docker Engine + Compose
|
||||
|
||||
> Docker Engine — это сервер контейнеров (демон `dockerd`).
|
||||
> Docker Compose — это инструмент для описания multi-container приложений в YAML
|
||||
> (формат `compose.yaml`/`docker-compose.yml`).
|
||||
|
||||
### 2.1. Debian / Ubuntu (рекомендуемый путь)
|
||||
|
||||
```bash
|
||||
# 1. Обновляем индекс пакетов и ставим prerequisites
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg \
|
||||
lsb-release
|
||||
|
||||
# 2. Добавляем официальный GPG-ключ Docker
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg \
|
||||
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# 3. Добавляем репозиторий Docker
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
|
||||
https://download.docker.com/linux/debian \
|
||||
$(lsb_release -cs) stable" \
|
||||
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
# 4. Ставим Docker Engine + CLI + Compose plugin
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
docker-ce \
|
||||
docker-ce-cli \
|
||||
containerd.io \
|
||||
docker-buildx-plugin \
|
||||
docker-compose-plugin
|
||||
```
|
||||
|
||||
> Для Ubuntu замените `debian` на `ubuntu` в строке с URL репозитория, остальное
|
||||
> идентично.
|
||||
|
||||
### 2.2. Альтернатива: официальный `install.sh`
|
||||
|
||||
Если не хочется возиться с репозиторием — Docker предоставляет скрипт, который
|
||||
сделает всё сам:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||
sudo sh get-docker.sh
|
||||
```
|
||||
|
||||
Этот же скрипт работает на Debian, Ubuntu, RHEL, Fedora, CentOS, AlmaLinux,
|
||||
Rocky и т. д. — внутри он сам определяет дистрибутив.
|
||||
|
||||
### 2.3. Другие дистрибутивы (краткая сводка)
|
||||
|
||||
| Дистрибутив | Что делать |
|
||||
|---|---|
|
||||
| Fedora / RHEL / Alma / Rocky | `sudo dnf -y install dnf-plugins-core && sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo && sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin` |
|
||||
| Arch / Manjaro | `sudo pacman -S docker docker-compose` |
|
||||
| openSUSE | `sudo zypper install docker docker-compose` |
|
||||
| TrueNAS SCALE | см. раздел 8 — там Docker уже встроен |
|
||||
|
||||
---
|
||||
|
||||
## 3. Постустановочная настройка Docker
|
||||
|
||||
### 3.1. Включаем автозапуск демона
|
||||
|
||||
```bash
|
||||
sudo systemctl enable --now docker
|
||||
sudo systemctl status docker # должно быть active (running)
|
||||
```
|
||||
|
||||
### 3.2. Разрешаем пользователю работать без `sudo`
|
||||
|
||||
По умолчанию `docker` требует root. Чтобы не набирать `sudo` каждый раз:
|
||||
|
||||
```bash
|
||||
sudo usermod -aG docker $USER
|
||||
# После этого нужно ПЕРЕЛОГИНИТЬСЯ (или выполнить newgrp docker):
|
||||
newgrp docker
|
||||
```
|
||||
|
||||
Проверка:
|
||||
|
||||
```bash
|
||||
docker version
|
||||
docker compose version
|
||||
docker run --rm hello-world
|
||||
```
|
||||
|
||||
Если `hello-world` скачался и напечатал приветствие — Docker готов.
|
||||
|
||||
### 3.3. Ограничение логов (опционально, но полезно)
|
||||
|
||||
Чтобы контейнеры не съедали диск логами, создайте `/etc/docker/daemon.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"log-driver": "json-file",
|
||||
"log-opts": {
|
||||
"max-size": "10m",
|
||||
"max-file": "3"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
И перезапустите демон:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Подготовка Proxmox
|
||||
|
||||
Эти шаги делаются в **веб-интерфейсе Proxmox**.
|
||||
|
||||
### 4.1. API-токен
|
||||
|
||||
1. **Datacenter → Permissions → API Tokens → Add**
|
||||
2. User: `root@pam` (для теста; в проде лучше завести отдельного пользователя —
|
||||
см. раздел «Безопасность» ниже)
|
||||
3. Token ID: например `panel`
|
||||
4. Privilege Separation: **выключить** (чтобы токен наследовал все права владельца)
|
||||
5. Скопируйте **Secret** — он показывается один раз.
|
||||
|
||||
В итоге получите пару:
|
||||
|
||||
```
|
||||
PVE_TOKEN_NAME=root@pam!panel
|
||||
PVE_TOKEN_VALUE=<тот самый секрет>
|
||||
```
|
||||
|
||||
Права, которые нужны панели:
|
||||
|
||||
- `VM.Allocate`, `VM.PowerMgmt`, `VM.Config.Disk`, `VM.Config.Network`,
|
||||
`VM.Config.CPU`, `VM.Config.Memory`, `VM.Config.Cloudinit`,
|
||||
`VM.Clone`, `VM.Audit`, `VM.Snapshot`, `VM.Backup`
|
||||
- `Sys.Audit` (для чтения статусов задач Proxmox)
|
||||
- Аналогичные права для `PVEAdmin` / `PVEAuditor` на ветке `/`
|
||||
|
||||
В тестовой среде проще всего выдать роль `PVEAdmin` на корень `/`.
|
||||
|
||||
### 4.2. Шаблон VM (для VM-инстансов)
|
||||
|
||||
1. Скачайте cloud-образ, например Ubuntu 22.04:
|
||||
```bash
|
||||
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
|
||||
```
|
||||
2. В Proxmox создайте VM, в **Hardware → CD/DVD** укажите этот образ.
|
||||
3. В **Cloud-Init → User**, **Password**, **SSH key** — заполните значения по умолчанию
|
||||
(панель их перезапишет своими).
|
||||
4. Запустите VM, убедитесь, что cloud-init отработал и сеть поднялась.
|
||||
5. Выключите VM и превратите её в шаблон:
|
||||
```bash
|
||||
qm template <vmid>
|
||||
```
|
||||
VMID запомните — он пойдёт в поле `source_vmid` шаблона в панели.
|
||||
|
||||
### 4.3. Шаблон LXC (для CT-инстансов)
|
||||
|
||||
1. Узел → **local (storage)** → **CT Templates → Template** → вкладка **Download**
|
||||
2. Скачайте, например, `debian-12-standard_12.7-1_amd64.tar.zst`
|
||||
3. Готово. В панели поле `source_template` будет иметь вид:
|
||||
```
|
||||
local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Клонирование и настройка репозитория
|
||||
|
||||
### 5.1. Клонируем
|
||||
|
||||
```bash
|
||||
git clone https://gitea.nasweb.ru/host/Proxmox-VPS-Panel.git
|
||||
cd Proxmox-VPS-Panel
|
||||
```
|
||||
|
||||
Структура должна выглядеть так:
|
||||
|
||||
```
|
||||
Proxmox-VPS-Panel/
|
||||
├── backend/
|
||||
├── frontend/
|
||||
├── docker-compose.yml
|
||||
└── .gitignore
|
||||
```
|
||||
|
||||
### 5.2. Готовим `.env` для backend
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
cp .env.example .env
|
||||
nano .env # или vim / любой редактор
|
||||
```
|
||||
|
||||
Заполните:
|
||||
|
||||
```env
|
||||
# Обязательно смените! Сгенерировать: openssl rand -hex 32
|
||||
SECRET_KEY=<случайная_строка_минимум_32_символа>
|
||||
|
||||
# Proxmox API
|
||||
PVE_HOST=https://192.168.31.2:8006
|
||||
PVE_NODE=pve
|
||||
PVE_TOKEN_NAME=root@pam!panel
|
||||
PVE_TOKEN_VALUE=<ваш_секрет_токена>
|
||||
|
||||
# CORS — домен фронтенда через запятую (без пробелов)
|
||||
ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
|
||||
|
||||
# Пароль БД — ОБЯЗАТЕЛЬНО должен совпадать с POSTGRES_PASSWORD
|
||||
# из .env рядом с docker-compose.yml
|
||||
DATABASE_URL=postgresql://panel:<тот_же_пароль_что_и_POSTGRES_PASSWORD>@db:5432/panel
|
||||
```
|
||||
|
||||
> ⚠️ `DATABASE_URL` обычно собирается автоматически внутри `docker-compose.yml`
|
||||
> через `${POSTGRES_USER}` и `${POSTGRES_PASSWORD}`. Если вы переопределяете
|
||||
> его здесь — убедитесь, что хост = `db` (имя сервиса в compose), а не
|
||||
> `localhost`, иначе backend не достучится до Postgres.
|
||||
|
||||
### 5.3. Генерируем секреты
|
||||
|
||||
```bash
|
||||
# SECRET_KEY для подписи JWT
|
||||
openssl rand -hex 32
|
||||
|
||||
# POSTGRES_PASSWORD для базы данных
|
||||
openssl rand -hex 16
|
||||
```
|
||||
|
||||
### 5.4. Создаём `.env` рядом с `docker-compose.yml`
|
||||
|
||||
Вернитесь в корень проекта:
|
||||
|
||||
```bash
|
||||
cd ..
|
||||
cat > .env <<'EOF'
|
||||
POSTGRES_USER=panel
|
||||
POSTGRES_PASSWORD=<тот_самый_пароль_из_openssl_rand_hex_16>
|
||||
POSTGRES_DB=panel
|
||||
FRONTEND_PORT=5173
|
||||
EOF
|
||||
chmod 600 .env # только владелец может читать — там секрет
|
||||
```
|
||||
|
||||
> Этот файл уже в `.gitignore`, но на всякий случай не пушьте его.
|
||||
|
||||
---
|
||||
|
||||
## 6. Запуск панели
|
||||
|
||||
### 6.1. Поднимаем стек
|
||||
|
||||
```bash
|
||||
docker compose pull # подтянуть базовые образы (postgres, alpine)
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
- `--build` нужен, потому что backend и frontend собираются из исходников
|
||||
(multi-stage Dockerfile внутри `backend/` и `frontend/`)
|
||||
- `-d` запускает в фоне
|
||||
|
||||
### 6.2. Проверяем, что всё поднялось
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
Все три сервиса (`db`, `backend`, `frontend`) должны быть в статусе `running`
|
||||
или `healthy`. Healthcheck у backend проверяет `http://localhost:8000/health`,
|
||||
у frontend — `http://localhost:5173/`, у БД — `pg_isready`.
|
||||
|
||||
Логи в реальном времени:
|
||||
|
||||
```bash
|
||||
docker compose logs -f
|
||||
# или только backend:
|
||||
docker compose logs -f backend
|
||||
```
|
||||
|
||||
### 6.3. Проверка API вручную
|
||||
|
||||
```bash
|
||||
curl http://localhost:5173/api/health
|
||||
# {"status":"ok"}
|
||||
|
||||
curl http://localhost:5173/api/health/ready
|
||||
# {"status":"ready","db":"ok"}
|
||||
```
|
||||
|
||||
> `/api/*` проксируется nginx-фронтенда на backend, поэтому порт 8000 наружу
|
||||
> не торчит.
|
||||
|
||||
### 6.4. Открываем UI
|
||||
|
||||
В браузере:
|
||||
|
||||
```
|
||||
http://<ip-сервера-панели>:5173
|
||||
```
|
||||
|
||||
1. Нажмите **Register** — зарегистрируйтесь.
|
||||
2. **Первый зарегистрированный пользователь автоматически становится админом.**
|
||||
Это важно — зайдите первым сами.
|
||||
3. Войдите как админ, откройте **Admin → Templates**, создайте шаблон:
|
||||
|
||||
- **Type**: `vm` или `lxc`
|
||||
- **Name**: что увидит клиент (например, `Ubuntu 22.04 / 1 vCPU / 1 GB`)
|
||||
- **Cores / Memory / Disk**: сколько ресурсов получит инстанс
|
||||
- **Source VMID** (для `vm`): VMID вашего VM-шаблона из шага 4.2
|
||||
- **Source template** (для `lxc`): путь вида
|
||||
`local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst`
|
||||
|
||||
4. Выйдите из админа, зарегистрируйте второго пользователя (или попросите
|
||||
клиента) — он уже будет `client` и увидит шаблон в дашборде.
|
||||
|
||||
---
|
||||
|
||||
## 7. Типовые ошибки и что с ними делать
|
||||
|
||||
| Симптом | Причина | Решение |
|
||||
|---|---|---|
|
||||
| `POSTGRES_PASSWORD is required` при `up` | не задан `POSTGRES_PASSWORD` в `.env` рядом с compose | см. шаг 5.4 |
|
||||
| Backend падает с `connection refused` на `db:5432` | compose стартует backend раньше, чем БД приняла соединения | уже лечится через `depends_on: condition: service_healthy`; подождите минуту |
|
||||
| `pve authentication failed` при создании VPS | неверный `PVE_TOKEN_VALUE` или истёк токен | пересоздайте токен в Proxmox и обновите `.env`, затем `docker compose restart backend` |
|
||||
| CORS-ошибка в браузере: «blocked by CORS policy» | в `ALLOW_ORIGINS` нет домена, с которого открываете панель | добавьте свой домен/IP в `backend/.env` → `ALLOW_ORIGINS`, затем `docker compose restart backend` |
|
||||
| `permission denied` при `qm template` | вы выполняете не от root | `sudo qm template <vmid>` |
|
||||
| Не приходит IP созданной VM | в VM-шаблоне не установлен `qemu-guest-agent` и не включён в Proxmox | установите `qemu-guest-agent` в шаблоне, в опциях VM включите `Run guest agent on boot` |
|
||||
| Долго создаётся VM/CT | это нормально — `qmclone`/`pct clone` могут занимать минуты на больших дисках | следите за прогрессом через `docker compose logs -f backend` или UI Proxmox |
|
||||
|
||||
---
|
||||
|
||||
## 8. Установка на TrueNAS SCALE
|
||||
|
||||
TrueNAS SCALE (Cobia / Dragonfish / Electric Eel / Fangtooth) уже содержит
|
||||
Docker Engine и Compose из коробки. Дополнительно ставить ничего не нужно.
|
||||
|
||||
### 8.1. Вариант A: «Custom App» через UI
|
||||
|
||||
1. **Apps → Discover Apps → Custom App**
|
||||
2. **Application Name**: `vps-panel`
|
||||
3. В секции **Container Images / Compose** переключитесь на режим
|
||||
«Custom Compose`» и вставьте содержимое нашего `docker-compose.yml`
|
||||
(или положите файлы в датасет и смонтируйте их как `/docker-compose.yml`).
|
||||
4. Переменные окружения задайте через UI:
|
||||
- `POSTGRES_USER` = `panel`
|
||||
- `POSTGRES_PASSWORD` = `<openssl rand -hex 16>`
|
||||
- `POSTGRES_DB` = `panel`
|
||||
- `FRONTEND_PORT` = `5173`
|
||||
- На отдельной вкладке для сервиса `backend` добавьте все `PVE_*` и
|
||||
`SECRET_KEY`, `ALLOW_ORIGINS`, плюс `env_file: ./backend/.env`
|
||||
5. **Storage**:
|
||||
- Для сервиса `db` смонтируйте `panel_db` (named volume) или
|
||||
путь на датасете типа `/mnt/tank/apps/vps-panel/db`
|
||||
6. Нажмите **Install**. Статус появится в **Installed Applications**.
|
||||
|
||||
### 8.2. Вариант B: shell + `docker compose`
|
||||
|
||||
```bash
|
||||
# Заходим на TrueNAS по SSH или открываем System Settings → Shell
|
||||
cd /mnt/tank/apps/vps-panel # путь, куда положили репозиторий
|
||||
cp backend/.env.example backend/.env
|
||||
nano backend/.env # заполняем
|
||||
cat > .env <<'EOF'
|
||||
POSTGRES_USER=panel
|
||||
POSTGRES_PASSWORD=<openssl rand -hex 16>
|
||||
POSTGRES_DB=panel
|
||||
FRONTEND_PORT=5173
|
||||
EOF
|
||||
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### 8.3. Reverse-proxy
|
||||
|
||||
TrueNAS Apps умеет автоматически прокидывать порты. Если нужен внешний доступ:
|
||||
|
||||
- Встроенный reverse-proxy TrueNAS (например, через приложение
|
||||
`nginx-proxy-manager` или `traefik`)
|
||||
- Или собственный reverse-proxy (Caddy, Nginx) с TLS через Let's Encrypt
|
||||
|
||||
Обязательно укажите итоговый внешний домен в `backend/.env → ALLOW_ORIGINS`,
|
||||
иначе CORS заблокирует запросы.
|
||||
|
||||
---
|
||||
|
||||
## 9. Обновление панели
|
||||
|
||||
```bash
|
||||
cd Proxmox-VPS-Panel
|
||||
git pull
|
||||
docker compose pull
|
||||
docker compose up -d --build
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
Миграций БД нет (используется `Base.metadata.create_all()`), так что апгрейд
|
||||
проходит без ручных шагов. Перед большими апгрейдами рекомендуется
|
||||
сделать бэкап volume `panel_db`:
|
||||
|
||||
```bash
|
||||
docker compose stop db
|
||||
docker run --rm \
|
||||
-v panel_db:/from \
|
||||
-v $(pwd)/backups:/to \
|
||||
alpine sh -c "tar czf /to/panel_db_$(date +%F).tgz -C /from ."
|
||||
docker compose start db
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Удаление
|
||||
|
||||
```bash
|
||||
cd Proxmox-VPS-Panel
|
||||
docker compose down # остановить и удалить контейнеры
|
||||
docker compose down -v # + удалить volume panel_db (ВСЕ ДАННЫЕ БД)
|
||||
docker image prune -a # удалить неиспользуемые образы
|
||||
```
|
||||
|
||||
Удаление **не трогает** VM и LXC на Proxmox — их панель создаёт через API,
|
||||
и они продолжат жить независимо.
|
||||
|
||||
---
|
||||
|
||||
## Краткий чек-лист «поставил и работает»
|
||||
|
||||
```
|
||||
[ ] Docker Engine + Compose установлены
|
||||
[ ] docker compose version показывает v2+
|
||||
[ ] В Proxmox создан API-токен
|
||||
[ ] В Proxmox есть VM-шаблон (если планируются VM)
|
||||
[ ] В Proxmox есть CT-шаблон (если планируются LXC)
|
||||
[ ] git clone репозитория выполнен
|
||||
[ ] backend/.env заполнен, SECRET_KEY сменён
|
||||
[ ] POSTGRES_PASSWORD сгенерирован и записан в .env рядом с compose
|
||||
[ ] docker compose up -d --build — все 3 сервиса running/healthy
|
||||
[ ] curl /api/health → {"status":"ok"}
|
||||
[ ] В браузере открыт http://<host>:5173, зарегистрирован админ
|
||||
[ ] Создан хотя бы один шаблон в Admin → Templates
|
||||
```
|
||||
|
||||
Если все галочки стоят — панель готова к работе.
|
||||
Reference in New Issue
Block a user