Importing from Mosquitto
Importing from Mosquitto
An existing Mosquitto installation describes who may connect and what they may do in two files: a password file and an ACL file, or a singledynamic-security.json. XMQ reads those files and turns them into its own accounts and topic permissions, so a migration starts from the rules the broker already enforces rather than from an empty set written by hand.
The import is on the Import from Mosquitto page of the configuration interface, with a second entry point on the Permissions page for resolving conflicts. It writes only accounts and rules: listeners, bridges, TLS, persistence and every other Mosquitto setting are not imported, because XMQ's configuration has a different shape and a half-copied listener block is worse than none. Set those up on the Listeners and Setup pages.
The files it reads
| File | Usually | What is imported |
|---|---|---|
password_file | /etc/mosquitto/passwd | Usernames and their password verifiers, as accounts. |
acl_file | /etc/mosquitto/aclfile | user, topic and pattern rules, as XMQ topic permissions. |
dynamic-security.json | Beside the Mosquitto configuration | Clients, roles, groups and their ACLs, flattened onto accounts and permissions. |
The files are read by the browser and sent to the broker as content. The XMQ server never opens /etc/mosquitto with its own privileges, and cannot be used to read a file the administrator could not read. If Mosquitto runs on another machine, copy the files to the machine where the interface is open; the password file holds secrets and should be deleted after the import.
Either file may be left empty, and then that part is not imported. Choosing a.json file sets the ACL format to dynamic security by itself; the selector beside the input can be changed if the name of the file does not say what it is. Accounts and rules are applied in one database transaction: either both arrive or neither does.
Plan, then apply
Preview reads the files and shows what would change without writing anything. For the password file it counts the accounts that are new, the ones that already exist, the verifiers this build cannot check and the lines it could not use. For the ACL it counts the rules that are new, already present, covered by an existing rule, in conflict with one, or not representable. Neither the plan nor the result ever shows a password.
Nothing is stored while a conflict is unresolved. An allow that overlaps a deny, or two rules that cannot both hold for the same subject, is shown on thePermissions page, where each one is resolved by keeping the existing rule, using the imported one, or skipping it. An import that is refused leaves the rule set exactly as it was. Importing the same file twice adds nothing: rules already present are recognised rather than duplicated, and a rule an existing rule already covers is not added.
An import of at least one ACL rule turns on deny by default: a client with no matching rule is denied, exactly as Mosquitto behaves when an ACL file is present. An empty ACL file leaves that setting alone - opening or locking the whole broker on no evidence would both be worse.
Password verifiers
| Verifier | Mosquitto | Handling |
|---|---|---|
| clear text | any | Accepted and re-hashed with this broker's own verifier. |
$7$ | 2.0 and newer | Checked natively; replaced with this broker's verifier at the first successful login. |
$6$ | 1.6 | Checked when the platform has crypt() - not on Windows. |
argon2id | 2.1 | Checked when OpenSSL is 3.2 or newer. Older source builds - Ubuntu 24.04 and older, Debian 12, RHEL 9, FreeBSD 14 - report it as not imported. |
A verifier this build cannot check is listed as not imported rather than stored as an account nobody can sign in to; that account's password has to be set again. An imported verifier is checked both by the interface's own accounts and by the user-database extension that MQTT clients authenticate against. Only verifiers read from a Mosquitto password file are affected: XMQ's own accounts and every other authentication path are unchanged.
ACL file rules
| Mosquitto | XMQ permission |
|---|---|
topic read F | subscribe allow on F |
topic write F | publish allow on F |
topic readwrite F | publish and subscribe allow on F |
topic deny F | publish and subscribe deny on F |
pattern ... %u / %c | One rule for every client, with the username or client id substituted when the rule is checked |
Rules are ordered the way Mosquitto would check them: the client's roles first, then its groups by priority, then the roles in each group, with each role's ACLs by their priority. A topic deny is checked before any allow, because that is what Mosquitto does.
Dynamic Security
A dynamic-security.json describes clients, roles and groups, and the rules a client gets come from all three. The import flattens that onto accounts: a client's rules become rules on user:<name>, in the order Mosquitto would check them. A client that is disabled is imported as a disabled account; clientid is checked by the import and reported when it would change how a %c rule matches.
An allowing defaultACLAccess becomes a # rule checked after everything else. A denying one needs no rule at all, because in XMQ a client with rules but no match is already denied. Rules that cannot be represented are listed as not imported, with the reason, rather than dropped silently.
Many devices from a spreadsheet
An XLS or XLSX file is not read directly. Save the sheet as CSV UTF-8, then make one username:password line per device. With the username in column A and the password in column B, a third column with=A2&":"&B2 produces the line; a small script does the same for larger sheets. The result is the password file described above, so it is imported through the same page: clear-text lines are accepted there and hashed with this broker's verifier.
That import puts every account in Default; it has no column for groups, so a fleet that needs one group per device type cannot be expressed this way. For very large files, import in batches: the broker hashes every password as it adds the account. The file holds clear passwords, so send it over HTTPS, delete it after the import, use unique passwords rather than one shared secret, and look at the plan for repeated usernames before applying it.
Known limitations
- Per-listener rules are not available. A rule applies to every MQTT and MQTT+SSL listener on the node. Separating what one listener permits from another has to be done with separate accounts or separate clusters.
- Read is subscribe. Mosquitto's
readand XMQ'ssubscribeare the same permission. A Dynamic SecuritypublishClientReceiveallow is therefore redundant and is reported as not imported; a denial is carried as a subscribe deny. - A subscription is matched as a filter. Dynamic Security distinguishes
subscribeLiteralfromsubscribePattern; both are stored as a filter. For ordinary clients the two are the same, but a rule written to permit one literal subscription also permits the equivalent wildcard. %cis only as good as the client id. A client id is chosen by the client unless it is bound by authentication. A client id or username containing+,#or/matches no pattern rule, so it cannot widen one.- An empty topic level is refused. A rule filter naming an empty level is treated as a typo by the import and by the control API alike.
+and#must each be a whole level, and#the last one. - Passwords are not imported as clear text files are. A verifier this build cannot check is reported rather than taken on trust, and has to be set again.
After the import, Test access on thePermissions page answers a specific question using the same evaluation the broker applies, and names the rule that decided - the quickest way to confirm that a migrated policy behaves as the old one did.
