Впервые здесь? Прочтите это первым 👋

Никогда не слышали про Marzban, «VPS» или «панель»? Отлично — здесь вся суть объясняется простыми словами. Опыт не нужен совсем.

Одним предложением: NexusPanel — это программа, которая позволяет запустить собственный VPN-сервис и продавать к нему доступ — немного похоже на то, как если бы вы держали свой маленький Netflix, только продаёте вы приватное, разблокированное и более быстрое интернет-соединение.

Вы арендуете дешёвый сервер, устанавливаете на него NexusPanel и получаете удобную веб-панель. В этой панели вы создаёте клиентов, и каждый клиент получает ссылку, которую вставляет в бесплатное приложение на телефоне. Он нажимает «подключиться» — и его интернет теперь идёт через ваш сервер. Вы берёте с него плату каждый месяц. Вот и весь бизнес.

Аналогия с магазином

Если вы представляете, как держать небольшой магазин, вы уже понимаете NexusPanel. Вот как всё устроено:

🧑‍💼
Вы

Владелец

Вы ведёте бизнес, назначаете цены и добавляете клиентов. Программистом быть не обязательно.

🖥️
VPS

Здание вашего магазина

Компьютер, который вы арендуете в дата-центре (≈ $5/месяц). Здесь живёт ваша панель. Провайдеры: Hetzner, Contabo, DigitalOcean…

🎛️
NexusPanel

Ваша касса и витрины

Панель управления, в которую вы заходите через браузер. Добавляйте клиентов, следите за трафиком, получайте оплату — всё отсюда.

🌍
Нода

Филиал за рубежом

Дополнительный сервер, например в Германии или Финляндии, чтобы клиенты могли выбирать, через какую страну подключаться. Необязательно — можно начать без нод.

🔗
Ссылка-подписка

Членская карта

Одна веб-ссылка, которую вы даёте каждому клиенту. В ней зашиты все настройки подключения — это всё, что ему когда-либо понадобится.

📱
Клиентское приложение

Дверь клиента

Бесплатное приложение (Happ, v2rayNG, Streisand…). Он один раз вставляет ссылку, нажимает «подключиться» — готово. Вы никогда не трогаете его телефон.

Так что же такое «Marzban»?
Marzban — это популярный бесплатный инструмент, которым люди годами пользуются ровно для этого. Он работает — но вы остаётесь сами по себе: ни поддержки, обновления вручную и никаких современных функций обхода блокировок. NexusPanel — это его взрослая версия с поддержкой. Если вы уже используете Marzban, вы можете перенести всё одной командой, и ваши клиенты ничего не заметят (их ссылки продолжат работать). Если же вы никогда с ним не сталкивались — тем лучше, вы начинаете с чистого листа и обходите все сложные этапы.

Как на самом деле движутся деньги

  1. Кому-то нужен приватный или разблокированный интернет, и он платит вам (принимайте криптовалюту автоматически через встроенный Telegram-бот или берите оплату любым удобным способом).
  2. Вы открываете NexusPanel и создаёте для него пользователя — задаёте срок действия и объём трафика. Занимает около 10 секунд.
  3. Вы отправляете ему ссылку-подписку.
  4. Он вставляет её в бесплатное приложение и нажимает «подключиться». Он в сети через ваш сервер.
  5. В следующем месяце он платит снова, чтобы оставаться активным. Повторяйте с любым числом клиентов.
Вам не нужно разбираться в сложных технологиях
Слова вроде VLESS, Xray, Reality или Hysteria — это просто разные виды туннелей, по которым идут данные. NexusPanel подбирает разумные значения по умолчанию — вы можете вести целый бизнес, так и не узнав, что они означают. Когда станет любопытно, глоссарий объяснит каждое из них одной строкой.

Готовы? Выберите точку старта

Перейдите к разделу С чего начать и выберите один из трёх путей: попробовать бесплатный период (без установки), установить с нуля на новом сервере или перейти с Marzban.

Слова, которые вам встретятся 📖

Каждый термин из этой документации, объяснённый одним простым предложением. Пробегитесь по нему сейчас; возвращайтесь всякий раз, когда какое-то слово вас собьёт с толку.

VPS virtual private server
Компьютер, который вы арендуете в дата-центре помесячно. На нём работает ваша панель. ~$4–6/месяц вполне достаточно для старта.
Панель
Веб-панель, в которую вы заходите, чтобы всем управлять — это и есть сам NexusPanel. Он живёт на вашем VPS.
Нода
Дополнительный сервер в другой локации, привязанный к вашей панели, чтобы клиенты могли выбирать, через какую страну подключаться. Полностью необязательна.
Пользователь он же клиент
Один человек, которому вы продаёте доступ. У каждого есть дата окончания, лимит трафика и собственная ссылка-подписка.
Ссылка-подписка «sub-ссылка»
Единственная ссылка, которую вы даёте клиенту. Его приложение читает её, чтобы понять, как подключиться. Если вы переходите с Marzban, эти ссылки продолжают работать.
Клиентское приложение
Бесплатное приложение, которое устанавливает клиент — например, Happ, v2rayNG, Streisand, Hiddify. Он один раз вставляет в него sub-ссылку.
Marzban
Более старая, бесплатная панель «сделай сам», с которой начинали многие операторы. NexusPanel — её обновлённый преемник с поддержкой, и он умеет импортировать конфигурацию Marzban одной командой.
Remnawave
Ещё одна панель управления VPN. NexusPanel умеет импортировать пользователей из живой Remnawave-панели по её API одной командой, сохраняя их ссылки-подписки рабочими.
Лицензия
Ваш ключ для запуска NexusPanel. Возьмите бесплатный 14-дневный пробный период или платный тариф через Telegram-бот. Без неё панель работает в пробном режиме.
Домен
Имя вроде panel.yoursite.com, указывающее на ваш VPS. Нужно для замочка в браузере (HTTPS). Необязательно, но настоятельно рекомендуется.
SSL / HTTPS
Замочек в браузере — шифрование, которое защищает входы в систему. NexusPanel настраивает его автоматически, если у вас есть домен.
Xray
Бесплатный движок «под капотом», который и перемещает зашифрованный трафик. Напрямую вы его почти не трогаете.
VLESS / VMess / Trojan / Shadowsocks
Разные виды туннелей, которые может использовать Xray. Как разные марки машин — все довезут вас до места. VLESS обычно используется по умолчанию.
Reality / XHTTP / ECH / Finalmask
Приёмы, благодаря которым ваш трафик выглядит как обычный сёрфинг, и его сложнее заблокировать. Включаются для каждого хоста; значений по умолчанию для начала достаточно.
Hysteria 2
Другой, очень быстрый тип туннеля, который особенно хорош на плохих или урезанных сетях. Необязателен; работает рядом с Xray.
Middle-сервер
Дешёвый ретранслятор, поставленный перед вашим основным сервером, чтобы обходить блокировки. Продвинутая тема — игнорируйте, пока это реально не понадобится.
Inbound / Хост
Конкретная «входная дверь» в ваш сервер (протокол + порт + настройки). В панели уже есть разумные; добавляйте новые по желанию.
Администратор / Реселлер
Дополнительные учётные записи, которые вы создаёте. Реселлер управляет своими клиентами в рамках заданных вами лимитов — удобно, когда под вами продают другие.
Лимит IP / устройств
Ограничение на количество телефонов или компьютеров, которые один клиент может использовать одновременно — мешает делиться паролем и съедать ваш трафик.
Самое сложное позади
Если всё это в общих чертах понятно — вы знаете достаточно, чтобы вести NexusPanel. Перейдите к разделу С чего начать и выберите путь.

С чего начать

Три пути. Выберите тот, что подходит вам, и вы запуститесь меньше чем за 10 минут.

NexusPanel — это мультиарендная VPN-панель: вы продаёте субаккаунты, ваши клиенты подключаются через любой v2ray-клиент, а вы держите всё в одной панели. Если вы новичок, самый быстрый способ увидеть, что она умеет, — бесплатный пробный период. Если вы уже используете Marzban, инструмент миграции перенесёт всё одной командой — пользователей, администраторов, хосты, сертификаты, и даже ваши существующие ссылки-подписки продолжат работать. Если вы используете Remnawave — то же самое, отдельной командой (см. Миграция с Remnawave).

Путь A · Без установки

Попробуйте бесплатный период

Откройте Telegram-бот, введите /start и получите бесплатный 14-дневный Pro-триал, без карты. С ним вы можете развернуть собственную панель и опробовать всё до оплаты.

⏱ 2 мин 💳 Карта не нужна
Открыть Telegram-бот →
Путь B · Новый VPS

Установка на чистом сервере

Одна команда на чистом VPS с Ubuntu 20.04+. Скрипт спросит вашу лицензию, домен и пароль администратора — вот и всё. SSL настраивается автоматически, если вы направите домен на сервер.

⏱ 5 мин 🖥 1 ГБ ОЗУ минимум
Команда установки ↓
Путь C · Переход с Marzban

Переход с Marzban

Тот же VPS, без перенастройки у клиентов. Инструмент миграции сначала делает пробный прогон и обратим — вы видите каждое изменение до того, как что-то будет затронуто, и можете откатиться в любой момент до финального переключения.

⏱ 10 мин 🔁 С возобновлением и откатом
Руководство по миграции ↓
Путь D · Переход с Remnawave

Переход с Remnawave

Одна команда переносит пользователей и их учётные данные из Remnawave в NexusPanel. Ссылки-подписки клиентов продолжают работать без перенастройки.

⏱ 10 мин 🔁 С пробным прогоном и откатом
Руководство по миграции ↓
Почему миграция безопасна
Инструмент никогда не пишет в вашу базу Marzban. Он делает снимок Marzban в копию только для чтения, строит состояние Nexus из этой копии и подменяет контейнеры лишь на самом последнем шаге. Если перед этой подменой что-то выглядит не так, вы прерываете процесс, и Marzban продолжает работать как ни в чём не бывало. Ваши существующие ссылки-подписки тоже продолжат работать после миграции — Nexus переносит JWT-секрет Marzban, поэтому каждая ссылка https://your-panel/sub/<token>, которая уже есть у ваших пользователей, остаётся рабочей.

Что вам понадобится

  • VPS с Ubuntu 20.04+ (или любым дистрибутивом семейства Debian), минимум 1 ГБ ОЗУ, рекомендуется 2 ГБ
  • Root-доступ по SSH к этому VPS
  • Домен, направленный на VPS (необязательно — даёт настоящий сертификат HTTPS без предупреждений; без него всё равно будет HTTPS, но с самоподписанным сертификатом, который один раз покажет предупреждение в браузере)
  • Лицензия NexusPanel (возьмите её в Telegram-боте, подойдёт бесплатный 14-дневный пробный период)

Как получить помощь

Если что-то не работает, попробуйте по порядку:

  1. Проверьте логи панели: cd /opt/panel && docker compose logs --tail 100
  2. Прочтите нужный раздел этой документации (боковое меню слева)
  3. Напишите нам в Telegram — ссылка в боте, отвечаем за часы, а не за дни

Что такое NexusPanel

Простыми словами
Это панель, в которую вы заходите, чтобы вести VPN-бизнес: добавлять клиентов, раздавать ссылки для подключения, видеть, кто онлайн, и получать оплату — всё в одном месте. Всё это для вас в новинку? Начните с раздела Впервые здесь? Прочтите это первым.

NexusPanel — это современная, многофункциональная панель управления прокси, созданная для VPN-провайдеров и сетевых администраторов. Она даёт единую панель для управления пользователями, нодами, подписками и аналитикой на нескольких серверах.

«Под капотом» полный набор возможностей включает:

  • Поддержку нескольких протоколов — VMess, VLESS, Trojan, Shadowsocks через Xray-core, плюс Hysteria 2 как отдельный сайдкар. Расширения транспорта и обфускации (XHTTP, Reality, ECH, фрагментация TLS, Finalmask) настраиваются для каждого хоста в панели.
  • Распределённые ноды — подключайте неограниченное число удалённых серверов из одной панели
  • Реальные лимиты на пользователя — трафик, срок действия, ограничения по IP и устройствам действительно применяются за счёт разбора access-лога Xray
  • Роли администраторов и привязку хостов — уровни «владелец», «администратор», «реселлер» с квотами трафика; назначайте конкретные хосты конкретным администраторам
  • REST API — 75+ эндпоинтов для автоматизации и интеграции
  • Аналитику в стиле Grafana — трафик во времени, рост числа пользователей, кольцевые диаграммы по протоколам/статусам, топ-потребители, нагрузка по трафику на ноды (с автообновлением)
  • Telegram-бот — платёжный бот для клиентов (криптовалюта через NOWPayments) плюс уведомления для администраторов
  • Систему лицензий — пробный → платные тарифы с heartbeat раз в 6 часов и уведомлениями об обновлениях Docker-образов
  • Зашифрованные Happ-ссылки — настоящие deeplink-и happ://crypt4/ на RSA-4096, скрывающие исходный URL подписки
  • 2FA — TOTP с QR-кодом и резервными кодами
  • Готовность к мобильным устройствам — адаптивная панель с нижней навигацией и выезжающим меню
  • Защиту кода — чувствительные Python-модули скомпилированы Cython в бинарники .so
  • Действенные уведомления внутри приложения — истекающие пользователи, лимиты трафика, офлайн-ноды, истечение лицензии

Требования

КомпонентМинимумРекомендуется
ОСUbuntu 20.04+ / Debian 11+Ubuntu 22.04 LTS
ОЗУ1 ГБ2 ГБ+
CPU1 vCPU, только x86-642 vCPU, x86-64
Диск10 ГБ20 ГБ+ (SSD)
Docker20.10+Последняя стабильная
ДоменНеобязательноРекомендуется (для SSL)
Примечание
Docker и Docker Compose устанавливаются автоматически скриптом быстрой установки, если их нет.
ARM-серверы не поддерживаются
Образы панели и ноды только под x86-64 — бинарники Xray и Hysteria внутри них ELF x86-64. Оба инсталлятора проверяют uname -m и на aarch64 останавливаются с объяснением, вместо того чтобы поставить то, что скачается без ошибок, а запуститься не сможет. VPS на Ampere/Graviton/Apple silicon не подойдут — берите тариф на amd64.

Быстрая установка

Выполните эту единственную команду на чистом VPS, чтобы установить NexusPanel с настройками по умолчанию:

bash
curl -sL https://nexuspanel.store/install | bash

Скрипт запросит у вас:

  1. License Key и Client ID — от @nexuspanelpayment_bot (бесплатный 14-дневный пробный ключ тоже подходит, но установщик всегда требует ключ — установки без лицензии не бывает)
  2. Домен — для SSL через Let's Encrypt (пропустите для работы только по IP)
  3. Имя пользователя и пароль администратора — для панели
  4. Порт панели — по умолчанию 8443

Затем он:

  1. Установит Docker и Docker Compose, если их нет
  2. Скачает ghcr.io/haitovs/nexus:latest (защищённый Cython продакшен-образ)
  3. Создаст /opt/panel/ с .env и docker-compose.yml — три сервиса: nexus-panel, nexus-redis (очередь, слушает только loopback) и nexus-worker. Воркер не опционален: без него не выполняется ничего по расписанию — подписки не публикуются, здоровье каналов не проверяется, упавший канал не переключается, статистика нод пустая, CDN-фронты не согласуются, — при этом панель продолжает считаться здоровой.
  4. Заполнит xray_config.json с включённым access-логом (нужно для применения лимитов IP/устройств) и откроет в файрволе все указанные в нём порты
  5. Запустит панель и выведет URL панели и учётные данные
  6. Выполнит quick-start (отключается через QUICKSTART=0): создаст демо-пользователя test, установит совмещённую ноду на этом же сервере и подключит её
  7. И только после того, как эта нода сообщит статус connected, установит DISABLE_LOCAL_XRAY=true и перезапустит панель, чтобы инбаунд-портами владела нода, а собственный Xray-ядро панели остановилось. Если после перезапуска панель не достучится до ноды, инсталлятор вернёт ядро обратно, вместо того чтобы оставить сервер вообще без трафика.
