Блог Clearway

Marzban или 3x-ui, а может Remnawave: сравнение панелей VPN для оператора

Коротко

Один сервер и вы сами себе админ — 3x-ui: один Go-бинарник, база в /etc/x-ui/x-ui.db, встроенная подписка на 2096, старт за 10 минут, от 512 МБ RAM. Три и больше нод, нужны шаблоны подписок под клиентов — Marzban: docker, marzban-node по 62050/62051, Jinja2-шаблоны по User-Agent; честная оговорка — темп релизов упал, это уже не «панель на вырост». Строите сервис с биллинг-ботом, лимитом устройств и автоматизацией — Remnawave: API-first, вебхуки, HWID из коробки, но Postgres + Valkey, от ~2 ГБ RAM и breaking changes между версиями. Спор «3х или Marzban» решается одним вопросом: сколько у вас будет серверов через полгода — в 3x-ui мультиноды нет вообще. И ни одна панель не спасает от блокировки IP ноды: это отдельный слой задачи, транспортный.

Архитектура: где проходит настоящая граница

Все три панели решают одну задачу — управляют пользователями Xray-core и раздают подписки. Сравнение панелей VPN осмысленно начинать не с интерфейса, а с того, что вам придётся эксплуатировать в 3 часа ночи.

3x-ui (форк MHSanaei от x-ui) — один Go-бинарник + SQLite. Панель и Xray на одном сервере, панель сама пишет конфиг и дёргает Xray API. Кроме systemd не нужно ничего.

bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
x-ui # меню: порт панели, basePath, логин, SSL
ls -la /etc/x-ui/x-ui.db # вся база сервиса — один файл

Marzban — Python/FastAPI в Docker, SQLite по умолчанию или MySQL/MariaDB. Панель отделена от ядра: локальный Xray плюс сколько угодно marzban-node по TLS с клиентскими сертификатами.

sudo bash -c "$(curl -sL https://github.com/Gozargah/Marzban-scripts/raw/master/marzban.sh)" @ install
marzban cli admin create --sudo
# конфиг: /opt/marzban/.env, docker-compose.yml
# данные: /var/lib/marzban/ (xray_config.json, templates/, db)

Remnawave — TypeScript/NestJS, обязательные PostgreSQL и Valkey/Redis, отдельный контейнер страницы подписки, агент remnanode на каждом сервере. После docker compose up -d вы увидите не один процесс, а четыре-пять контейнеров (backend, db, valkey, subscription-page) плюс внешний reverse proxy — панель наружу сама не смотрит. Пошаговая установка разобрана у нас в отдельном материале, здесь важен сам факт: это распределённая система, а не «программа на сервере».

Практический вывод: 3x-ui — «панель = сервер». Marzban и Remnawave — «панель = центр управления, серверы = ноды». Это и есть главная развилка.

Мультинода: где 3x-ui упирается в потолок

У 3x-ui мультиноды нет. Совсем. Пять серверов — это пять независимых панелей, пять баз, пять раз руками завести клиента. Обходные пути существуют (склеить подписку своим скриптом, продублировать inbound с теми же UUID), но это самодельный костыль, который чинить будете вы.

Marzban: нода — отдельный контейнер, панель ходит на два порта.

# /opt/marzban-node/docker-compose.yml
services:
 marzban-node:
 image: gozargah/marzban-node:latest
 restart: always
 network_mode: host
 environment:
 SSL_CLIENT_CERT_FILE: "/var/lib/marzban-node/ssl_client_cert.pem"
 SERVICE_PROTOCOL: "rest"
 volumes:
 - /var/lib/marzban-node:/var/lib/marzban-node

62050 (сервисный) и 62051 (Xray API) открываем только для IP панели — это не паранойя, открытый 62051 отдаёт статистику и управление ядром:

ufw allow from <IP_ПАНЕЛИ> to any port 62050,62051 proto tcp

Важно: если Xray на ноде запущен в Docker с network_mode: host, ufw его не закрывает при обычной установке — правила для контейнерных портов пишутся в цепочку DOCKER-USER. Проверяйте iptables -L DOCKER-USER -n после настройки, а не только ufw status.

Remnawave: агент получает сертификат панели одной переменной и слушает 2222 (наружу выставлять не нужно).

