Cuando ya tienes varios servidores VPN y decenas o cientos de usuarios, Marzban se queda pequeño, y muchos se pasan a Remnawave, un panel pensado para muchos servidores a la vez. Para mudarte no hace falta volver a crear los usuarios ni enviarles claves nuevas. Remnawave tiene una utilidad oficial, remnawave-migrate, que recoge los usuarios de Marzban a través de su API y los crea en Remnawave. En este artículo veremos qué transfiere, cómo hacer la migración sin cortes y cómo conseguir que los enlaces de suscripción antiguos sigan funcionando.
Hemos repetido toda la migración en nuestro servidor. Marzban está instalado en él con nuestro script, la utilidad de migración es la versión 2.1.0, Remnawave la 3.4.5 y la página de suscripción la 8.0.0.
Cómo funciona la migración
Un panel VPN guarda dos grupos de datos distintos. El primero tiene que ver con los usuarios. Son los nombres, los identificadores para los protocolos, los límites de tráfico y las fechas de caducidad. El segundo tiene que ver con los propios servidores. Son la configuración de Xray, los puertos, las claves de Reality y los sitios de camuflaje. La utilidad solo transfiere el primer grupo, y la parte del servidor la configuras de nuevo en Remnawave. Tiene sentido, porque Remnawave funciona de otra manera. En él, los ajustes de las conexiones se guardan en perfiles de configuración, y las conexiones en sí funcionan en nodos separados.
Para cada usuario, la utilidad transfiere el nombre, el estado, el UUID para VLESS, las contraseñas de Trojan y Shadowsocks, el límite de tráfico y su modo de reinicio, la fecha de caducidad, la fecha de creación y la descripción. A partir de la dirección de suscripción de Marzban obtiene el identificador corto de la suscripción en Remnawave. El tráfico consumido no está en esta lista, así que los contadores de Remnawave empezarán desde cero. Si en Marzban un usuario tenía un reinicio anual del tráfico, en Remnawave pasará a «sin reinicio», porque allí no existe ese periodo. Los usuarios sin fecha de caducidad recibirán la fecha 31/12/2099, que el panel muestra como infinito.
Hay además un detalle poco evidente. Remnawave no acepta nombres de menos de seis caracteres, así que la utilidad añade guiones bajos a los nombres cortos. En nuestra prueba, alice pasó a ser alice_ y bob se convirtió en bob___. Esto no afecta a las suscripciones, porque los enlaces antiguos encuentran a estos usuarios también después del cambio de nombre.
Como los UUID de los usuarios se conservan pero la parte del servidor se crea de nuevo, los dispositivos tienen que recibir una configuración nueva después de la migración. Lo más sencillo es hacerlo a través de la suscripción. Si la suscripción se conserva, la aplicación recogerá sola los nuevos ajustes en la siguiente actualización, y el usuario no tendrá que hacer nada.
Qué necesitas
- Un Marzban en funcionamiento, desde el que vamos a pasar los usuarios.
- Un panel Remnawave listo con al menos un nodo, un perfil VLESS Reality y un host. Si todavía no lo tienes, instálalo con nuestras instrucciones. Comprueba que la conexión funciona con un usuario de prueba y solo después pasa al resto.
- Acceso por SSH al servidor de Marzban. Lo más cómodo es ejecutar la utilidad directamente en él.
Paso 1. Crea un token de API en Remnawave
La utilidad crea los usuarios a través de la API de Remnawave, y para ello necesita un token.
- En el panel de Remnawave, abre Remnawave Settings y baja hasta el bloque API tokens.
- Pulsa el botón + en la esquina inferior derecha del bloque.
- Escribe un nombre, por ejemplo
migrate, y el plazo de validez en días. Para la migración basta con un día. - Elige el conjunto de permisos Full access (Полный доступ) y pulsa Create (Создать).
- Copia el token. El panel solo lo muestra una vez.

