Переезд с Marzban на Remnawave без потери пользователей

Переносим пользователей из Marzban в Remnawave утилитой remnawave-migrate: токен API, UUID сквада, пробный и полный перенос, сохранение старых ссылок подписки через nginx. Debian и Ubuntu.

21 октября 2026 г.·5 мин чтения·remnawave, marzban, xray, migration

Когда серверов становится несколько, а пользователей — десятки, Marzban начинает тесниться, и обычно переходят на Remnawave. Заново создавать пользователей и рассылать ключи не нужно: официальная утилита remnawave-migrate забирает их из Marzban через API и создаёт в Remnawave. Ниже — что именно переносится, как сделать это без простоя и как оставить рабочими старые ссылки подписки. Проверено с remnawave-migrate 2.1.0 и Remnawave 3.4.x.

Сервер для панели можно взять на tanaka.host: Германия, Ubuntu или Debian при заказе, оплата по дням.

Что переносится, а что нет

Панель хранит две группы данных. Первая — про пользователей: имена, UUID, лимиты, сроки. Вторая — про серверы: конфиги Xray, порты, ключи Reality, сайты для маскировки. Утилита переносит только первую. Серверную часть в Remnawave вы настраиваете заново, потому что она устроена иначе — профили конфигурации и отдельные ноды.

По каждому пользователю переносятся: имя, статус, UUID для VLESS, пароли Trojan и Shadowsocks, лимит трафика и стратегия сброса, дата окончания, дата создания, описание. Из адреса подписки Marzban берётся короткий идентификатор подписки. Что не переносится и меняется:

Что Как будет в Remnawave
Израсходованный трафик Счётчики начинаются с нуля
Ежегодный сброс трафика Станет «без сброса», такого периода нет
Без срока действия Дата 31.12.2099, в панели показывается как бесконечность
Имена короче 6 символов Дополняются подчёркиваниями: alice → alice_, bob → bob___. Старые ссылки подписки таких пользователей находят

UUID сохраняются, но серверная часть новая, поэтому устройствам нужна новая конфигурация. Если у людей сохранена подписка — приложение само её обновит.

Что нужно

  • Работающий Marzban с известными логином и паролем администратора.
  • Готовая Remnawave: хотя бы одна нода, профиль VLESS Reality и хост. Проверьте на тестовом пользователе, что подключение работает, и только потом переносите остальных.
  • SSH на сервер Marzban — утилиту удобнее запускать там.

1. Токен API в Remnawave

Настройки → блок Токены API → +. Название migrate, срок — одного дня хватит, права — Полный доступ → Создать. Скопируйте токен сразу: панель показывает его один раз.

Токен даёт полный доступ к панели. Храните как пароль и удалите после переезда.

2. UUID сквада

В Remnawave пользователь получает подключения только через сквад с профилем. Перенесёте без сквада — подписки будут пустыми. Поэтому сразу добавим всех в Default-Squad, где включён ваш профиль Reality. UUID сквада — через API:

curl -s -H "Authorization: Bearer ТОКЕН" https://panel.ваш-домен.com/api/internal-squads \
  | python3 -c "import json,sys; [print(s['uuid'], s['name']) for s in json.load(sys.stdin)['response']['internalSquads']]"

Скопируйте UUID из строки с Default-Squad.

3. Утилита на сервере Marzban

mkdir -p /opt/remnawave-migrate && cd /opt/remnawave-migrate
wget https://github.com/remnawave/migrate/releases/download/v2.1.0/remnawave-migrate-v2.1.0-linux-amd64.tar.gz
tar -xf remnawave-migrate-v2.1.0-linux-amd64.tar.gz
./remnawave-migrate --help

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

4. Пробный перенос

Сначала пять последних пользователей, чтобы убедиться, что всё настроено правильно:

cd /opt/remnawave-migrate

export PANEL_TYPE=marzban
export PANEL_URL=http://127.0.0.1:8000
export PANEL_USERNAME=admin
export PANEL_PASSWORD='пароль_администратора_marzban'

