MQTT has gradually become one of the most useful pieces of infrastructure in my Realm Labs setup.

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.