Skip to main content

Migration from Marzban

Marzban stores data in MySQL or MariaDB, while XLADA stores it in PostgreSQL. A direct transfer of the database directory between different DBMSs is impossible: users are moved through the panel API, and old subscription links keep working via the subscription page compatibility mode. A "one-command" transfer is possible only for user data; the Xray configuration, nodes, and hosts are set up again in XLADA.

What is transferred​

Marzban dataHow it is transferred
Usernamesusername in POST /api/users
Trojan and Shadowsocks passwords, VLESS UUIDthe trojanPassword, ssPassword, vlessUuid fields
Traffic limit and reset periodtrafficLimitBytes, trafficLimitStrategy
Expiration dateexpireAt in ISO 8601 format
Status (active, disabled, limited, expired)status
Squad assignmentinternal-squads or bulk operations
Old subscription linksMARZBAN_LEGACY_* mode on the subscription page

Administrators, traffic history, inbound/outbound, and hosts are not transferred — they are created again in XLADA via config profiles and hosts.

Limitations
  • The user type in Marzban is determined by the protocol: vless needs vlessUuid, trojan needs trojanPassword, shadowsocks needs ssPassword. If you do not transfer the protocol, the user will need a new key.
  • A username in XLADA is Latin letters, digits, _, and - only (in the API, no shorter than three characters). When an old link is parsed, invalid characters are replaced with _, and a name shorter than six characters is padded to six. Create users in this form right away, otherwise the old link will not find its owner.
  • There is no ready-made importer inside the panel: a separate migration tool lives in the xray-panel/migrate organization repository, and the panel only accepts data through the API.

The subscription page can accept old Marzban links and match them to XLADA users by name. The mode is turned on by environment variables:

VariablePurpose
MARZBAN_LEGACY_LINK_ENABLEDenables the compatibility module
MARZBAN_LEGACY_SECRET_KEYthe secret from the Marzban database; several keys — comma-separated
MARZBAN_LEGACY_SUBSCRIPTION_VALID_FROMcutoff: links created before the date are not accepted
MARZBAN_LEGACY_DROP_REVOKED_SUBSCRIPTIONSdrop the connection for revoked subscriptions
CUSTOM_SUB_PREFIXsubscription link prefix, for example sub

When the mode is enabled, MARZBAN_LEGACY_SECRET_KEY is required — without it the subscription page container will not start.

services:
remnawave-subpage:
image: ghcr.io/xray-panel/subscription-page:latest
restart: unless-stopped
environment:
- APP_PORT=3010
- REMNAWAVE_PANEL_URL=http://remnawave:3000
- REMNAWAVE_API_TOKEN=token_from_panel
- MARZBAN_LEGACY_LINK_ENABLED=true
- MARZBAN_LEGACY_SECRET_KEY=secret_from_marzban_db
- CUSTOM_SUB_PREFIX=sub

The secret lives in the jwt table of the Marzban database:

SELECT secret_key FROM jwt LIMIT 1;
Which links the mode understands

Both Marzban schemes are supported: a JWT with the HS256 algorithm and the access: subscription field, and a base64url token with a SHA-256 signature. If there is no user with that name in XLADA, the old link will not open.

Step-by-step plan​

  1. Inventory. Export the list of users from Marzban and save the secret_key from the jwt table. Count the users — this is the reference for verification.
  2. Installing XLADA. Bring up the panel and nodes following the Panel Installation and Node Installation instructions, create an API token in Settings → API Tokens.
  3. Transferring users. Create them with POST /api/users, keeping the name, expiration date, and traffic limit:
curl -sX POST https://panel.example.com/api/users \
-H "Authorization: Bearer $XLADA_API_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"username": "john_doe", "expireAt": "2026-01-17T15:38:45.065Z", "trafficLimitBytes": 0, "trafficLimitStrategy": "NO_RESET"}'
  1. Squads. Distribute the transferred users across internal squads — one by one or in bulk via /api/users/bulk/update-squads.
  2. Old links. Deploy the subscription page with MARZBAN_LEGACY_* from the example above and restart its container.
  3. Verification. Open a couple of old Marzban links: the page must show XLADA user data. Then check fresh links in the Users section.
tip

Transfer 5–10 users first and make sure that both login and the old link work. Do not turn off Marzban until you have compared the user count and made sure the clients connected.

What's next​