Broker Setup TLS Example

Full MQTT broker mTLS walkthrough — create CA and server/user certificates, start TLS broker, publish with client certs, optional CA on blockchain.


Configure MQTT TLS and authentication

Full worked example for securing AnyLog’s MQTT message broker with TLS and optional client certificates (mTLS). For the shorter overview, see MQTT Message Broker — MQTT over TLS and mTLS.

Create CA Authority for self signed TLS certificates

<id generate certificate authority where country = US and
  state = CA and locality = "Redwood City" and
  org = MQTT_CA_TLS and
  output_name = "MQTT_CA_TLS" and
  expiration_days = 3650
>

Create certificate request

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = "Anylog MQTT broker TLS"
  and hostname = op1
  and alt_name = 192.168.1.60
  and ip = 192.168.1.60 and
  output_name = "server-mqtt-op1"
>

Sign certificate with above CA

<id sign certificate request where ca_org = MQTT_CA_TLS and ca_output_name = "MQTT_CA_TLS"
  and server_org = "Anylog MQTT broker TLS" and output_name = "server-mqtt-op1"
  and expiration_days = 3650
>

Writes under !pem_dir: MQTT_CA_TLS.crt / .key, server-mqtt-op1.csr / .key / .pem, then server-mqtt-op1.crt.

Notes:

  • The server certificate requires IP address(es) and/or a domain name, for example:
    • IPAddress:192.168.1.60
    • DNS:localhost
  • All commands in this self-signed walkthrough are issued on an operator node, say op1.
  • Optional: if the CA private key must stay on a remote master (not on this operator), sign with certificate_authority = !master_node instead of a local CA key. See Optional: remote signing with a master. Remote master signing is not required for this walkthrough.

Create user certificates for an organization

If the organization that wants to connect to the AnyLog MQTT TLS broker does not have user certificates, create them and pass the following to the organization:

  • user*.crt / user*.key (one pair per user; CN matches allowed_users, e.g. user1, user2)
  • MQTT_CA_TLS.crt (broker TLS CA public key — so the client can trust the broker)

Do not share any other private key with the organization.

Example on the operator:

<id generate certificate authority where country = US and
  state = CA and locality = "Redwood City" and
  org = MQTT_CA_users and
  output_name = "MQTT_CA_users" and
  hostname = MQTT_CA_users and
  expiration_days = 3650
>

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = AnyLog and hostname = user1 and output_name = "user1"
>

<id sign certificate request where ca_org = MQTT_CA_users and ca_output_name = "MQTT_CA_users"
  and server_org = AnyLog and output_name = "user1" and expiration_days = 825
>

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = AnyLog and hostname = user2 and output_name = "user2"
>

<id sign certificate request where ca_org = MQTT_CA_users and ca_output_name = "MQTT_CA_users"
  and server_org = AnyLog and output_name = "user2" and expiration_days = 825
>

Writes under !pem_dir: MQTT_CA_users.crt / .key, plus user1 / user2 .csr / .key / .crt.

Give the organization: user1.crt / user1.key, user2.crt / user2.key, and MQTT_CA_TLS.crt only. Keep all other keys and CA material on the AnyLog side.

Start MQTT broker

Start the broker with the certificate files written above (!pem_dir is typically ./data/pem):

<run message broker where external_ip = 192.168.1.60 and external_port = 8883 and threads = 6
  and enable_tls = true
  and tls_cert = !pem_dir/server-mqtt-op1.crt
  and tls_key = !pem_dir/server-mqtt-op1.key
  and users_ca = !pem_dir/MQTT_CA_users.crt
  and allowed_users = (user1, user2)
>

allowed_users is optional. When set, user1, user2, etc. are the CN values in the client certificates that are allowed to connect.

users_ca (MQTT_CA_users.crt) authenticates MQTT clients (mTLS). It is not the same file as the broker listener CA (MQTT_CA_TLS.crt).

Make use of existing certificate files, coming from an outside organization

If an outside organization already provides the broker TLS material and the client CA, put those files on the Operator under !pem_dir (or another path you choose). Use distinct names (for example an ext_ prefix) so they are not confused with certificates generated in the sections above:

Role Example files
Broker listener certificate / key ext_server_tls.crt, ext_server_tls.key
Client authentication CA (mTLS) ext_MQTT_CA_users.crt
<run message broker where external_ip = 192.168.1.60 and external_port = 8883 and threads = 6
  and enable_tls = true
  and tls_cert = !pem_dir/ext_server_tls.crt
  and tls_key = !pem_dir/ext_server_tls.key
  and users_ca = !pem_dir/ext_MQTT_CA_users.crt
  and allowed_users = (user1, user2)
>

Requirements for the external server certificate:

  • It must cover the broker IP and/or DNS name clients will use (for example IPAddress:192.168.1.60 or DNS:mqtt.example.com).
  • Clients need the matching CA (or trust chain) that signed ext_server_tls.crt so they can validate the broker.
  • users_ca must be the CA that issued the client certificates whose CNs appear in allowed_users.

Create local broker for ingestion

For a given topic (my_topic) or all topics:

<run msg client where broker = local and
       topic = (name = my_topic and
       dbms = mydb and
       table = my_topic and
       column.payload.str = "bring [value]")
>

Publish data from a client using TLS and user certificate

mosquitto_pub -p 8883 -h 192.168.1.60 \
  --cafile ./MQTT_CA_TLS.crt \
  --cert ./user1.crt \
  --key ./user1.key \
  -d \
  -m '{"value":"enabled"}' \
  -t test2

Note: --cafile ./MQTT_CA_TLS.crt may be required if the client application cannot trust the self-signed certificate used for the AnyLog broker TLS listener.

MQTT Explorer client setup

In MQTT Explorer, configure the connection to mqtt://192.168.1.60:8883/ with:

  • SERVER CERTIFICATE (CA): MQTT_CA_TLS.crt (or the broker listener CA)
  • CLIENT CERTIFICATE: e.g. user1.crt / AnyLogUser1.crt
  • CLIENT KEY: e.g. user1.key / AnyLogUser1.key

MQTT Explorer TLS setup

Share CA Users in the blockchain

Full example: create a custom client CA (MQTT_CA_users), publish its public certificate as a ca policy, then reuse it on Operators as users_ca (no file copy to every node).

1. Create MQTT_CA_users on the Master

set master_node = 192.168.1.88:32048

<id generate certificate authority where country = US and
  state = CA and locality = "Redwood City" and
  org = MQTT_CA_users and
  output_name = "MQTT_CA_users" and
  hostname = MQTT_CA_users and
  expiration_days = 3650
>

Writes !pem_dir/MQTT_CA_users.crt and !pem_dir/MQTT_CA_users.key. Keep the .key on the Master only.

Optionally issue user certs signed by this CA (same as Create user certificates for an organization):

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = AnyLog and hostname = user1 and output_name = "user1"
>

<id sign certificate request where ca_org = MQTT_CA_users and ca_output_name = "MQTT_CA_users"
  and server_org = AnyLog and output_name = "user1" and expiration_days = 825
>

2. Add MQTT_CA_users to the blockchain

Publish the public certificate (contents of !pem_dir/MQTT_CA_users.crt) as a ca policy:

# Paste the PEM text from !pem_dir/MQTT_CA_users.crt into the certificate field
<policy = {"ca":{
  "name": "MQTT_CA_users",
  "company": "AnyLog",
  "usage": "CA for mqtt_users",
  "certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n"
}}
>

blockchain prepare policy !policy
blockchain insert where policy = !policy and local = true and master = !master_node

Do not put MQTT_CA_users.key in the policy — only the public certificate.

3. Verify the policy

blockchain get ca where name = MQTT_CA_users
blockchain get ca where name = MQTT_CA_users bring [ca][certificate]

4. On an Operator — load users_ca from the blockchain

users_ca = blockchain get ca where name = MQTT_CA_users bring [ca][certificate]

<run message broker where external_ip = 192.168.1.60 and external_port = 8883 and threads = 6
  and enable_tls = true
  and tls_cert = !pem_dir/server-mqtt-op1.crt
  and tls_key = !pem_dir/server-mqtt-op1.key
  and users_ca = !users_ca
  and allowed_users = (user1, user2)
>

If the listener certificate came from an outside organization instead, use those paths (for example !pem_dir/ext_server_tls.crt / .key) as in Make use of existing certificate files.

Scenario: Master node + Operator with remote signing

Remote signing is optional. Use it when the CA private key must stay on the AnyLog Master node. Background: Optional: remote signing with a master.

