Skip to content

MQTT / EMQX

Broker: mqtts.tagai.xyz:8883 (TLS listener, verify_peer=true, fail_if_no_peer_cert=true — client certificates are required, not optional).

Authentication

Devices authenticate with per-device X.509 client certificates (mTLS), not usernames/passwords. This is the only auth method actually in production — a JWT secondary-auth scheme was researched and designed but never implemented; see decisions/ history if you're picking that work back up.

  • CA and cert generation: task mqtt:init (one-time CA setup), then task mqtt:cert DEVICE=<id> per device (scripts/provision-mqtt-certs.sh, 2-year cert validity)
  • Certs land in config/<device-id>/mqtt/ on the control node and get synced to /home/{{ ansible_user }}/.node-red/mqtt/ on the device by the mqtt_client and node_red Ansible roles
  • Renewal: task ansible:renew-certs — warns/renews when a cert has fewer than 30 days left (mqtt_cert_expiry_threshold_days in ansible/inventory/production/group_vars/all.yml)

Broker-side setup

Full EMQX 6 configuration (TLS listener, certificate authenticator) is in reference/emqx-mtls-configuration.md and reference/emqx-certificate-auth-setup.md, with the actual EMQX config file at reference/emqx-certificate-auth.conf.

Device-side (Node-RED)

Node-RED's MQTT client node configuration and cert wiring: reference/nodered-mqtt-client.md, reference/mqtt-mtls-implementation.md.

Checking a device's certificate

ssh tagai@<device>-ssh.tagai.uk
openssl x509 -in ~/.node-red/mqtt/client.crt -noout -enddate