HiveMQ

The technical documentation for UMH implementation of the service HiveMQ Community Edition, which is the MQTT broker from 0.9.10 onwards.

We use Hive-MQ community Edition version 2022.1 in our stack, you can build a base version of it separately or install the configured version with our entire stack through the methods listed in our Get Started section.

We made some modifications to the configuration, namely adding extensions for better configuration and configuring the HiveMQ broker to fit better into our stack. For more information about Hive-MQ Community Edition, make sure to look into their extensive documentation

In the following table we will list the elements we used in the config.xml file we provide on startup of the hivemq container.

Listeners

The following elements are all inside the / base element in the config file, for more information look at the bottom of this page for an example. For more information read here.

ElementDescriptioncontainsPossible valuesExample values
<tcp-listener>element for a basic TCP connection1 of each elements: <port>, <bind-address>, <name>--
<tls-tcp-listener>element for a secure TCP connection1 of each elements: <port>, <bind-address>, <name>, <tls>--
<websocket-listener>element for a basic WebSocket connection1 of each elements: <port>, <bind-address>, <name>--
<tls-websocket-listener>element for a secure WebSocket connection1 of each elements: <port>, <bind-address>, <name>, <tls>--
<tls>element contains tls details for secure connectionsvariable, possible elements: <protocols>, <keystore>, <truststore>, <client-authentication-mode>, <cipher-suites>, <prefer-server-cipher-suites>--
<port>port number for listenersvalid port numberany valid port number<port>1883</port>
<bind-address>bind address for listenersvalid IP addressany valid IP address<bind-address>0.0.0.0</bind-address>
<name>name for the listenerthe name for the listenerany string<name>hivemq-mqtt</name>
<protocols>element contains enabled protocols for the listener<protocol> elements for each protocol enabled--
<protocol>name of a protocolvalid protocol name“TLSv1”, “TLSv1.1”, “TLSv1.2”, “TLSv1.3”<protocol>“TLSv1.3” </protocol>
<keystore>element for a keystore1 of each elements: <path>, <password>, <private-key-password>--
<truststore>element for a truststore1 of each elements: <path>, <password>--
<password>password to open the respective storethe valid password to the corresponding elementUTF-8 string<password> changeme <password>
<path>path to where the respective store is storeda valid relative pathvalid path as a string<path> /stores/truststore.jks <path>
<client-authentication-mode>Determines which way HiveMQ handles authenticationA key to describe what way certificates are needed by the clientNONE, POSSIBLE, REQUIRED<client-authentication-mode>REQUIRED</client-authentication-mode>
<cipher-suites>element contains enabled cipher suites<cipher-suite> elements--
<cipher-suite>cipher suitea valid cipher suite namevalid cipher suite names<cipher-suite>TLS_RSA_WITH_AES_128_CBC_SHA</cipher-suite>
<prefer-server-cipher-suites>optional element, which enables preferential use of cipher suites higher up in the <cipher-suites> elementa boolean valuetrue, false<prefer-server-cipher-suites>true</prefer-server-cipher-suites>

Persistence

The following elements are all inside the / base element in the config file, for more information look at the bottom of this page for an example. For details, read here

ElementDescriptioncontainsPossible valuesExample values
<client-session>Manages persistence of the client sessionone of each elements: <general>, <queued-messages>, <subscriptions>--
<general>details how the client session generally handles persistence<mode> element--
<mode>persistence handling mode (either memory based or disk based)stringin-memory, file<mode>file</mode>
<queued-message>details how the client session handles persistence of queued messagesone of each elements: <mode>, <queued-messages-strategy>, <max-queued-messages>--
<max-queued-messages>maximum number of queued messages for a specific clienta positive integerpositive integers<max-queued-messages>1800000</max-queued-messages>
<queued-messages-strategy>Handles what to do when message queue is fullstring which determines discarding strategydiscard, discard-oldest<queued-messages-strategy>discard-oldest</queued-messages-strategy>
<subscriptions>details how the client session handles persistence on granted subscriptions<mode> element--
<message-flow>details how incoming and outgoing message flow persistence is handled<incoming> , <outgoing>--
<incoming>contains mode for incoming messages<mode> element--
<outgoing>contains mode for incoming messages<mode> element--
<retained-messages>details how the client handles persistence of retained messages<mode> element--
<publish-payloads>details how publish payloads are stored<mode> element--
<attribute>details how session attributes are stored<mode> element--
<client-group>details how client groups are stored<mode> element--

