Mosquitto MQTT Broker
What is MQTT?
MQTT is a simple, light weight "pub/sub" messaging protocol. Its light weight nature has meant it is found in many IoT applications, but actually, it's plenty good enough to be used in far "bigger" settings as well. It's rapidly becoming one of our go-to favourite technologies for a variety of projects.
What is Mosquitto?
Mosquitto is a simple light-weight MQTT broker. A broker is a sort of message exchange, where senders and receivers go to exchange their messages.
We rather like Mosquitto because easy things are easy, and it's incredibly powerful. It's also very light-footed, so can run on very small, resource constrained systems but also scales up to really big setups pretty easily.
All that said, Mosquitto doesn't natively have any clustering capability. It may be possible to do something similar with "bridges", but it'll take a bit of hand-cranking to do so.
The absolute simplest setup for Mosquitto is to just install the APT or RPM
package and start it up. If you do this, it'll listen on
localhost and will
allow anyone connecting to do pretty much whatever they like.
This kind of setup is great for development or for trying out Mosquitto, but it isn't terribly useful because of course no one on the network can use it. It's tempting to alter the configuration to listen on all networks, but we'd generally advise against that for anything other than a quick test or evaluation.
One Step Further
Getting a simple setup onto the network is an obvious next step. A common first pattern is to allow anything on the server to write to MQTT, and anything on the network to read it. This is an easy way to "broadcast" information from an application to multiple receivers on the network.
Mosquitto 2 and later has Dynamic Security. This allows an administrator to alter the security setup while the broker is running, but most importantly allows for roles, groups and permissions.
Before we get into Dynamic Security, the first thing we need to do is to setup
a network listener on
localhost and another on the network interface. We can
then tell Mosquitto that we want
per_listener_settings so that we can set
one as read/write and the other as read-only.
First, we tell Mosquitto we want
per_listener_settings by putting a config
/etc/mosquitto/conf.d/aa.conf (so it is read first):
Next, we can setup the
localhost listener with (more or less) the default
setting, which let anyone connecting there to do pretty much what they like.
This config goes into
listener 1883 127.0.0.1 allow_anonymous true
Then we can setup the network listener. On this one we tell Mosquitto we want
to use Dynamic Security, so we can go on to say we only want it to allow read
only. We can put this into
listener 1883 188.8.131.52 plugin /usr/lib/aarch64-linux-gnu/mosquitto_dynamic_security.so plugin_opt_config_file /etc/mosquitto/dynamic-security.json allow_anonymous true
(here, 184.108.40.206 is the IP address of the network interface of the server)
This concludes all the file editing required, and so is a great time to restart the server to make all of it take effect.
The last part of setup is to configure Dynamic Security. Dynamic Security is all documented quite nicely, but it's quite a lot to take in. As a super-brief start, we'll initialise it with:
mosquitto_ctrl dynsec init /etc/mosquitto/dynamic-security.json admin-user
This will ask for a password and then create an administrator level user called
admin-user. From then on, all interactions need the username and password to
be specified, for example:
mosquitto_ctrl -u admin-user -h localhost dynsec <command> ...
To allow anyone on the network to be able to read (only) our MQTT service,
we need to create a group, and give it a role, and mark it as being the
We'll start by creating the role:
mosquitto_ctrl <options> dynsec createRole readonly
...and add an ACL to the role:
mosquitto_ctrl <options> dynsec addRoleACL <rolename> <acltype> <topic filter> allow|deny <priority>
Since we want anonymous read-only access to everything, we can do something like this:
mosquitto_ctrl <options> dynsec addRoleACL readonly publishClientReceive # allow 1 mosquitto_ctrl <options> dynsec addRoleACL readonly subscribePattern # allow 1
Once the role is created, we can create a group:
mosquitto_ctrl <options> dynsec createGroup anonymous
...and add the role to it:
mosquitto_ctrl <options> dynsec addGroupRole anonymous readonly 1
...and then finally ensure anonymous connections get assigned to our group:
mosquitto_ctrl <options> dynsec setAnonymousGroup anonymous
Being Dynamic Security, there's no need to restart the server for any of this to take effect. We'd advise some careful testing to make sure it's all doing exactly what you expect.
Dynamic Security write to the
/etc/mosquitto/dynamic-security.json file. You
shouldn't edit the file directly, but it is okay to back it up so that if you
need to restore the server you can do it without having to re-run the above
commands (but be careful with file permissions). It's also possible to make another
server with the same
dynamic-security.json file, although we'd advise changing
the admin password if you decide to do that.
How you run your message broker is of course a matter of preference and whatever policies might be in place. Unless we're specifically looking to do less, we'd generally advise locking things down quite a bit so that the devops/sysadmin is responsible for allowing new topics for applications, which means they can also monitor them, and possibly co-ordinate between application teams, manage deployment to production and so on. Others may prefer applications to be able to make any topics they like (perhaps in a particular namespace), and use a form of discovery to work out what to monitor.
Either way, as a general rule, anonymous access is usually a bad thing, and each application should have its own credentials to connect to the broker and applications that only read a topic shouldn't have access to write to it.
Pre-Emptive can help with MQTT setups as well as a world of other technologies and topologies. Contact us to see how we can help you.