Configuration
Configuration
The complete MQTT platform in one small binary: broker, SQL rules, data connectors and multi-tenancy in a single process.
Validate, reload and explain settings. Use it to change files safely. You get diffs, versions and source layers.
flowchart LR Op["operator"] -- "POST /api/v1/config/reload" --> API["management API"] API -- "apply indra.toml" --> C["broker-config"]Before you start
- Start the broker from First start.
- Set
INDRA_API_KEYto an operator key. The examples read it.
Note: Calls except
/healthzneed an operator API key. Pass it asAuthorization: Bearer $INDRA_API_KEY.
Configuration validation, reload, history and setting lookup
POST /api/v1/config/diff
Show the diff a reload would apply
Operation id: diffConfig.
Parameters:
No parameters.
Request body:
Media type application/json:
Required: snapshot.
| Field | Type | Description |
|---|---|---|
snapshot | object |
Responses:
| Status | Description |
|---|---|
| 200 | Setting diff with redacted secrets |
| 400 | Candidate names each offending setting |
Response 200 body:
Media type application/json:
{ "type": "object", "properties": { "diff": { "type": "array", "items": { "type": "object" } } }}Notes:
-
Send
snapshot. An empty required string fails with 400. -
Related calls sit on the same tag page.
Not verified: see ../_verification/failures.md.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X POST 'http://127.0.0.1:18083/api/v1/config/diff' \ -H "Authorization: Bearer $INDRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "snapshot": {}}'GET /api/v1/config/explain
Explain one setting value and its source layer
Operation id: explainConfig.
Parameters:
| Name | In | Required | Type | Description |
|---|---|---|---|---|
key | query | true | string | Setting key such as session.max_qos0_backlog |
Request body:
No request body.
Responses:
| Status | Description |
|---|---|
| 200 | Effective value with source layer |
| 400 | Query key is missing |
| 404 | Unknown setting key |
Response 200 body:
Media type application/json:
{ "type": "object"}Notes:
-
An unknown id fails with 404.
-
Related calls sit on the same tag page.
Not verified: see ../_verification/failures.md.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X GET 'http://127.0.0.1:18083/api/v1/config/explain?key=session.max_qos0_backlog' \ -H "Authorization: Bearer $INDRA_API_KEY"GET /api/v1/config/history
List configuration versions newest first
Operation id: listConfigHistory.
Parameters:
No parameters.
Request body:
No request body.
Responses:
| Status | Description |
|---|---|
| 200 | Version list without snapshots |
Response 200 body:
Media type application/json:
{ "type": "object", "properties": { "versions": { "type": "array", "items": { "type": "object" } } }}Notes:
- Related calls sit on the same tag page.
Verified: the example flow below runs this call.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X GET 'http://127.0.0.1:18083/api/v1/config/history' \ -H "Authorization: Bearer $INDRA_API_KEY"GET /api/v1/config/history/{id}
Get one configuration version
Operation id: getConfigHistoryVersion.
Parameters:
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | true | integer | Version id |
secrets | query | false | string | Set to raw to get the snapshot with its secrets as stored. This needs a full administrator: the administrator role with no scope list. Backup export uses it, so the export file holds secrets. |
Request body:
No request body.
Responses:
| Status | Description |
|---|---|
| 200 | Version with redacted snapshot |
| 403 | The query secrets=raw needs a full administrator |
| 404 | Version does not exist |
Response 200 body:
Media type application/json:
{ "type": "object", "properties": { "id": { "type": "integer" }, "actor": { "type": "string" }, "timestamp_secs": { "type": "integer" }, "summary": { "type": "string" }, "changes": { "type": "array", "items": { "type": "string" } }, "snapshot": { "type": "object" } }}Notes:
-
An unknown id fails with 404.
-
Related calls sit on the same tag page.
Not verified: see ../_verification/failures.md.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X GET 'http://127.0.0.1:18083/api/v1/config/history/1' \ -H "Authorization: Bearer $INDRA_API_KEY"POST /api/v1/config/history/{id}/restore
Restore one configuration version
Operation id: restoreConfigHistoryVersion.
Parameters:
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | true | integer | Version id |
Request body:
Media type application/json:
| Field | Type | Description |
|---|---|---|
actor | string |
Responses:
| Status | Description |
|---|---|
| 200 | Restored version with applied diff |
| 404 | Version does not exist |
Notes:
-
An unknown id fails with 404.
-
Related calls sit on the same tag page.
Not verified: see ../_verification/failures.md.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X POST 'http://127.0.0.1:18083/api/v1/config/history/1/restore' \ -H "Authorization: Bearer $INDRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "actor": ""}'POST /api/v1/config/reload
Apply a candidate configuration snapshot
Operation id: reloadConfig.
Parameters:
No parameters.
Request body:
Media type application/json:
Required: snapshot.
| Field | Type | Description |
|---|---|---|
snapshot | object | |
actor | string | |
summary | string |
Responses:
| Status | Description |
|---|---|
| 200 | Reloaded version with applied diff |
| 400 | Candidate names each offending setting |
| 500 | Reload failed after validation |
Response 200 body:
Media type application/json:
{ "type": "object", "properties": { "version": { "type": "integer" }, "diff": { "type": "array", "items": { "type": "object" } }, "pending_live": { "type": "array", "items": { "type": "string" } } }}Notes:
-
Send
snapshot. An empty required string fails with 400. -
Related calls sit on the same tag page.
Not verified: see ../_verification/failures.md.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X POST 'http://127.0.0.1:18083/api/v1/config/reload' \ -H "Authorization: Bearer $INDRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "snapshot": {}, "actor": "", "summary": ""}'POST /api/v1/config/validate
Validate a candidate configuration snapshot
Operation id: validateConfig.
Parameters:
No parameters.
Request body:
Media type application/json:
Required: snapshot.
| Field | Type | Description |
|---|---|---|
snapshot | object |
Responses:
| Status | Description |
|---|---|
| 200 | Candidate applies cleanly |
| 400 | Candidate names each offending setting |
Response 200 body:
Media type application/json:
{ "type": "object", "properties": { "ok": { "type": "boolean", "example": true } }}Notes:
-
Send
snapshot. An empty required string fails with 400. -
Related calls sit on the same tag page.
Not verified: see ../_verification/failures.md.
Example:
# Illustrative request. Values come from the schema above.# The example flow below runs verified calls on a live broker.curl -s -X POST 'http://127.0.0.1:18083/api/v1/config/validate' \ -H "Authorization: Bearer $INDRA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "snapshot": {}}'Example flow
Read real rows through the management API, then read them back. The docs harness runs this flow against a started broker.
python3 - <<'PY'import os, urllib.requestport = os.environ.get("API_PORT", "18083")key = os.environ.get("API_KEY", "")base = f"http://127.0.0.1:{port}"def get(path): req = urllib.request.Request(base + path, method="GET") req.add_header("Authorization", f"Bearer {key}") with urllib.request.urlopen(req, timeout=5) as r: return r.status, r.read().decode()s1, b1 = get("/api/v1/config/history")assert s1 == 200, b1assert "versions" in b1, b1s2, b2 = get("/api/v1/config/history")assert s2 == 200, b2assert b1 == b2, "read back the same version list"print("OK")PYOKCheck that it works
Start the broker with this file. The health endpoint returns OK.
[node]id = "doc-ref"
[listeners.tcp]bind = "0.0.0.0:1883"
[listeners.tls]bind = "0.0.0.0:8883"
[listeners.ws]bind = "0.0.0.0:8083"
[listeners.wss]bind = "0.0.0.0:8084"
[listeners.api]bind = "0.0.0.0:18083"
[logging]level = "warn"python3 - <<'PY'import os, socketport = int(os.environ.get("API_PORT", "18083"))sock = socket.create_connection(("127.0.0.1", port), timeout=5)sock.sendall(b"GET /healthz HTTP/1.0\r\nHost: docs\r\n\r\n")print(sock.makefile().read().strip().splitlines()[-1])PYOKCheck one documented call. GET /api/v1/config/history answers 200 with its rows. It prints OK.
python3 - <<'PY'import os, urllib.requestport = os.environ.get("API_PORT", "18083")key = os.environ.get("API_KEY", "")base = f"http://127.0.0.1:{port}"req = urllib.request.Request(base + "/api/v1/config/history", method="GET")req.add_header("Authorization", f"Bearer {key}")with urllib.request.urlopen(req, timeout=5) as r: body = r.read().decode() assert r.status == 200, bodyassert "versions" in body, bodyprint("OK")PYOKNext steps
- API reference: the other tags.
- Configuration reference: the settings behind the rows.
- Metrics reference: the counter names.