export REMNAWAVE_URL=https://panel.ваш-домен.com
export REMNAWAVE_TOKEN=ТОКЕН
export INTERNAL_SQUAD=UUID_СКВАДА

./remnawave-migrate --last-users=5 --preserve-status --preserve-subhash

PANEL_URL — адрес, по которому открываете панель Marzban; 8000 — порт по умолчанию, если меняли UVICORN_PORT в /opt/marzban/.env, подставьте свой.

Два параметра в конце важны:

  • --preserve-status сохраняет статусы. Без него все перенесённые станут активными, включая отключённых и просроченных.
  • --preserve-subhash сохраняет идентификаторы подписок Marzban — без этого старые ссылки нельзя будет обслуживать.

Утилита пишет каждого пользователя в журнал и заканчивает строкой Migration completed successfully!. Строки was sanitized to — имя дополнено до шести символов. Откройте Пользователи в Remnawave и сверьте лимиты, даты, статусы и наличие Default-Squad.

5. Полный перенос

Переменные из прошлого шага живут, пока открыто то же окно терминала:

./remnawave-migrate --preserve-status --preserve-subhash

Утилита идёт пачками по 100 и пропускает тех, кто уже создан при пробном прогоне.

6. Старые ссылки подписки

Два пути.

Разослать новые ссылки. Самый простой и надёжный, если людей немного. Ссылка — в карточке каждого пользователя в Remnawave.

Продолжить обслуживать старые. Страница подписки Remnawave умеет понимать ссылки Marzban, если знает секретный ключ, которым Marzban их подписывал. Для SQLite:

sqlite3 /var/lib/marzban/db.sqlite3 "SELECT secret_key FROM jwt LIMIT 1;"

Если sqlite3 нет — apt install -y sqlite3. На MySQL — тот же запрос в базе Marzban.

Поставьте страницу подписки по разделу «Страница подписки» статьи про Remnawave и добавьте в её .env:

MARZBAN_LEGACY_LINK_ENABLED=true
MARZBAN_LEGACY_SECRET_KEY=секретный_ключ_marzban
CUSTOM_SUB_PREFIX=sub

CUSTOM_SUB_PREFIX должен совпадать с путём подписок в Marzban (по умолчанию sub). Пересоздайте контейнер: docker compose up -d --force-recreate. Страница отвечает только через обратный прокси с HTTPS, напрямую по HTTP — ошибка Reverse proxy and HTTPS are required в журнале.

Старые ссылки ведут на старый сервер. Они выглядят как http://IP_сервера:ПОРТ/sub/.... Если старый сервер удаляете — проще разослать новые ссылки.

Если старый сервер остаётся, перенаправьте /sub/ на новую страницу подписки. В nginx перед Marzban (например /etc/nginx/sites-available/marzban-panel) перед location / { добавьте, подставив домен страницы подписки:

    location /sub/ {
        proxy_pass https://sub.ваш-домен.com;
        proxy_set_header Host sub.ваш-домен.com;
        proxy_ssl_server_name on;
        proxy_ssl_name sub.ваш-домен.com;
    }
nginx -t && systemctl reload nginx

После этого старая ссылка Marzban отдаёт подписку Remnawave для перенесённого пользователя, а ссылка отключённого отвечает Subscription disabled.

7. Отключите Marzban

Когда люди получили новую конфигурацию и ходят через Remnawave:

marzban down

Не удаляйте сразу — пусть полежит несколько дней на случай отката. Перед окончательным удалением сохраните /var/lib/marzban, лучше по статье про резервные копии.

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

  • Ошибка авторизации в Remnawave. Проверьте токен и REMNAWAVE_URL. Если панель закрыта дополнительной защитой в Caddy, создайте ключ API в её портале авторизации и передайте --dest-headers="X-Api-Key:ключ".
  • У перенесённых пустая подписка. Не попали в сквад с профилем. Добавьте в Default-Squad вручную или перенесите заново с --internal-squad. Проверьте видимость хоста.
  • Один способ сброса трафика для всех. --preferred-strategy со значением NO_RESET, DAY, WEEK или MONTH.
  • Перенесётся ли израсходованный трафик. Нет, только лимит и стратегия сброса.