# /opt/remnanode/.env
APP_PORT=2222
SSL_CERT="eyJub2RlQ2VydFBlbSI6..." # копируется из панели при создании ноды

Честное сравнение: у Marzban мультинода проверена годами и стабильна, но xray_config.json один на все ноды — разные транспорты на разных серверах делаются тегами и исключениями, это неудобно и легко разъезжается. В Remnawave профиль конфигурации назначается по нодам, а пользователи привязаны к сквадам (в 2.x — internal squads, раньше это были просто inbounds) — гибче и меньше ручной синхронизации.

Подписки и клиенты: где сервис ломается на практике

Подписка — это то, что видит клиент, и оттуда приходит большая часть тикетов.

3x-ui. Встроенный subscription-сервис на отдельном порту (по умолчанию 2096), два эндпоинта: /{subPath}/{id} — base64-список, /{subJsonPath}/{id} — JSON для клиентов, которые его понимают. Настраивается в Panel Settings → Subscription. Заголовки profile-title и subscription-userinfo панель проставляет сама, шаблонов под конкретные приложения нет.

Marzban. Самая гибкая шаблонизация из трёх: Jinja2 в /var/lib/marzban/templates/ и выдача по User-Agent — Clash получает YAML, sing-box получает JSON, остальным уходит base64.

# /opt/marzban/.env
CUSTOM_TEMPLATES_DIRECTORY="/var/lib/marzban/templates/"
SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html"
CLASH_SUBSCRIPTION_TEMPLATE="clash/default.yml"
SUB_PROFILE_TITLE="MyService"
SUB_UPDATE_INTERVAL="6"

Remnawave. Страница подписки — отдельный сервис (remnawave-subscription-page, по умолчанию 3010) с JSON-шаблонами под типы клиентов, глубокой интеграцией с Happ (deeplink, роутинг, шифрование ссылки) и HWID-лимитом устройств. Это единственная из трёх, где «не больше N устройств» встроено, а не прикручено сбоку.

Общая боль, от панели не зависящая: клиенты кэшируют подписку. По наблюдениям, iOS-приложения держат старый список часами после смены нод. Первое, что надо сделать на фронте:

location /sub/ {
 proxy_pass http://127.0.0.1:3010; # remnawave-subscription-page; для 3x-ui — 2096
 add_header Cache-Control "no-store, no-cache, must-revalidate" always;
 proxy_hide_header Etag;
}

Если и после этого клиент показывает старые серверы — помогает только переподписка: удалить ссылку и добавить заново. Это поведение приложения, а не баг панели.

API, боты и биллинг: чем автоматизировать

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

Marzban — OpenAPI-схема на /docs, токен по паролю админа, объект первого класса — пользователь:

TOKEN=$(curl -s -X POST 'https://panel.example.com/api/admin/token' \
 -d 'username=admin&password=***' | jq -r.access_token)

curl -s -X POST 'https://panel.example.com/api/user' \
 -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
 -d '{"username":"user_1042","proxies":{"vless":{"flow":""}},
 "inbounds":{"vless":["VLESS-XHTTP"]},
 "data_limit":107374182400,"expire":1790000000,"status":"active"}'

Remnawave — API-first: всё, что делает веб-морда, доступно снаружи. Токен создаётся в панели, дальше POST /api/users с username, trafficLimitBytes, expireAt, activeInternalSquads, плюс вебхуки на события (истёк, превысил лимит) — главный аргумент, если вы пишете свой шоп-бот. Оговорка из практики: если панель прикрыта дополнительной защитой на реверс-прокси (кастомный заголовок или cookie-авторизация), бот обязан слать её тоже, иначе получите 403 при рабочих кредах — это самая частая «непонятная» поломка интеграции.

3x-ui — API есть, но он вторичен: POST /login за cookie, дальше /panel/api/inbounds/list и /panel/api/inbounds/addClient, где клиент передаётся строкой JSON внутри JSON. Работает, но писать биллинг поверх больно: вы оперируете inbound'ами, а не пользователями, и любое изменение конфига требует переписывать settings целиком.

Готовые магазины-боты: под Marzban их исторически больше (наследие большого сообщества), под Remnawave экосистема моложе, но растёт быстрее и почти вся на актуальном API. Под 3x-ui есть встроенный телеграм-бот самой панели — он про уведомления и бэкапы, а не про продажи.

