Starting with MQTT protocol and ejabberd MQTT broker

Update January 2022: This tutorial is slightly out of date. In case of problems, please consult the corresponding section in the ejabberd documentation: MQTT Support.

MQTT stands for Message Queuing Telemetry Transport. It is a simple and lightweight publish/subscribe messaging protocol: MQTT broker sends & relays messages to MQTT clients. It was designed for constrained devices and low-bandwidth, high-latency or unreliable networks. All while attempting to ensure reliability and some degree of assurance of delivery. This makes the protocol ideal for the Internet of Things (IoT). Another good fit are mobile apps where bandwidth and battery power are at a premium.

» Don’t want to manage ejabberd MQTT broker yourself?
ProcessOne experts will make your business instantly connected. Contact us »

Starting with MQTT protocol and ejabberd MQTT broker

ejabberd and MQTT

ejabberd MQTT broker is included in every installation of latest ejabberd versions and is available on port 1883 out-of-the-box. In my first ejabberd tutorial I installed ejabberd on my private server. I didn’t do any additional configuration towards an MQTT broker, so lets see if it’s really there.

To do this test, we need an MQTT client. We can use one of existing the GUI clients like MQTT FX or one of the best CLI clients, Mosquitto. It supports Linux, Windows and macOS. You can easily install it on the macOS using Homebrew with: brew install mosquitto

Subscribe the MQTT client

ejabberd acts as an MQTT broker, so first we need a client to subscribe to receive relayed messages. We do this with the following command on the machine where we installed Mosquitto:

mosquitto_sub -h mqtt.fluux.io -t "test/channel/1" -d

Publish with MQTT client

Once there’s a first subscriber, our ejabberd MQTT broker will relay any message sent from the publisher:

mosquitto_pub -h mqtt.fluux.io -t "test/channel/1" -m "This is a test message"

You will see “This is a test message” appear under the mosquitto_sub process. However, mqtt.fluux.io is a public MQTT broker, not my private server, meaning anyone can publish, subscribe and intercept messages. It’s not really meant for production.

ejabberd MQTT broker initial configuration doesn’t allow unauthorized connections, which is good. To connect, we need to use a username and password that’s already registered on our ejabberd server.

Subscribe and publish to MQTT broker with authenticated user

Lets first go to the ejabberd admin console, which is at example.com:5443/admin if we assume the configuration from my tutorial series. Lets create a new user, broker@example.com. Then, we need to add this user to the ACL in our ejabberd configuration file:

acl:
  ...
  publisher:
    user:
      - "broker@example.com"
  subscriber:
    user:
      - "broker@example.com"

Finally, we need to let mod_mqtt know who can interact with our ejabberd MQTT broker:

  mod_mqtt:
    access_publish:
      "#":
        - allow: publisher
        - deny
    access_subscribe:
      "#":
        - allow: subscriber
        - deny

Here we specify to let the publishers and subscribers, defined earlier in ejabberd ACL, have access to any channel. We block access to all channels for any unauthenticated connections. To test this, start the subscriber again with broker@example.com and its password:

mosquitto_sub -h example.com -t "test/channel/1" -u broker@example.com -P ******* -d

In another window, lets publish a test message:

mosquitto_pub -h example.com -t "test/channel/1" -m "This is a test message" -u broker@example.com -P *******

The subscriber process should display the published message. However, we still have all these MQTT messages coming and going in cleartext, unencrypted. To make it even more secure, lets set up TLS encryption for our MQTT broker.

Configure MQTT broker TLS encryption in ejabberd

There are two ways to do this. You can either create a new listener on another port, and keep the cleartext 1883 open. Or, as I prefer, simply add tls: true to the existing mod_mqtt listener:

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

This configuration will use your existing global certificate files to encrypt the mod_mqtt connections with TLS. To be able to connect our subscribers and publishers to the TLS encrypted MQTT broker, we need to let them know which certificate to use.

First, download the certificate files your ejabberd MQTT broker is using. These are the files defined at the top of your ejabberd configuration file in certfiles section. Then, download the latest cacert.pem. Finally, supply these certificates to the subscriber and publisher:

mosquitto_sub -h example.com -t "test/channel/1" -u broker@example.com -P ******* -d -p 1883 --cafile /path/to/cacert.pem --cert /path/to/ejabberd/fullchain.pem --key /path/to/ejabberd/privkey.pem
mosquitto_pub -h example.com -t "test/channel/1" -m "This is a test message" -u broker@example.com -P ******* -p 1883 --cafile /path/to/cacert.pem --cert /path/to/ejabberd/fullchain.pem --key /path/to/ejabberd/privkey.pem

You should see the test message appear under the subscriber process.

What can we do with ejabberd MQTT broker?

To conclude, thanks to ejabberd we now have a powerful XMPP server running together with a scalable MQTT broker. Connections on both protocols are TLS encrypted and limited to authenticated users. We have the capability to chat one-to-one, operate one-to-many multi-user chatrooms and interconnect publish-subscribe many-to-many client networks.

It’s an especially interesting setup to create interactions between digital and physical world. Next time, we will try to send MQTT messages based on XMPP events. But why? Well, for example, we could control MQTT IoT devices via commands sent to a chat with an XMPP bot assistant. And the bot could talk back to us about the events at our home. The possibilities are endless!

In this ejabberd tutorial series:

Photo by Josh Hild on Unsplash


Let us know what you think 💬


Leave a Comment


This site uses Akismet to reduce spam. Learn how your comment data is processed.