HiveMQ Edge MQTT Bridges

HiveMQ Edge offers bidirectional MQTT bridge functionality to connect it to enterprise MQTT brokers and forward messages or receive messages from upstream.

You can configure bridges on the HiveMQ Edge UI or in your HiveMQ Edge configuration file.

Example HiveMQ Edge bridge configuration:
<hivemq>
...
    <mqtt-bridges>
        <mqtt-bridge>
            <id>my-hivemq-cloud-bridge</id>
            <remote-broker>
                <host>your.broker.host</host>
                <port>1883</port>
            </remote-broker>
            <forwarded-topics>
                <forwarded-topic>
                    <filters>
                        <mqtt-topic-filter>mytopic/#</mqtt-topic-filter>
                    </filters>
                </forwarded-topic>
            </forwarded-topics>
            <remote-subscriptions>
                <remote-subscription>
                    <filters>
                        <mqtt-topic-filter>myothertopic/#</mqtt-topic-filter>
                    </filters>
                </remote-subscription>
            </remote-subscriptions>
        </mqtt-bridge>
    </mqtt-bridges>
...
</hivemq>
Table 1. Available MQTT bridge parameters
Name Default Mandatory Description

id

yes

Unique identifier for this bridge. The identifier can contain letters, digits, underscores, and hyphens only.

remote-broker

yes

Connection information for the remote broker. For more information, see remote-broker.

forwarded-topics

no

Local topics that the bridge forwards to the remote broker. For more information, see Topic Mapping.

remote-subscriptions

no

Remote topics that the bridge subscribes to and publishes locally. For more information, see Topic Mapping.

loop-prevention

enabled, max 1 hop

no

Optional setting to reduce the possibility of unintentional message loops with MQTT bridging. For more information, see loop-prevention.

persist

true

no

Defines whether messages that wait for the remote broker keep their QoS level. For more information, see Message Queueing.

A bridge without forwarded-topics and without remote-subscriptions starts, but processes no messages. HiveMQ Edge logs a warning for such a bridge.

Bridge Remote Broker Configuration

The remote broker configuration contains all configurations about the MQTT connection/session to the remote broker.

Example bridge configuration with all remote broker settings:

<hivemq>
...
    <mqtt-bridges>
        <mqtt-bridge>
            <id>my-hivemq-cloud-bridge</id>
            <remote-broker>
                <host>my.broker.url</host>
                <port>1883</port>
                <authentication>
                    <mqtt-simple-authentication>
                        <username>user1</username>
                        <password>pass1</password>
                    </mqtt-simple-authentication>
                </authentication>
                <tls>
                    <enabled>true</enabled>
                    <keystore>
                        <path>/path/to/keystore.jks</path>
                        <password>pass2</password>
                        <private-key-password>pass3</private-key-password>
                    </keystore>
                    <truststore>
                        <path>/path/to/truststore.jks</path>
                        <password>pass4</password>
                    </truststore>
                    <cipher-suites>
                        <cipher-suite>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</cipher-suite>
                        <cipher-suite>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</cipher-suite>
                        <cipher-suite>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</cipher-suite>
                        <cipher-suite>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA</cipher-suite>
                    </cipher-suites>
                    <protocols>
                        <protocol>TLSv1.2</protocol>
                        <protocol>TLSv1.3</protocol>
                    </protocols>
                    <handshake-timeout>10</handshake-timeout>
                    <verify-hostname>true</verify-hostname>
                </tls>
                <mqtt>
                    <clean-start>false</clean-start>
                    <client-id>my-custom-mqtt-client-identifier</client-id>
                    <keep-alive>60</keep-alive>
                    <session-expiry>3600</session-expiry>
                </mqtt>
            </remote-broker>
            ...
        </mqtt-bridge>
    </mqtt-bridges>
...
</hivemq>
Table 2. remote-broker element options
Name Default Mandatory Description

host

yes

Hostname or IP address of the remote broker.

port

1883

no

Port of the remote broker.