Security

The following elements are all inside the / base element in the config file, for more information look at the bottom of this page for an example. For more information red here.

ElementDescriptioncontainsPossible valuesExample values
<allow-empty-client-id>allows the use of empty client IDs<enabled> element--
<enabled>enables or disables the meta-elementboolean valuetrue, falsefalse
<utf8-validation>enables UTF-8 validation of topic names and client IDs<enabled> element--

Extensions

Our HiveMQ implementation uses an init-container to download and install the following extensions:

These extensions are configured by the config-extensions.yaml. For detailed information visit their respective github documentation listed below. Nevertheless, we provide explanation regarding our standard configuration.

RBAC file extension

This one uses an XML markup format for its configuration. In the table below we give a quick rundown of what the config contains. Make sure to check out their GitHub documentation for more details.

ElementDescriptioncontainsPossible valuesExample Values
<users>Base element, entirety of <users><user> elements--
<user>First indentation element, <users> is composed of these elementsone of each elements: <name>, <password>, <roles>--
<name>Name of the userusername as stringany<name> FACTORYINPUT </name>
<password>password for the username, in our case it is a custom encrypted hash, see this article for more informationpasswordpassword without whitespaces<password>changeme</password>
<roles>Roles users can havedepending on location: base element contains <role> elements, defining the <role>s; as a subelement of <user> it defines what roles a user has--
<id>id of a <role><id> of a defined <role>valid MQTT topic structure<id>superuser
<role>Role, base element <roles> is composed of these elementsone <id> element, one <permissions> element--
<permissions>collection of all pub/sub <permission>s the role hasone or multiple elements--
<permission>A sub/pub permission for the rolea valid <topic> element--
<topic>Topic for the <permission> elementa valid topic structure stringall valid topic structures<topic>ia/#

Heartbeat

This one uses an XML markup format for its configuration. In the table below we give a quick rundown of what the config contains. Make sure to check out their GitHub documentation for more details.

ElementDescriptioncontainsPossible valuesExample Values
<bind-address>(required) Base element, IP Address the service is bound tovalid IP addressany valid IP address<bind-address>0.0.0.0</bind-address>
<port>(optional) Base element, port under which the service is available. 9090 if unset.valid port numberany valid port number<port> 9090 </port>
<path>(required) Base element, path where the heartbeat HTTP service is located. Default ist /heartbeatvalid pathany valid path<path> /heartbeat </path>

Prometheus

This one uses a yaml style key:value pair in its configuration. For more information make sure to check out their [GitHub documentation]

