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), thentask 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 themqtt_clientandnode_redAnsible roles - Renewal:
task ansible:renew-certs— warns/renews when a cert has fewer than 30 days left (mqtt_cert_expiry_threshold_daysinansible/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