Когда VPN-серверов становится несколько, а пользователей десятки и сотни, Marzban начинает тесниться, и многие переходят на Remnawave, панель, рассчитанную на много серверов сразу. Переезд не требует заново создавать пользователей и рассылать им новые ключи. У Remnawave есть официальная утилита remnawave-migrate, которая забирает пользователей из Marzban через его API и создаёт их в Remnawave. В этой статье мы разберём, что она переносит, как провести перенос без простоя и как сделать так, чтобы старые ссылки подписки продолжили работать.
Весь переезд мы повторили на нашем сервере. Marzban на нём установлен нашим скриптом, утилита переноса версии 2.1.0, Remnawave 3.4.5, страница подписки 8.0.0.
Как устроен переезд
Панель VPN хранит две разные группы сведений. Первая относится к пользователям. Это имена, идентификаторы для протоколов, лимиты трафика и сроки действия. Вторая относится к самим серверам. Это настройки Xray, порты, ключи Reality и сайты для маскировки. Утилита переносит только первую группу, а серверную часть в Remnawave вы настраиваете заново, и это логично, ведь Remnawave устроен иначе. В нём настройки подключений хранятся в профилях конфигурации, а сами подключения работают на отдельных нодах.
Для каждого пользователя утилита переносит имя, статус, UUID для VLESS, пароли для Trojan и Shadowsocks, лимит трафика и способ его сброса, дату окончания, дату создания и описание. Из адреса подписки Marzban она получает короткий идентификатор подписки в Remnawave. Израсходованный трафик в этом списке не значится, поэтому счётчики в Remnawave начнутся с нуля. Если в Marzban у пользователя стоял ежегодный сброс трафика, в Remnawave он станет «без сброса», потому что такого периода там нет. Пользователи без срока действия получат дату 31.12.2099, в панели она отображается как бесконечность.
Есть и одна неочевидная деталь. Remnawave не принимает имена короче шести символов, поэтому утилита дописывает к коротким именам подчёркивания. В нашей проверке alice стала alice_, а bob превратился в bob___. На подписки это не влияет, старые ссылки находят таких пользователей и после переименования.
Так как UUID пользователей сохраняются, а серверная часть создаётся заново, устройствам после переезда нужно получить новую конфигурацию. Проще всего это сделать через подписку. Если подписка сохранена, приложение само заберёт новые настройки при следующем обновлении, и пользователю ничего не придётся делать.
Что понадобится
- Работающий Marzban, из которого будем переносить пользователей.
- Готовая панель Remnawave с хотя бы одной нодой, профилем VLESS Reality и хостом. Если её ещё нет, установите по нашей инструкции. Проверьте, что подключение работает на тестовом пользователе, и только потом переносите остальных.
- Подключение по SSH к серверу Marzban. Утилиту удобнее всего запускать прямо на нём.
Шаг 1. Создайте токен API в Remnawave
Утилита создаёт пользователей через API Remnawave, и ей нужен токен.
- В панели Remnawave откройте Настройки и прокрутите страницу до блока Токены API.
- Нажмите кнопку + в правом нижнем углу блока.
- Введите название, например
migrate, и срок действия в днях. Для переезда хватит одного дня. - Выберите набор прав Полный доступ и нажмите Создать.
- Скопируйте токен. Панель показывает его только один раз.

Создание токена API
Токен даёт полный доступ к панели
Храните его как пароль и удалите после переезда, если он больше не нужен.
Шаг 2. Узнайте UUID сквада
В Remnawave пользователь получает подключения только через сквад, в который входит профиль конфигурации. Если перенести пользователей без сквада, их подписки окажутся пустыми. Поэтому сразу при переносе добавим их в сквад Default-Squad, в котором у вас включён профиль VLESS Reality. UUID сквада можно получить через API.
# Вместо ТОКЕН и panel.ваш-домен.com подставьте свои значения
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
# Скачиваем и распаковываем версию 2.1.0
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. Сделайте пробный перенос
Сначала перенесите несколько последних пользователей, чтобы убедиться, что всё настроено верно. Если Marzban установлен нашим скриптом, логин и пароль администратора лежат в файле /root/marzban-credentials.txt, и команда ниже сама возьмёт их оттуда.
cd /opt/remnawave-migrate
# Данные Marzban из файла, который создал наш скрипт
export PANEL_TYPE=marzban
export PANEL_URL=http://127.0.0.1:ПОРТ_ПАНЕЛИ
export PANEL_USERNAME=$(awk '/^Логин:/ {print $2}' /root/marzban-credentials.txt)
export PANEL_PASSWORD=$(awk '/^Пароль:/ {print $2}' /root/marzban-credentials.txt)
# Данные Remnawave
export REMNAWAVE_URL=https://panel.ваш-домен.com
export REMNAWAVE_TOKEN=ТОКЕН
export INTERNAL_SQUAD=UUID_СКВАДА
# Переносим только 5 последних пользователей
./remnawave-migrate --last-users=5 --preserve-status --preserve-subhashВместо ПОРТ_ПАНЕЛИ укажите порт из адреса панели Marzban, его скрипт вывел в конце установки. Если Marzban ставили иначе, укажите в PANEL_URL адрес, по которому открываете панель, а логин и пароль впишите вручную.
Два параметра в конце команды важны.
--preserve-statusсохраняет статусы пользователей. Без него все перенесённые пользователи станут активными, даже если в Marzban они были отключены или у них закончился срок.--preserve-subhashсохраняет идентификаторы подписок Marzban. Он нужен, чтобы старые ссылки подписки можно было продолжать обслуживать, об этом ниже.
Утилита пишет в журнал каждого обработанного пользователя и в конце сообщает Migration completed successfully!. Строки was sanitized to означают, что имя было дополнено до шести символов.