Creación del token de API
El token da acceso completo al panel
Guárdalo como si fuera una contraseña y bórralo después de la migración si ya no lo necesitas.
Paso 2. Averigua el UUID del squad
En Remnawave, un usuario solo recibe conexiones a través de un squad que incluya un perfil de configuración. Si pasas los usuarios sin squad, sus suscripciones quedarán vacías. Por eso, ya durante la migración los añadiremos al squad Default-Squad, en el que tienes activado el perfil VLESS Reality. El UUID del squad se puede obtener a través de la API.
# Sustituye TOKEN y panel.tu-dominio.com por tus propios valores
curl -s -H "Authorization: Bearer TOKEN" https://panel.tu-dominio.com/api/internal-squads \
| python3 -c "import json,sys; [print(s['uuid'], s['name']) for s in json.load(sys.stdin)['response']['internalSquads']]"El comando mostrará la lista de squads. Copia el UUID de la línea con Default-Squad.
Paso 3. Descarga la utilidad en el servidor de Marzban
# Carpeta para la utilidad
mkdir -p /opt/remnawave-migrate && cd /opt/remnawave-migrate
# Descargamos y descomprimimos la versión 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
# Lista de parámetros
./remnawave-migrate --help
Parámetros de la utilidad de migración
Antes de ejecutarla, mira en la página de versiones publicadas si ha salido una más reciente y, si hace falta, cambia el número en el comando.
Paso 4. Haz una migración de prueba
Primero pasa unos cuantos de los últimos usuarios para asegurarte de que todo está bien configurado. Si Marzban se instaló con nuestro script, el usuario y la contraseña del administrador están en el archivo /root/marzban-credentials.txt, y el comando de abajo los tomará de ahí por sí solo.
cd /opt/remnawave-migrate
# Datos de Marzban del archivo que creó nuestro script
export PANEL_TYPE=marzban
export PANEL_URL=http://127.0.0.1:PANEL_PORT
export PANEL_USERNAME=$(awk '/^Логин:/ {print $2}' /root/marzban-credentials.txt)
export PANEL_PASSWORD=$(awk '/^Пароль:/ {print $2}' /root/marzban-credentials.txt)
# Datos de Remnawave
export REMNAWAVE_URL=https://panel.tu-dominio.com
export REMNAWAVE_TOKEN=TOKEN
export INTERNAL_SQUAD=SQUAD_UUID
# Pasamos solo los 5 últimos usuarios
./remnawave-migrate --last-users=5 --preserve-status --preserve-subhashNuestro script escribe este archivo en ruso, así que las palabras Логин (usuario) y Пароль (contraseña) del comando deben quedarse tal cual y no se traducen.
En lugar de PANEL_PORT, indica el puerto de la dirección del panel de Marzban, que el script mostró al final de la instalación. Si instalaste Marzban de otra forma, pon en PANEL_URL la dirección con la que abres el panel y escribe el usuario y la contraseña a mano.
Hay dos parámetros importantes al final del comando.
--preserve-statusconserva el estado de los usuarios. Sin él, todos los usuarios migrados quedarán activos, aunque en Marzban estuvieran desactivados o se les hubiera acabado el plazo.--preserve-subhashconserva los identificadores de suscripción de Marzban. Hace falta para poder seguir atendiendo los enlaces de suscripción antiguos, de lo que hablamos más abajo.
La utilidad anota en el registro cada usuario que procesa y al final muestra Migration completed successfully!. Las líneas con was sanitized to indican que un nombre se ha completado hasta los seis caracteres.

Migración de prueba de tres usuarios
Abre la sección Users de Remnawave y revisa los usuarios migrados. Deben coincidir los límites de tráfico, las fechas de caducidad y los estados, y en el bloque Internal squads debe aparecer Default-Squad.

