Secure ThingsBoard MQTTS with X.509 Certificate Chain and Auto-Provisioning

On this page8 sections

This guide builds on:

to enable:

  • Native MQTT over TLS (port 8883)
  • X.509 client certificate authentication
  • Device auto-provisioning using CN from the certificate
  • Full Root + Intermediate CA structure

Why We Removed MQTTS from HAProxy

In the earlier setup, HAProxy terminated TLS for MQTTS on port 8883 and forwarded unencrypted MQTT to ThingsBoard.

This approach does not support X.509 client authentication because:

  • ThingsBoard never sees the client certificate
  • Auto-provisioning using CN fails
  • Mutual TLS is broken

To support X.509 authentication and provisioning, we now:

  • Remove all MQTT handling from HAProxy
  • Let ThingsBoard directly terminate TLS on port 8883

Directory Layout

cert-x509/
├── devices
│   └── SN-000001
│       ├── SN-000001.crt
│       ├── SN-000001.csr
│       └── SN-000001.key
├── intermediate
│   ├── intermediate.csr
│   ├── intermediate.key
│   ├── intermediate.pem
│   └── intermediate.srl
├── rootCA.key
├── rootCA.pem
├── rootCA.srl
└── servers
    └── thingsboard
        ├── server.crt
        ├── server.csr
        ├── server.key
        └── server_chain.pem

1. Generate Root + Intermediate CA

Before you create a Root CA

This guide starts with a new private PKI: OpenSSL creates a Root CA, then that root signs a dedicated IoT Intermediate CA. It does not assume that you already have a private Root CA.

If you already have a Root CA, such as the one used by Step CA, you can reuse it to sign an IoT Intermediate CA, subject to its CA constraints. Skip the new Root CA generation commands below. For the EJBCA approach, follow this follow-up guide instead of creating the intermediate manually here.

The directory layout above is a working example, not a recommendation to keep CA private keys on the ThingsBoard server. Keep the Root CA private key in a protected signing environment, preferably offline, with secure backups. Use the Intermediate CA for routine issuance. Public CA certificates can be distributed to establish trust; CA private keys stay with their respective signing systems.

mkdir -p ~/cert-x509/intermediate

# Root CA (NO OU)
openssl genrsa -out ~/cert-x509/rootCA.key 4096
openssl req -x509 -new -key ~/cert-x509/rootCA.key -days 3650 -sha256 \
  -subj "/C=TW/ST=Taipei/L=Taipei/O=maksonlee.com/CN=MaksonLee Root CA" \
  -out ~/cert-x509/rootCA.pem

# Intermediate CA
openssl genrsa -out ~/cert-x509/intermediate/intermediate.key 4096
openssl req -new -key ~/cert-x509/intermediate/intermediate.key \
  -subj "/C=TW/ST=Taipei/L=Taipei/O=maksonlee.com/OU=IoT/CN=MaksonLee ThingsBoard Intermediate CA" \
  -out ~/cert-x509/intermediate/intermediate.csr

openssl x509 -req -in ~/cert-x509/intermediate/intermediate.csr \
  -CA ~/cert-x509/rootCA.pem -CAkey ~/cert-x509/rootCA.key \
  -CAcreateserial -out ~/cert-x509/intermediate/intermediate.pem \
  -days 1825 -sha256 \
  -extfile <(printf "basicConstraints=CA:TRUE,pathlen:0\nkeyUsage=critical,keyCertSign,cRLSign")

2. Remove MQTT from HAProxy

Edit /etc/haproxy/haproxy.cfg, remove following

# MQTTS (8883 -> MQTT 1883)
frontend mqtts-in
        bind *:8883 ssl crt /etc/haproxy/certs/thingsboard.maksonlee.com.pem
        mode tcp
        option tcplog
        default_backend thingsboard-mqtt
 
backend thingsboard-mqtt
        mode tcp
        server tb-mqtt 127.0.0.1:1883 check

Reload:

sudo systemctl reload haproxy
  • HAProxy handles only HTTPS (port 443)
  • MQTT (port 8883) will be handled natively by ThingsBoard

3. Enable Native MQTTS in ThingsBoard

Server certificate and device certificates

In this guide, the private Intermediate CA signs both the MQTT server certificate and the device certificates. These serve different purposes: the device verifies the server certificate, while ThingsBoard verifies the device certificate. They do not have to share a CA. The EJBCA follow-up uses Let’s Encrypt for the server and the existing private Root plus EJBCA Intermediate for device identities.

  • Create server cert
mkdir -p ~/cert-x509/servers/thingsboard/
cd ~/cert-x509/servers/thingsboard/

openssl genrsa -out server.key 2048
openssl req -new -key server.key \
  -subj "/C=TW/ST=Taipei/L=Taipei/O=maksonlee.com/OU=IoT/CN=thingsboard.maksonlee.com" \
  -out server.csr

openssl x509 -req -in server.csr \
  -CA ../../intermediate/intermediate.pem -CAkey ../../intermediate/intermediate.key \
  -CAcreateserial -out server.crt -days 825 -sha256

# Create server_chain.pem (used by ThingsBoard server)
cat ~/cert-x509/servers/thingsboard/server.crt ~/cert-x509/intermediate/intermediate.pem > ~/cert-x509/servers/thingsboard/server_chain.pem
  • Install in ThingsBoard
sudo mkdir -p /etc/thingsboard/certs
sudo cp server_chain.pem /etc/thingsboard/certs/server_chain.pem
sudo cp server.key /etc/thingsboard/certs/server.key
sudo chown -R thingsboard:thingsboard /etc/thingsboard/certs
  • Configure ThingsBoard
sudo vi /etc/thingsboard/conf/thingsboard.conf
export MQTT_SSL_ENABLED=true
export MQTT_SSL_CREDENTIALS_TYPE=PEM
export MQTT_SSL_PEM_CERT=/etc/thingsboard/certs/server_chain.pem
export MQTT_SSL_PEM_KEY=/etc/thingsboard/certs/server.key
  • Restart
sudo systemctl restart thingsboard

4. Configure Device Profile

In ThingsBoard Web UI:

  • Go to Device Profiles → temp-humidity → Device provisioning
  • Set
    Provision strategy: X509 Certificates Chain
    Create new devices: Enabled
    Certificate in PEM format: Paste your Intermediate CA
    CN Regular Expression variable: (.*)
  • Apply changes

Devices signed by this Intermediate CA will be trusted, and CN (e.g. SN-000001) will become the device name

5. Issue Device Certificate

mkdir -p ~/cert-x509/devices/SN-000001/
cd ~/cert-x509/devices/SN-000001/

openssl genrsa -out SN-000001.key 2048
openssl req -new -key SN-000001.key \
  -subj "/C=TW/ST=Taipei/L=Taipei/O=maksonlee.com/OU=Devices/CN=SN-000001" \
  -out SN-000001.csr

openssl x509 -req -in SN-000001.csr \
  -CA ../../intermediate/intermediate.pem -CAkey ../../intermediate/intermediate.key \
  -CAcreateserial -out SN-000001.crt -days 1095 -sha256

6. Connect Device over MQTTS

mosquitto_pub -d -q 1 \
  -h thingsboard.maksonlee.com \
  -p 8883 \
  --cafile ~/cert-x509/rootCA.pem \
  --cert   ~/cert-x509/devices/SN-000001/SN-000001.crt \
  --key    ~/cert-x509/devices/SN-000001/SN-000001.key \
  -t "v1/devices/me/telemetry" \
  -m '{"temperature": 25.8}'

The device will be auto-provisioned as SN-000001, assigned to the correct profile, and telemetry will be accepted over mutual TLS.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top