systemref

Deploying Lightweight Edge Gateways — Configuring an MQTT Broker on an Industrial Raspberry Pi

H. Maqsood Jun 29, 2026 2 min read mqtt rasberry-pi edge-gateway modbus iot mosquitto
An MQTT broker at the network edge collects data from legacy shop-floor devices over Modbus and republishes it to cloud platforms — without modifying the devices themselves.

Legacy shop-floor devices — PLCs, drives, power meters — speak Modbus TCP or RTU. They predate cloud connectivity and have no native MQTT support. An edge gateway running Mosquitto reads these devices over their existing protocol and republishes to any MQTT subscriber, including cloud IoT platforms. The devices see a normal Modbus poll. The cloud sees a structured message stream.


Hardware

A Raspberry Pi 4 (4GB) handles up to ~10,000 messages/second at this workload.

For industrial deployment:

  • Enclosure: DIN rail mount (Multicomp Pro, Waveshare, or equivalent). Control cabinets don't accommodate desktop hardware.
  • Power: 24VDC-to-5V DIN rail PSU. USB power adapters are not rated for continuous industrial duty.
  • Storage: Industrial-grade microSD (Transcend or SanDisk Industrial) or USB SSD. Consumer microSD fails under continuous write workloads within months.
  • Network: Assign a static IP at the switch level (DHCP reservation or manual). DHCP lease expiry in OT environments is a silent failure mode.

Install Mosquitto

sudo apt update && sudo apt install -y mosquitto mosquitto-clients
sudo systemctl enable mosquitto
sudo systemctl start mosquitto

Minimal broker config at /etc/mosquitto/conf.d/broker.conf:

# Internal OT network — authenticated, plaintext
listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd

# Cloud-facing — TLS required
listener 8883
cafile   /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/broker.crt
keyfile  /etc/mosquitto/certs/broker.key
require_certificate false

Create an OT client credential:

sudo mosquitto_passwd -c /etc/mosquitto/passwd ot_client
sudo systemctl restart mosquitto

Do not expose port 1883 outside the OT network segment. It is authenticated but not encrypted — suitable only on a trusted L2 segment behind a firewall.


Modbus-to-MQTT bridge

Read Modbus registers with pymodbus, publish to MQTT with paho-mqtt:

# modbus_bridge.py
from pymodbus.client import ModbusTcpClient
import paho.mqtt.client as mqtt
import json, time

DEVICE_IP   = '192.168.10.5'
BROKER_HOST = 'localhost'
TOPIC_BASE  = 'factory/cell-01/drive-01'

modbus = ModbusTcpClient(DEVICE_IP, port=502)
mq = mqtt.Client(client_id='bridge-drive-01')
mq.username_pw_set('ot_client', 'YOUR_PASSWORD')
mq.connect(BROKER_HOST, 1883)

modbus.connect()
mq.loop_start()

while True:
    result = modbus.read_holding_registers(address=0, count=4, slave=1)
    if not result.isError():
        payload = {
            'speed_rpm':  result.registers[0],
            'current_a':  result.registers[1] / 10.0,
            'temp_c':     result.registers[2] / 10.0,
            'status_word': result.registers[3],
            'ts': time.time()
        }
        mq.publish(TOPIC_BASE, json.dumps(payload), qos=1)
    time.sleep(1)

Use QoS 1 (at-least-once). QoS 0 drops messages silently on a broker restart or client disconnect — unacceptable for production telemetry. Run this as a systemd service with Restart=always.


Cloud bridge

Mosquitto's built-in bridge forwards topics to a remote broker. For AWS IoT Core:

# /etc/mosquitto/conf.d/cloud_bridge.conf
connection cloud-aws
address YOUR_ENDPOINT.iot.us-east-1.amazonaws.com:8883

bridge_cafile   /etc/mosquitto/certs/AmazonRootCA1.pem
bridge_certfile /etc/mosquitto/certs/device-cert.pem
bridge_keyfile  /etc/mosquitto/certs/device-private.pem

topic factory/# out 1

cleansession  false
start_type    automatic

cleansession false tells the remote broker to retain the session and queue messages during disconnections. Set max_queued_messages 10000 in the main config to cap RAM usage when the cloud link is down for extended periods.


Operational monitoring

Mosquitto exposes internal metrics on the $SYS topic tree:

mosquitto_sub -v -t '$SYS/#'

Key metrics to watch:

Topic Meaning
$SYS/broker/clients/connected Active subscriber count
$SYS/broker/messages/received Inbound message rate
$SYS/broker/publish/messages/dropped Messages dropped due to queue overflow
$SYS/broker/connection/cloud-aws/state Bridge connection state (0/1)

A non-zero dropped message count means the queue limit was hit — either the cloud link was down too long or the queue ceiling is too low. Address the root cause before raising the ceiling.