Сводная таблица: 3x-ui vs Marzban vs Remnawave

Данные — на лето 2026, перед установкой сверяйтесь с актуальными релизами; требования по RAM — по наблюдениям на боевых установках, а не из документации.

Критерий3x-uiMarzbanRemnawave
СтекGo, один бинарникPython/FastAPI, DockerTypeScript/NestJS, Docker
БазаSQLiteSQLite / MySQL / MariaDBPostgreSQL + Valkey
RAM панелиот 512 МБот 1 ГБот ~2 ГБ
Мультиноданетда (62050/62051)да (remnanode, 2222)
Разные конфиги по нодамн/дплохо: один xray_configда, профили конфигураций
Шаблоны подписокминимумJinja2 по User-AgentJSON-шаблоны, Happ
Лимит устройств (HWID)нетнетвстроен
API под биллингесть, неудобныйхороший, OpenAPIлучший, вебхуки
Телеграм-ботвстроен (алерты, бэкап)внешниевнешние
Темп разработкиактивныйзамедлилсябыстрый, breaking changes
Порог входанизкийсреднийвысокий
Кому1 сервер, старт2–10 нод, работающий сервиссервис на вырост

Чего обычно не учитывают в спорах «сравнение панелей VPN» — цену ошибки. 3x-ui теряется вместе с сервером, но и восстанавливается копированием одного файла. Remnawave требует уважения к миграциям: docker compose pull на смене major-версии без дампа Postgres — прямой путь к простою, а откат назад по схеме БД не предусмотрен.

Эксплуатация: бэкапы, обновления, миграция

О чём не думают при выборе и о чём жалеют через полгода.

3x-ui — бэкап это копия файла:

systemctl stop x-ui
cp /etc/x-ui/x-ui.db /root/backup/x-ui-$(date +%F).db
systemctl start x-ui

По наблюдениям, SQLite начинает подтормаживать на нескольких сотнях активных клиентов с частым обновлением статистики трафика — это сигнал, что пора менять панель, а не тюнить её.

Marzban — забираем и конфиги, и данные:

tar czf /root/marzban-$(date +%F).tar.gz /opt/marzban /var/lib/marzban
marzban restart && marzban logs -f

При тысяче с лишним пользователей переезжайте с SQLite на MariaDB (SQLALCHEMY_DATABASE_URL в .env), иначе поймаете database is locked на записи статистики.

Remnawave — только логический дамп, копии volume недостаточно:

docker ps --format '{{.Names}}' | grep db # уточните имя контейнера
docker compose exec -T remnawave-db \
 pg_dump -U postgres -d postgres > /root/remnawave-$(date +%F).sql

Правило простое: дамп до docker compose pull, всегда, и читать CHANGELOG перед сменой минорной версии — там регулярно бывают несовместимые изменения API и схемы.

Миграция. Community-скрипты Marzban → Remnawave существуют и в целом переносят пользователей, UUID, лимиты и даты. Официальной поддержки у них нет, поэтому схема одна: поднять Remnawave параллельно, перелить пользователей, выдать новые ссылки-подписки и держать старую панель живой хотя бы неделю. Ссылки при переезде меняются в любом случае — домен и формат страницы подписки другие. Обратной миграции (Remnawave → Marzban) практически нет, и это стоит считать фактором блокировки выбора.

Чего не решает ни одна панель: заблокированный IP ноды

Панель управляет пользователями и подписками. К доступности IP она отношения не имеет: когда ТСПУ выкашивает адрес ноды, ни 3x-ui, ни Marzban, ни Remnawave не помогут — нужен вход на «белом» домене, чтобы клиент ходил на whitelist-адрес, а тот уже — на вашу ноду. Этим и занимается Clearway: CDN-фронт для нод операторов; техника ниже применима и без него.

Один техфакт, который экономит часы отладки: у Yandex CDN нет POST, поэтому аплинк XHTTP уходит методом GET, а GET разрешён только в режиме packet-up. Если mode не задан явно, соединение либо не встаёт, либо рвётся на первом крупном запросе — отсюда классическое «в одном приложении работает, в другом нет». Минимальный инбаунд:

