Cloud-only IoT pipelines are brittle during connectivity outages. I prefer running a local MQTT broker on Raspberry Pi and forwarding data upstream when possible.
Mosquitto with persistent sessions and retained state gives a robust baseline. I split topics by device class and enforce ACL rules so each client publishes only to its namespace.
For observability, I forward broker metrics into a small dashboard and alert on queue growth, client churn, and authentication failures.
This edge-first approach keeps automation loops responsive locally, while still allowing cloud analytics once links recover.
A minimal broker configuration
The baseline I deploy is deliberately small. It defines one authenticated listener, turns on persistence so retained messages and queued QoS 1/2 traffic survive a restart, and points at an ACL file rather than allowing anonymous access:
# /etc/mosquitto/mosquitto.conf
listener 1883 0.0.0.0
persistence true
persistence_location /var/lib/mosquitto/
autosave_interval 60
# Authentication and authorization
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl
log_dest file /var/log/mosquitto/mosquitto.log
The password file is generated with mosquitto_passwd -c /etc/mosquitto/passwd <user>, and the ACL file restricts each client to its own namespace so a compromised sensor cannot publish everywhere:
# /etc/mosquitto/acl
user ingest
topic readwrite site/#
user sensor-greenhouse
topic write site/greenhouse/#
Store-and-forward bridge to the cloud
The point of the edge broker is that local automation keeps working when the upstream link is down. A bridge handles the forwarding, and with persistence enabled it queues messages while the WAN is offline and replays them on reconnect:
# --- Bridge to upstream cloud broker ---
connection cloud-uplink
address cloud.example.org:8883
bridge_protocol_version mqttv311
# Forward local telemetry up; do not pull everything back down
topic site/# out 1 "" ""
# Survive outages: keep the queue and retry
bridge_insecure false
cleansession false
notifications true
restart_timeout 30
try_private true
cleansession false is the key line for store-and-forward: it keeps the bridge's queued messages across reconnects instead of discarding them. I keep the topic mapping one-directional (out) unless the cloud genuinely needs to command local devices, which avoids surprise loops between the two brokers.
Sources
- Imported from the previous version of the site (gaborl.hu). Original publication around 2024-12-30.
Update history
- — Adopted from previous gaborl.hu (Hugo) site via legacy import.