Уведомления об обновлениях
После установки панель раз в 6 часов делает heartbeat на ваш лицензионный сервер. Автообновление по умолчанию выключено: когда выходит новая версия, панель показывает уведомление «доступно обновление», а вы применяете его командой nexus update на сервере.

Установка одной командой (подробно)

Скрипт установки принимает необязательные флаги для настройки:

bash
# Рекомендуется — передайте свой License Key + Client ID (от @nexuspanelpayment_bot)
curl -sL https://nexuspanel.store/install | bash -s -- \
  --license YOUR_LICENSE_KEY \
  --client YOUR_CLIENT_ID \
  --domain panel.example.com \
  --port 8443

# То же самое через переменные окружения вместо флагов
curl -sL https://nexuspanel.store/install | LICENSE_ID=YOUR_LICENSE_KEY CLIENT_ID=YOUR_CLIENT_ID DOMAIN=panel.example.com bash

# Только по IP (без домена) — просто опустите --domain, HTTPS всё равно будет (самоподписанный сертификат)
curl -sL https://nexuspanel.store/install | bash -s -- \
  --license YOUR_LICENSE_KEY \
  --client YOUR_CLIENT_ID

License Key и Client ID обязательны — получите их у @nexuspanelpayment_bot. Запустите bash -s -- --help, чтобы увидеть все флаги (--port по умолчанию 8443, а также --username, --password, --ssl, --migrate).

Когда скрипт завершится, он напечатает URL панели, имя администратора и пароль — используйте их для входа. Не используйте примеры из этой документации (вроде myadmin/securepass123) — они не сработают.

Панель доступна по адресу https://YOUR_DOMAIN:8443/dashboard/ (или https://YOUR_IP:8443/dashboard/ при установке только по IP).