Operators do not get CA private keys (MQTT_CA_TLS.key, MQTT_CA_users.key). For users_ca, either copy MQTT_CA_users.crt from the Master or load it from the blockchain (see below). MQTT clients get MQTT_CA_TLS.crt.

Who Gets
Master Keeps CA private keys; creates CAs and signs CSRs; can publish MQTT_CA_users to the blockchain
Operator server-mqtt-op1.crt / .key (remote sign) + users_ca via file copy or blockchain
MQTT clients user*.crt / .key and MQTT_CA_TLS.crt

Topology

Node IP:port (example) Holds Does
Master 192.168.1.88:32048 MQTT_CA_TLS.key, optionally MQTT_CA_users.key Creates CAs; signs CSRs
Operator op1 192.168.1.60 server-mqtt-op1.key Creates broker CSR; remote-signs; runs MQTT broker
MQTT clients user1.key / user2.key Publish with mTLS

On the Master — create broker CA once

<id generate certificate authority where country = US and
  state = CA and locality = "Redwood City" and
  org = MQTT_CA_TLS and
  output_name = "MQTT_CA_TLS" and
  expiration_days = 3650
>

Keep MQTT_CA_TLS.key on the Master only.

Create the client CA and user certificates on the Master (local sign), then give clients only user*.crt / user*.key and MQTT_CA_TLS.crt:

<id generate certificate authority where country = US and
  state = CA and locality = "Redwood City" and
  org = MQTT_CA_users and
  output_name = "MQTT_CA_users" and
  hostname = MQTT_CA_users and
  expiration_days = 3650
>

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = AnyLog and hostname = user1 and output_name = "user1"
>

<id sign certificate request where ca_org = MQTT_CA_users and ca_output_name = "MQTT_CA_users"
  and server_org = AnyLog and output_name = "user1" and expiration_days = 825
>

Optional — publish MQTT_CA_users.crt to the blockchain for reuse on every Operator (same steps as Share CA Users in the blockchain):

set master_node = 192.168.1.88:32048

# Paste the PEM text from !pem_dir/MQTT_CA_users.crt into [certificate]
<policy = {"ca":{
  "name": "MQTT_CA_users",
  "company": "AnyLog",
  "usage": "CA for mqtt_users",
  "certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n"
}}
>

blockchain prepare policy !policy
blockchain insert where policy = !policy and local = true and master = !master_node

On the Operator — broker CSR + remote sign

set master_node = 192.168.1.88:32048

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = "Anylog MQTT broker TLS"
  and hostname = op1
  and alt_name = 192.168.1.60
  and ip = 192.168.1.60 and
  output_name = "server-mqtt-op1"
>

<id sign certificate request where ca_org = MQTT_CA_TLS and ca_output_name = "MQTT_CA_TLS"
  and server_org = "Anylog MQTT broker TLS" and output_name = "server-mqtt-op1"
  and expiration_days = 3650
  and certificate_authority = !master_node
>

Result on the Operator: server-mqtt-op1.crt under !pem_dir. The Operator never receives MQTT_CA_TLS.key or MQTT_CA_users.key.

On the Operator — get users_ca (file copy or blockchain)

Option A — copy the file from Master

Copy MQTT_CA_users.crt from the Master’s !pem_dir into the Operator’s !pem_dir. Do not copy CA private keys.

<run message broker where external_ip = 192.168.1.60 and external_port = 8883 and threads = 6
  and enable_tls = true
  and tls_cert = !pem_dir/server-mqtt-op1.crt
  and tls_key = !pem_dir/server-mqtt-op1.key
  and users_ca = !pem_dir/MQTT_CA_users.crt
  and allowed_users = (user1, user2)
>

Option B — load from the blockchain (after the Master published the ca policy above)

users_ca = blockchain get ca where name = MQTT_CA_users bring [ca][certificate]

<run message broker where external_ip = 192.168.1.60 and external_port = 8883 and threads = 6
  and enable_tls = true
  and tls_cert = !pem_dir/server-mqtt-op1.crt
  and tls_key = !pem_dir/server-mqtt-op1.key
  and users_ca = !users_ca
  and allowed_users = (user1, user2)
>

Additional Operators repeat the CSR + remote-sign steps with their own output_name and IP (for example server-mqtt-op2), then use Option A or B for users_ca.