authentication

no authentication

no

Username and password for the remote broker. For more information, see Authentication configuration.

tls

no TLS

no

TLS settings for the connection to the remote broker. For more information, see TLS configuration.

mqtt

no

MQTT session settings of the bridge client. For more information, see Remote broker MQTT connection configuration.

websocket

disabled

no

WebSocket transport settings. For more information, see WebSocket Support.

Authentication configuration

HiveMQ Edge bridges support MQTT username/password based authentication.

<hivemq>
...
    <mqtt-bridges>
        <mqtt-bridge>
            ...
            <remote-broker>
                <authentication>
                    <mqtt-simple-authentication>
                        <username>user1</username>
                        <password>pass1</password>
                    </mqtt-simple-authentication>
                </authentication>
              </remote-broker>
              ...
        </mqtt-bridge>
    </mqtt-bridges>
...
</hivemq>
Table 3. authentication element options
Name Default Mandatory Description

username

yes

Username

password

yes

Password

Both elements are required in the configuration file, and HiveMQ Edge sends credentials only when both are set. A bridge created through the REST API or the UI with a username and no password connects without authentication. When HiveMQ Edge rewrites config.xml, such a bridge is written without its authentication element. Leading or trailing whitespace in a username or password is sent to the remote broker as entered. HiveMQ Edge logs a warning for such a value.

TLS configuration

Secured connections can be configured with the tls configuration section.

<hivemq>
...
    <mqtt-bridges>
        <mqtt-bridge>
            <remote-broker>
                <tls>
                    <enabled>true</enabled>
                    <keystore>
                        <path>/path/to/keystore.jks</path>
                        <password>pass2</password>
                        <private-key-password>pass3</private-key-password>
                    </keystore>
                    <truststore>
                        <path>/path/to/truststore.jks</path>
                        <password>pass4</password>
                    </truststore>
                    <cipher-suites>
                        <cipher-suite>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</cipher-suite>
                        <cipher-suite>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</cipher-suite>
                        <cipher-suite>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</cipher-suite>
                        <cipher-suite>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA</cipher-suite>
                    </cipher-suites>
                    <protocols>
                        <protocol>TLSv1.2</protocol>
                        <protocol>TLSv1.3</protocol>
                    </protocols>
                    <handshake-timeout>10</handshake-timeout>
                    <verify-hostname>true</verify-hostname>
                </tls>
                ...
            </remote-broker>
            ...
        </mqtt-bridge>
    </mqtt-bridges>
...
</hivemq>

Mutual TLS (using client certificate) is automatically enabled if the keystore is set.

Table 4. tls element options
Name Default Mandatory Description

enabled

false

yes

Specifies whether TLS is enabled.

keystore

no

The keystore that contains the client certificate and private key to use for mTLS. If not set mTLS will not be used.

truststore

default java system truststore

no

The truststore containing the trusted certificates. If no truststore is set, the default system truststore is used.

cipher-suites

no

A list of cipher suites to support.

protocols

no

A list of protocols to support.

handshake-timeout

10

no

The duration of the TLS handshake timeout in seconds.

verify-hostname

true

no

Specifies whether the server certificate hostname is verified.

<hivemq>
...
    <mqtt-bridges>
        <mqtt-bridge>
            <remote-broker>
                <tls>
                    <keystore>
                        <path>/path/to/keystore.jks</path>
                        <password>pass2</password>
                        <private-key-password>pass3</private-key-password>
                    </keystore>
                    ...
                </tls>
                ...
            </remote-broker>
            ...
        </mqtt-bridge>
    </mqtt-bridges>
...
</hivemq>
Table 5. keystore element options
Name Default Mandatory Description

path

yes

The path on the local filesystem to the keystore. Keystores in JKS format and in PKCS12 format (.p12 or .pfx file extension) are supported.

password

yes

The password for the keystore.

private-key-password

yes

The password for the private key in the keystore.

