Migrations
Importing accounts from other authentication plugins and moving data between storage backends.
mineLogin handles two different kinds of migration:
| Kind | Use case | How it runs |
|---|---|---|
| External migration | You are switching from another authentication plugin (AuthMe, LimboAuth, …) | Automatically on proxy startup |
| Internal migration | You are keeping mineLogin but changing the storage backend (H2 → MySQL, …) | Manually via console commands |
Tip: Always create a full backup of both the source and the target database before starting any migration. Schedule migrations during low-traffic periods.
External Migration
mineLogin can import accounts directly from another authentication plugin. Passwords are not reset — the original hashes are imported as-is, so your players keep the passwords they already have.
Supported Plugins
Providers run in the order below. FastLogin runs last so that accounts imported from another plugin can still be upgraded to premium status.
| Order | Plugin | Provider ID | Auto-detected config |
|---|---|---|---|
| 1 | AuthMe / AuthMeReloaded | authme | plugins/AuthMe/config.yml, plugins/AuthMeReloaded/config.yml |
| 2 | DynamicBungeeAuth | dynamicbungeeauth | plugins/DynamicBungeeAuth/Config.yml |
| 3 | JPremium | jpremium | plugins/JPremium/configuration.yml |
| 4 | LibreLogin | librelogin | plugins/LibreLogin/config.conf |
| 5 | nLogin | nlogin | plugins/nLogin/config.yml |
| 6 | LimboAuth | limboauth | plugins/limboauth/config.yml |
| 7 | FastLogin | fastlogin | plugins/FastLogin/config.yml |
Supported Source Databases
| Database | Supported |
|---|---|
| MySQL | ✅ |
| MariaDB | ✅ (uses the MySQL driver) |
| SQLite | ✅ |
| H2 | ✅ |
| PostgreSQL | ❌ |
| MongoDB | ❌ |
Tip: The source database is only read, never modified. You can keep the old plugin installed until you have verified the migration.
How It Works
- Keep the source plugin data in its standard location, for example
plugins/AuthMeorplugins/limboauth. - Start the proxy. mineLogin reads the source plugin configuration and writes a migration file to
plugins/mineLogin/migrations/<provider-id>.yml. - Review the generated file. If mineLogin could read the source configuration,
pls-change-me-after-configuring-thisis already set totrueand the migration runs on that same startup. - After a successful run,
completedis set totrueso the migration never runs twice.
If mineLogin could not find the source plugin configuration, it writes an empty template instead and skips the migration. Fill in the connection details manually and set pls-change-me-after-configuring-this: true, then restart the proxy.
Accounts that already exist in mineLogin are updated rather than duplicated, so re-running a migration against a partially imported database is safe.
Tip: A failed migration stops the proxy on purpose. This prevents players from registering new accounts on top of a half-imported database.
Migration File Reference
provider-id: limboauth
pls-change-me-after-configuring-this: true
completed: false
driver: H2
host: 127.0.0.1
port: 3306
database: limboauth
user: your-remote-username
password: user-db-password
use-ssl: false
file-db-path: plugins/limboauth/limboauth-v2.mv.db
table-name: AUTH
columns:
username: NICKNAME
password: HASH
| Option | Type | Description |
|---|---|---|
provider-id | String | Identifies the source plugin. Never change this value. |
pls-change-me-after-configuring-this | Boolean | Migration only runs when this is true |
completed | Boolean | Managed by the plugin — set to true after a successful run |
driver | Enum | Source database type: MYSQL, SQLITE or H2 |
host | String | Source database address (MySQL only) |
port | Integer | Source database port (MySQL only) |
database | String | Source database name (MySQL only) |
user | String | Source database user (MySQL only) |
password | String | Source database password (MySQL only) |
use-ssl | Boolean | Enable SSL for the source connection (MySQL only) |
file-db-path | String | Path to the source file, relative to the server root (SQLite/H2 only) |
table-name | String | Source table name |
columns | Map | Column name overrides — keys depend on the provider |
Tip: You only need to touch
columnsif the source plugin uses a non-standard schema. Leave it as generated otherwise.
AuthMe
Reads the AuthMe account table directly. The plugin folder may be named either AuthMe or AuthMeReloaded.
Source databases: MySQL, MariaDB, SQLite | Default table: authme
| AuthMe column | mineLogin field | columns key |
|---|---|---|
realname | Username | username |
username | Username fallback | fallback-username |
password | Password hash | password |
salt | Salt | salt |
email | email | |
regip | Register address | register-address |
ip | Last join address | last-join-address |
regdate | Register time | register-time |
lastlogin | Last join time | last-join-time |
Column names are read from the DataSource section of the AuthMe config, so custom schemas are picked up automatically.
Passwords: the hash format is detected automatically. If the salt column is missing, the salt is extracted from $SHA$salt$hash values.
Premium accounts: AuthMe does not track premium status, so every account is imported as cracked with an offline UUID generated from the username. Run the FastLogin migration afterwards to restore premium status.
Tip: Unlike the other providers, AuthMe aborts the migration on an unrecognised hash format instead of skipping the account. This is intentional — a silently skipped AuthMe account would look identical to a never-registered one.
DynamicBungeeAuth
Source databases: MySQL only | Default table: playerdata
| DynamicBungeeAuth column | mineLogin field | columns key |
|---|---|---|
name | Username | username |
uuid | Account UUID | uuid |
password | Password hash | password |
salt | Salt | salt |
premium | Premium state | premium |
email | email | |
reg_ip | Register address | register-address |
log_ip | Last join address | last-join-address |
firstjoin | Register time | register-time |
lastjoin | Last join time | last-join-time |
Passwords: the hash algorithm is read from Options.PasswordHash and stored under the hash-algorithm key in the migration file.
| Algorithm | Requires salt column |
|---|---|
AUTHME-SHA256 | No |
SHA256 | Yes |
SHA512 (default) | Yes |
SMD5 | Yes |
Premium accounts: taken from the boolean premium column.
JPremium
Source databases: MySQL only | Default table: user_profiles
| JPremium column | mineLogin field | columns key |
|---|---|---|
lastNickname | Username | username |
uniqueId | Account UUID | unique-id |
premiumId | Premium UUID | premium-id |
hashedPassword | Password hash | password |
lastAddress | Last join address | last-join-address |
firstSeen | Register time | register-time |
lastSeen | Last join time | last-join-time |
Passwords: SHA256$, SHA512$, BCRYPT$ and plain $2a$ hashes are supported.
Premium accounts: an account with a filled premiumId is imported as premium and keeps that UUID.
SSL is enabled unless the JPremium storageProperties list contains useSSL=false.
LibreLogin
Reads the HOCON configuration at plugins/LibreLogin/config.conf to detect whether LibreLogin runs on SQLite or MySQL.
Source databases: MySQL, SQLite | Default table: librepremium_data
| LibreLogin column | mineLogin field | columns key |
|---|---|---|
last_nickname | Username | username |
uuid | Account UUID | uuid |
premium_uuid | Premium UUID | premium-id |
hashed_password | Password hash | password |
salt | Salt | salt |
algo | Hash algorithm | algorithm |
email | email | |
secret | 2FA secret | secret |
ip | Last join address | last-join-address |
joined | Register time | register-time |
last_authentication | Last join time | last-join-time |
last_seen | Last join time fallback | last-seen-time |
Passwords: the per-account algo column decides how the hash is rebuilt. Supported values are SHA-256, SHA-512, BCRYPT-2A, BCRYPT-2B, BCRYPT-2X, BCRYPT-2Y and ARGON-2ID. LibreLogin splits BCrypt and Argon2 hashes across the salt and algo columns, so mineLogin reassembles them into standard hash strings.
Premium accounts: an account with a filled premium_uuid is imported as premium and keeps that UUID.
Two-factor authentication: TOTP secrets are imported from the secret column.
nLogin
Source databases: MySQL, SQLite | Default table: nlogin
| nLogin column | mineLogin field | columns key |
|---|---|---|
last_name | Username | username |
unique_id | Account UUID | unique-id |
mojang_id | Premium UUID | premium-id |
password | Password hash | password |
last_ip | Last join address | last-join-address |
creation_date | Register time | register-time |
last_seen | Last join time | last-join-time |
Passwords: BCrypt ($2a$), Argon2 ($argon2), AuthMe-style ($SHA$), $SHA256$ and $SHA512$ hashes are supported.
Premium accounts: an account with a filled mojang_id is imported as premium and keeps that UUID.
Accounts without a unique_id are skipped.
LimboAuth
LimboAuth stores every account in a single AUTH table. mineLogin reads it directly, so no export step is needed.
Source databases: H2, MySQL, MariaDB, SQLite | Default table: AUTH
| LimboAuth column | mineLogin field | columns key |
|---|---|---|
NICKNAME | Username | username |
LOWERCASENICKNAME | Username fallback | fallback-username |
HASH | Password hash | password |
UUID | Account UUID | uuid |
PREMIUMUUID | Premium UUID | premium-id |
TOTPTOKEN | 2FA secret | secret |
IP | Register address | register-address |
LOGINIP | Last join address | last-join-address |
REGDATE | Register time | register-time |
LOGINDATE | Last join time | last-join-time |
Passwords: LimboAuth hashes with BCrypt, which mineLogin supports natively — players log in with their existing passwords immediately. LimboAuth can also keep hashes imported from other plugins through its own MIGRATION_HASH option; those formats are detected automatically, and accounts using an unsupported format are skipped with a console warning.
Premium accounts: an account with an empty HASH and a filled PREMIUMUUID logs in through Mojang instead of using a password. These are imported as premium accounts keeping their premium UUID and no password. An account with neither a password nor a premium UUID is skipped.
Two-factor authentication: TOTP secrets from TOTPTOKEN are imported, so players keep their 2FA without scanning a new QR code. LimboAuth has no recovery codes, so mineLogin recovery codes start out empty.
Storage backends:
LimboAuth storage-type | Supported | Default source path |
|---|---|---|
h2 | ✅ | plugins/limboauth/limboauth-v2.mv.db |
mysql | ✅ | — |
mariadb | ✅ | — |
sqlite | ✅ | plugins/limboauth/limboauth.db |
postgresql | ❌ | — |
Tip: If only the legacy H2 v1 file (
limboauth.mv.db) exists, start LimboAuth once so it upgrades the file to v2 before migrating. mineLogin logs a warning in this case.
FastLogin
FastLogin only tracks which players are premium — it stores no passwords. This provider therefore never creates accounts, it only upgrades accounts that already exist in mineLogin. That is why it runs last, after the password-carrying providers.
Source databases: MySQL, MariaDB, SQLite | Default table: premium
| FastLogin column | mineLogin field | columns key |
|---|---|---|
Name | Username | username |
UUID | Premium UUID | uuid |
Premium | Premium state | premium |
Rows with Premium = false are ignored. Rows for players who do not exist in mineLogin are reported as skipped — import their passwords from another plugin first.
Internal Migration
Use this to move existing mineLogin data between storage backends, for example from H2 to MySQL. All commands must be executed from the proxy console.
Step 1: Export Data
Run the export command in the proxy console:
minelogin internalMigration export
Monitor the console for confirmation that all user data has been exported.
Step 2: Update Configuration
Stop the proxy server and change the data-type and connection details in your configuration to the new database backend. Save the file.
Step 3: Restart and Import
Start the proxy server, then run:
minelogin internalMigration import
Wait for the console to confirm that the import has completed. Prevent new players from joining until the migration is finished.
Step 4: Verify
Check that player data is intact by using /ml userinfo <username> on a few accounts. Once verified, you can remove the old database and temporary files.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
| Migration is skipped on startup | pls-change-me-after-configuring-this is false | Fill in the migration file and set it to true |
| Migration is skipped after a successful run | completed is true | Set it back to false to run it again |
| Proxy stops with a validation error | Source table or column does not exist | Check table-name and columns against the source database |
| Source database file does not exist | Wrong file-db-path | The path is relative to the server root, not to the plugin folder |
| Accounts reported as skipped | Missing password, missing premium UUID, or unsupported hash format | Review the console warnings — these accounts need to register again |
| Everything skipped in a FastLogin run | The accounts do not exist in mineLogin yet | Import passwords from the original auth plugin first |
| Unsupported source database type | The source plugin uses PostgreSQL or MongoDB | Export the data to MySQL, SQLite or H2 first |