Skip to content

# MQTT Support

## Benefits

ejabberd is a multiprotocol server that supports MQTT out of the box since ejabberd Business Edition 4.0 and ejabberd Community Server 19.02

There are major benefits in using MQTT service embedded in ejabberd:

1. MQTT service relies on ejabberd infrastructure code, that has been battle tested since 15+ years, like the clustering engine. ejabberd MQTT service has been tested on large scale and can support millions of concurrent connections highly efficiently. ejabberd MQTT is rock-solid and highly scalable.
2. The ejabberd APIs and modules can be reused in MQTT. Authentication, virtual hosting, database backends, ... They both work with XMPP and MQTT. You can also share your security policy, as defined in the configuration file between the two protocols.
3. You can leverage existing skills and plugins you have written for ejabberd, like for example custom authentication.
4. You can deploy services that take advantage of both protocols and have them interoperate with each other, on a single platform, with a single tool.
5. ejabberd supports MQTT 5: it is a state of the art, modern MQTT server. And it also supports MQTT 3.1.1 in case you want to use previous clients.

In summary:

- You can switch between XMPP and MQTT as you wish, even use both protocols on the same infrastructure.
- You will save on infrastructure, given the high-performance of the platform.
- You get support on solution design for real-time infrastructure and can get help choosing between XMPP and MQTT, from a vendor that has no interest in selling one protocol more than another.

ejabberd Business Edition offers a different clustering than eCS. Using MQTT with ejabberd Business Edition means you can leverage:

- The clustering engine of eBE will be used for the MQTT service. It means that you have a more scalable cluster, that supports geoclustering. With geoclustering, you can deploy a single MQTT service across different datacenters, spread in different regions. You can deploy a truly global service.
- The backend integration that are supported in ejabberd Business Edition will be available in MQTT. You have no need to develop support for new API.

## Basic Setup

Maybe you already have MQTT enabled in your ejabberd server, as it comes enabled by default in many distributions.

MQTT support in ejabberd is enabled by adding `mod_mqtt` to the list of `listen` and the list of `modules` like this:

    listen:
      -
        port: 1883
        module: mod_mqtt
        backlog: 1000

    modules:
      mod_mqtt: {}

The listener on port 1883 is MQTT over cleartext TCP/IP connection; you can later setup encryption, WebSocket, and encrypted WebSocket.

For available options you can consult the mod_mqtt listener and the mod_mqtt module.

## Test Setup

Start ejabberd server and you can connect to ejabberd MQTT service with your preferred MQTT client.

Let's use the clients included with mosquitto, available in Debian, Brew and many others (see mosquitto downloads).

First of all register several accounts and subscribe one to the topic `test/1` with:

    ejabberdctl register author localhost Pass
    ejabberdctl register user1 localhost Pass

    mosquitto_sub -u user1@localhost -P Pass -t "test/1" -d -v

    Client (null) sending CONNECT
    Client (null) received CONNACK (0)
    Client (null) sending SUBSCRIBE (Mid: 1, Topic: test/1, QoS: 0, Options: 0x00)
    Client (null) received SUBACK
    Subscribed (mid: 1): 0

Then go to another terminal or window and publish something on that topic:

    mosquitto_pub -u author@localhost -P Pass -t "test/1" -d -m "ABC"

    Client (null) sending CONNECT
    Client (null) received CONNACK (0)
    Client (null) sending PUBLISH (d0, q0, r0, m1, 'test/1', ... (3 bytes))
    Client (null) sending DISCONNECT

You will see the message received and displayed in the `mosquitto_sub` window:

    Client (null) received PUBLISH (d0, q0, r0, m0, 'test/1', ... (3 bytes))
    test/1 ABC

## Access Control

The mod_mqtt module provides two options for access control:

- `access_subscribe` to restrict access for subscribers,
- and `access_publish` to restrict access for publishers.

Both options accept mapping `filter: rule` where `filter` is an MQTT topic filter and `rule` is the standard ejabberd Access Rule.

As an example, let's say only `author@localhost` is allowed to publish to topic "/test/1/" and its subtopics, while only `user1@localhost` is allowed to subscribe to this topic and its subtopics, and nobody else can publish or subscribe to anything else. The configuration will look something like this:

    acl:
      publisher:
        user: author@localhost
      subscriber:
        user: user1@localhost

    modules:
      mod_mqtt:
        access_publish:
          "test/1/#":
            - allow: publisher
            - deny
          "#":
            - deny
        access_subscribe:
          "test/1/#":
            - allow: subscriber
            - deny
          "#":
            - deny

## Encryption

### Self-Signed Certificate

If you have already setup encryption in ejabberd, you can bypass this step.

If you want to use TLS, you may want to create a self-signed certificate (at least to get started). The following page is a nice guide: Mosquitto SSL Configuration -MQTT TLS Security.

Here is a summary of the steps, adapted for ejabberd MQTT:

    openssl genrsa -des3 -out ca.key 4096
    openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
    openssl genrsa -out server.key 4096
    openssl req -new -out server.csr -key server.key
    openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360
    cat server.crt server.key > mqtt.pem

Now copy `mqtt.pem` to the path with ejabberd configuration files, and configure accordingly:

    certfiles:
      - "/etc/ejabberd/mqtt.pem"

### Configure Encryption

Add a new listener with `tls` option in the port number 8883 (the standard for encrypted MQTT):

    listen:
      -
        port: 1883
        module: mod_mqtt
        backlog: 1000
      -
        port: 8883
        module: mod_mqtt
        backlog: 1000
        tls: true

The listener on port 1883 is MQTT over cleartext TCP/IP connection. The listener on port 8883 is MQTT over TLS. You can enable both or only one of them depending on your needs.

### Test Encryption

You can repeat the commands from previous test, appending `-p 8883` to use the encrypted port. If you are using a self-signed certificate as explained previously, you will also have to append `--cafile server.crt`. For example:

    mosquitto_sub -u user1@localhost -P Pass -t "test/1" -d -v -p 8883 --cafile server.crt

## WebSocket

### Setup WS

Add `mod_mqtt` as a request_handler on the ejabberd_http listener:

    listen:
      -
        port: 5280
        module: ejabberd_http
        request_handlers:
          /mqtt: mod_mqtt

This configuration maps the path `/mqtt` to the MQTT WebSocket handler on the main ejabberd HTTP listener.

You can enable listeners independently, for example enable only the WebSocket listener and not the TCP/IP ones.

### Test WS

Our beloved mosquitto client does not support MQTT over WebSocket, so you may have to find some capable MQTT client. For example, in MQTTX, setup in the login window:

- Host: `ws://` `localhost`
- Port: 5280
- Path:`/mqtt`

If you need an example on how to use MQTTJS library, you can check our small example project: mqttjs-demo

### Encrypted WS

To enable encryption on WebSocket, enable `tls` like this:

    listen:
      -
        port: 5281
        ip: "::"
        module: ejabberd_http
        tls: true
        request_handlers:
          /mqtt: mod_mqtt

For testing this in the MQTTX client:

- Host: `wss://` `localhost`
- Port: 5281
- Path: `/mqtt`
- SSL/TLS: true
- Certificate: CA signed server
- If you used a self-signed certificate, you will have to disable SSL Secure