Предупреждение «Not Secure» при установке только по IP
Без домена панель всё равно работает по HTTPS, но с самоподписанным сертификатом (для Let's Encrypt нужен домен). Браузер один раз покажет предупреждение «Not Secure» / «Соединение не защищено» при первом открытии панели — нажмите Advanced → Proceed (Chrome) или Visit this website (Safari), чтобы продолжить. Это ожидаемо и безопасно: соединение всё равно зашифровано, просто сертификат не подписан публичным центром сертификации. Позже можно привязать домен для сертификата без предупреждений.

Первые шаги в панели

После входа в панель — вот самый быстрый путь к первому рабочему подключению:

  1. Создайте пользователя — Панель → UsersAdd User. Задайте дату окончания и лимит трафика, затем скопируйте ссылку подписки и передайте её в клиентское приложение (Happ, v2rayNG, Streisand…).
  2. Добавьте ноду (по желанию) — Панель → NodesAdd New Node, скопируйте сгенерированную команду быстрой установки, выполните её на сервере ноды, затем вернитесь и заполните Name + Address, чтобы подключить её. Подробнее в разделе Установка ноды.
  3. Настройте домен подписки — если ссылки подписки должны отдаваться с другого хоста/домена, чем сама панель, задайте XRAY_SUBSCRIPTION_URL_PREFIX в редакторе окружения (Settings → Env) и используйте Save & Restart — эта настройка применяется только после полного перезапуска.

Ручная установка

Скрипт установки выше — поддерживаемый способ: он сам аутентифицируется в приватном реестре образов, пишет рабочий .env и настраивает файрвол. Чтобы собрать всё вручную:

bash
# 1. Образ приватный — обычный `docker pull` вернёт "denied", пока вы не
#    авторизуетесь. Обменяйте лицензию на короткоживущий токен для pull:
curl -s -X POST https://nexuspanel.store/api/registry-token \
  -H 'Content-Type: application/json' \
  -d '{"license_id":"YOUR_LICENSE_KEY","client_id":"YOUR_CLIENT_ID"}'
# → {"token": "...", "username": "..."} — войдите с ним:
echo $TOKEN | docker login ghcr.io -u $USERNAME --password-stdin

# 2. Скачать образ
docker pull ghcr.io/haitovs/nexus:latest

# 3. Написать /opt/panel/.env — все ключи см. в разделе Env Reference ниже.
#    Минимум: UVICORN_PORT, SUDO_USERNAME, SUDO_PASSWORD, SQLALCHEMY_DATABASE_URL,
#    LICENSE_ID, CLIENT_ID
mkdir -p /opt/panel /var/lib/panel /var/lib/nexus
nano /opt/panel/.env

# 4. Запустить с docker-compose.yml из раздела "Примеры Docker Compose" ниже
cd /opt/panel
docker compose up -d

# Посмотреть логи
docker compose logs -f

С SSL (Certbot)

Чтобы включить HTTPS с бесплатным сертификатом Let's Encrypt:

bash
# Установить certbot
apt install -y certbot

# Получить сертификат (сначала остановите панель, если используется порт 80)
docker compose down
certbot certonly --standalone -d panel.example.com

# Добавить в .env
UVICORN_SSL_CERTFILE="/etc/letsencrypt/live/panel.example.com/fullchain.pem"
UVICORN_SSL_KEYFILE="/etc/letsencrypt/live/panel.example.com/privkey.pem"

# Примонтировать сертификаты в docker-compose.yml и перезапустить
docker compose up -d

Добавьте задание cron для автоматического продления:

bash
0 3 * * * certbot renew --quiet --deploy-hook 'docker restart nexus-panel'
Продление не сработает, пока порт 80 занят инбаундом
certbot renew заново запускает аутентификатор --standalone, которому нужен порт 80 — а Xray панели (и совмещённой ноды) по умолчанию слушает 80. На таком сервере cron ничего не продлевает и делает это молча: certbot пишет в свой лог, панель — нет. Либо продлевайте вручную примерно раз в 60 дней последовательностью docker compose downcertbot certonlydocker compose up -d выше, либо выпускайте сертификат способом, которому порт 80 не нужен (плагин DNS-01 или обратный прокси с TLS-ALPN на 443).

С PostgreSQL

Для продакшен-развёртываний PostgreSQL предпочтительнее SQLite. Установите BACKEND_MODE=modern и используйте драйвер, который реально входит в поставку панели — psycopg2 (синхронный), а не asyncpg:

bash
# Задать в .env
BACKEND_MODE=modern
SQLALCHEMY_DATABASE_URL="postgresql+psycopg2://nexus:${POSTGRES_PASSWORD}@127.0.0.1:5432/nexus"
REDIS_URL="redis://127.0.0.1:6379/0"
POSTGRES_PASSWORD=$(openssl rand -hex 24)

Затем замените compose-файл на такой, который поднимает Postgres 16 и Redis 7 рядом с панелью и воркером. docker-compose.modern.yml из репозитория на вашем сервере отсутствует — инсталлятор его не пишет, и в образ он не входит, так что копировать нечего. Redis и воркер уже есть в compose, который написал инсталлятор, так что добавить нужно только Postgres. Оставьте panel, redis и worker как есть, а панель направьте на Postgres через SQLALCHEMY_DATABASE_URL в .env:

yaml — add to /opt/panel/docker-compose.yml
  postgres:
    image: postgres:16-alpine
    container_name: nexus-postgres
    restart: always
    network_mode: host
    environment:
      POSTGRES_DB: nexus
      POSTGRES_USER: nexus
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
      PGPORT: 5432
    command: [postgres, -c, listen_addresses=127.0.0.1]
    volumes:
      - /var/lib/nexus/postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U nexus -d nexus"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 20s
asyncpg не установлен
Панель поставляется с psycopg2-binary, а не с asyncpg — URL вида postgresql+asyncpg:// не найдёт драйвер. Всегда используйте postgresql+psycopg2://.

Примеры Docker Compose

Classic (SQLite) — то, что реально пишет установщик

yaml — /opt/panel/docker-compose.yml
services:
  panel:
    image: ghcr.io/haitovs/nexus:latest
    container_name: nexus-panel
    restart: always
    env_file: .env
    network_mode: host
    dns: [8.8.8.8, 1.1.1.1]
    volumes:
      - /var/lib/panel:/var/lib/panel
      - /var/lib/nexus:/var/lib/nexus
      - ./.env:/app/env.live
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      NEXUS_HOST_ENV_FILE: /app/env.live
    healthcheck:
      test: ["CMD", "curl", "-skf", "http://127.0.0.1:8443/api/v1/health"]
      interval: 30s
      timeout: 5s
      start_period: 30s
      retries: 3

  redis:
    image: redis:7-alpine
    container_name: nexus-redis
    restart: always
    network_mode: host
    command: ["redis-server", "--appendonly", "yes", "--bind", "127.0.0.1", "--port", "6379"]
    volumes:
      - /var/lib/nexus/redis:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-h", "127.0.0.1", "-p", "6379", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 5s

  worker:
    image: ghcr.io/haitovs/nexus:latest
    container_name: nexus-worker
    restart: always
    env_file: .env
    network_mode: host
    depends_on: [redis]
    command: ["python", "-m", "arq", "app.worker.WorkerSettings"]
    healthcheck:
      test: ["CMD", "python", "-c", "import redis; redis.from_url('redis://127.0.0.1:6379').ping()"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 15s
    volumes:
      - /var/lib/panel:/var/lib/panel
      - /var/lib/nexus:/var/lib/nexus
      - ./.env:/app/env.live
    environment:
      NEXUS_HOST_ENV_FILE: /app/env.live

network_mode: host обязателен — панель и любой совмещённый нод/middle-relay привязывают порты напрямую на хосте, а монтирование docker-сокета (только для чтения) нужно для one-click SSH-установки нод и middle-серверов. /var/lib/nexus — не опциональный том: там лицензионный модуль кеширует своё состояние, без него панель не может подтвердить лицензию. Замените 8443 в healthcheck на ваш UVICORN_PORT; при обслуживании домена также примонтируйте /etc/letsencrypt:/etc/letsencrypt:ro и укажите UVICORN_SSL_CERTFILE/UVICORN_SSL_KEYFILE на выданный сертификат.

У воркера должен быть собственный healthcheck
nexus-worker запускается из того же образа, что и панель, поэтому без указанного выше healthcheck он наследует образный, который дёргает эндпоинт панели — недоступный из воркера. Контейнер тогда навсегда остаётся unhealthy, хотя задачи выполняются нормально, и это выглядит как сломанная установка. redis-cli в образе панели нет, поэтому ping идёт через Python-клиент. Если ваш сервер ставился до появления воркера, повторный запуск инсталлятора добавит redis и worker на месте, не трогая данные.

Полный стек (PostgreSQL + Redis)

См. раздел С PostgreSQL выше — classic-compose уже содержит Redis и воркер, поэтому полный стек — это тот же файл плюс один сервис postgres из того раздела.

Справочник по конфигурации

NexusPanel полностью настраивается через переменные окружения. Задавайте их в файле .env или передавайте напрямую в Docker.

Совет
Скопируйте .env.example в .env и раскомментируйте нужные переменные. У всех переменных есть разумные значения по умолчанию.

Сервер

ПеременнаяПо умолчаниюОписание
UVICORN_HOST0.0.0.0Адрес привязки сервера
UVICORN_PORT8443HTTP-порт
UVICORN_UDSПуть к Unix-сокету (переопределяет host/port)
UVICORN_SSL_CERTFILEПуть к SSL-сертификату (fullchain.pem)
UVICORN_SSL_KEYFILEПуть к приватному ключу SSL
UVICORN_SSL_CA_TYPEpublicТип CA: public или private
DASHBOARD_PATH/dashboard/URL-путь к веб-панели
ALLOWED_ORIGINSИсточники CORS через запятую
SUDO_USERNAMEИмя первого суперадминистратора
SUDO_PASSWORDПароль первого суперадминистратора
JWT_ACCESS_TOKEN_EXPIRE_MINUTES1440Срок жизни токена в минутах (по умолчанию 24 ч)

База данных

ПеременнаяПо умолчаниюОписание
SQLALCHEMY_DATABASE_URLsqlite:////var/lib/nexus/db.sqlite3Строка подключения к базе данных
SQLALCHEMY_POOL_SIZE10Размер пула соединений
SQLIALCHEMY_MAX_OVERFLOW12Максимум соединений сверх размера пула
BACKEND_MODEclassicclassic (SQLite/Postgres, по умолчанию) или modern (добавляет очередь событий на Redis)
REDIS_URLСтрока подключения к Redis; обязательна при BACKEND_MODE=modern
Строка подключения к PostgreSQL
Используйте postgresql+psycopg2://user:pass@host:5432/dbname. В образе есть psycopg2-binary и нет asyncpg, поэтому URL с asyncpg падает на старте с ошибкой «can't load plugin».
Режим modern backend
Задайте BACKEND_MODE=modern и укажите REDIS_URL, чтобы включить очередь событий на Redis. Сам Redis уже установлен — инсталлятор пишет сервис redis:7, слушающий только loopback, и задаёт REDIS_URL, потому что фоновому воркеру он нужен как очередь независимо от BACKEND_MODE. Большинству развёртываний менять это не нужно.

Xray

ПеременнаяПо умолчаниюОписание
XRAY_JSON/var/lib/nexus/xray_config.jsonПуть к конфигурации ядра Xray
XRAY_EXECUTABLE_PATH/usr/local/bin/xrayПуть к бинарнику Xray
XRAY_ASSETS_PATH/usr/local/share/xrayПуть к geoip.dat и geosite.dat
XRAY_SUBSCRIPTION_URL_PREFIXПубличный префикс URL для ссылок-подписок (например, https://sub.example.com). Изменения вступают в силу только после полного перезапуска панели — используйте Save & Restart в редакторе Env, а не перезапуск контейнера.
XRAY_SUBSCRIPTION_PATHsubСегмент URL-пути для подписок
XRAY_EXCLUDE_INBOUND_TAGSТеги inbound через пробел, которые нужно исключить
DISABLE_LOCAL_XRAYfalseНе запускать собственное ядро Xray у панели. Инсталлятор ставит true после того, как совмещённая quick-start нода сообщит о подключении: иначе оба процесса привязываются к одним и тем же инбаунд-портам — SO_REUSEPORT это позволяет, ядро ОС делит соединения между ними, а access-лог, который читает лимитер IP/устройств, пишет только локальное ядро панели, поэтому лимиты недоприменяются. Верните false, если удалили локальную ноду.
XRAY_ACCESS_LOG/var/lib/nexus/xray-access.logAccess-лог, который разбирает лимитер IP/устройств. Панель включает его в xray_config.json при загрузке, если он ещё не включён.
XRAY_FALLBACKS_INBOUND_TAGТег inbound, используемый для fallback-маршрутизации

Подписка

ПеременнаяПо умолчаниюОписание
SUB_PROFILE_TITLESubscriptionОтображаемое имя в клиентских приложениях
SUB_SUPPORT_URLСсылка на поддержку, включаемая в информацию о подписке
SUB_UPDATE_INTERVAL12Интервал автообновления у клиента (часы)
EXTERNAL_CONFIGURL внешнего конфига для интеграции с клиентом
USE_CUSTOM_JSON_DEFAULTfalseВключить свой JSON-конфиг для клиента по умолчанию
USE_CUSTOM_JSON_FOR_V2RAYNfalseВключить свой JSON для V2RayN
USE_CUSTOM_JSON_FOR_V2RAYNGfalseВключить свой JSON для V2RayNG
USE_CUSTOM_JSON_FOR_STREISANDfalseВключить свой JSON для Streisand
USE_CUSTOM_JSON_FOR_HAPPfalseВключить свой JSON для Happ
SUB_RATE_LIMIT_PER_MINUTE60Максимум запросов подписки с одного IP в минуту (в процессе, сбрасывается при перезапуске)
SUB_ENABLE_ETAGtrueВозвращать ETag / учитывать If-None-Match, чтобы экономить трафик на неизменившихся подписках
SUB_GZIP_MIN_SIZE512Сжимать gzip ответы подписки больше этого числа байт

Шаблоны

ПеременнаяПо умолчаниюОписание
CUSTOM_TEMPLATES_DIRECTORY/var/lib/panel/templates/Базовый каталог для своих шаблонов
SUBSCRIPTION_PAGE_TEMPLATEsubscription/index.htmlШаблон страницы подписки пользователя
HOME_PAGE_TEMPLATEhome/index.htmlШаблон главной страницы панели
CLASH_SUBSCRIPTION_TEMPLATEclash/default.ymlШаблон подписки Clash
CLASH_SETTINGS_TEMPLATEclash/settings.ymlШаблон настроек Clash
V2RAY_SUBSCRIPTION_TEMPLATEv2ray/default.jsonШаблон подписки V2Ray
V2RAY_SETTINGS_TEMPLATEv2ray/settings.jsonШаблон настроек V2Ray
SINGBOX_SUBSCRIPTION_TEMPLATEsingbox/default.jsonШаблон подписки Sing-box
SINGBOX_SETTINGS_TEMPLATEsingbox/settings.jsonШаблон настроек Sing-box
MUX_TEMPLATEmux/default.jsonШаблон конфигурации мультиплексирования
USER_AGENT_TEMPLATEuser_agent/default.jsonШаблон разбора user-agent
GRPC_USER_AGENT_TEMPLATEuser_agent/grpc.jsonШаблон user-agent для gRPC

Telegram

ПеременнаяПо умолчаниюОписание
TELEGRAM_API_TOKENТокен бота от @BotFather
TELEGRAM_ADMIN_IDID пользователей Telegram для администраторов через запятую
TELEGRAM_LOGGER_CHANNEL_IDID канала для сообщений логов
TELEGRAM_DEFAULT_VLESS_FLOWxtls-rprx-visionVLESS flow по умолчанию для пользователей, созданных ботом
TELEGRAM_PROXY_URLURL прокси для подключений к Telegram API

Уведомления

ПеременнаяПо умолчаниюОписание
NOTIFY_STATUS_CHANGEtrueУведомлять при смене статуса пользователя
NOTIFY_USER_CREATEDtrueУведомлять о создании нового пользователя
NOTIFY_USER_UPDATEDtrueУведомлять об изменении пользователя
NOTIFY_USER_DELETEDtrueУведомлять об удалении пользователя
NOTIFY_USER_DATA_USED_RESETtrueУведомлять о сбросе использованного трафика
NOTIFY_USER_SUB_REVOKEDtrueУведомлять об отзыве подписки
NOTIFY_IF_DATA_USAGE_PERCENT_REACHEDtrueУведомлять при достижении порога трафика
NOTIFY_IF_DAYS_LEFT_REACHEDtrueУведомлять при достижении порога по сроку действия
NOTIFY_LOGINtrueУведомлять о входе администратора
LOGIN_NOTIFY_WHITE_LISTIP, исключаемые из уведомлений о входе
NOTIFY_DAYS_LEFT3,7Пороги «дней до окончания» для уведомлений
NOTIFY_REACHED_USAGE_PERCENT80,90Пороги процента использования
RECURRENT_NOTIFICATIONS_TIMEOUT180Минут между повторными уведомлениями
NUMBER_OF_RECURRENT_NOTIFICATIONS3Максимум повторных уведомлений на событие
DISCORD_WEBHOOK_URLWebhook Discord для уведомлений в стиле Telegram
WEBHOOK_ADDRESSУстаревшее: статические URL webhook через запятую. Для новых настроек используйте интерфейс Webhooks в панели.
WEBHOOK_SECRETУстаревшее: HMAC-секрет для доставки на WEBHOOK_ADDRESS. Webhooks в панели управляют секретами для каждого эндпоинта.

Брендинг (White-Label)

ПеременнаяПо умолчаниюОписание
BRAND_NAMEPanelНазвание панели, отображаемое в интерфейсе и письмах
BRAND_LOGO_URLURL изображения своего логотипа
BRAND_FAVICON_URLURL своего favicon

Безопасность

ПеременнаяПо умолчаниюОписание
DEFENDER_ENABLED0 в коде, 1 — как пишет инсталляторРегистрирует роутеры IP Defender. Если выключено, около 112 эндпоинтов — вся поверхность /defender/… плюс маршруты провайдеров AWS, Bunny, Fastly, Gcore и Alibaba ESA — вообще не монтируются, и страницы IP Defender в панели отдают 404. В логе загрузки будет defender: routers NOT registered. Текущее состояние возвращает GET /api/v1/system в поле defender_enabled.
CAPTCHA_PROVIDERdisabledПровайдер капчи: disabled, turnstile или builtin
TURNSTILE_SITE_KEYSite key Cloudflare Turnstile
TURNSTILE_SECRET_KEYSecret key Cloudflare Turnstile
LOGIN_RATE_LIMIT10/minuteНе подключён. Это значение не читается кодом, поэтому его изменение ни на что не влияет и никакого лимита попыток в минуту не действует. Переменная сохранена, чтобы существующий .env продолжал работать. От перебора защищают две настройки блокировки ниже.
LOGIN_LOCKOUT_THRESHOLD10Неудачных попыток с одного IP клиента, после которых этот IP блокируется на POST /api/v1/admin/token. Это и есть настоящая защита от перебора.
LOGIN_LOCKOUT_DURATION_MINUTES30Длительность блокировки в минутах

Логирование

ПеременнаяПо умолчаниюОписание
LOG_LEVELINFOУровень логов: DEBUG, INFO, WARNING, ERROR
LOG_FORMATtextФормат логов: text или json
LOG_FILE_PATHПисать логи в файл (в дополнение к stdout)
LOG_MAX_SIZE_MB10Максимальный размер файла лога до ротации
LOG_BACKUP_COUNT5Сколько ротированных файлов логов хранить

Метрики (Prometheus)

ПеременнаяПо умолчаниюОписание
METRICS_ENABLEDfalseВключить эндпоинт /metrics для Prometheus
METRICS_TOKENBearer-токен, нужный для сбора метрик

Дополнительные переменные

ПеременнаяПо умолчаниюОписание
ACTIVE_STATUS_TEXTActiveСвоя метка для статуса «активен»
EXPIRED_STATUS_TEXTExpiredСвоя метка для статуса «истёк»
LIMITED_STATUS_TEXTLimitedСвоя метка для статуса «ограничен»
DISABLED_STATUS_TEXTDisabledСвоя метка для статуса «отключён»
ONHOLD_STATUS_TEXTOn-HoldСвоя метка для статуса «на удержании»
USERS_AUTODELETE_DAYS-1Автоудаление истёкших пользователей через N дней (-1 = отключено)
USER_AUTODELETE_INCLUDE_LIMITED_ACCOUNTSfalseВключать в автоудаление пользователей, ограниченных по трафику
JOB_CORE_HEALTH_CHECK_INTERVAL10Интервал проверки работоспособности (секунды)
JOB_RECORD_NODE_USAGES_INTERVAL30Интервал записи использования нод
JOB_RECORD_USER_USAGES_INTERVAL10Интервал записи использования пользователей
JOB_REVIEW_USERS_INTERVAL10Интервал проверки пользователей на истечение
JOB_SEND_NOTIFICATIONS_INTERVAL30Интервал отправки уведомлений
DISABLE_RECORDING_NODE_USAGEfalseОтключить запись использования нод
DEBUGfalseВключить режим отладки с горячей перезагрузкой
DOCSfalseВключить Swagger UI по адресу /docs
VITE_BASE_API/api/v1/Базовый путь API для сборки фронтенда

Панель управления

Панель управления NexusPanel — это современное веб-приложение на React, доступное по адресу /dashboard/. Она предоставляет полный интерфейс для управления вашей прокси-инфраструктурой.

Страница обзора

Главная страница панели показывает статистику в реальном времени с одного взгляда:

  • Всего пользователей — количество активных, истёкших, ограниченных, отключённых
  • Использование трафика — суммарная отдача/загрузка с графиками тренда
  • Статус нод — индикаторы онлайн/офлайн с процентом нагрузки
  • Недавняя активность — последние создания пользователей, подключения и действия администраторов
  • Распределение по протоколам — круговая диаграмма используемых протоколов

Управление пользователями

Страница «Пользователи» поддерживает полное управление жизненным циклом:

  • Создание пользователя — задайте имя, лимит трафика, дату окончания, протоколы, лимит устройств, лимит IP
  • Редактирование пользователя — меняйте все поля, включая статус (активен, отключён, на удержании)
  • Массовые операции — выбирайте нескольких пользователей для массового обновления, сброса трафика или удаления
  • Поиск и фильтрация — фильтруйте по статусу, администратору, протоколу или ищите по имени
  • Ссылки-подписки — копирование URL подписки, генерация QR-кода
  • Статистика использования — отдача/загрузка по каждому пользователю с историческими данными

Ноды

Управляйте удалёнными нодами Xray, подключёнными к панели:

  • Добавление ноды — укажите адрес, порт и коэффициент использования
  • Статус подключения — онлайн/офлайн в реальном времени с задержкой
  • Флаги стран — автоматическое отображение флага по локации ноды (60+ стран)
  • Изменение порядка — перетаскивайте или используйте стрелки, чтобы задать порядок отображения
  • Сертификат — просмотр и копирование SSL-сертификата ноды для удалённой настройки
  • Отслеживание аптайма — исторический процент аптайма по каждой ноде

Хосты и расширенные настройки TLS

У каждого inbound Xray есть одна или несколько строк-хостов, которые говорят генератору подписок, какой адрес, порт и параметры TLS выдавать в клиентских конфигах. Полный набор полей по каждому хосту:

ПолеНазначение
RemarkОтображаемое имя в клиентских приложениях
AddressДомен или IP сервера, к которому подключается клиент
PortПереопределить порт прослушивания inbound
SNI / HostTLS Server Name Indication и HTTP-заголовок Host
Security / ALPN / FingerprintПрофиль TLS: none / tls / reality; h2/http1.1; uTLS Chrome/Firefox/Safari
Allow InsecureПропускать проверку TLS-сертификата (используйте только за CDN, где сертификат не виден)
Country codeISO 3166-1 alpha-2 — управляет региональным переупорядочиванием подписки
Allowed / Denied AdminsОграничить хост конкретными суб-администраторами (пусто = все администраторы)

ECH (Encrypted Client Hello)

ECH скрывает SNI от пассивных наблюдателей — расширение TLS-рукопожатия шифруется с помощью открытого ключа, опубликованного в DNS. Включается для каждого хоста: переключите ECH и вставьте блоб ECHConfig от вашего провайдера CDN/DNS. Требуется клиент с поддержкой ECH (Happ, Chrome 117+).

Фрагментация TLS

Разбивает TLS ClientHello на меньшие TCP-сегменты, обходя сопоставление DPI с шаблоном по первому пакету. Используйте, когда активна блокировка по SNI, но CDN недоступен.

  • Размер фрагмента — байт на фрагмент, например 100-200 (случайный диапазон)
  • Задержка фрагмента — мс между фрагментами, например 10-20

Фрагментация записей TLS

Фрагментирует на уровне записей TLS, а не TCP. Более агрессивно, чем фрагментация ClientHello; используйте, когда стандартная фрагментация TLS всё ещё определяется по отпечатку.

Настройки Noise

Вставляет случайные шумовые пакеты перед настоящим TLS-рукопожатием, чтобы сбить снятие отпечатка по потоку. Поле JSON:

json
[{"type": "rand", "packet": "10-50", "delay": "5-10"}]

Тип rand отправляет случайные байты; тип str отправляет буквальную hex-строку. Размер пакета и задержка принимают запись диапазоном.

Случайный User-Agent

Делает HTTP User-Agent случайным при каждом запросе, чтобы избежать снятия отпечатка клиента на транспортах WS/HTTP.

Протоколы и кастомные inbound

NexusPanel не ограничена набором inbound, с которым она поставляется. Любой протокол, который поддерживает сам бинарник Xray, можно добавить как новый inbound и выдать пользователям — без изменения кода и без передеплоя. Это sudo-only workflow через JSON-редактор, а не фиксированный список протоколов.

ПротоколУровень поддержки
VLESS, VMess, Trojan, ShadowsocksПолная — панель выпускает учётные данные для каждого пользователя и рендерит ссылки подписки (vless://, vmess://, trojan://, ss://)
Hysteria2Полная, но отдельная подсистема — собственный CRUD для inbound на /api/v1/hy2-inbounds и собственная обработка сертификатов, не через редактор Core Settings ниже
Любой другой протокол Xray (socks, http, dokodemo-door, wireguard, …)Работает как inbound, но панель не может выпустить для него учётные данные пользователя — не годится как клиентский протокол

Не поддерживается вообще: SSH, SlowDNS, ZIVPN и udp-custom — это не протоколы Xray, и добавить их таким способом нельзя, что бы вы ни вставили в конфиг.

Добавление протокола

Откройте модальное окно Core Settings в шапке дашборда (JSON-редактор всего конфига Xray) или вызовите PUT /api/v1/core/config напрямую. Только для sudo-администраторов — не-sudo администраторы не могут редактировать core-конфиг. Списка разрешённых протоколов нет: что принимает бинарник Xray, то принимает и панель.

Отправка нового конфига безопасна по построению:

  • Дублирующиеся теги inbound/outbound отклоняются до того, как что-либо записано.
  • Кандидат проверяется запуском настоящего бинарника Xray; при отклонении возвращается HTTP 400 с собственным текстом ошибки Xray.
  • Предыдущий конфиг сохраняется как соседний файл .prev и восстанавливается автоматически, если ядро не переживает рестарт.
  • Ноды перезапускаются поочерёдно (NODE_ROLLING_RESTART_DELAY, по умолчанию 3с между нодами), так что у клиентов всегда есть рабочая нода для переключения.
  • Побайтово идентичная отправка — это no-op, рестарта не происходит.

При первом появлении нового тега inbound строка хоста создаётся для него автоматически с адресом {SERVER_IP} — добавлять её вручную не обязательно, хотя обычно вы захотите отредактировать её под свой домен/CDN.

При свежей установке создаётся 8 inbound, все VLESS, на портах 443, 80, 82, 1024, 2008, 2010, 2015, 2016. Любой порт вне этого списка свободен для нового inbound.

Охват уже существующих пользователей

Вот момент, который чаще всего путает:

  • Добавление ещё одного inbound протокола, который у пользователей уже есть, автоматически охватывает их всех — пустой список inbounds в прокси пользователя означает «все inbound этого протокола».
  • Добавление нового протокола так не работает, потому что каждому пользователю нужна отдельная строка proxy для него. Чтобы добавить его одним вызовом, используйте bulk-эндпоинт ниже.
json — новый inbound Trojan/WS
{
  "tag": "trojan-ws-2020",
  "listen": "0.0.0.0",
  "port": 2020,
  "protocol": "trojan",
  "settings": {
    "clients": []
  },
  "streamSettings": {
    "network": "ws",
    "security": "none",
    "wsSettings": {
      "path": "/",
      "heartbeatPeriod": 20
    },
    "sockopt": {
      "tcpKeepAliveInterval": 20
    }
  },
  "sniffing": {
    "enabled": false,
    "destOverride": ["http", "tls"]
  }
}

Добавьте этот объект в массив inbounds вашего текущего core-конфига (порт 2020 свободен при свежей установке) и сохраните.

bash — API
# Выдать новый протокол пользователям, у которых его ещё нет
curl -X POST /api/v1/users/bulk/update \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"usernames":["alice","bob"],"add_proxies":["trojan"]}'

add_proxies только добавляет: он никогда не убирает протокол, который у пользователя уже есть, а пользователи, у которых он уже есть, пропускаются, а не переиздают учётные данные. Требует лицензионную функцию bulk_ops; неизвестное имя протокола вернёт 400 со списком поддерживаемых.

Пошагово

  1. Добавьте inbound (модальное окно Core Settings или PUT /api/v1/core/config) — панель проверяет его настоящим бинарником Xray и перезапускает ноды поочерёдно.
  2. Проверьте страницу Hosts — строка хоста для нового тега создана автоматически; отредактируйте адрес/SNI под ваш CDN или домен.
  3. Если это совершенно новый протокол, выдайте его существующим пользователям через POST /api/v1/users/bulk/update с add_proxies. Если это просто ещё один inbound протокола, который у них уже есть, этот шаг не нужен — они уже его получили.

Сессии

Отслеживайте активные подключения устройств и управляйте ими:

  • Активные сессии — просмотр всех подключённых в данный момент устройств
  • Сессии по пользователю — смотрите, какие устройства использует конкретный пользователь
  • Отключение — принудительно завершайте отдельные сессии
  • История IP — отслеживайте историю подключений пользователя по IP

Аналитика

Комплексная панель аналитики с:

  • Сводкой — всего пользователей, активные подключения, трафик, обзор выручки
  • Распределением по протоколам — разбивка использования по протоколам (VMess, VLESS и т. д.)
  • Нагрузкой на ноды — число подключений и использование трафика по каждой ноде
  • Аптаймом нод — процент аптайма за периоды 24 ч, 7 д, 30 д
  • Топ-пользователями — крупнейшие потребители трафика
  • Истекающими пользователями — пользователи, у которых срок истекает в течение настраиваемого числа дней

Управление администраторами

Ролевая система администраторов с тремя уровнями:

РольВозможности
ВладелецПолный доступ: управление администраторами, нодами, системными настройками, всеми пользователями
АдминистраторУправление пользователями (всеми), просмотр нод и аналитики, ограниченные настройки
РеселлерУправление только своими пользователями, ограничен квотами max_users и max_traffic_bytes

У каждого администратора могут быть квоты:

  • max_users — максимальное число пользователей, которое администратор может создать
  • max_traffic_bytes — общая квота трафика по всем его пользователям

Настройки

  • Двухфакторная аутентификация — включение/отключение TOTP 2FA со страницы настроек
  • Конфигурация ядра Xray — редактирование сырого JSON Xray в 2-колоночном виде (редактор слева, живые логи и статус справа)
  • Редактор Env — редактирование SMTP, токенов, флагов функций прямо в интерфейсе с маскировкой секретов; Save & Restart перезапускает панель
  • Hysteria2 — управление inbound-ами hy2 со страницы настроек (Pro/Business/Пробный)
  • Информация о лицензии — тариф, оставшиеся дни, текущее/максимальное число пользователей/нод

Группы пользователей

Группы пользователей (называемые Squads в Remnawave) позволяют сегментировать пользователей для управления видимостью inbound-ов и переопределения подписок. Лицензия Pro, только для sudo.

Каждая группа может делать что-то одно или всё из перечисленного:

  • Фильтр inbound (applies_to_inbounds) — CSV тегов inbound. Пользователи в группе получают записи подписки только для соответствующих inbound-ов. Пусто = все inbound-ы.
  • Переопределение шаблона (override_template_id) — использовать другой шаблон подписки для участников этой группы.
  • Переопределение хостов (override_hosts) — внедрять другие строки-хосты в подписки участников (например, дать VIP-группе хост с прямым IP, скрытый от всех остальных).

Добавляйте пользователей в группу со страницы деталей пользователя или через API. Пользователь может состоять не более чем в одной группе.

bash — API
# Список групп
curl /api/v1/user-groups -H "Authorization: Bearer TOKEN"

# Создать VIP-группу, которая получает только inbound-ы hy2 + VLESS-Reality
curl -X POST /api/v1/user-groups \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"VIP","applies_to_inbounds":"hy2-main,vless-reality"}'

# Добавить пользователя в группу
curl -X POST /api/v1/user-groups/1/members \
  -d '{"username":"alice"}' -H "Authorization: Bearer TOKEN"

Наборы inbound

Набор inbound — это именованный CSV тегов inbound, который вы назначаете ноде. Когда у ноды есть набор inbound, на ней активируются только эти inbound-ы — остальные подавляются. Используйте это, чтобы запускать разные наборы протоколов на разных нодах: например, нода A получает VLESS+Trojan, нода B — VLESS+hy2.

Лицензия Pro, только для sudo.

bash — API
# Создать набор inbound
curl -X POST /api/v1/inbound-sets \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"UDP nodes","tags":"hy2-main,vmess-ws"}'

# Назначить ноде (задать inbound_set_id у ноды)
curl -X PUT /api/v1/node/1 \
  -d '{"inbound_set_id": 2}' -H "Authorization: Bearer TOKEN"

Правила ответа подписки

Правила подписок позволяют настраивать, как выглядит ответ подписки пользователя, в зависимости от его клиента. Правила сопоставляются со свойствами запроса и применяют действие.

Поле сопоставленияОператорыДействия
user_agentequals / contains / regextemplate / status / headers
client_osequals / contains / regextemplate / status / headers

Примеры:

  • Сопоставление user_agent contains "Happ" → действие template = happ-custom — выдавать оптимизированный под Happ шаблон клиентам Happ
  • Сопоставление client_os equals "iOS" → действие headers = {"Content-Type": "text/plain"}
  • Глобальные правила (только для sudo, admin_id = NULL) применяются ко всем пользователям независимо от того, какому администратору они принадлежат

Правила вычисляются по возрастанию priority. Побеждает первое совпадение.

bash — API
# Создать правило: выдавать шаблон sing-box клиентам Karing
curl -X POST /api/v1/sub-rules \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Karing","match_field":"user_agent","match_op":"contains",
     "match_value":"Karing","action":"template","action_arg":"singbox-default"}'

