Skip to content
Stand with Ukraine flag

Bulk provisioning

TBMQ provides a bulk import tool that lets system administrators manage large numbers of MQTT client credentials using a CSV file.

The import implements an upsert pattern: the system identifies existing credentials by Name. If a match is found, the entry is updated; otherwise, a new one is created.

Bulk import is available to the system administrator at AuthenticationClient credentialsImport Basic credentials, or over REST at POST /api/mqtt/client/credentials/bulk_import.

Each line in the CSV file corresponds to one credential record. The file must contain at least two columns and at least one data row, and every line must have the same number of columns as the first one — a ragged line aborts the import with Invalid file format. Line: '<n>' before anything is saved. Name is always required, along with Client ID or Username (or both) — Basic credentials with neither are rejected.

The resulting Client ID / Username combination must also be unique across all client credentials, even though the upsert key is Name. A row that would duplicate a combination already in use fails with Such MQTT Client credentials are already created! when it would create a credential, or New MQTT Client credentials are already created! when it would update one.

Example CSV:

Name Client type Client ID Username Password Sub auth rule patterns Pub auth rule patterns Description
Sensor_Device DEVICE sensor-01 mqtt-user-01 secretPass sensors/1/data;sensors/all/data sensors/1/cmd Demo device client
Application_Manager APPLICATION app-mgr-01 alerts/.*

How the broker processes this file:

Sensor_Device — creates a new DEVICE credential using client ID sensor-01, username mqtt-user-01, and the description Demo device client. The plain-text password is encoded on import. Subscribe and publish topic patterns are parsed using ; as the delimiter.

Application_Manager — creates a new APPLICATION credential with client ID app-mgr-01. Username, password, and description are null because those cells are empty. The subscribe auth rule pattern is null, which forbids all subscriptions. The publish auth rule is set to alerts/.*.

Authorization rule patterns are regular expressions, not MQTT topic filters — alerts/.* matches any topic starting with alerts/, whereas alerts/# would be read as a literal #. Each pattern is compiled on import, so a row with an invalid expression fails. Client type values are case-insensitive, so device and DEVICE are equivalent.

  1. Select a file

    Upload your prepared CSV file.

  2. Import configuration

    Configure how the system reads the file:

    • CSV delimiter — the character separating values (,, ;, |, or Tab). Defaults to ,.
    • Auth rule patterns delimiter — the delimiter used to split multiple topic patterns within a single cell. Defaults to ;. Must differ from the CSV delimiter: whichever character one dropdown holds is greyed out in the other.
    • First line contains column names — enabled by default; when enabled, the first row is used for automatic column mapping in the next step.

    Automatic mapping matches a header cell, case-insensitively, against the internal column name — NAME, CLIENT_TYPE, CLIENT_ID, USERNAME, PASSWORD, SUB_AUTH_RULE_PATTERNS, PUB_AUTH_RULE_PATTERNS, DESCRIPTION. A friendly heading such as Client ID does not match and arrives as Not assigned, so map it by hand in the next step. With the option disabled, the first column defaults to Name, the second to Client ID, and the rest to Not assigned.

  3. Select columns type

    Assign a Column type to each CSV column:

    • Name — required for identification and upsert logic.
    • Client typeDEVICE or APPLICATION. Defaults to DEVICE when the column is absent.
    • Client ID — the unique MQTT client identifier.
    • Username — the MQTT username.
    • Password — the MQTT password, encoded during import.
    • Subscribe auth rule patterns — regular expressions for allowed subscribe topics.
    • Publish auth rule patterns — regular expressions for allowed publish topics.
    • Description — optional description.

    Every column must be assigned a type — a column left as Not assigned blocks the step. Each type can be used only once; once assigned, it is greyed out in the remaining dropdowns. The step also requires Name plus Client ID or Username, and reports Columns Name and Client ID/Username are required until both are set. Because of this, the way to leave a field untouched is to omit its column from the file, not to leave it unassigned in the UI — see Data handling rules.

  4. Creating new entities

    The broker processes rows using your column mapping. Rows are independent and imported in parallel, so a failing row does not roll back or block the others.

  5. Done

    A summary shows how many entries were created, how many were updated, and how many failed. Expand Details to see the failures, listed as Line <n>: <reason>, so you can fix those rows and re-run the import — successfully imported rows will simply be updated in place on the second pass.

  • To update a field: Provide a new value in the corresponding CSV column — see the password policy below for exceptions.
  • To preserve existing data: Omit the column from the file, or leave the cell empty — with the exception of authorization rule patterns, which follow their own policy below.

Empty cells are simply skipped: the field keeps whatever value it already had. Authorization rule columns are the one exception — for them, an empty cell is a meaningful instruction.

Existing passwords are protected during bulk import:

  • If a credential already has a password, it cannot be changed or cleared via bulk import.
  • A password can only be set if the credential is newly created or if the existing credential has no password.

For authorization rule columns, a column that is present with an empty cell means something different from a column that is absent from the file:

New credentials:

Column state Result
Column present, cell empty Authorization rule set to null — forbids all topics
Column absent from the file Authorization rule set to .* — allows all topics

Existing credentials:

Column state Result
Column present, cell empty Authorization rule updated to null — revokes all permissions
Column absent from the file Authorization rule preserved — existing permissions unchanged