Raspberry Pi

Mosquitto Bridge Configuration: Forward Local Topics to a Cloud Broker over TLS

Configure a Mosquitto bridge on a Raspberry Pi that forwards selected local topics to a cloud MQTT broker over TLS, receives commands back, queues messages during outages and avoids message loops.

Diagram of a Raspberry Pi local broker forwarding topics to a cloud broker using a mosquitto bridge configuration over TLS
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

A good mosquitto bridge configuration lets a local broker on a Raspberry Pi keep serving devices on the LAN while forwarding exactly the topics you choose to a cloud broker. In this tutorial you will build a bridge that connects to ConnectMQ over TLS with portal credentials, remaps topics so each site has its own namespace, sends commands back down, queues messages through internet outages and avoids the classic message loop. Each option is explained, so you can adapt the file instead of copying it blindly.

How a Mosquitto Bridge Works

A bridge is not a special protocol. The local Mosquitto broker opens an outbound connection to the remote broker and behaves like a normal MQTT client: it subscribes on one side and republishes on the other, according to topic lines in its config. That has three useful consequences:

  • No inbound ports. The Pi connects out over port 8883, just like a browser connecting to a website. Your router stays closed.
  • The remote broker needs nothing special. Any standards-compliant broker accepts a bridge, because it simply sees a client log in with a username, password and client ID.
  • You choose what crosses the boundary. Only topics matched by a topic line leave or enter the site.

In this setup the remote side is ConnectMQ, a managed MQTT broker. The bridge authenticates with the generated credentials from the portal like any other device. If you have not set up the local broker yet, follow install Mosquitto on Raspberry Pi first.

 Sensors / PLC gateway / Node-RED (LAN)
          |  mqtt://pi:1883  (local users)
          v
 +---------------------------+
 |  Mosquitto on Raspberry Pi |
 |  bridge "connectmq"        |
 +---------------------------+
          |  mqtts://broker.connectmq.com:8883
          |  remote_username / remote_password / remote_clientid
          v
 +---------------------------+
 |  ConnectMQ cloud broker    |  dashboards, phones, other sites
 +---------------------------+

Before You Start

  1. A Raspberry Pi with Mosquitto 2.0 running and at least one authenticated local listener.
  2. A cloud broker with credentials. Sign up at the portal, choose a plan, create a broker and copy the generated username, password and client ID. The client ID is bound to those credentials, so the bridge must use it exactly.
  3. A plan for topic names. Decide how local topics should look in the cloud. A site prefix such as site1/ keeps several Pis from colliding.

For a quick experiment without an account you can bridge to the public MQTT test broker on port 1883 with no credentials and any unique client ID, using a random prefix like connectmq/demo/3c7d52/. Everything there is publicly readable, so use only dummy data.

The Complete Mosquitto Bridge Configuration

Create /etc/mosquitto/conf.d/bridge-connectmq.conf:

# ---- Connection ----
connection connectmq
address broker.connectmq.com:8883
bridge_protocol_version mqttv311
try_private false
start_type automatic
restart_timeout 5 60
keepalive_interval 60

# ---- TLS ----
bridge_capath /etc/ssl/certs
bridge_insecure false

# ---- Credentials from the ConnectMQ portal ----
remote_clientid YOUR_CLIENT_ID
remote_username YOUR_USERNAME
remote_password YOUR_PASSWORD

# ---- Session and queueing ----
cleansession false
local_clientid bridge-connectmq-local

# ---- Status topic (published on the remote side) ----
notifications true
notifications_local_only false
notification_topic site1/bridge/state

# ---- Topic mapping ----
# Telemetry up: local "sensors/#" -> remote "site1/sensors/#"
topic sensors/# out 1 "" site1/
# Machine states up, retained values preserved
topic machines/+/state out 1 "" site1/
# Commands down: remote "site1/cmd/#" -> local "cmd/#"
topic cmd/# in 1 "" site1/

Restart and follow the log:

sudo chmod 0640 /etc/mosquitto/conf.d/bridge-connectmq.conf
sudo chown root:mosquitto /etc/mosquitto/conf.d/bridge-connectmq.conf
sudo systemctl restart mosquitto
sudo journalctl -u mosquitto -f

You should see Connecting bridge connectmq (broker.connectmq.com:8883) followed by no errors. The permission change matters because the file contains the remote password.

Option by Option

Option Value here Why
address broker.connectmq.com:8883 TLS port of the cloud broker
bridge_protocol_version mqttv311 Widely supported; MQTT 5 bridging is also possible on recent Mosquitto
try_private false Avoids a Mosquitto-only bridge flag that non-Mosquitto brokers may reject
restart_timeout 5 60 Back off from 5 s up to 60 s between reconnect attempts
bridge_capath /etc/ssl/certs System CA store validates the broker's Let's Encrypt certificate
bridge_insecure false Keep hostname verification on, always
remote_clientid Portal client ID Must match the issued credentials
cleansession false Keep sessions so QoS 1 messages queue during outages
notifications true Publishes 1 when the bridge connects and 0 (as last will) when it drops
notification_topic site1/bridge/state Keeps the status inside your own namespace

Understanding the topic Line

The syntax is topic <pattern> <direction> <qos> <local-prefix> <remote-prefix>. Mosquitto strips the local prefix from a local topic and adds the remote prefix when forwarding out, and does the reverse for in. With an empty local prefix (written as "") and remote prefix site1/:

  • Local sensors/boiler/temp becomes remote site1/sensors/boiler/temp.
  • Remote site1/cmd/pump1/set becomes local cmd/pump1/set.

Note that the remote prefix ends with a slash. Without it you get site1sensors/..., a mistake that is easy to make and hard to spot.