<hivemq>
...
    <mqtt-bridges>
        <mqtt-bridge>
            <remote-broker>
                <tls>
                    <truststore>
                        <path>/path/to/truststore.jks</path>
                        <password>pass4</password>
                    </truststore>
                   ...
                </tls>
                ...
            </remote-broker>
            ...
        </mqtt-bridge>
    </mqtt-bridges>
...
</hivemq>
Table 6. truststore element options
Name Default Mandatory Description

path

yes

The path on the local filesystem to the truststore. Truststores in JKS format and in PKCS12 format (.p12 or .pfx file extension) are supported.

password

yes

The password for the truststore.

Remote broker MQTT connection configuration

<hivemq>
...
    <mqtt-bridges>
        <mqtt-bridge>
            <id>my-hivemq-cloud-bridge</id>
            <remote-broker>
                <mqtt>
                    <clean-start>false</clean-start>
                    <client-id>my-custom-mqtt-client-identifier</client-id>
                    <keep-alive>60</keep-alive>
                    <session-expiry>3600</session-expiry>
                </mqtt>
                ...
            </remote-broker>
            ...
        </mqtt-bridge>
    </mqtt-bridges>
...
</hivemq>
Table 7. Available remote broker MQTT connection parameters
Name Default Mandatory Description

clean-start

false

no

Defines whether the client wants to start a new session upon reconnection (clean-start = true) or resume a previous session if present (clean-start = false). The default in the configuration file is false. The bridge then resumes its session on the remote broker after a reconnection. A bridge created in the UI or through the REST API defaults to true. For MQTT 3 clients, the clean start setting is used for the clean session.

client-id

ID of the bridge

no

Specifies the client identifier of the bridge MQTT client. If no client identifier is set, the identifier of the bridge is used.

keep-alive

60

no

The time in seconds that the broker permits between when a bridge MQTT client finishes sending one MQTT packet and starts to send the next. The broker must disconnect a client that does not send a message or a PINGREQ packet in one and a half times the stated keep alive interval. The default setting is 60 seconds.

session-expiry

3600

no

The time in seconds until the session of the bridge MQTT client expires after the connection is lost or closed. The default setting is 3600 seconds (one hour). Session expiry is only available for MQTT 5 remote brokers.

Loop prevention

It is possible to create infinite message loops with MQTT bridging. Unintentional message loops can increase the load on your MQTT brokers significantly. To mitigate the possibility of overload due to uncontrolled message loops, HiveMQ Edge enables basic loop-prevention by default.

The loop-prevention configuration utilizes an MQTT 5 user property to set duplication limits for PUBLISH messages.

Hop Counting

The bridge tracks the movement (hops) of PUBLISH messages within the bridge and stores the count in the hmq-bridge-hop-count user property of the message.

The hop count is incremented at the moment the PUBLISH message enters the bridge.

If the bridge registers an increment in the hmq-bridge-hop-count user property of a PUBLISH message that exceeds the hop-count-limit in your loop-prevention configuration, the bridge discards the message.

Hop counting provides a simple way to avoid potential loop-creation without the need for complex topic naming configurations.
When you use the default hop-count-limit of 1, no duplicate messages are possible. If you configure the hop-count-limit to a value that is greater than 1, a fixed number of duplicate messages are possible, but no loops can form.

Duplicates can also be prevented through correct configuration with a proper topic structure.
Example Loop Prevention Configuration
...
<mqtt-bridges>
        <mqtt-bridge>
            ...
            <loop-prevention>
                <enabled>true</enabled>
                <hop-count-limit>1</hop-count-limit>
            </loop-prevention>
            ...
        </mqtt-bridge>
    </mqtt-bridges>
...

Topic Mapping

Topic mapping filters the messaging flow from the source topics to the destination topics. Each topic can consist of one or more topic levels. Topic levels are separated by a forward slash (topic level separator).

Topic mapping functions are bidirectional.
Table 8. Bridge Topic Mapping Options
Topic Filter Setting Description

filters

Defines which messages the bridge processes.