Webhooks

NexusPanel доставляет подписанные HTTP POST-события на любой зарегистрированный вами URL. Каждая доставка содержит заголовок X-Nexus-Signature — HMAC-SHA256 тела с секретом вашего эндпоинта.

Области событий

ОбластьСобытия
user.*user.created, user.updated, user.deleted, user.expired, user.disabled, user.data_used_reset
node.*node.connected, node.disconnected, node.reconnecting
service.*service.started, service.stopped
billing.*billing.renewed, billing.expired
errors.*errors.cert_expired, errors.xray_crash
hwid.*hwid.mismatch, hwid.reset

Оставьте области пустыми, чтобы получать все события. Доставка повторяется с экспоненциальной задержкой; после максимального числа попыток событие помечается как неудачное и отбрасывается.

bash — API
# Зарегистрировать эндпоинт
curl -X POST /api/v1/webhooks \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://my-server/hook","scopes":"user.*,node.*"}'
# Ответ содержит секрет (показывается один раз)

# Отправить тестовую доставку
curl -X POST /api/v1/webhooks/1/test -H "Authorization: Bearer TOKEN"

# Проверить подпись в вашем обработчике (пример на Python)
# expected = hmac.new(secret, body, sha256).hexdigest()
# assert expected == request.headers["X-Nexus-Signature"]
Устаревший подход через env
WEBHOOK_ADDRESS (URL через запятую) и WEBHOOK_SECRET по-прежнему работают как статическая альтернатива через переменные окружения. Для новых настроек используйте интерфейс панели — он поддерживает секреты, области и историю доставки для каждого эндпоинта.

Страница клиентов

Панель → Клиенты показывает подобранный список рекомендуемых VPN-клиентов со значками платформ, ссылками для скачивания и заметками по использованию. Операторы делятся URL этой страницы с конечными пользователями.

КлиентПлатформыЗаметки
HappiOS / macOS / Windows / AndroidРекомендуется — нативный sub URL, привязка по HWID, офлайн-кэш
v2RayTuniOS / macOS / AndroidПопулярный клиент для iOS, поддержка VLESS-Reality
KaringВсе платформыНа основе Sing-box, сильная кроссплатформенность
ShadowrocketiOS$2.99 в App Store США — надёжен на iOS
V2rayNGAndroidКлассический клиент для Android
FlClashXWindows / macOS / Linux / AndroidСовместим с Mihomo/Clash
StreisandiOS / macOSПоддерживает свой JSON — задайте USE_CUSTOM_JSON_FOR_STREISAND=true

Система лицензий

NexusPanel использует центральный лицензионный сервер (nexuspanel.store) для проверки установок и доставки обновлений. Так клиенты распределяются по тарифам, тарифицируются и поддерживаются в актуальном состоянии.

Как работает heartbeat

  • Каждые 6 часов панель вызывает POST /api/validate на лицензионном сервере со своими license_id, client_id, отпечатком железа и телеметрией использования: версия панели, версия Xray, ОС и версия Python, всего/активных пользователей, активные ноды, общий трафик, аптайм хоста и результат самопроверки целостности. Имя хоста и список ваших серверов не передаются.
  • Лицензионный сервер сохраняет это и отвечает {tier, expires_at, latest_version, update_available, docker_image}.
  • AUTO_UPDATE по умолчанию выключен — инсталлятор пишет AUTO_UPDATE=false. Когда update_available приходит истинным, панель лишь запоминает это; обновление вы применяете сами командой nexus update. Включить автоматический путь можно через nexus auto-update on — тогда на следующем хартбите панель в фоне выполнит docker compose pull && docker compose up -d --force-recreate.

Тарифы

Четыре публичных тарифа. Именно их вы увидите сегодня в платёжном боте:

ТарифЦенаНодыАдминыIP-Defender
Free$011
Пробный (Pro Trial)Бесплатно, 14 днейБезлимит1
Pro$30/месБезлимитБезлимит
Business$60/месБезлимитБезлимит✓ + бот для реселлеров
Standard, Starter и Growth остались — но только для продления
Операторы, купившие один из этих тарифов до появления новой линейки, продолжают продлевать его по старой цене и лимитам. Новым покупателям в платёжном боте эти тарифы не показываются — не предлагайте их как вариант выбора.

Free — $0