Пробный перенос трёх пользователей
Откройте в Remnawave раздел Пользователи и проверьте перенесённых пользователей. У них должны совпадать лимиты трафика, даты окончания и статусы, а в блоке внутренних сквадов должен стоять Default-Squad.

Пользователи после переноса
Шаг 5. Перенесите всех пользователей
Если пробный перенос прошёл успешно, запустите утилиту без ограничения числа пользователей. Переменные из прошлого шага сохраняются, пока открыто то же окно терминала.
./remnawave-migrate --preserve-status --preserve-subhashУтилита обрабатывает пользователей пачками по 100 и сама учитывает тех, кто уже был создан при пробном переносе.
Шаг 6. Сохраните старые ссылки подписки
После переезда пользователям нужно получить подписку из Remnawave. Есть два пути.
Разослать новые ссылки. Это самый простой и надёжный вариант, если пользователей немного. Новая ссылка каждого пользователя есть в его карточке в Remnawave.
Продолжить обслуживать старые ссылки. Страница подписки Remnawave умеет понимать ссылки Marzban. Для этого ей нужен секретный ключ, которым Marzban подписывал свои ссылки. Если Marzban работает на SQLite, как после нашего скрипта, ключ можно получить одной командой.
# Если команда не найдена, установите её: apt install -y sqlite3
sqlite3 /var/lib/marzban/db.sqlite3 "SELECT secret_key FROM jwt LIMIT 1;"
Секретный ключ Marzban, на скриншоте он скрыт
Если Marzban работает на MySQL, выполните тот же запрос SELECT secret_key FROM jwt LIMIT 1; в его базе.
Затем установите страницу подписки по разделу «Страница подписки» нашей статьи про Remnawave и добавьте в её файл .env строки для старых ссылок.
MARZBAN_LEGACY_LINK_ENABLED=true
MARZBAN_LEGACY_SECRET_KEY=секретный_ключ_marzban
CUSTOM_SUB_PREFIX=subCUSTOM_SUB_PREFIX должен совпадать с путём подписок в Marzban, по умолчанию это sub. После изменения пересоздайте контейнер командой docker compose up -d --force-recreate. Страница подписки отвечает только через обратный прокси с HTTPS, поэтому её нужно опубликовать через Caddy, как описано в той же статье. Напрямую по HTTP она отказывает с ошибкой Reverse proxy and HTTPS are required в журнале.
Старые ссылки ведут на старый адрес
Ссылки Marzban указывают на адрес его сервера. После нашего скрипта они выглядят как http://IP_сервера:ПОРТ/sub/.... Если вы удаляете старый сервер, проще разослать пользователям новые ссылки.
Если старый сервер остаётся работать, перенаправьте его запросы /sub/ на новую страницу подписки. На сервере 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 вида http://IP_сервера:ПОРТ/sub/... после этого вернула подписку Remnawave для перенесённого пользователя, а ссылка отключённого пользователя ответила сообщением Subscription disabled.
Шаг 7. Отключите Marzban
Когда пользователи получили новую конфигурацию и подключаются через Remnawave, остановите Marzban.
marzban downНе удаляйте его сразу. Пусть сервер с остановленным Marzban полежит несколько дней, чтобы при необходимости можно было вернуться. Перед окончательным удалением сохраните копию папки /var/lib/marzban.
Частые вопросы
Утилита пишет ошибку авторизации в Remnawave
Проверьте токен и адрес панели в REMNAWAVE_URL. Если панель Remnawave закрыта дополнительной защитой Caddy, создайте ключ API в её портале авторизации и передайте его параметром --dest-headers="X-Api-Key:ключ".
У перенесённых пользователей пустая подписка
Пользователи не попали в сквад с профилем. Добавьте их в Default-Squad в панели Remnawave или перенесите заново с параметром --internal-squad. Также проверьте, что у хоста включена видимость.
Можно ли поменять способ сброса трафика для всех сразу
Да, параметр --preferred-strategy задаёт один способ для всех перенесённых пользователей. Возможные значения NO_RESET, DAY, WEEK и MONTH.
Перенесётся ли израсходованный трафик
Нет. Утилита переносит лимит трафика и способ его сброса, а счётчик израсходованного трафика в Remnawave начинается заново.
Наши ресурсы
Telegram-канал: https://t.me/f3cloud_news
Сайт хостинга: https://f3cloud.com