excludes

Defines a subset of topics from the topic filter that are not forwarded to the destination topic. The excludes setting is only available for forwarded-topics.

destination

Modifies the selected topic to map to a different topic at the local or remote broker. This modification is executed before the message is published.

preserve-retain

Defines whether the retained message flags of retained messages in the selected data stream are kept. The default is false.

max-qos

The highest QoS level with which the bridge publishes the messages. Messages with a higher QoS level are downgraded to this level. Set max-qos explicitly for every forwarded topic and remote subscription.

queue-limit

The maximum number of QoS 1 and QoS 2 messages that wait for the remote broker for this forwarded topic. The default is the global max-queue-size of the MQTT configuration. The queue-limit setting is only available for forwarded-topics.

custom-user-properties

Adds custom static user properties to the messages processed by the bridge. Both the key and the value of a user property must be non-empty.

Example forwarded topic
<forwarded-topic>
    <filters>
        <mqtt-topic-filter>topicA/#</mqtt-topic-filter>
        <mqtt-topic-filter>house/#/temperature</mqtt-topic-filter>
    </filters>
    <destination>{#}</destination>
    <excludes>
        <mqtt-topic-filter>topicA/not-this</mqtt-topic-filter>
    </excludes>
    <preserve-retain>false</preserve-retain>
    <max-qos>2</max-qos>
    <custom-user-properties>
        <user-property>
            <key>my-key</key>
            <value>my-value</value>
        </user-property>
    </custom-user-properties>
</forwarded-topic>
Example remote subscription
<remote-subscription>
    <filters>
        <mqtt-topic-filter>topicA/#</mqtt-topic-filter>
        <mqtt-topic-filter>house/#/temperature</mqtt-topic-filter>
    </filters>
    <destination>remote/topic</destination>
    <max-qos>2</max-qos>
    <custom-user-properties>
        <user-property>
            <key>my-key</key>
            <value>my-value</value>
        </user-property>
    </custom-user-properties>
</remote-subscription>

Modifications of destination tag based on a topic filter:

  • Variables can be used inside the destination and excludes tags

  • Each topic level can be addressed by number, starting with 1

  • Static text can be added

  • A prefix and postfix can be used

Topic Filter Configuration Examples

Forward to a Static Remote Topic Example

Example forward to a static remote topic
<filters>
   <mqtt-topic-filter>+/status</mqtt-topic-filter>
</filters>
<destination>remote/data</destination>

Original topic: machine/status
Resulting topic: remote/data

Exclude Specific Topics Example

Example topic exclusion (only local-subscription)
<filters>
   <mqtt-topic-filter>clients/+/+</mqtt-topic-filter>
</filters>
<excludes>
   <mqtt-topic-filter>clients/id1/status</mqtt-topic-filter>
</excludes>

Original topic: clients/id1/status
Resulting topic: <not forwarded>

  • The bridge consumes all topics that match the filter and forwards messages other than messages to the excluded topics to the destination topic.

Add Prefix and Postfix as Destination Example

<filters>
   <mqtt-topic-filter>+/status</mqtt-topic-filter>
</filters>
<destination>prefix/{#}/data</destination>

Original topic: machine/status
Resulting topic: prefix/machine/status/data

  • The bridge consumes all topics that match the filter and uses the full MQTT topic from the client as the destination topic at the remote broker with a prefix and a postfix.

Topic Level Configuration Examples

Parts of Topic Filter as Destination Example

<filters>
   <mqtt-topic-filter>+/+/+/+</mqtt-topic-filter>
</filters>
<destination>prefix/{1-3}/data</destination>

Original topic: a/b/c/d
Resulting topic: prefix/a/b/c/data

  • This example uses a four-level incoming filter. The bridge forwards all publish topics that match the pattern.

  • For the destination topic at the remote broker, only the first three parts of the local publish topic are used and a prefix and a postfix are added.

Prefix, Postfix, and Topic Filter Parts as Destination Example I

<filters>
   <mqtt-topic-filter>a/+/+/+</mqtt-topic-filter>
</filters>
<excludes>
   <mqtt-topic-filter>+/client2/#</mqtt-topic-filter>
</excludes>
<destination>prefix/{2-3}/data</destination>

Original topic: a/b/c/d
Resulting topic: prefix/b/c/data

Original topic: a/client2/c/d
Resulting topic: <not forwarded>

  • This example uses a four-level incoming filter. The bridge forwards all publish topics that match the pattern.

  • For the destination topic at the remote broker, only the second and third parts of the local publish topic are used and a prefix (prefix) and postfix (data) are added.

  • Messages that have the string client2 at the second level are not forwarded.

Prefix, Postfix, and Topic Filter Parts as Destination Example II

<filters>
   <mqtt-topic-filter>+/+/+/+</mqtt-topic-filter>
</filters>
<destination>prefix/{2}/NEU/{4}/data</destination>

Original topic: a/b/c/d
Resulting topic: prefix/b/NEU/d/data

  • This example uses a four-level incoming filter. The bridge forwards all publish topics that match the pattern.

  • For the destination topic at the remote broker, only the second and fourth level from the incoming topic are used. The third level is replaced with a constant and a prefix is added.

Additional Topic Level Addressing Examples

  • {2}: Topic filter level 2

  • {2 - #}: Topic filter level 2 and all following levels

  • {#}: Whole topic filter

  • prefix/{#}/postfix: Whole topic filter inside prefix and postfix

  • {1}/A/{2}/B: Level 1 + "/A" + level 2 + "/B"

  • {#}/{1-3): Whole topic filter + level 1, 2, and 3

Connecting HiveMQ Edge to HiveMQ Cloud

To connect HiveMQ Edge with HiveMQ Cloud for free, you can log in to HiveMQ Cloud, Start a free cluster and enter your credentials either into the HiveMQ Edge UI or into your configuration file.

MQTT Bridge Configuration on the HiveMQ Edge User Interface

Go to MQTT Bridges → Add bridge connection and add the following values

  • Host ← <your-cluster-url>.hivemq.cloud

  • Port ← 8883

  • Username ← <your-username> from Access Management in HiveMQ Cloud

  • Password ← <your-password> from Access Management in HiveMQ Cloud

  • In the Security Tab in HiveMQ Edge enable Transport Layer Security (TLS)

  • Add a local or remote subscription

UI-Connection details for a new MQTT bridge
UI-Security settings for an MQTT bridge

WebSocket Support

The HiveMQ Edge Bridge supports WebSocket connections. To configure WebSocket use the common fields such as host and port from your remote broker in the bridge connection UI. To specifically activate a WebSocket connection select the Enabled checkbox. To specify the server path or sub-protocol, enter the necessary information in the Server Path and Sub-protocol fields.

Configuration for WebSocket

In the configuration file, the WebSocket settings are part of the remote-broker element:

<remote-broker>
    ...
    <websocket>
        <enabled>true</enabled>
        <server-path>/mqtt</server-path>
        <subprotocol>mqtt</subprotocol>
    </websocket>
</remote-broker>
Table 9. websocket element options
Name Default Mandatory Description

enabled

false

yes

Specifies whether the bridge connects over WebSocket. The element is required inside websocket. Without a websocket element, the bridge connects over TCP.

server-path

/mqtt

no

The path on the remote broker that accepts the WebSocket connection.

subprotocol

mqtt

no

The WebSocket subprotocol that the bridge requests.

Message Queueing and Reconnection

While the remote broker is unreachable, the bridge queues the messages of every forwarded topic. The bridge delivers them when the connection returns. The bridge reconnects automatically. The delay between attempts starts at one second and doubles up to 128 seconds. A random jitter of up to 25 percent is added. The bridge does not reconnect after you stop it.

Messages with QoS 1 and QoS 2 are queued up to the queue-limit, for each topic filter of the forwarded topic. Without a queue-limit, the global max-queue-size applies. Messages with QoS 0 are queued in memory and are not counted against these limits. When a queue is full, new messages are discarded. With the discard-oldest strategy of the MQTT configuration, the oldest message is dropped instead.

Queued messages are kept when HiveMQ Edge restarts, when the bridge restarts, and when the bridge fails to start. They are also kept when another subscription of the same bridge is edited. Stopping a bridge through the REST API or the UI discards its queued messages. Removing a bridge, or changing the topic filters or the destination of a subscription, discards the messages queued for that subscription. A configuration reload that changes nothing about a bridge does not restart the bridge.

Queued messages survive a restart of HiveMQ Edge only with the file-native persistence mode, which requires a commercial license. With in-memory persistence, the queue is lost when HiveMQ Edge stops. For more information, see Offline Buffering.

Each topic filter of a forwarded topic owns one internal queue. HiveMQ Edge derives the name of that queue from the sorted topic filters and the destination of the subscription. Two forwarded topics of one bridge collide when they share a destination and their sorted topic filters join to the same string. An example is the filters ab and c versus the filters a and bc, both with the same destination. HiveMQ Edge refuses to start a bridge with colliding forwarded topics and logs an error that names both subscriptions. Change a topic filter or the destination of one of them to resolve the collision.

The internal queues of a bridge are reserved for the bridge. An MQTT client that subscribes to the shared subscription of a bridge queue is disconnected. A client that already holds such a subscription loses it when the bridge starts.

Offline Buffering

Each bridge can be configured in such a way that MQTT traffic that is forwarded to a remote broker is persisted using the offline buffering functionality. For detailed configuration information, see Offline Buffering.

The Offline Buffering feature requires a commercial license. To obtain a license, please contact our sales@hivemq.com to obtain a license.
Example configuration for a bridge to enable offline buffering
<mqtt-bridge>
    ...
    <forwarded-topics>
        <forwarded-topic>
            <filters>
                <mqtt-topic-filter>sourceTopic</mqtt-topic-filter>
            </filters>
            <destination>destinationTopic</destination>
            <max-qos>1</max-qos>
        </forwarded-topic>
    </forwarded-topics>
    ...
    <persist>true</persist>
</mqtt-bridge>

In the example configuration, the persist flag is set to true. The MQTT payloads HiveMQ Edge transmits over the bridge are then buffered with their QoS level. When persist is set to false, every message from a local subscription is downgraded to QoS 0 before it is queued. HiveMQ Edge logs this when such a bridge is created or updated through the REST API or the UI. For your convenience, it is also possible to configure the persistence from the HiveMQ Edge UI:

UI-Screenshot for Persistence

Via configuration file

Add the following section to your configuration file <HIVEMQ_HOME>/conf/config.xml between the <hivemq> tags.

<mqtt-bridges>
    <mqtt-bridge>
        <id>my-hivemq-cloud-bridge</id>
        <remote-broker>
            <host>yoururl.hivemq.cloud</host>
            <port>8883</port>
            <authentication>
                <mqtt-simple-authentication>
                    <!-- you can create these credentials in 'Access Management' in HiveMQ Cloud -->
                    <username>your-mqtt-username</username>
                    <password>your-mqtt-password</password>
                </mqtt-simple-authentication>
            </authentication>
            <tls>
                <enabled>true</enabled>
            </tls>
        </remote-broker>
        <forwarded-topics>
            <forwarded-topic>
                <filters>
                    <mqtt-topic-filter>#</mqtt-topic-filter>
                </filters>
                <destination>hivemq-edge/{#}</destination>
            </forwarded-topic>
        </forwarded-topics>
        <!-- add more forwarded topic or remote subscriptions here -->
    </mqtt-bridge>
</mqtt-bridges>

This will create a bridge to your HiveMQ Cloud cluster and forward every message originating from or published to HiveMQ Edge to your HiveMQ Cloud cluster and prefixes the topic with hivemq-edge/.