ElementDescriptioncontainsPossible valuesExample Values
hostIP Address the service is bound tovalid IP addressany valid IP address0.0.0.0
portThe port which the servlet will listen to. 9399 if unset.valid port numberany valid port number9399
metric_pathThe path for the service which gets called by Prometheus. It must start with a slash.valid pathany valid path/prometheus
Example main hivemq config file
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{include "united-manufacturing-hub.fullname" .}}-hivemqce-hive
data:
  config.xml: |
    <?xml version="1.0"?>
    <hivemq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <listeners>
            {{- if .Values.hivemqce.service.mqtt.enabled}}
            <tcp-listener>
                <port>1883</port>
                <bind-address>0.0.0.0</bind-address>
                <name>hivemq-mqtt</name>
            </tcp-listener>
            {{- end}}
            {{- if .Values.hivemqce.service.mqtts.enabled}}
            <tls-tcp-listener>
                <port>8883</port>
                <bind-address>0.0.0.0</bind-address>
                <name>hivemq-secure-mqtt</name>
                <tls>
                    <protocols>
                        {{range .Values.hivemqce.service.mqtts.tls_versions}}
                        <protocol>{{.}}</protocol>
                        {{end}}
                    </protocols>
                    <keystore>
                        <path>/stores/keystore.jks</path>
                        <password>{{.Values._000_commonConfig.infrastructure.mqtt.tls.keystorePassword}}</password>
                        <private-key-password>{{.Values._000_commonConfig.infrastructure.mqtt.tls.privateKeyPassword}}</private-key-password>
                    </keystore>
                    <truststore>
                        <path>/stores/truststore.jks</path>
                        <password>{{.Values._000_commonConfig.infrastructure.mqtt.tls.truststorePassword}}</password>
                    </truststore>
                    <client-authentication-mode>REQUIRED</client-authentication-mode>
                    <cipher-suites>
                        {{range .Values.hivemqce.service.mqtts.cipher_suites}}
                        <cipher-suite>{{.}}</cipher-suite>
                        {{end}}
                    </cipher-suites>
                    <prefer-server-cipher-suites>true</prefer-server-cipher-suites>
                </tls>
            </tls-tcp-listener>
            {{- end}}
            {{- if .Values.hivemqce.service.ws.enabled}}
            <websocket-listener>
                <port>8080</port>
                <bind-address>0.0.0.0</bind-address>
                <path>/mqtt</path>
                <name>hivemq-websocket</name>
                <subprotocols>
                    <subprotocol>mqttv3.1</subprotocol>
                    <subprotocol>mqtt</subprotocol>
                </subprotocols>
                <allow-extensions>true</allow-extensions>
            </websocket-listener>
            {{- end}}
            {{- if .Values.hivemqce.service.wss.enabled}}
            <tls-websocket-listener>
                <port>8443</port>
                <bind-address>0.0.0.0</bind-address>
                <path>/mqtt</path>
                <name>hivemq-secure-websocket</name>
                <subprotocols>
                    <subprotocol>mqttv3.1</subprotocol>
                    <subprotocol>mqtt</subprotocol>
                </subprotocols>
                <allow-extensions>true</allow-extensions>
                <tls>
                    <protocols>
                        {{range .Values.hivemqce.service.wss.tls_versions}}
                        <protocol>{{.}}</protocol>
                        {{end}}
                    </protocols>
                    <keystore>
                        <path>/stores/keystore.jks</path>
                        <password>{{.Values._000_commonConfig.infrastructure.mqtt.tls.keystorePassword}}</password>
                        <private-key-password>{{.Values._000_commonConfig.infrastructure.mqtt.tls.privateKeyPassword}}</private-key-password>
                    </keystore>
                    <truststore>
                        <path>/stores/truststore.jks</path>
                        <password>{{.Values._000_commonConfig.infrastructure.mqtt.tls.truststorePassword}}</password>
                    </truststore>
                    <client-authentication-mode>REQUIRED</client-authentication-mode>
                    <cipher-suites>
                        {{range .Values.hivemqce.service.wss.cipher_suites}}
                        <cipher-suite>{{.}}</cipher-suite>
                        {{end}}
                    </cipher-suites>
                    <prefer-server-cipher-suites>true</prefer-server-cipher-suites>
                </tls>
            </tls-websocket-listener>
            {{- end}}
        </listeners>
        <persistence>
            <client-session>
                <general>
                    <mode>file</mode>
                </general>
                <queued-messages>
                    <max-queued-messages>1800000</max-queued-messages>
                    <queued-messages-strategy>discard-oldest</queued-messages-strategy>
                    <mode>file</mode>
                </queued-messages>
                <subscriptions>
                    <mode>file</mode>
                </subscriptions>
            </client-session>
            <message-flow>
                <incoming>
                    <mode>file</mode>
                </incoming>
                <outgoing>
                    <mode>file</mode>
                </outgoing>
            </message-flow>
            <retained-messages>
                <mode>file</mode>
            </retained-messages>
            <publish-payloads>
                <mode>file</mode>
            </publish-payloads>
            <attribute>
                <mode>file</mode>
            </attribute>
            <client-group>
                <mode>file</mode>
            </client-group>
        </persistence>
        <security>
            <allow-empty-client-id>
                <enabled>false</enabled>
            </allow-empty-client-id>
            <utf8-validation>
                <enabled>true</enabled>
            </utf8-validation>
        </security>
    </hivemq>    
{{end}}
Example extension config file
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{include "united-manufacturing-hub.fullname" .}}-hivemqce-extension
data:
# https://github.com/hivemq/hivemq-file-rbac-extension
  credentials.xml: |
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <file-rbac>
    <users>
        <user>
            <name>FACTORYINPUT</name>
            <password>{{.Values.factoryinput.mqtt.encryptedPassword}}</password>
            <roles>
                <id>ia_read_write</id>
            </roles>
        </user>
        <user>
            <name>MQTT_KAFKA_BRIDGE</name>
            <password>{{.Values.mqttkafkabridge.mqtt.encryptedPassword}}</password>
            <roles>
                <id>ia_read_write</id>
            </roles>
        </user>
        <user>
            <name>MQTT_BRIDGE</name>
            <password>{{.Values.mqttbridge.mqtt.encryptedPassword}}</password>
            <roles>
                <id>ia_read_write</id>
            </roles>
        </user>
        <user>
            <name>SENSORCONNECT</name>
            <password>{{.Values.sensorconnect.mqtt.encryptedPassword}}</password>
            <roles>
                <id>ia_read_write</id>
            </roles>
        </user>
        <user>
            <name>IOTSENSORSMQTT</name>
            <password>{{.Values.iotsensorsmqtt.mqtt.encryptedPassword}}</password>
            <roles>
                <id>ia_raw</id>
            </roles>
        </user>
        <user>
            <name>PACKMLSIMULATOR</name>
            <password>{{.Values.packmlmqttsimulator.env.mqtt.encryptedPassword}}</password>
            <roles>
                <id>packmlsimulator</id>
            </roles>
        </user>
        <user>
            <name>node-red</name>
            <password>{{.Values.nodered.mqtt.encryptedPassword}}</password>
            <roles>
                <id>packmlsimulator</id>
                <id>umh_read_write</id>
                <id>ia_read_write</id>
            </roles>
        </user>
        {{if .Values._000_commonConfig.infrastructure.mqtt.adminUser.enabled}}
        <user>
            <name>{{.Values._000_commonConfig.infrastructure.mqtt.adminUser.name}}</name>
            <password>{{.Values._000_commonConfig.infrastructure.mqtt.adminUser.encryptedPassword}}</password>
            <roles>
                <id>superuser</id>
            </roles>
        </user>
        {{end}}
    </users>
    <roles>
        <role>
            <id>umh_read_write</id>
            <permissions>
                <permission>
                    <topic>umh/#</topic>
                </permission>
            </permissions>
        </role>
        <role>
            <id>ia_read_write</id>
            <permissions>
                <permission>
                    <topic>ia/#</topic>
                </permission>
            </permissions>
        </role>
        <role>
            <id>ia_raw</id>
            <permissions>
                <permission>
                    <topic>ia/raw/#</topic>
                </permission>
            </permissions>
        </role>
        <role>
            <id>packmlsimulator</id>
            <permissions>
                <permission>
                    <topic>{{.Values.packmlmqttsimulator.env.site}}/{{.Values.packmlmqttsimulator.env.area}}/{{.Values.packmlmqttsimulator.env.productionline}}/#</topic>
                </permission>
            </permissions>
        </role>
        <role>
            <id>superuser</id>
            <permissions>
                <permission>
                    <topic>#</topic>
                </permission>
            </permissions>
        </role>
    </roles>
    </file-rbac>


    heartbeat.xml: |
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <heartbeat-extension-configuration>
        <port>9090</port>
        <bind-address>0.0.0.0</bind-address>
        <path>/heartbeat</path>
    </heartbeat-extension-configuration>



    prometheus.properties: |
        ip=0.0.0.0
        port=9399
        metric_path=/metrics