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

Когда серверов становится несколько, а пользователей — десятки, 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. - Перенесётся ли израсходованный трафик. Нет, только лимит и стратегия сброса.