{
 "tag": "xhttp-cdn",
 "listen": "127.0.0.1",
 "port": 8443,
 "protocol": "vless",
 "settings": { "clients": [], "decryption": "none" },
 "streamSettings": {
 "network": "xhttp",
 "security": "none",
 "xhttpSettings": {
 "host": "front.example.com",
 "path": "/tunnel",
 "mode": "packet-up"
 }
 }
}

Куда класть: 3x-ui — вкладка Inbounds, транспорт xhttp; Marzban — /var/lib/marzban/xray_config.json или редактор в панели, затем marzban restart; Remnawave — профиль конфигурации ноды. Детальный разбор транспорта, TLS на фронте и защиты origin у нас в отдельных материалах про XHTTP через CDN.

Два правила ломают больше всего установок. Первое: extra на ноде и в клиенте должны совпадать — панель генерирует ссылку из своего представления конфига, и если вы правили xhttpSettings руками мимо панели, клиент получит не тот extra и соединение не встанет. Второе: не добавляйте экзотические obfuscation-поля — они ломают совместимость между версиями Xray, нода на свежем ядре и клиент полугодовой давности просто молча не договорятся. Минимальный набор полей живёт дольше.

Частые вопросы

3х или Marzban для первого сервера — что ставить новичку?

3x-ui. Один бинарник, SQLite, установка и настройка подписки — минут десять. Marzban даёт мультиноду и шаблоны, но за это вы платите Docker'ом, отдельной БД и более длинным списком того, что может сломаться. Если второго сервера не планируется, усложнять незачем.

Marzban или 3x ui, если серверов уже три?

Marzban. В 3x-ui три сервера — это три отдельные панели и три ручных заведения каждого клиента; рассинхрон начинается на первой же неделе. Но если вы только запускаете сервис и уже знаете, что будет биллинг-бот и лимит устройств, смотрите сразу на Remnawave — иначе мигрировать придётся через полгода.

Marzban мёртв? Стоит ли начинать на нём в 2026?

Не мёртв, но по наблюдениям темп релизов заметно упал против 2023–2024, а часть сообщества ушла в форки-наследники. Работающие установки продолжают работать, боты и шаблоны никуда не делись. Для нового проекта «на вырост» я бы выбрал Remnawave; для существующей инсталляции срочной причины мигрировать нет.

Сколько пользователей держит каждая панель?

Точных цифр никто не публикует, поэтому по наблюдениям: 3x-ui на SQLite комфортно живёт до нескольких сотен активных клиентов на сервер, Marzban на SQLite — примерно до тысячи, дальше нужен MariaDB/MySQL. Remnawave на Postgres упирается уже не в панель, а в CPU и сеть нод. Узкое место почти всегда — запись статистики трафика, а не число строк в базе.

Какая панель лучше работает с XHTTP за CDN?

Все три одинаково: за транспорт отвечает Xray-core, а не панель. Разница только в удобстве — в Remnawave профили конфигураций назначаются по нодам, в Marzban конфиг общий на все ноды, в 3x-ui inbound правится прямо в UI. Требование от выбора не зависит: если CDN не умеет POST, аплинк идёт GET, значит в xhttpSettings обязателен явный mode packet-up, а extra на ноде и в клиенте должны совпадать.

Панель спасёт, если IP ноды заблокировали?

Нет. Панель — это учёт пользователей и раздача подписок. При блокировке адреса помогает только смена IP или фронт на «белом» домене: клиент ходит на whitelist-адрес CDN, CDN ходит на вашу ноду. Панель при этом остаётся любой — менять её в такой ситуации бессмысленно.

Можно ли перенести пользователей с Marzban на Remnawave без потери подписок?

Пользователей, UUID, лимиты и даты окончания переносят community-скрипты. Сами ссылки-подписки сохранить нельзя: домен и формат страницы подписки другие, клиентам придётся переподписаться. Рабочая схема — поднять Remnawave параллельно, перелить базу, разослать новые ссылки и не гасить старую панель минимум неделю.

Whitelisted-вход для вашего VPN-сервиса

Clearway даёт «белый» CDN-вход перед вашей нодой — устойчивый к троттлингу операторов. Первые 10 ГБ бесплатно, без карты.

Попробовать →