Вся панель, на одной ноде, навсегда — без карты, без отсчёта дней триала. Та же задача, что бесплатно решают Marzban или Remnawave, только под управлением NexusPanel. Проверено на живой панели: вторая нода отклоняется с License limit reached (1/1 nodes), второй админ — так же на 1/1, а /api/v1/defender/* отвечает 403. Пользователи не ограничены — продавайте сколько угодно на этой одной ноде. Пункт IP-Defender вообще не появляется в боковом меню на Free — он не показан-и-заблокирован, его там просто нет.

Пробный — Pro Trial

Без банковской карты, без регистрации — откройте Telegram-бот и введите /start. Вы получите бесплатный 14-дневный Pro-триал: пользователи и ноды без ограничений, карта не нужна. Одну возможность Pro он всё же не даёт: лимит админов остаётся равным 1, и создание второго аккаунта отклоняется с License admin limit reached (1/1 admins) — проверено на живой триальной панели. Полный доступ к дашборду, включая IP-Defender. Достаточно, чтобы оценить на реальном трафике перед выбором между Pro и Business.

Pro — $30/месяц

Неограниченное число нод, пользователей и админов, плюс IP-Defender: проверено — 200 на каждом маршруте /api/v1/defender/* на живой панели Pro. Также включено:

  • Массовые операции (включить/отключить/сбросить/удалить/добавить протокол сотням пользователей разом)
  • ECH (Encrypted Client Hello) и транспортный слой защиты от снятия отпечатков Finalmask
  • Группы пользователей и наборы inbound для сегментации уровня реселлеров
  • Ретрансляцию через Middle-сервер с автогенерируемыми правилами iptables
  • Приоритетную поддержку

White-label брендинг (свой домен панели + логотип) — не привилегия Pro: это одна общая настройка, которая уже есть у всех тарифов, включая Free.

Business — $60/месяц

Всё из Pro, плюс бот для реселлеров, через который продают ваши реселлеры: проверено — /api/v1/seller/* подключён и отвечает на живой панели Business, и 404 — маршрута просто нет, а не ошибка доступа — на любом другом тарифе. Это тариф именно для реселлинга: реселлеры технически являются строками таблицы админов, поэтому Business также не имеет ограничения на число админов.

Сравнение возможностей

ВозможностьFreeПробныйProBusiness
Максимум пользователейБезлимитБезлимитБезлимитБезлимит
Максимум нод1БезлимитБезлимитБезлимит
Максимум админов11БезлимитБезлимит
СрокНавсегда14 дней30 дней/мес30 дней/мес
Все протоколы (VLESS, VMess, Trojan, SS)
Hysteria 2 (выдача пользователям)
Управление inbound Hysteria 2
Аналитика в стиле Grafana
Просмотр живых сессий
Журнал аудита
CLI оператора
IP-Defender
Массовые операции
ECH + Finalmask
Группы пользователей и наборы inbound
Ретрансляция через Middle-сервер
Бот для реселлеров
White-label брендинг
Пробный и Free — не путайте
Пробный — это временный Pro-триал: полный набор функций, включая IP-Defender, на 14 дней. Free — постоянный тариф со всей панелью, кроме Defender, ограниченный одной нодой и одним админом. Это не один продукт с разным таймером — у Free никогда не было Defender, а у Пробного просто заканчиваются 14 дней. Есть и обратный нюанс: ретрансляция через Middle-сервер и подготовка CDN/каналов подписки проверяются по названию тарифа, а не по набору функций, поэтому Пробный — несмотря на то что открывает почти всё остальное — исключён из них так же, как и Free. Панель без лицензии тоже показывает «trial», но ограничена базовым набором, как у Free, а не полным набором настоящего триала.

Покупка лицензии

Откройте @nexuspanelpayment_bot в Telegram. Нажмите View Plans, выберите тариф, выберите срок (1/3/6/12 месяцев с растущими скидками), выберите криптовалюту (USDT TRC20, BTC, ETH, LTC, TRX и 200+ других) и отправьте точную показанную сумму на указанный кошелёк. Как только NOWPayments подтвердит платёж, бот выдаст ваши License Key и Client ID.

Льготный период

Если ваша лицензия истекла, панель продолжает работать в льготном режиме 72 часа, чтобы вы могли продлить без простоя. После этого API переходит в режим только для чтения, пока не будет восстановлена действующая лицензия.

Обновление уже работающей панели

Покупка выдаёт новые LICENSE_ID и CLIENT_ID — покупка Pro или Business взамен Free или Пробного не продлевает уже имеющуюся у вас лицензию. Если у вас уже работает панель, не запускайте установщик заново — он ставится поверх работающей панели, это не путь обновления. Правильные шаги:

bash
nexus edit-env      # укажите новые LICENSE_ID и CLIENT_ID
nexus restart

nexus edit-env открывает файл .env панели для правки LICENSE_ID и CLIENT_ID; nexus restart подхватывает новую лицензию на следующем heartbeat.

Если правка .env как будто ничего не меняет
В старых версиях операторского CLI nexus команда nexus restart выполняла docker compose restart, которая сохраняет исходное окружение контейнера и вообще не применяет изменения .env. Это исправлено — теперь nexus restart пересоздаёт контейнер. Если вы правите .env и тариф после рестарта не меняется, ваш скрипт nexus старше этого исправления — обновите его (nexus update или заново скачайте scripts/nexus-cli.sh), а не пытайтесь править .env ещё раз.

Применение лимитов IP и устройств

NexusPanel применяет лимиты IP и устройств по каждому пользователю в реальном времени, разбирая access-лог Xray — а не только при импорте подписки. Именно это заставляет ip_limit и device_limit действительно работать.

Как это работает

  1. Xray пишет по одной строке в $XRAY_ACCESS_LOG на каждое принятое подключение.
  2. Задание enforce_limits запускается каждые 60 секунд, читает хвост лога (с учётом смещения и ротации) и извлекает пары (user_id, client_ip) за последние LIMIT_WINDOW_SECONDS (по умолчанию 600 = 10 минут).
  3. Для каждого пользователя подсчитываются уникальные IP. Если их число превышает ip_limit (или device_limit, если ip_limit не задан) и пользователь сейчас active и ip_limit_mode == "limit", пользователь переводится в статус limited.
  4. Все увиденные IP записываются в user_ip_history. Просмотреть IP по пользователю можно через GET /api/v1/user/{username}/ips.

Необходимая конфигурация xray

При установке по умолчанию это включается автоматически. Для существующих установок панель при запуске автоматически правит ваш xray_config.json, добавляя путь к access-логу. Конфигурация вручную:

json
{
  "log": {
    "loglevel": "warning",
    "access": "/var/lib/panel/xray-access.log"
  }
}

Настраиваемые параметры

Переменная окруженияПо умолчаниюНазначение
XRAY_ACCESS_LOG/var/log/xray/access.logПуть к файлу access-лога Xray
LIMIT_WINDOW_SECONDS600Скользящее окно для подсчёта уникальных IP
LIMIT_ENFORCE_INTERVAL60Как часто (секунды) запускается задание применения лимитов

Резервные копии

NexusPanel выполняет автоматическое резервное копирование базы данных каждый день в 03:00 UTC через задание backup APScheduler.

Куда сохраняются копии

  • Локальные файлы: /var/lib/panel/backups/backup_YYYYMMDD_HHMMSS.sqlite3 (или .sql для PostgreSQL)
  • Хранятся последние 7 копий; более старые автоматически удаляются
  • Если настроены TELEGRAM_API_TOKEN и TELEGRAM_ADMIN_ID, каждая копия также отправляется вам в Telegram документом, чтобы у вас была копия вне сервера

Резервное копирование вручную

bash
# SQLite
docker exec nexus-panel cp /var/lib/panel/db.sqlite3 /var/lib/panel/backups/manual.sqlite3

# Или возьмите файл напрямую с хоста
cp /var/lib/panel/db.sqlite3 ~/panel-backup-$(date +%F).sqlite3

Восстановление

  1. Остановите панель: cd /opt/panel && docker compose down
  2. Замените файл БД: cp /path/to/backup.sqlite3 /var/lib/panel/db.sqlite3
  3. Перезапустите: docker compose up -d
Настраиваемые параметры
BACKUP_DIR — куда пишутся копии (по умолчанию /var/lib/panel/backups)
BACKUP_RETENTION — сколько последних копий хранить (по умолчанию 7)

Зашифрованные подписки Happ

Кнопка «H» у каждого пользователя в панели генерирует настоящий deeplink happ://crypt4/<base64> с использованием RSA-4096 PKCS1v15 и официального открытого ключа Happ. После добавления в клиент Happ пользователь не может посмотреть, изменить или поделиться исходным URL подписки.

URL подписки длиннее 501 байта (лимит RSA-4096 + PKCS1v15) автоматически переходят на обычный формат happ://add/<base64>.

Ведение бизнеса

Простыми словами
Повседневная работа — это в основном один цикл: клиент платит, вы создаёте ему пользователя, отправляете ссылку. Всё ниже — это тот же цикл плюс несколько настроек, которые позволяют вырасти дальше нескольких десятков клиентов.

Ваш первый клиент

  1. Панель → ПользователиДобавить пользователя.
  2. Укажите имя пользователя, выберите дату истечения и лимит трафика (или оставьте оба без ограничений), выберите протоколы.
  3. Сохраните — панель сразу сгенерирует ссылку на подписку.
  4. Отправьте клиенту ссылку. Он вставляет её в клиентское приложение (см. страницу Клиенты с рекомендациями) и подключается.

Всё это доступно и через API для автоматизации — см. API пользователей, если хотите создавать аккаунты скриптом из собственного магазина или бота.

Лимиты устройств и IP

Лимиты устройств и IP (см. как работает контроль) — это не только защита от злоупотреблений, но и рычаг для ценообразования. Частая структура:

ТарифЛимит устройствТипичное применение
Персональный1–2Один человек, одно-два устройства
Семейный / Командный4–6Общий доступ для семьи или небольшой команды, цена выше
Безлимитный0 (выкл.)Премиум-тариф без ограничений — и цена соответствующая

Установите device_limit (или ip_limit) при создании или редактировании пользователя. Клиенты, превысившие лимит, автоматически переводятся в статус limited — следить за этим вручную не нужно.

Админы и реселлеры

Если под вами продают другие люди — друзья, сотрудники или суб-реселлеры — выдайте каждому отдельный логин администратора вместо того, чтобы делиться своим. Полное описание см. в разделе Управление администраторами; коротко:

  • Владелец (вы) — видит всё, управляет остальными админами.
  • Админ — управляет пользователями, но не настройками панели и не другими админами.
  • Реселлер — управляет только своими пользователями, в рамках лимитов max_users и max_traffic_bytes, которые вы задаёте.

Так вы масштабируетесь без необходимости лично проводить каждую продажу: реселлер заходит в свой аккаунт, создаёт и обслуживает своих клиентов, не видя и не трогая чужих.

Самообслуживание через Telegram

После подключения Telegram-бота клиенты сами проверяют свой трафик (/usage), заново получают ссылку (/sub) и смотрят подключённые устройства (/devices) — без обращения к вам. Это снимает большую часть обращений в поддержку вида «а работает ли ещё мой VPN».

Ценообразование

NexusPanel не устанавливает ваши цены — это полностью на ваше усмотрение и зависит от вашего рынка. Для старта большинство операторов учитывают:

  • Ваши расходы — VPS панели, ноды, ваша лицензия NexusPanel (см. тарифы и цены), а также трафик, если провайдер берёт за него плату.
  • Ваше отличие от конкурентов — больше слотов на устройства, больше локаций нод, приоритетная поддержка, или просто стабильность, когда у конкурентов её нет.
  • Ваш рынок — сколько берут похожие сервисы там, где живут ваши клиенты. Пакетные многомесячные тарифы (по аналогии со скидками 3/6/12 месяцев у самой панели) — частый способ повысить удержание клиентов.

Принимайте оплату так, как удобно вам — вручную через Telegram или мессенджеры, через бота для оплаты, или через собственный магазин, который вызывает API пользователей и создаёт аккаунт автоматически после оплаты.

Бот для реселлеров

Только Business
Недоступен на Free, Пробном и Pro — проверено: на этих тарифах каждый маршрут /api/v1/seller/* отвечает 404, а на Business возвращает реальные данные.

Бот для реселлеров — это то, через что реально продают ваши реселлеры: Telegram-бот для модели реселлинга, а не для конечных пользователей. Это отдельный сервис, свой контейнер, не часть образа панели. Поэтому его API-поверхность на других тарифах просто отсутствует, а не отвечает ошибкой доступа: /api/v1/seller/* подключается к панели только когда лицензия явно называет функцию seller.

Проверенная рабочая поверхность:

  • Баланс и леджер реселлера — у каждого реселлера есть баланс и текущий журнал пополнений и трат.
  • Жизненный цикл конфигов — выдача, продление и удаление клиентских конфигов прямо из бота.
  • Тарифы — планы, которые продают реселлеры; цены и управление ими — на вашей стороне.
  • Способы пополнения — как реселлеры пополняют баланс (ручное подтверждение, крипта и другие настроенные каналы) и просмотр ожидающих пополнений.

Бот обращается к вашей панели через тот же API реселлинга (PANEL_API_URL + логин админа панели) и требует собственный SELLER_BOT_TOKEN от BotFather. Это отдельный деплой от самой панели — см. seller_bot/ в репозитории, если разворачиваете его; эта страница не даёт пошаговую инструкцию по настройке контейнера — это операционная деталь, зависящая от конкретного развёртывания.

Ноды

Что такое нода

Простыми словами
Нода — это просто ещё один сервер в другой стране, которым управляет ваша панель. Добавьте ноду в Германии — и ваши клиенты смогут подключаться «через Германию». Управляете вы ими всеми из той же панели. Для старта ноды не нужны — ваш первый сервер уже сам по себе обслуживает клиентов.

Нода — это удалённый сервер с ядром Xray, который подключается обратно к вашему экземпляру NexusPanel. Ноды позволяют распределять прокси-точки по нескольким серверам и географическим локациям, управляя всем из одной панели.

Панель общается с нодами по защищённому gRPC-соединению с использованием взаимного TLS. Через этот канал передаются конфигурации пользователей и данные о трафике.

Установка ноды

Панель → НодыДобавить новую ноду открывает окно с двумя вкладками — выберите подходящую в зависимости от того, есть ли у панели SSH-доступ к серверу ноды.

Auto install (рекомендуется)

Вставьте IP свежего VPS и данные SSH-входа (пароль root или приватный ключ) — панель сделает всё остальное: подключится по SSH, установит Docker и агент ноды со встроенным mTLS-сертификатом, зарегистрирует ноду и дождётся подключения. Ничего копировать и запускать вручную не нужно — пароль/ключ SSH используется один раз и нигде не сохраняется.

Manual (резервный вариант — если панель не может достучаться до ноды по SSH)

Вкладка Manual вместо этого генерирует готовую к вставке однострочную команду со встроенным сертификатом панели. Никакой записи файла сертификата вручную.

  1. Панель → НодыДобавить новую ноду → вкладка Manual
  2. Нажмите Copy Install Command — команда включает сертификат, порт, порт API и URL панели
  3. Вставьте и выполните на сервере ноды
  4. Введите IP ноды и порты в панели → Add Node
bash — пример сгенерированной команды
curl -sL https://nexuspanel.store/install-node | bash -s -- \
  --port 62060 \
  --api-port 62061 \
  --panel-url 'https://panel.example.com:8443' \
  --cert-b64 '<base64-cert>'

Установщик автоматически ждёт снятия блокировок apt/dpkg — его безопасно запускать на только что развёрнутом VPS. Не пропускайте --panel-url: без него аутентификация Hysteria 2 на этой ноде останется отключённой, пока вы не зададите её позже.

Сертификат и порты

NexusNode аутентифицируется в панели с помощью подписывающего сертификата панели:

  • Порт подключения к панели: 62060
  • Порт API Xray: 62061
  • CN сертификата: Panel — значение ssl_target_name в конфиге ноды должно совпадать
  • Сертификат один раз запрашивается из GET /api/v1/node/settings (или встраивается командой установки) и сохраняется в /var/lib/nexus-panel-node/ssl_client_cert.pem
Файрвол
Откройте входящие TCP 62060 и TCP 62061 на сервере ноды для IP панели. Также откройте любые прокси-порты (443, 80 и т. д.) для конечных пользователей.

Docker Compose для ноды

Это реальный compose-файл, который генерирует установщик в /opt/nexus-panel-node/docker-compose.yml — для справки, если настраиваете его вручную:

yaml — /opt/nexus-panel-node/docker-compose.yml
services:
  node:
    image: ghcr.io/haitovs/nexus-node:latest
    container_name: nexus-panel-node
    restart: always
    network_mode: host
    environment:
      SERVICE_PORT: 62060
      XRAY_API_PORT: 62061
      SSL_CERT_FILE: /var/lib/nexus-panel-node/ssl_cert.pem
      SSL_KEY_FILE: /var/lib/nexus-panel-node/ssl_key.pem
      SSL_CLIENT_CERT_FILE: /var/lib/nexus-panel-node/ssl_client_cert.pem
      # Sidecar Hysteria2 — пусто отключает его, пока не передан --panel-url
      PANEL_HY2_AUTH_URL: "https://panel.example.com:8443/api/v1/hy2-auth"
    volumes:
      - /var/lib/nexus-panel-node:/var/lib/nexus-panel-node
      - /etc/hysteria:/etc/hysteria

network_mode: host означает, что раздела ports: в Docker нет — нода привязывает все порты (сервисный, API и все инбаунды Xray/Hysteria, к которым подключаются пользователи) напрямую на хосте.

Несколько нод

Чтобы добавить ноды в разных локациях:

  1. Установите сервис ноды на каждый сервер с помощью сгенерированной однострочной команды
  2. В панели добавьте каждую ноду с её публичным IP и портами
  3. Назначьте флаг страны — он управляет и визуальной сеткой, и региональным переупорядочиванием подписки
  4. Перетаскиванием задайте порядок отображения в сетке
  5. Задайте коэффициент использования для каждой ноды (например, 1.5 означает, что трафик считается с множителем 1.5×)
Региональное переупорядочивание подписки
Ссылки-подписки автоматически сортируются по стране подписчика: сначала ближайшая нода, затем тот же континент, потом остальные. Определяется через CF-IPCountry (Cloudflare) или локальную базу MaxMind. Задайте country_code на каждой строке-хосте, чтобы это работало.

Устранение неполадок нод

ПроблемаРешение
Нода показывает «Offline»Проверьте, что файрвол разрешает TCP 62060 от панели; проверьте сертификат в /var/lib/nexus-panel-node/ssl_client_cert.pem
Connection refusedУбедитесь, что Docker-контейнер запущен: docker compose ps
Ошибка сертификатаСкопируйте сертификат из панели заново (GET /api/v1/node/settings); проверьте ssl_target_name = Panel
Высокая задержкаПроверьте сетевой маршрут между панелью и нодой; убедитесь, что заданы управление перегрузкой BBR и буферы сокетов 64 МБ
Пользователи не могут подключиться через нодуПроверьте, что прокси-порты (443, 80 и т. д.) открыты для конечных пользователей в файрволе ноды

Справочник API

Все эндпоинты API находятся под /api/v1/. Включите интерактивный Swagger UI, задав DOCS=true и зайдя на /docs.

Аутентификация

Получите JWT access-токен, отправив учётные данные:

POST /api/v1/admin/token
bash
curl -X POST https://panel.example.com:8443/api/v1/admin/token \
  -d "username=admin&password=admin&grant_type=password"

# Ответ:
# {"access_token": "eyJ...", "token_type": "bearer"}

# Используйте токен в последующих запросах:
curl -H "Authorization: Bearer eyJ..." https://panel.example.com:8443/api/v1/system

Если для администратора включена 2FA, передайте TOTP-код в заголовке X-TOTP-Code.

Запрос выше работает как есть на установке по умолчанию: капча при входе выключена (CAPTCHA_PROVIDER=disabled), потому что это защита только для дашборда, а её включение заставляет любой скриптовый логин получать 400 Captcha required. От перебора уже защищает блокировка после неудачных попыток (LOGIN_LOCKOUT_THRESHOLD / LOGIN_LOCKOUT_DURATION_MINUTES), а не LOGIN_RATE_LIMIT, который не читается кодом. Если вы всё же включите CAPTCHA_PROVIDER, скрипты должны сначала вызвать GET /api/v1/admin/captcha и вернуть X-Captcha-Id и X-Captcha-Answer.

Эндпоинты 2FA
POST /api/v1/admin/2fa/setup — сгенерировать TOTP-секрет + резервные коды
POST /api/v1/admin/2fa/enable — проверить код и активировать 2FA
POST /api/v1/admin/2fa/disable — деактивировать 2FA

Пользователи

POST /api/v1/user

Создать нового пользователя с протоколами, лимитом трафика, сроком действия, лимитом устройств и лимитом IP.

GET /api/v1/users

Список всех пользователей. Автоматически ограничивается по администратору для несудо-аккаунтов.

GET /api/v1/user/{username}

Получить детальную информацию о пользователе, включая статистику использования и ссылки-подписки.

PUT /api/v1/user/{username}

Обновить поля пользователя (лимит трафика, срок действия, статус, протоколы и т. д.).

DELETE /api/v1/user/{username}

Безвозвратно удалить пользователя и все связанные данные.

Массовые операции

POST /api/v1/users/bulk/update
POST /api/v1/users/bulk/delete
POST /api/v1/users/bulk/reset

Экспорт

GET /api/v1/export/users

Скачать всех пользователей в виде CSV-файла.

GET /api/v1/export/subscription-links

Экспортировать все ссылки-подписки в виде обычного текста.

Администраторы

POST /api/v1/admin

Создать нового администратора с ролью (owner, admin, reseller), max_users и max_traffic_bytes.

GET /api/v1/admins

Список всех учётных записей администраторов.

Ноды

GET /api/v1/inbounds

Список всех протокольных inbound-ов.

GET /api/v1/hosts

Получить конфигурации хостов (только sudo).

Аналитика

GET /api/v1/analytics/summary

Сводная статистика для обзора панели.

GET /api/v1/analytics/protocols

Разбивка распределения по протоколам.

GET /api/v1/analytics/nodes/load

Число подключений и трафик по каждой ноде.

GET /api/v1/analytics/nodes/uptime

Проценты аптайма нод.

GET /api/v1/analytics/users/expiring?days=30

Пользователи, у которых срок истекает в течение указанного числа дней.

GET /api/v1/analytics/users/top?limit=10

Топ-пользователи по потреблению трафика.

Сессии

GET /api/v1/sessions/active?hours=24

Активные сессии устройств за последние N часов.

GET /api/v1/sessions/user/{username}

Сессии конкретного пользователя.

DELETE /api/v1/sessions/{session_id}

Принудительно отключить сессию устройства.

Система

GET /api/v1/system

Системная статистика, включая CPU, память и трафик. Несудо-администраторы видят обнулённые значения для чувствительных метрик.

GET /api/v1/health

Эндпоинт проверки работоспособности, возвращающий статус базы данных и ядра Xray.

GET /metrics

Эндпоинт метрик, совместимый с Prometheus. Требует METRICS_ENABLED=true и METRICS_TOKEN для аутентификации.

Полная документация API
Для полных схем запросов/ответов включите DOCS=true в вашем .env и зайдите на http://your-panel/docs для интерактивного Swagger UI.

Telegram-бот

Настройка

  1. Откройте Telegram и напишите @BotFather
  2. Отправьте /newbot и следуйте подсказкам, чтобы создать бота
  3. Скопируйте токен бота (например, 123456789:AAAA...)
  4. Узнайте свой ID пользователя Telegram (напишите @userinfobot)
  5. Добавьте в ваш .env:
env
TELEGRAM_API_TOKEN="123456789:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
TELEGRAM_ADMIN_ID="987654321"
TELEGRAM_LOGGER_CHANNEL_ID=-1001234567890

Перезапустите панель после добавления токена. Бот запустится автоматически.

Команды бота

КомандаОписание
/usageПроверить использование трафика и остаток квоты
/subПолучить ссылку-подписку и QR-код
/statsСтатистика панели (только администратор)
/devicesПросмотр подключённых устройств
/helpСписок всех доступных команд
/broadcastОтправить сообщение всем пользователям (только администратор)

Настройки уведомлений

Telegram-бот отправляет уведомления о различных событиях, когда это настроено. Управляйте каждым типом уведомлений по отдельности через переменные .env (см. конфигурацию уведомлений).

Уведомления отправляются:

  • На ID администраторов — личные сообщения каждому администратору из TELEGRAM_ADMIN_ID
  • В канал логов — все события в TELEGRAM_LOGGER_CHANNEL_ID

Поля, включаемые в уведомления о создании / изменении

Уведомления о создании и изменении пользователя включают следующие поля, если они заданы у пользователя:

ПолеОтображается какКогда включается
Имя пользователяUsername: aliceВсегда
Лимит трафикаTraffic Limit: 50 GBВсегда (показывает «Unlimited», если не задан)
Дата окончанияExpire Date: 2026-06-01Всегда (показывает «Never», если не задана)
ПротоколыProxies: vless, trojanВсегда
Сброс лимита трафикаData Limit Reset Strategy: monthlyВсегда
Лимит устройствDevice Limit: 3Только когда > 0
Лимит IPIP Limit: 5 (limit)Только когда > 0; режим показан рядом
Лимит HWIDHWID Limit: 2Только когда > 0
Есть следующий планHas Next Plan: TrueВсегда
ЗаметкаNote: Paid in advance 6moТолько если не пуста; обрезается до 120 символов
Интеграция с Discord
Задайте DISCORD_WEBHOOK_URL, чтобы получать те же уведомления в канал Discord. Embed-ы Discord включают те же расширенные поля.

Каналы доставки подписок

Доставляйте sub URL через инфраструктуру, которую цензоры не могут заблокировать.

Когда домен вашей панели заблокирован в России, Иране, Китае или Туркменистане, клиенты не могут получить обновления своих подписок. Каналы доставки подписок решают это, публикуя конфиг каждого пользователя в статический файл на инфраструктуре Google / Cloudflare / GitHub / Telegram — на хостах, которые цензоры не могут заблокировать целиком, не сломав массовые приложения, которыми пользуются миллионы.

Требование к лицензии
Управление каналами доставки подписок требует Pro или Business (легаси-лицензии Standard/Growth тоже подходят для продления). На Free — нет, и на 14-дневном Pro Trial тоже нет: эта проверка идёт по названию тарифа, а не по набору функций, поэтому триал, открывающий почти всё остальное, здесь всё равно отвечает 402 и панель показывает баннер с предложением апгрейда. Канал Direct (собственный /sub/<token> панели) работает всегда и тарифа не требует.

Как это работает

  1. Вы настраиваете один или несколько каналов в Настройки → Каналы доставки подписок.
  2. Каждый пользователь получает стабильный публичный URL на этом канале (например, https://firebasestorage.googleapis.com/…?alt=media&token=…).
  3. Значок ⊞ (сетка) в каждой строке пользователя в таблице открывает поповер со всеми доступными URL — Direct, зашифрованный Happ и каждый настроенный канал. Копирование или показ QR в два клика.
  4. Когда вы редактируете хосты или конфиг Xray, панель автоматически переопубликовывает всех активных пользователей в Firebase (и другие каналы) в течение ~10–30 секунд через фоновый воркер. Ручной Backfill после рутинных правок конфига не нужен.

Доступные каналы

КаналПровайдерБесплатный лимитЛучше всего для
Firebase StorageGoogle~50K запросов/день на плане SparkОсновной антицензурный канал
Firebase HostingGoogleТот же план Spark, что и у StorageВторая поверхность Firebase (*.web.app) — другой SNI и другой edge CDN в том же проекте, поэтому остаётся доступной, когда Storage заблокирован. Публикуется сайтом целиком, а не по одному пользователю, поэтому обновляется пакетно, а не на каждое изменение.
Cloudflare R2Cloudflare10 ГБ/месяц, без платы за исходящий трафикВторичный; иной поставщик, чем Firebase
GitHub GistGitHub / MicrosoftНеограниченные публичные gist-ыПростой запасной вариант; крайне живучий
GitLab SnippetGitLabНеограниченные публичные сниппетыПодтверждённо доступен в Туркменистане даже в окна жёстких блокировок — второе зеркало рядом с Firebase для тех, кто не может достучаться до него
Доставка через TelegramTelegramБесплатноЭкстренная доставка, когда всё остальное не работает
Пул Nginx-проксиВаши VPSСтоимость VPSПолный контроль оператора над ретранслятором
Тестируйте со стороны панели, а не со своего ноутбука
Кнопка Test (значок обновления в каждой строке канала) загружает реальный тестовый блоб и скачивает его обратно через исходящую сеть панели — а не из вашего браузера. Это важно: ваш локальный DNS может быть в порядке, тогда как регион ваших клиентов блокирует URL. Тест измеряет, может ли сервер панели достучаться до URL, — а именно это определяет, будет ли доставлено обновление подписки.

Firebase Storage

Рекомендуемый первый канал. Бесплатный лимит покрывает ~50K запросов подписки в день. Размещён в IP-пространстве Google — цензоры не могут заблокировать его целиком, не сломав Google Maps, Gmail и множество других приложений.

Однократная настройка на console.firebase.google.com

  1. Создайте проект — Add project → назовите его (например, nexus-subs) → план Spark (бесплатный) → Create.
  2. Включите Storage — Build → Storage → «Get started» → «Start in production mode» → выберите локацию → Done.
  3. Задайте правила хранилища — Storage → Rules → замените на:
firebase rules
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /sub_{file=**} {
      allow read: if true;
      allow write: if false;
    }
  }
}
  1. Сгенерируйте ключ сервисного аккаунта — Project Settings (⚙) → Service accounts → «Generate new private key» → Download. Относитесь к нему как к паролю.
  2. Найдите имя бакета — Storage → вверху показано gs://your-project.firebasestorage.app. Скопируйте часть после gs://.

В панели

  1. Настройки → Каналы доставки подписок → Firebase Storage → ⚙
  2. Вставьте имя бакета и JSON сервисного аккаунта (всё содержимое файла)
  3. Включите Enabled, задайте Priority (меньше = предпочтительнее; 10 — хорошее начало)
  4. Сохраните → нажмите Test (значок обновления)

Как читать результат теста

Успешный тест выглядит так:

result
firebase: end-to-end OK in 1840ms
✓ creds   (180ms): bucket reachable
✓ upload  (650ms): published to https://firebasestorage.googleapis.com/…
✓ fetch   (820ms): GET 200 (87 bytes, attempt 1)
✓ match     (1ms): content matches
✓ cleanup (180ms): test blob deleted
Шаг, который не прошёлВероятная причинаРешение
credsJSON сервисного аккаунта неверен или истёкСгенерируйте ключ заново в Firebase Console
uploadStorage не включён или неверные правилаПерепроверьте шаги настройки 2–3
fetchПравило публичного чтения не примененоВставьте правила из шага 3 заново
matchEdge-кэш отдал устаревший блоб (редко)Обычно повторы это скрывают; сообщите о баге, если повторяется
cleanupСервисный аккаунт только для чтенияУдалите блобы nexus_test_* вручную

Применить к существующим пользователям

После того как тест пройдёт, нажмите Backfill внизу карточки «Каналы доставки подписок». Это немедленно запустит загрузки в Firebase для всех активных пользователей через фоновый воркер. Для 200 пользователей ожидайте 30–120 секунд.

Стабильные URL при смене плана
URL Firebase никогда не меняется для конкретного пользователя — перезаписывается только содержимое блоба. Клиенты один раз импортируют URL в свой VPN-клиент, и он автоматически обновляется при каждой смене плана без каких-либо действий с их стороны.

Cloudflare R2

S3-совместимое объектное хранилище без платы за исходящий трафик. Используйте как вторичный канал наряду с Firebase — иной поставщик означает, что региональная блокировка одного не выводит из строя оба.

Настройка на dash.cloudflare.com

  1. R2 (левое меню) → Create bucket → назовите его (например, nexus-subs).
  2. Откройте бакет → Settings → Public access → включите. Скопируйте URL https://pub-<id>.r2.dev.
  3. Вверху справа страницы R2 → Manage R2 API tokens → Create token → Object Read & Write (ограничьте вашим бакетом) → сохраните Access Key ID + Secret.
  4. Ваш Account ID — это 32-символьный hex внизу справа страницы панели R2.

В панели

Настройки → Каналы доставки подписок → Cloudflare R2 → ⚙:

ПолеГде найти
Account ID Cloudflare32-символьный hex из шага 4
Имя бакетанапример, nexus-subs
Access key IDИз шага 3
Secret access keyИз шага 3 (показывается один раз)
База публичного URLhttps://pub-<id>.r2.dev из шага 2
Не подключайте к R2 свой домен
Свои домены блокируются на уровне DNS. Общий хост pub-<id>.r2.dev получает то же преимущество против блокировок, что и Firebase — он общий с тысячами других бакетов R2.

GitHub Gist

Бесплатно, размещено на GitHub (IP Microsoft). Крайне живучий вариант — хороший низкоприоритетный запасной канал, который ничего не стоит.

Настройка

  1. github.com/settings/tokens → Personal access tokens → Tokens (classic) → Generate new token.
  2. Имя: nexus-gists. Область: отметьте ТОЛЬКО gist. Срок: 1 год (поставьте напоминание о продлении).
  3. Скопируйте токен ghp_… — увидеть его снова не получится.

В панели

Настройки → Каналы доставки подписок → GitHub Gist → ⚙ → вставьте PAT → Сохранить → Test.

Доставка через Telegram

Доступен в IR/RU/TM именно в те периоды, когда другие каналы недоступны. Это запасной канал из разряда «панель горит, и у пользователя больше ничего нет».

Это доставка, а не автообновление
Пользователь получает deep-link t.me/<bot>?start=sub_<token>, а не самообновляющийся URL. Он нажимает на него один раз, и бот присылает ему в личные сообщения файл .txt с его конфигом. Задавайте очень высокий Priority (маленький номер приоритета) только если вы настроили обработчик /start у бота — иначе ссылка ведёт на бота, который не отвечает.

Настройка — отдельный бот (рекомендуется)

  1. Напишите @BotFather в Telegram → /newbot → выберите имя и username (должен заканчиваться на bot).
  2. Скопируйте токен, который выдаст BotFather.
  3. Настройки → Каналы доставки подписок → Telegram → ⚙:
    • Username бота: без @
    • Токен бота: вставьте из BotFather
  4. Сохраните → Test. Тест вызывает getMe и проверяет, что возвращённый username совпадает с тем, что вы вставили.

Если у вас уже задан TELEGRAM_API_TOKEN в .env для доставки уведомлений, поле токена бота можно оставить пустым — канал использует эту переменную окружения. Не рекомендуется по соображениям безопасности: утечка токена бота уведомлений раскрыла бы и файлы подписок.

Пул Nginx-прокси

Когда все каналы статического хранилища отключаются или блокируются по регионам, переходите на собственный парк дешёвых ретрансляторов-VPS. Каждый хост в пуле получает свой домен; панель распределяет пользователей по хостам по весу.

Предварительная подготовка

Поднимите дешёвые VPS (Hetzner CCX13 / Contabo и т. п. — €4–5/месяц каждый). Этот канал ничего не разворачивает за вас — он лишь распределяет пользователей по хостам, которые у вас уже работают, поэтому каждый участник пула должен быть готов до того, как вы пропишете его здесь.

Участник пула — это обычный nginx-фронт с TLS: свой домен, свой сертификат Let's Encrypt и один блок location /sub/, который проксирует на панель, подставляя домен самой панели в заголовок Host — панель сверяет его с XRAY_SUBSCRIPTION_URL_PREFIX, чтобы разобрать токен. Всё остальное отдаёт 404, так что наружу открыт только подписочный путь.

Пусть панель соберёт фронт сама
Вместо ручного nginx-конфига используйте IP Defender → Sub-Fronts: укажите адрес VPS и доступы, и панель развернёт ровно такой фронт по SSH вместе с сертификатом. Эти фронты управляются отдельно от данного канала — пул здесь остаётся ручным путём для хостов, которые вы не хотите отдавать панели.

В панели

Настройки → Каналы доставки подписок → Nginx-прокси → ⚙. Конфигурация в JSON:

json
{
  "hosts": [
    { "host": "alpha.shop",  "subscription_path": "sub", "weight": 1 },
    { "host": "beta.shop",   "subscription_path": "sub", "weight": 1 },
    { "host": "gamma.shop",  "subscription_path": "sub", "weight": 5 }
  ]
}

Хост с weight: 5 получает в 5 раз большую долю пользователей, чем хост с weight: 1. Сохраните → Test проверяет TLS-рукопожатие для каждого члена пула.

Каналы доставки подписок — интерфейс панели

Поповер подписки (для каждого пользователя)

В каждой строке таблицы пользователей есть значок ⊞ (сетка). Нажатие на него открывает поповер со списком всех URL, которые оператор может дать клиенту:

СтрокаЧто этоКопирование + QR
DirectОбычный URL /sub/<token>, отдаваемый панельюТолько копирование
Happ (зашифрованный)Зашифрованная форма AES-256-CBC через /user/<u>/encrypt-subТолько копирование
Firebase / R2 / GistURL статического хранилища из включённых каналовКопирование + QR
TelegramDeep-link на доставку через ботаТолько копирование
Nginx-проксиURL ретранслятораТолько копирование

URL предзагружаются при открытии поповера, поэтому копирование безопасно по жесту — нет асинхронной задержки между кликом и записью в буфер обмена.

Бейджи состояния каналов

Каждая строка канала в Настройки → Каналы доставки подписок показывает бейдж состояния по последней проверке. Cron запускается каждые 15 минут. Принудительно запустить свежую проверку можно в любой момент кнопкой Test.

Автопереопубликация при изменении конфигурации

Редактирование хостов или конфига ядра Xray запускает автоматическую рассылку: все активные пользователи, у которых изменилось содержимое подписки, переопубликовываются на каждый настроенный канал в течение ~10–30 секунд. Воркер пропускает пользователей, у которых отрендеренный конфиг не изменился (короткое замыкание по хэшу содержимого), поэтому правка хоста, затрагивающая только 50 из 200 пользователей, вызывает всего 50 записей в Firebase.

Backfill

Кнопка Backfill (внизу карточки «Каналы доставки подписок») немедленно загружает всех активных пользователей на все включённые каналы. Используйте её один раз после добавления нового канала — после этого автопереопубликация поддерживает всё в актуальном состоянии.

Hysteria2

Hysteria2 — это протокол на базе QUIC/UDP, который даёт в 3–5× большую пропускную способность, чем TCP, на сетях «последней мили» с потерями (мобильная связь, 4G в СНГ, Иран). Он работает как отдельный демон рядом с Xray — а не как inbound Xray — потому что Xray-core не поддерживает протокол hysteria2 нативно.

Ограничение по лицензии: создание и управление inbound-ами hy2 требует функции hysteria2_managePro, Business и 14-дневный Pro Trial (он выдаётся с полным набором функций Pro); легаси-лицензии Standard/Growth тоже её имеют. На Free этой функции нет. Панель без лицензии откатывается к базовому набору и видит записи подписки hy2, но не может управлять inbound-ами. Выдача hy2 пользователям никогда не ограничивается.

Требуется открытый UDP в файрволе
Hysteria2 использует UDP. Прежде чем добавлять хост для ноды, убедитесь, что UDP-порт (например, 2053) открыт в панели вашего хостинг-провайдера — Contabo, Aeza, PTR по умолчанию блокируют UDP.

Добавить inbound Hysteria2

Панель → НастройкиHysteria2Add Inbound

Требуется sudo-администратор
Inbound-ы Hysteria2 могут создавать и управлять ими только sudo (супер) администраторы. Несудо-администраторы не видят и не редактируют inbound-ы hy2.
ПолеЗначениеЗаметки
Taghy2-mainЛюбое уникальное имя
Listen port2053UDP — должен быть открыт в файрволе
Obfs typesalamanderРекомендуется — скрывает UDP от DPI в CN/IR/RU
Obfs passwordнадёжный случайныйopenssl rand -hex 24
Masquerade URLhttps://www.bing.comHTTPS-сайт, под который hysteria маскируется для DPI-проб
SNIbing.comTLS SNI, предъявляемый клиентам
TLS cert / keyоставьте пустым для автоПанель автоматически генерирует 10-летний самоподписанный сертификат, если не указано

Создание inbound синхронизирует конфигурацию на каждую подключённую ноду и запускает демон hysteria на каждой. SSH не требуется.

Добавить хосты для каждой ноды

Панель → Хосты → нажмите карточку inbound Hysteria2 → Add Host

Добавьте по одной строке-хосту на каждую ноду, на которой хотите открыть hy2:

ПолеПримерОбязательно
RemarkDE Frankfurt hy2Да
Addressde.example.comДа — публичный домен или IP ноды
Port2053Да — UDP-порт на этой ноде
Country codeDEРекомендуется — управляет региональным переупорядочиванием подписки

Генераторы подписок автоматически выдают записи hy2:// для каждого включённого хоста наряду с существующими ссылками VLESS/VMess. Клиенты увидят их при следующем обновлении подписки.

Через API (требуются учётные данные sudo-администратора):

bash
# 1. Получить токен с помощью имени и пароля суперадминистратора
TOKEN=$(curl -s -X POST /api/v1/admin/token \
  -d "username=YOUR_ADMIN&password=YOUR_PASSWORD" \
  | jq -r .access_token)

# 2. Список inbound-ов hy2
curl /api/v1/hy2-inbounds -H "Authorization: Bearer $TOKEN"

# 3. Добавить хост к inbound id=1
curl -X POST /api/v1/hy2-inbounds/1/hosts \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"remark":"DE Frankfurt","address":"de.example.com","port":2053,"country_code":"DE"}'

Проверка и устранение неполадок

После добавления хоста запросите URL подписки — вы должны увидеть запись hy2:// наряду со ссылками VLESS. Импортируйте в Nekobox, sing-box или Happ и подключитесь.

ПроблемаДиагностика
Нет hy2:// в подпискеПроверьте, что хост включён и задан country_code; убедитесь, что тариф лицензии Pro/Business/Пробный (или легаси-лицензия Standard/Growth)
UDP connection refusedТест: nc -vu <node> 2053 извне ДЦ. Порт не открыт в файрволе провайдера.
Таймаут UDPПровайдер или middlebox «съедает» UDP — попробуйте obfs salamander или другой порт
Ошибка TLSСамоподписанный сертификат: убедитесь, что у клиента allowinsecure: true или укажите отпечаток сертификата
Демон не запускается на нодеdocker logs nexus-panel-node 2>&1 | grep hysteria на сервере ноды

Middle-сервер (NAT-ретранслятор)

Middle-сервер — это дешёвый VPS, который стоит между вашими пользователями и нодами. Он ретранслирует трафик через iptables DNAT, поэтому пользователи подключаются к одному стабильному IP независимо от того, какая нода их обслуживает. Полезно, когда IP ноды блокируют в какой-то стране — замените ноду, заново сгенерируйте NAT на middle-сервере, обновите одну запись хоста.

Соглашения по портам
TCP inbound-ы: порт middle 50031–50036 → порт ноды 31–36 (совпадает с id ноды). UDP inbound-ы Hysteria2: порты 50041+ назначаются по каждому inbound. Все они автогенерируются из состояния БД панели — вы никогда не правите их вручную.

Первоначальная настройка

Сгенерируйте одноразовую команду установки из панели, затем вставьте её на новом VPS от root:

  1. В панели перейдите в Настройки → Middle-серверы и нажмите Generate install command.
  2. Скопируйте показанную команду — она выглядит так:
bash
curl -fsSLk https://panel.example.com:8443/api/v1/middle-server/i/<token> | sudo bash

Токен одноразовый и истекает через 30 минут. В истории shell не появляется никаких учётных данных.

Ручная / скриптовая установка (без доступа к интерфейсу панели)
bash
read -p "Panel URL: " _P
read -p "Admin username: " _U
read -sp "Admin password: " _W; echo
curl -fsSL -k -u "$_U:$_W" "$_P/api/v1/middle-server/bootstrap.sh" | sudo bash
unset _P _U _W

Скрипт генерируется из вашего текущего списка нод и inbound-ов Hysteria 2, поэтому перезапускайте его каждый раз, когда добавляете или удаляете что-либо из них.

Скрипт:

  • Установит iptables-persistent
  • Применит тюнинг ядра (BBR, большие буферы, conntrack)
  • Построит все правила DNAT из текущего состояния БД панели
  • Выведет таблицу записей-хостов для добавления в панели

После завершения скрипта перейдите на страницу Хостов и добавьте по одной записи-хосту на каждую выведенную скриптом строку, используя IP middle-сервера и выведенный порт.

Повторный запуск безопасен
Скрипт сбрасывает существующие правила перед применением новых. Запускайте его каждый раз, когда добавляете ноду, добавляете inbound Hysteria2 или меняете IP ноды.

Переход на новый middle-сервер

Когда текущий middle-сервер заблокирован или вы хотите перейти на другой VPS:

  1. Подключитесь по SSH к новому VPS и выполните ту же единственную команду выше
  2. В панели → страница Хостов отредактируйте каждый хост, чей адрес указывает на старый IP middle-сервера, и смените его на новый IP. Порты остаются прежними.
  3. Готово — никаких изменений нод, никакой перенастройки у пользователей
Не забудьте про хосты Hysteria2
Если у вас есть хосты Hysteria2, которые маршрутизируются через middle-сервер, обновите и их адреса.

Фронтинг и обход блокировок

Простыми словами
Фронтинг означает, что трафик ваших клиентов внешне выглядит так, будто идёт к Cloudflare, Amazon, Google, Fastly или Bunny — а не к вашему VPS. Чтобы заблокировать вас, цензору пришлось бы заблокировать весь этот облачный сервис целиком, а это сломает миллионы никак не связанных с вами сайтов. Большинство сетей на это не идут, поэтому ваш трафик проходит.
IP-Defender требует Pro или Business
Весь раздел Defender — Overview, Sources, IP Pool, Hosts, Shield, Setup — это платное отличие Free от всех тарифов выше него. На лицензии Free каждый маршрут /api/v1/defender/* отвечает 403, а пункт Defender вообще не появляется в боковом меню панели — его нет, а не «есть, но отключено». На Пробном, Pro и Business он есть.

IP-Defender NexusPanel делает всё это за вас: следит за каждым фронтинг-хостом, определяет блокировку и заменяет адрес на рабочий — автоматически или в один клик. Открывается из Панель → Defender, устроенного как конвейер:

ГруппаЧто там
Start hereOverview — карта состояния, страница по умолчанию
PipelineSources (URL подписок конкурентов — для анализа), ② IP Pool (проверяемые адреса-кандидаты), ③ Hosts (ваши действующие фронтинг-записи — сюда же добавляется хост за Cloudflare)
InfrastructureShield (доска статусов с карточкой на каждого провайдера — клик по карточке открывает страницу провайдера) и Setup (где вы добавляете API-ключи провайдеров)

Использовать все провайдеры не обязательно. Начните с одного — Cloudflare проще всего и бесплатен — и добавляйте остальные позже, если нужна избыточность или вы обслуживаете регионы с разной картиной блокировок.

IP-Defender

IP-Defender — это фоновая задача, которая непрерывно проверяет, работает ли ещё каждый фронтинг-хост. Она не ждёт жалобы от клиента.

  1. Healthy (здоров) — хост опрашивается и отвечает нормально.
  2. Suspect (подозрителен) — опросы начинают проваливаться. Одна неудачная проверка ничего не запускает; нужна устойчивая серия сбоев, прежде чем защитник воспримет это всерьёз — так короткий сетевой сбой не приведёт к лишней замене.
  3. Blocked (заблокирован) — сбои продолжаются. Защитник выбирает рабочий адрес того же вида (хост Cloudflare заменяется только на другой адрес Cloudflare, хост AWS — только на другой AWS; смешивание видов ломает сертификат, который ожидает клиент) и обновляет его автоматически.
  4. Cooldown (охлаждение) — после замены старый адрес какое-то время не используется повторно, чтобы хост не «дёргался» туда-сюда.
Можно заменить и вручную
На каждой странице провайдера в Shield есть своё действие для ротации/замены (формулировка отличается: Swap front, Rotate account, Rotate IP…). Если вы уже знаете, что хост заблокирован — клиент пожаловался, или вы сами проверили — не обязательно ждать автоматический детектор.
Fastly и Bunny не умеют быстро ротироваться
Cloudflare, AWS и Google могут переключиться на свежий адрес за секунды. Fastly и Bunny — нет: если их edge заблокирован, вы пересоздаёте CDN/связку с новыми edge-IP, а не получаете мгновенную замену. Учитывайте это при выборе провайдеров для рынка с частыми блокировками.

Поскольку Xray сам по себе не пишет трафик в разрезе по хостам, защитник опирается на активные опросы, а не на графики трафика. Это нормально — вы увидите время «последней проверки» на каждом хосте, а не счётчики трафика в реальном времени.

Cloudflare

Самый простой провайдер для старта — бесплатного тарифа достаточно для фронтинга. Через edge-узлы Cloudflare проходит огромное количество обычных сайтов, поэтому их блокировка задевает много легитимного трафика, и сети на это неохотно идут. Cloudflare в NexusPanel решает две разные задачи, и открываются они по-разному:

  1. В Cloudflare создайте API-токен с правом редактирования DNS для домена, через который будете фронтить.
  2. Панель → DefenderSetup → добавьте учётные данные, провайдер cloudflare, вставьте API-токен.
  3. Фронтинг самого VPN-трафика: Панель → DefenderHosts (Pipeline, шаг 3) → добавьте хост, указывающий на ваш домен за Cloudflare (DNS-запись с «оранжевым облаком»). Отдельную дистрибуцию создавать не нужно — Cloudflare это просто DNS + прокси, и IP-Defender следит за этим хостом как за любым другим.
  4. Доступность ссылки на подписку: Панель → DefenderShield → карточка Cloudflare открывает отдельную страницу, которая ротирует домен, с которого раздаются ссылки на подписку (PRIMARY/STANDBY, с автоматическим escape, если этот домен заблокируют). Это другая задача, не связанная с фронтингом VPN-трафика — она про то, чтобы клиенты могли обновлять конфиг.

AWS CloudFront

CDN от Amazon — другой вендор, отличный от Cloudflare, и это важно: если вы используете оба, сети, заблокировавшей один, придётся отдельно разбираться и со вторым.

  1. В AWS создайте IAM-пользователя с правами CloudFront + Route 53 и сгенерируйте access key.
  2. Панель → DefenderSetup → добавьте учётные данные, провайдер aws, вставьте access key ID и secret.
  3. Панель → DefenderShield → карточка AWS CloudFront, чтобы создать дистрибуцию CloudFront и увидеть её текущий входной IP и статус.

Тарификация AWS CloudFront зависит от использования (в основном от исходящего трафика) — следите за ней, если гоните через неё серьёзный объём трафика.

Google (Cloud Run)

Фронтинг через инфраструктуру Google run.app — те же хостнеймы, что используют бесчисленные обычные приложения Cloud Run.

  1. В Google Cloud создайте сервисный аккаунт с правами Cloud Run + DNS и скачайте его JSON-ключ.
  2. Панель → DefenderSetup → добавьте учётные данные, провайдер google, вставьте ключ сервисного аккаунта.
  3. Панель → DefenderShield → карточка Google Cloud Run, чтобы развернуть и управлять фронтинг-сервисом.

Сервисы Cloud Run должны быть публично доступны, чтобы работать как фронт — панель делает это сама при развёртывании сервиса.

Fastly

Fastly — провайдер с подключением в один клик, точно как Cloudflare, AWS и Google: вы даёте edge-IP, панель строит всё остальное.

  1. В Fastly создайте API-токен с областью действия global (нужна, чтобы создавать CDN-сервисы).
  2. Панель → DefenderSetup → добавьте учётные данные, провайдер fastly, вставьте токен.
  3. Панель → DefenderShield → карточка Fastly → вставьте свои edge-IP Fastly (по одному на строку или через запятую) и нажмите Create CDN. Панель поднимет сервис Fastly, настроенный как ваш текущий, и сама подключит нужный inbound и по одному хосту на каждый edge-IP.

У Fastly нет быстрой ротации: если edge-IP заблокирован, заново запустите Create CDN с новыми edge-IP, а не ждите автоматическую замену.

Bunny CDN

Bunny работает иначе, чем остальные провайдеры: не панель создаёт CDN за вас, а вы создаёте его на bunny.net, а панель его адаптирует.

  1. На bunny.net создайте одну pull zone на тарифе Standard с включёнными WebSockets.
  2. Добавьте в эту pull zone правило для каждой ноды (Edge Rule): Host == bunny-<node>.<ваш-домен>, переопределяющее Origin URL на http://<ip-ноды>:2009 (inbound VLESS BUNNY WS этой ноды). Одно правило на каждую ноду.
  3. Панель → DefenderSetup → добавьте учётные данные, провайдер bunny, вставьте API-ключ вашего аккаунта Bunny.
  4. Панель → DefenderShield → карточка Bunny CDN → нажмите Auto-wire per node. Панель прочитает правила вашей pull zone, сопоставит каждый origin IP с нодой в панели и создаст по одному управляемому хосту Bunny на каждую совпавшую ноду. Перезапускайте при добавлении ноды или исправлении правила.
  5. Нажмите Refresh edge IPs, чтобы засеять опубликованные edge-IP Bunny в пул ротации.

Как и у Fastly, у Bunny нет быстрой ротации — заблокированный edge означает починку pull zone и повторный auto-wire, а не мгновенную замену.

Azure

Azure — это не CDN-фронт вроде остальных: он разворачивает ротируемую VM-ретранслятор (та же идея, что Middle-сервер, только Azure сам поднимает VM и меняет её IP), чтобы у заблокированной ноды появился свежий входной IP без изменений на самой ноде.

  1. Создайте Service Principal: az ad sp create-for-rbac --role Contributor --scopes /subscriptions/<id>.
  2. Панель → DefenderShield → карточка Azure → вставьте tenant ID, client ID, client secret и subscription ID, затем нажмите Verify & connect. У Azure своя форма учётных данных прямо здесь — она не проходит через Setup, как у остальных провайдеров.
  3. Выберите регион (панель предлагает вариант, определённый по вашим подпискам) и нажмите Create relay — это развернёт небольшую VM на Ubuntu со статическим IP, размер выбирается автоматически как самый дешёвый.
  4. Установите middle-агент на полученный IP и переведите его в промоут, как для любого middle-сервера (см. Middle-сервер → Первоначальная настройка).

Если IP ретранслятора позже заблокируют, нажмите Rotate IP на странице Azure, затем заново запустите установку middle-сервера на новом IP и перепроверьте из-под заблокированной сети.

Миграция с Marzban

Простыми словами
Уже используете Marzban? Это переносит всё в NexusPanel — ваших клиентов, настройки и даже их существующие ссылки — одной командой. Ваши клиенты ничего не делают и ничего не замечают. Инструмент сначала показывает каждое изменение и может быть отменён вплоть до финального шага, так что пробовать безопасно.

Инструмент nexus cli migrate переносит живую установку Marzban в NexusPanel без какой-либо перенастройки у конечных пользователей. Он работает на том же хосте, что и Nexus, читает каталог данных Marzban напрямую и использует атомарный конечный автомат из 9 этапов с полным откатом вплоть до команды finalize.

Совместимость JWT
Инструмент миграции извлекает JWT_SECRET_KEY Marzban и сохраняет его как MARZBAN_LEGACY_JWT_SECRET в окружении Nexus. Каждая существующая ссылка-подписка Marzban продолжает работать с первого дня — пользователям ничего не нужно импортировать заново.

Предварительные требования

  • Marzban версии 0.6.0–0.8.4 (официальный скрипт установки, marzban или marzban_cli)
  • NexusPanel установлен на том же хосте или может читать /var/lib/marzban/
  • Свободное место на диске для снимка SQLite-базы Marzban

Шаг 1: Пробный прогон

Всегда сначала делайте пробный прогон. Он делает снимок базы Marzban, повторяет каждый импорт в черновую копию и завершается за секунды. В Nexus или Marzban ничего не записывается.

bash
# Посмотреть, что было найдено
nexus cli migrate discover

# Репетиция: снимок + импорт + проверка на черновой БД, без побочных эффектов
nexus cli migrate run --dry-run

Прочтите отчёт о пробном прогоне в /var/lib/nexus/migration/dryrun-<ts>.json. Подтвердите число пользователей, список администраторов и что MARZBAN_LEGACY_JWT_SECRET был извлечён. Исправьте все отмеченные ошибки перед продолжением.

Шаг 2: Боевое переключение

bash
# Боевой прогон — останавливает Marzban, импортирует, перезапускает Nexus
nexus cli migrate run --yes

Критический путь (MARZBAN_STOP → NEXUS_RESTART) занимает ~15–30 секунд. VPN-трафик нод продолжается без перерыва — ноды работают независимо от панели. Недоступен лишь ненадолго эндпоинт URL подписки.

Если VERIFY не проходит, срабатывает автооткат: конфигурации Nexus восстанавливаются, а Marzban перезапускается. Проверьте docker logs nexus-panel --tail 200, чтобы найти первопричину, затем перезапустите.

bash
# После наблюдения за продакшеном в течение нескольких часов:
nexus cli migrate finalize    # освобождает снимок, закрывает прогон

# Если нужно отменить (только до finalize):
nexus cli migrate rollback

Что переносится

ДанныеПереноситсяЗаметки
Пользователи (имя, трафик, срок)ДаВсе профили, квоты, UUID сохраняются
Прокси / протоколы пользователейДаVMess, VLESS, Trojan, Shadowsocks
Учётные записи администраторовДаПароли переносятся
Хосты (прокси-точки)ДаВсе строки-хосты копируются, поля только для Nexus по умолчанию выключены
Inbound-ы XrayДаКопируются из xray_config.json Marzban
Токен Telegram-бота, флаги NOTIFY_*ДаЗаписываются в .env Nexus
JWT-секрет (совместимость sub URL)ДаСохраняется как MARZBAN_LEGACY_JWT_SECRET — существующие sub URL продолжают работать
История напоминаний-уведомленийДаПредотвращает повторную отправку уведомлений «истекает через 3 дня»
Конфигурации нодНетNexus использует порты 62060/62061; добавьте ноды заново через панель с новым сертификатом
Routing/dns/outbounds XrayНетТолько inbound-ы; вставьте свои блоки в Настройки → редактор ядра после миграции
Хосты Hysteria2НетВ Marzban нет hy2 — добавьте через Панель → Хосты после миграции

Чек-лист после миграции

После завершения nexus cli migrate run --yes CLI выводит таблицу перенесённых хостов. Проверьте их, а затем:

  1. Проверьте старый URL-подписку Marzban — он должен вернуть валидный конфиг (проверка совместимости JWT)
  2. Проверьте число пользователей: docker exec nexus-panel sqlite3 /var/lib/panel/db.sqlite3 'SELECT COUNT(*) FROM users;'
  3. Выполните nexus cli migrate post-cutover, чтобы найти оставшиеся демоны Marzban (marzguard, cron-хуки certbot)
  4. Если используете Hysteria2: добавьте inbound + по одному хосту на ноду (см. раздел Hysteria2)
  5. Добавьте ноды заново через Панель → Ноды (новый сертификат, порты 62060/62061)
  6. Выполните nexus cli migrate finalize, чтобы освободить снимок, когда всё стабильно
bash — быстрая проверка
# Здоровье
curl -sk https://<your-domain>/api/v1/health

# Старый sub URL должен вернуть 200 с содержимым конфига
curl -sk "https://<your-domain>/sub/<marzban-token>" | head -c 200

# Поиск остатков Marzban
nexus cli migrate post-cutover

Миграция с Remnawave

Главное преимущество
Существующая ссылка-подписка каждого клиента продолжает работать. В Remnawave ссылка использует непрозрачный короткий идентификатор — NexusPanel сохраняет его при переносе, поэтому старый URL /sub/<token> резолвится и после миграции, клиентам не нужно ничего перенастраивать.

Инструмент nexus cli migrate remnawave подключается к живой панели Remnawave по её API (URL и логин/пароль администратора) и импортирует пользователей в NexusPanel.

bash
# По умолчанию — пробный прогон: подключается, извлекает и показывает, что будет
# импортировано и какие имена конфликтуют, ничего не пишет
nexus cli migrate remnawave run --url https://ваша-remnawave-панель --username ADMIN --password ...

# Применить изменения
nexus cli migrate remnawave run --url https://ваша-remnawave-панель --username ADMIN --password ... --run

--yes нужен, только если такое имя пользователя уже есть в NexusPanel — без него боевой прогон откажется выполняться, а не перезапишет данные. --insecure пропускает проверку TLS-сертификата (для Remnawave с самоподписанным сертификатом). --page-size (по умолчанию 250) задаёт размер страницы при обращении к API Remnawave.

bash
# Откат — удаляет ровно тех пользователей и алиасы, которые создал прогон
nexus cli migrate remnawave rollback
ДанныеПереноситсяЗаметки
Пользователи, лимиты и израсходованный трафикДаСрок действия и статус тоже переносятся
Учётные данные по протоколамДаVLESS UUID, пароль Trojan, пароль Shadowsocks
Ссылка-подпискаДаНепрозрачный short-id Remnawave сохраняется как алиас — старый URL продолжает работать
Telegram ID пользователяНетВ NexusPanel у пользователя нет такого поля — инструмент выводит предупреждение
Хосты и нодыНетНастраиваются на стороне NexusPanel; уже перенесённые учётные данные пользователей сразу работают с ними

Безопасность

Двухфакторная аутентификация (2FA)

NexusPanel поддерживает 2FA на базе TOTP (совместимо с Google Authenticator, Authy и т. д.):

  1. Перейдите в Настройки в панели
  2. Нажмите Enable 2FA
  3. Отсканируйте QR-код приложением-аутентификатором
  4. Введите 6-значный код для подтверждения
  5. Сохраните резервные коды в безопасном месте

Через API:

bash
# Сгенерировать TOTP-секрет и резервные коды
curl -X POST /api/v1/admin/2fa/setup -H "Authorization: Bearer TOKEN"

# Активировать 2FA (укажите TOTP-код для проверки)
curl -X POST /api/v1/admin/2fa/enable \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"code": "123456"}'

# Вход с 2FA
curl -X POST /api/v1/admin/token \
  -H "X-TOTP-Code: 123456" \
  -d "username=admin&password=admin&grant_type=password"

Защита капчей

Защитите страницу входа от атак перебором с помощью капчи:

Cloudflare Turnstile

env
CAPTCHA_PROVIDER="turnstile"
TURNSTILE_SITE_KEY="0x4AAAAAAA..."
TURNSTILE_SECRET_KEY="0x4AAAAAAA..."

Встроенная капча

env
CAPTCHA_PROVIDER="builtin"

Встроенная капча не требует внешних сервисов и генерирует простые математические задачи.

Блокировка входа

Эндпоинт входа защищён блокировкой по IP, она включена по умолчанию:

env
LOGIN_LOCKOUT_THRESHOLD=10
LOGIN_LOCKOUT_DURATION_MINUTES=30

# Не подключён: не читается кодом, задавать его бессмысленно.
LOGIN_RATE_LIMIT="10/minute"

После 10 неудачных попыток с одного IP клиента этот IP блокируется на POST /api/v1/admin/token на 30 минут. Блокировка хранится в памяти (в рамках процесса) и сбрасывается при перезапуске сервера.

LOGIN_RATE_LIMIT показан выше только потому, что он есть в поставляемых файлах .env. Он не реализован — его никто не читает, и он не ограничивает число попыток входа в минуту. Настраивайте вместо него LOGIN_LOCKOUT_THRESHOLD.

SSL / TLS

Для продакшен-развёртываний всегда используйте HTTPS. Варианты:

  • Прямой SSL — задайте UVICORN_SSL_CERTFILE и UVICORN_SSL_KEYFILE
  • Обратный прокси — используйте Nginx или Caddy впереди с терминацией SSL
  • Cloudflare — проксируйте через Cloudflare в режиме Full (Strict) SSL

Пример обратного прокси Nginx

nginx
server {
    listen 443 ssl http2;
    server_name panel.example.com;

    ssl_certificate     /etc/letsencrypt/live/panel.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/panel.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

FAQ

Как сменить пароль администратора

Вариант 1: Обновите переменную окружения SUDO_PASSWORD и перезапустите панель.

Вариант 2: Используйте API:

bash
curl -X PUT /api/v1/admin/admin \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"password": "newSecurePassword123"}'

Как сделать резервную копию

SQLite

bash
# Сначала остановите панель для чистой копии
docker compose stop panel
cp /var/lib/nexuspanel/db.sqlite3 /backups/db-$(date +%Y%m%d).sqlite3
docker compose start panel

# Или используйте онлайн-бэкап SQLite (без простоя)
sqlite3 /var/lib/nexuspanel/db.sqlite3 ".backup /backups/db-$(date +%Y%m%d).sqlite3"

PostgreSQL

bash
docker compose exec db pg_dump -U nexus nexuspanel > /backups/db-$(date +%Y%m%d).sql
Совет
Также делайте резервные копии вашего .env, xray_config.json и любых своих шаблонов.

Как обновить

bash
cd /opt/nexuspanel

# Скачать последние образы
docker compose pull

# Перезапустить с новой версией
docker compose up -d

# Проверить логи на статус миграций
docker compose logs -f panel

Миграции базы данных выполняются автоматически при запуске. Всегда делайте резервную копию базы перед обновлением.

Как добавить свои шаблоны

Свои шаблоны позволяют управлять выводом подписки для разных клиентов:

  1. Создайте файлы шаблонов в каталоге шаблонов:
bash
mkdir -p /var/lib/nexuspanel/templates/clash
nano /var/lib/nexuspanel/templates/clash/custom.yml
  1. Укажите шаблон в .env:
env
CUSTOM_TEMPLATES_DIRECTORY="/var/lib/panel/templates/"
CLASH_SUBSCRIPTION_TEMPLATE="clash/custom.yml"

Шаблоны поддерживают синтаксис Jinja2 с доступом к данным пользователя, конфигам прокси и настройкам панели.

Настройка страницы подписки

Страница подписки для пользователя (показывается при открытии ссылки-подписки в браузере) полностью настраиваема:

  1. Скопируйте шаблон по умолчанию как отправную точку:
bash
cp -r /opt/nexuspanel/app/templates/subscription \
  /var/lib/nexuspanel/templates/subscription
  1. Отредактируйте /var/lib/nexuspanel/templates/subscription/index.html
  2. Задайте в .env:
env
SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html"

Доступные переменные шаблона включают: user, sub_url, clash_url, singbox_url, usage, expire_date и brand_name.


Документация NexusPanel — Сделано с заботой.