Usuarios después de la migración
Paso 5. Pasa todos los usuarios
Si la migración de prueba ha ido bien, ejecuta la utilidad sin limitar el número de usuarios. Las variables del paso anterior se mantienen mientras siga abierta la misma ventana del terminal.
./remnawave-migrate --preserve-status --preserve-subhashLa utilidad procesa los usuarios en lotes de 100 y tiene en cuenta por sí sola los que ya se crearon en la migración de prueba.
Paso 6. Conserva los enlaces de suscripción antiguos
Después de la migración, los usuarios tienen que recibir la suscripción de Remnawave. Hay dos caminos.
Enviar los enlaces nuevos. Es la opción más sencilla y fiable si tienes pocos usuarios. El enlace nuevo de cada usuario está en su ficha de Remnawave.
Seguir atendiendo los enlaces antiguos. La página de suscripción de Remnawave sabe entender los enlaces de Marzban. Para ello necesita la clave secreta con la que Marzban firmaba sus enlaces. Si Marzban funciona con SQLite, como ocurre después de nuestro script, puedes obtener la clave con un solo comando.
# Si no se encuentra el comando, instálalo con apt install -y sqlite3
sqlite3 /var/lib/marzban/db.sqlite3 "SELECT secret_key FROM jwt LIMIT 1;"
La clave secreta de Marzban, oculta en la captura
Si Marzban funciona con MySQL, ejecuta la misma consulta SELECT secret_key FROM jwt LIMIT 1; en su base de datos.
Después instala la página de suscripción siguiendo la sección «Página de suscripción» de nuestro artículo sobre Remnawave y añade a su archivo .env las líneas para los enlaces antiguos.
MARZBAN_LEGACY_LINK_ENABLED=true
MARZBAN_LEGACY_SECRET_KEY=marzban_secret_key
CUSTOM_SUB_PREFIX=subCUSTOM_SUB_PREFIX debe coincidir con la ruta de las suscripciones en Marzban, que por defecto es sub. Después del cambio, recrea el contenedor con el comando docker compose up -d --force-recreate. La página de suscripción solo responde detrás de un proxy inverso con HTTPS, así que hay que publicarla a través de Caddy, como se explica en el mismo artículo. Si se accede directamente por HTTP, se niega a responder y deja en el registro el error Reverse proxy and HTTPS are required.
Los enlaces antiguos llevan a la dirección antigua
Los enlaces de Marzban apuntan a la dirección de su servidor. Después de nuestro script tienen este aspecto http://SERVER_IP:PORT/sub/.... Si vas a borrar el servidor antiguo, es más sencillo enviar a los usuarios los enlaces nuevos.
Si el servidor antiguo sigue funcionando, redirige sus peticiones a /sub/ hacia la nueva página de suscripción. En el servidor de Marzban, abre el archivo /etc/nginx/sites-available/marzban-panel y añade este bloque antes de la línea location / {, cambiando el dominio por la dirección de tu página de suscripción.
location /sub/ {
proxy_pass https://sub.tu-dominio.com;
proxy_set_header Host sub.tu-dominio.com;
proxy_ssl_server_name on;
proxy_ssl_name sub.tu-dominio.com;
}Comprueba la configuración y aplícala.
nginx -t && systemctl reload nginxHemos probado este esquema. Después de hacerlo, un enlace antiguo de Marzban del tipo http://SERVER_IP:PORT/sub/... devolvió la suscripción de Remnawave del usuario migrado, y el enlace de un usuario desactivado respondió con el mensaje Subscription disabled.
Paso 7. Apaga Marzban
Cuando los usuarios hayan recibido la configuración nueva y se conecten a través de Remnawave, detén Marzban.
marzban downNo lo borres enseguida. Deja el servidor con Marzban detenido unos días para poder volver atrás si hace falta. Antes de borrarlo del todo, guarda una copia de la carpeta /var/lib/marzban.
Preguntas frecuentes
La utilidad da un error de autorización en Remnawave
Comprueba el token y la dirección del panel en REMNAWAVE_URL. Si el panel de Remnawave está cerrado con la protección adicional de Caddy, crea una clave de API en su portal de autorización y pásala con el parámetro --dest-headers="X-Api-Key:clave".
Los usuarios migrados tienen la suscripción vacía
Los usuarios no han entrado en un squad con perfil. Añádelos a Default-Squad en el panel de Remnawave o vuelve a migrarlos con el parámetro --internal-squad. Comprueba también que el host tiene activado el interruptor Host visibility.
Se puede cambiar el modo de reinicio del tráfico para todos a la vez
Sí, el parámetro --preferred-strategy fija un mismo modo para todos los usuarios migrados. Los valores posibles son NO_RESET, DAY, WEEK y MONTH.
Se transfiere el tráfico consumido
No. La utilidad transfiere el límite de tráfico y su modo de reinicio, y el contador de tráfico consumido empieza de cero en Remnawave.
Nuestros recursos
Canal de Telegram: https://t.me/f3cloud_news
Web del hosting: https://f3cloud.com