Home Assistant, Node-RED, Raspberry Pis, ESP32 microcontrollers and custom projects all need a simple way of exchanging commands and status information. Rather than building direct connections between every device, MQTT provides a central messaging layer that everything can use.
I originally ran the MQTT broker on a Raspberry Pi, which worked perfectly well. As the homelab evolved, however, it made more sense to move the broker onto my Synology DS224+ alongside the rest of my always-on infrastructure.
In this guide I’ll deploy Eclipse Mosquitto using Docker and Portainer on a Synology DS224+, configure persistent storage, and connect devices across the Realm Labs network.
What MQTT Actually Does
MQTT stands for Message Queuing Telemetry Transport.
Despite the name, the important concept is fairly simple: devices don’t normally communicate directly with each other.
Instead, they connect to an MQTT broker.
A device can publish a message to a topic:
tardis/light/set
Another device can subscribe to that topic.
When a message such as:
ON
is published, the broker delivers it to anything subscribed to that topic.
This creates a very flexible architecture.
ESP32 ───────┐
│
Raspberry Pi ├──── MQTT Broker ──── Node-RED
│
Home Assistant ───┘
Devices don’t need to know where every other device is located. They only need to know the address of the MQTT broker and which topics they should publish or subscribe to.
Why Move MQTT to the Synology?
Mosquitto is extremely lightweight, so a Raspberry Pi is already more than capable of running it.
Moving it to the Synology wasn’t about performance.
It was about centralising infrastructure.
My DS224+ is already running continuously and hosts several services used around Realm Labs. Running Mosquitto there means MQTT is no longer dependent on one of my Raspberry Pi project controllers remaining online.
It also gives me:
- persistent Docker storage
- straightforward backups
- management through Portainer
- a single fixed MQTT endpoint
- less infrastructure running directly on individual Raspberry Pis
My Synology DS224+ currently sits at:
192.168.68.20
So that becomes the MQTT endpoint used throughout the lab.
192.168.68.20:1883
The Realm Labs MQTT Architecture
MQTT now acts as a small internal message bus between several systems.
For example:
┌──────────────────┐
│ Home Assistant │
└────────┬─────────┘
│
│
┌──────────┐ ┌──────▼───────┐ ┌──────────┐
│ ESP32 │◄────────►│ Mosquitto │◄────────►│ Node-RED │
└──────────┘ │ 192.168.68.20│ └──────────┘
└──────┬───────┘
│
┌─────▼──────┐
│Raspberry Pi│
│ Controllers│
└────────────┘
One example is my automated model TARDIS.
Node-RED can publish a command such as:
pi/tardis/command
The Raspberry Pi inside the project subscribes to that topic and performs the requested action.
The same approach can be used for lighting, sensors, relays, dashboards and practically anything else capable of speaking MQTT.
Creating the Mosquitto Folders
First I created somewhere on the Synology to store the persistent Mosquitto configuration.
The structure is essentially:
mosquitto/
├── config/
├── data/
└── log/
Mosquitto expects its main configuration file inside the config directory:
mosquitto.conf
Using persistent directories is important because otherwise configuration and broker data could disappear when the Docker container is recreated.
Creating mosquitto.conf
For an initial test on a trusted internal network, the configuration can be kept extremely simple.
Create:
mosquitto/config/mosquitto.conf
with:
listener 1883
allow_anonymous true
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
This creates the standard MQTT listener on TCP port 1883.
The line:
allow_anonymous true
allows clients to connect without a username or password.
That’s convenient while testing, but I’ll cover authentication later because permanently running an unrestricted broker isn’t ideal even on a home network.
Deploying Mosquitto in Portainer
With the directories prepared, open:
Portainer → Stacks → Add stack
I called mine:
mosquitto
The stack is very small:
services:
mosquitto:
image: eclipse-mosquitto:latest
container_name: mosquitto
restart: unless-stopped
ports:
- "1883:1883"
volumes:
- /path/to/mosquitto/config:/mosquitto/config
- /path/to/mosquitto/data:/mosquitto/data
- /path/to/mosquitto/log:/mosquitto/log
Replace:
/path/to/mosquitto/
with the actual location of the Mosquitto folders on your Synology.
Then select:
Deploy the stack
Portainer will download the Eclipse Mosquitto image and start the container.
Checking Mosquitto Has Started
Once deployed, open:
Containers → mosquitto → Logs
You should see Mosquitto start and listen on port:
1883
The broker should now be reachable at:
192.168.68.20:1883
That address can now be used by Home Assistant, Node-RED, Raspberry Pis, ESP32 devices or anything else on the network.
Testing MQTT from Linux
One of the easiest ways of confirming everything works is with the Mosquitto command-line tools.
On Debian, Ubuntu or Raspberry Pi OS:
sudo apt update
sudo apt install mosquitto-clients
Open one terminal and subscribe to everything:
mosquitto_sub -h 192.168.68.20 -t "#" -v
The # wildcard subscribes to every topic visible to the client.
Now open another terminal and publish a message:
mosquitto_pub \
-h 192.168.68.20 \
-t "realmlabs/test" \
-m "Hello Realm Labs"
The subscriber should immediately show:
realmlabs/test Hello Realm Labs
At that point the broker is working.
Connecting Node-RED
Node-RED has excellent MQTT support built in.
Add either an:
mqtt in
or:
mqtt out
node and configure the broker as:
Server: 192.168.68.20
Port: 1883
A simple flow might subscribe to:
home/sensors/temperature
while another MQTT node publishes commands to:
home/lights/office/set
This is where MQTT becomes particularly useful because Node-RED can act as the automation layer while Mosquitto handles message delivery.
Connecting an ESP32
The same broker can be used by ESP32 microcontrollers.
Using the Arduino PubSubClient library, the broker configuration looks something like:
#include <WiFi.h>
#include <PubSubClient.h>
const char* mqtt_server = "192.168.68.20";
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
client.setServer(mqtt_server, 1883);
}
A device can then publish data:
client.publish(
"home/lab/esp32/temperature",
"22.4"
);
Node-RED or Home Assistant could subscribe to that topic and react immediately.
Using MQTT with Raspberry Pi Projects
Raspberry Pis can also subscribe to MQTT directly from Python.
For example, the Pi controller used by my TARDIS project listens for MQTT instructions and executes local GPIO and audio actions.
Conceptually:
Node-RED
│
│ MQTT
▼
pi/tardis/command
│
▼
Mosquitto
│
▼
Raspberry Pi
│
├── GPIO lighting
├── audio
└── Python scripts
This separation works particularly well.
Node-RED decides what should happen, while the Raspberry Pi is responsible for physically doing it.
The two systems only need MQTT to communicate.
A Better Topic Structure
Once more than a handful of devices use MQTT, naming topics consistently becomes important.
I prefer hierarchical names such as:
realmlabs/tardis/light/set
realmlabs/tardis/status
realmlabs/garage/temperature
realmlabs/office/light/set
realmlabs/esp32/temperature
That makes it possible to subscribe to groups of devices.
For example:
realmlabs/tardis/#
subscribes to everything associated with the TARDIS.
Or:
realmlabs/+/temperature
can match temperature topics from several devices.
A sensible topic structure saves a lot of confusion once MQTT starts spreading throughout the network.
Adding MQTT Authentication
Once the basic setup is working, anonymous access should ideally be disabled.
Open a terminal inside the Mosquitto container or use an appropriate Mosquitto installation to create a password file:
mosquitto_passwd -c /mosquitto/config/passwords realmlabs
Enter a password when prompted.
Then modify mosquitto.conf:
listener 1883
allow_anonymous false
password_file /mosquitto/config/passwords
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
Restart the container.
Clients will now require the username and password before they can connect.
Node-RED and Home Assistant both support MQTT credentials directly within their broker configuration.
Should MQTT Be Exposed to the Internet?
Generally, no.
My Mosquitto broker is designed as an internal Realm Labs service.
I don’t expose port 1883 directly through the router.
If remote access is required, I would much rather connect back into the home network through a VPN such as WireGuard and then access MQTT as though I were at home.
If MQTT genuinely needs to operate across untrusted networks, TLS certificates and stronger access controls should be configured.
Simply forwarding port 1883 to the Internet is not something I’d recommend.
The Result
Moving Mosquitto onto the Synology DS224+ has given Realm Labs a simple central communication layer for automation projects.
The architecture is now effectively:
Realm Labs Network
Synology DS224+
192.168.68.20
│
Mosquitto
│
┌──────────────┼──────────────┐
│ │ │
Node-RED Home Assistant ESP32
│
│
Raspberry Pi
Controllers
│
├── TARDIS
├── lighting
├── GPIO
└── future projects
Mosquitto itself requires almost no resources, but putting it at the centre of the network makes everything around it much easier to integrate.
And that’s really the strength of MQTT.
Rather than every project becoming another isolated collection of scripts and APIs, they can all communicate through one lightweight messaging system.
As Realm Labs continues to grow, this little Mosquitto container is likely to end up connecting a surprising amount of it.