QoS on the Bridge

The QoS on a topic line is the maximum used across the bridge. QoS 1 is the practical choice: it guarantees delivery with acknowledgements and is supported on every plan, including the free Serverless plan, which caps QoS at 1. Use QoS 2 only if you are on a plan that supports it and the data truly cannot tolerate duplicates. The MQTT QoS levels explained article covers the trade-offs.

Queueing During Internet Outages

With cleansession false, the local broker keeps the bridge's session while the connection is down and queues QoS 1 messages for it. When the link returns, the backlog drains to the cloud. The queue is bounded by max_queued_messages (and optionally max_queued_bytes) in your main config. Size it for the longest outage you want to cover; on a Pi with an SD card, keep it moderate, because persisted queues are written to disk at each autosave. QoS 0 messages are not queued, which is another reason to bridge telemetry at QoS 1.

Remember that the cloud side applies its own limits too. If a long backlog arrives in a burst, a broker with per-plan quotas and flood protection may throttle it, so very long outages are better handled by an application-level buffer such as the one in the offline message buffering guide.

Testing the Bridge End to End

Subscribe on the cloud side. With the public broker you can use mosquitto_sub directly; with a private broker use a second set of credentials or the portal's in-browser MQTT client:

mosquitto_sub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
  -u YOUR_USERNAME_2 -P YOUR_PASSWORD_2 -i YOUR_CLIENT_ID_2 \
  -t 'site1/#' -v

Publish locally on the Pi:

mosquitto_pub -h localhost -u sensors -P 'sensors-password' -i t1 -q 1 \
  -t sensors/boiler/temp -m 64.2

The cloud subscriber prints site1/sensors/boiler/temp 64.2 and site1/bridge/state 1. Now test the downlink. Subscribe locally to cmd/#, then publish from the cloud side to site1/cmd/pump1/set. The message arrives locally as cmd/pump1/set.

Finally, test an outage: stop the network on the Pi (sudo nmcli networking off), publish a few QoS 1 messages locally, re-enable networking and watch them arrive in the cloud. The bridge state topic goes to 0 while the link is down, delivered by the broker as the bridge's last will.

Avoiding Loops in Your Mosquitto Bridge Configuration

A loop happens when a message forwarded out comes back in and is forwarded out again. The most common cause is a both rule, or overlapping in and out patterns, on the same topics:

# Dangerous: anything under site1/ bounces back and forth
topic # both 1 "" site1/

Keep directions on separate subtrees: telemetry and states go out, commands come in under a different branch (cmd/). If you truly need both, prefer MQTT 5 bridging with no-local subscriptions where your Mosquitto version supports it, and test carefully. Never bridge # without a prefix in either direction.

Multiple Sites, One Cloud Broker

Each Pi gets its own credentials and its own prefix (site1/, site2/, ...). Dashboards subscribe to +/sensors/# to see every site, or to one prefix for a single site. Because each bridge has a unique client ID tied to its credentials, revoking one site never affects the others. Paid Serverless plans add shared subscriptions, which help when several cloud consumers need to split the combined stream. Industrial sites can go further and adopt an ISA-95 style hierarchy such as enterprise/site/area/line/cell, which the portal detects and shows in its devices view.

Troubleshooting

Log message or symptom Cause Fix
Connection Refused: not authorised Wrong credentials or client ID Copy all three from the portal again
certificate verify failed Missing CA store or wrong time Install ca-certificates, check NTP with timedatectl
Bridge connects, nothing arrives Topic pattern or prefix mismatch Remember the trailing slash in prefixes
Connection drops every few seconds Another client using the same client ID One client ID per connection
Messages lost during outages QoS 0 or cleansession true Use QoS 1 and cleansession false
Message storm after enabling the bridge Loop from overlapping in/out rules Separate subtrees for each direction

Bridge Your Pi to ConnectMQ

Create a free Serverless broker at app.connectmq.com, no credit card required, paste the generated username, password and client ID into your bridge file and watch your site's topics appear in the portal's live topic explorer. For the broader gateway design around this bridge, read Raspberry Pi as an IoT gateway, and for the full Pi series, the Raspberry Pi MQTT tutorial.

Frequently Asked Questions

Does ConnectMQ need a special bridge feature for Mosquitto?

No. The Mosquitto bridge connects as a normal MQTT client using the username, password and client ID from the portal, so any plan works.

Should I bridge with MQTT 3.1.1 or MQTT 5?

MQTT 3.1.1 is the simplest and most widely tested choice for bridges. Recent Mosquitto versions support mqttv50 bridging if you need MQTT 5 features on the bridge link.

Why set try_private to false?

When enabled, Mosquitto signals that it is a bridge using a non-standard protocol flag intended for Mosquitto-to-Mosquitto links. Turning it off keeps the connection fully standard for other brokers.

How many messages does the bridge queue during an outage?

As many as max_queued_messages and max_queued_bytes allow, for QoS 1 and 2 messages with cleansession false. QoS 0 messages are dropped while the link is down.

Related articles

Pico W vs Pico 2 W for MQTT: RP2040 vs RP2350 Performance, Memory and TLS

The Pico 2 W keeps the Pico W's footprint and Wi-Fi chip but swaps the RP2040 for the faster RP2350. This comparison looks at what that means for MQTT devices: CPU, memory, TLS, security features, software support, and which board to buy for which project.

8 min read

Raspberry Pi RFID MQTT Access Logging with the RC522 Reader

Wire an RC522 RFID reader to a Raspberry Pi, read tags in Python, check them against a local allowlist and publish every access attempt as an MQTT event that loggers, dashboards and alerting tools can consume.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.