Версия 1.0 | 12 сентября 2026 | Панель: https://vpn.avk27.ru
* уже настроен)webproxy3x-ui можно установить официальным скриптом (bash <(curl -Ls .../install.sh), systemd-служба на хосте) или Docker-образом ghcr.io/mhsanaei/3x-ui. Для этого сервера выбран Docker-контейнер:
| Критерий | Docker-контейнер ✅ | Установка на уровне системы |
|---|---|---|
| Соответствие архитектуре сервера | Вся инфраструктура (NPM, Portainer, Dozzle, Uptime Kuma, проекты) — в Docker | Единственный systemd-сервис рядом с Docker-инфраструктурой |
| Доступ к панели | По имени контейнера 3x-ui:2053 из сети webproxy → NPM даёт HTTPS + сертификат Let's Encrypt | Панель слушает порт на хосте, нужен отдельный порт в ufw и проброс через IP:порт |
| Обновление | docker compose pull && up -d, образ целиком (панель + Xray согласованы) | Повторный запуск скрипта, обновления Xray привязаны к релизам панели |
| Логи и управление | Dozzle, Portainer — как у остальных сервисов | journalctl, отдельная служба |
| Полное удаление | docker compose down + удаление каталога, следов на хосте нет | Скрипт uninstall + ручная чистка /usr/local/x-ui, /etc/x-ui, systemd |
| Изоляция | Панель не публикуется наружу (только через NPM) | Панель по умолчанию доступна с любого IP на своём порту |
⚠️ Предыстория: на сервере параллельно существовали обе установки — Docker-контейнер (август) и системная установка (24.08, перезапущена 12.09). Хост vpn.avk27.ru в NPM указывал на 193.32.179.138:3571, тогда как системная панель слушала порт 3517 (переставленные цифры) — из-за этого панель по домену не открывалась. Обе установки удалены, выполнена чистая установка в Docker.
Клиент (браузер, админ)
│
▼ https://vpn.avk27.ru (порт 443)
Nginx Proxy Manager ───► контейнер 3x-ui:2053 (панель, сеть webproxy)
│
├── база: /opt/3x-ui/data/db (sqlite)
└── серт: /opt/3x-ui/data/cert
VPN-клиенты (v2rayNG, Streisand, ...)
│
▼ vpn.avk27.ru:20000–20100 (TCP/UDP напрямую, мимо NPM)
хост:20000-20100 ──► контейнер 3x-ui (inbounds Xray)
ufw: диапазон 20000:20100/tcp и /udp разрешён
Проверяем и удаляем обе старые установки (данные старых подключений при этом теряются):
# Системная установка
which x-ui; ls /usr/local/x-ui /etc/x-ui 2>/dev/null; systemctl status x-ui
# Docker-установка
docker ps -a | grep -i x-ui
docker images | grep -i 3x-ui
ls /opt/3x-ui 2>/dev/null
cd /opt/3x-ui
docker compose down --remove-orphans
docker rmi ghcr.io/mhsanaei/3x-ui:latest
rm -rf /opt/3x-ui
systemctl stop x-ui
systemctl disable x-ui
rm -f /etc/systemd/system/x-ui.service
systemctl daemon-reload && systemctl reset-failed
rm -rf /usr/local/x-ui /etc/x-ui /usr/bin/x-ui /etc/default/x-ui
# Проверка, что следов не осталось (cron, logrotate, процессы)
crontab -l | grep -i xui; ls /etc/logrotate.d | grep -i xui; pgrep -a xray
В админке NPM (Hosts → Proxy Hosts) удалите устаревшие хосты прежних попыток (например, cdn01.avk27.ru, 3x-ui.avk27.ru) вместе с их сертификатами (раздел SSL Certificates). Хост vpn.avk27.ru — исправьте согласно шагу 6.
mkdir -p /opt/3x-ui/data/db /opt/3x-ui/data/cert
cd /opt/3x-ui
Файл /opt/3x-ui/docker-compose.yml:
services:
3x-ui:
image: ghcr.io/mhsanaei/3x-ui:latest
container_name: 3x-ui
restart: unless-stopped
volumes:
- ./data/db:/etc/x-ui/ # база sqlite (настройки, inbound-ы, клиенты)
- ./data/cert:/root/cert/ # сертификаты, если понадобятся
environment:
- XRAY_VMESS_AEAD_FORCED=false
# Веб-панель — НЕ публикуем напрямую наружу, идёт через NPM (vpn.avk27.ru) по сети webproxy
expose:
- "2053"
# Входящие подключения VPN-клиентов — публикуем напрямую (NPM их проксировать не умеет).
# Диапазон подобран с запасом; в ufw уже открыт целиком.
ports:
- "20000-20100:20000-20100"
- "20000-20100:20000-20100/udp"
networks:
- webproxy
networks:
webproxy:
external: true
Ключевые моменты:
expose вместо ports для 2053 — панель доступна только внутри сети webproxy, наружу только через NPM;webproxy — та же внешняя сеть, что у NPM и остальных сервисов.
cd /opt/3x-ui
docker compose up -d
docker ps --filter name=3x-ui
docker logs 3x-ui --tail 20
Образ стартует с логином/паролем admin/admin и корневым путём /. Сразу задайте собственные учётные данные и секретный путь (дополнительная защита: без пути панель отдаёт 404):
# Сгенерировать значения
openssl rand -hex 4 # для имени пользователя
openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c 22 # пароль
openssl rand -hex 8 # секретный путь
# Применить (подставьте свои значения)
docker exec 3x-ui /app/x-ui setting -username <ЛОГИН> -password <ПАРОЛЬ> -webBasePath /<СЕКРЕТНЫЙ_ПУТЬ>/
docker restart 3x-ui
# Проверка настроек
docker exec 3x-ui /app/x-ui setting -show
# Ожидается: port: 2053, webBasePath: /xxxx/, hasDefaultCredential: false
Сохраните доступ в файл с правами 600 (на сервере он уже создан — /opt/3x-ui/PANEL_CREDENTIALS.txt):
cat > /opt/3x-ui/PANEL_CREDENTIALS.txt << 'EOF'
URL: https://vpn.avk27.ru/<СЕКРЕТНЫЙ_ПУТЬ>/
Логин: <ЛОГИН>
Пароль: <ПАРОЛЬ>
EOF
chmod 600 /opt/3x-ui/PANEL_CREDENTIALS.txt
В админке NPM создайте (или исправьте) Proxy Host:
| Поле | Значение |
|---|---|
| Domain Names | vpn.avk27.ru |
| Scheme | http |
| Forward Hostname / IP | 3x-ui |
| Forward Port | 2053 |
Затем:
⚠️ Если правка выполняется напрямую в базе NPM (/opt/infrastructure/npm/data/database.sqlite): после изменения не забудьте синхронизировать рендер-конфиг /opt/infrastructure/npm/data/nginx/proxy_host/<id>.conf (значения $server/$port, include force-ssl.conf) и перезагрузить nginx: docker exec nginx-proxy-manager nginx -t && docker exec nginx-proxy-manager nginx -s reload. Рестарт контейнера NPM сам конфиги не перегенерирует.
Диапазон для VPN-клиентов уже открыт (сделано ранее); панель и подписка наружу не публикуются:
ufw status | grep 20000
# 20000:20100/tcp ALLOW IN Anywhere
# 20000:20100/udp ALLOW IN Anywhere
# Если правил нет — добавить:
ufw allow 20000:20100/tcp
ufw allow 20000:20100/udp
https://vpn.avk27.ru/<СЕКРЕТНЫЙ_ПУТЬ>/ и войдите;www.microsoft.com:443 (или другой крупный сайт); serverNames — тот же домен;xtls-rprx-vision;vpn.avk27.ru:порт (диапазон 20000–20100).
# 1. Панель отвечает по HTTPS (ожидается 200)
curl -s -o /dev/null -w "%{http_code}\n" https://vpn.avk27.ru/<СЕКРЕТНЫЙ_ПУТЬ>/
# 2. HTTP принудительно редиректит на HTTPS (ожидается 301)
curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" http://vpn.avk27.ru/<СЕКРЕТНЫЙ_ПУТЬ>/
# 3. Без секретного пути панель скрыта (ожидается 404)
curl -s -o /dev/null -w "%{http_code}\n" https://vpn.avk27.ru/
# 4. Внутри сети webproxy (из контейнера NPM)
docker exec nginx-proxy-manager curl -s -o /dev/null -w "%{http_code}\n" http://3x-ui:2053/<СЕКРЕТНЫЙ_ПУТЬ>/
# 5. Порт inbound-а доступен снаружи (с локальной машины)
nc -zv vpn.avk27.ru 20031
# Обновление (панель + Xray одной командой)
cd /opt/3x-ui && docker compose pull && docker compose up -d
# Логи
docker logs -f 3x-ui
# Перезапуск
docker restart 3x-ui
# Бэкап: /opt/3x-ui/include в backup.sh (см. заметку ниже)
tar -czf /opt/backups/3x-ui-$(date +%F).tar.gz /opt/3x-ui/data /opt/3x-ui/docker-compose.yml
Скрипт /opt/scripts/backup.sh бэкапит NPM и /opt/projects; каталог /opt/3x-ui в него уже добавлен отдельным tar-архивом.
| Симптом | Причина / решение |
|---|---|
| Панель по vpn.avk27.ru отдаёт 502 | Контейнер 3x-ui не запущен или не в сети webproxy: docker ps, docker network inspect webproxy; forward-хост в NPM должен быть 3x-ui:2053 |
| 404 на верном пути | Опечатка в webBasePath — проверьте docker exec 3x-ui /app/x-ui setting -show |
| Клиент не подключается к inbound | Порт должен быть из опубликованного диапазона 20000–20100 и открыт в ufw; Reality dest должен быть доступен с сервера |
| Забыли пароль панели | docker exec 3x-ui /app/x-ui setting -username <новый> -password <новый> и docker restart 3x-ui |
| Сброс всех настроек панели | docker exec 3x-ui /app/x-ui setting -reset (клиенты и inbound-ы сохранятся в БД) |
/ — 404);/opt/3x-ui/PANEL_CREDENTIALS.txt (права 600);