MQTT is a messaging protocol intended for smaller applications (in “footprint”, not necessarily scale) which is available since 1999 but is currently receiving a lot of attention since the rise of the internet of things and the need to send small messages as simply as possible. In this tutorial I will show how to install a mosquitto server on Debian/Ubuntu based systems.

The server will require authentication and TLS (using Let’s Encrypt).

Prerequisites

The following things are needed for all of this to work:

  • A publicly accessible server
  • Debian/Ubuntu based system
  • A DNS A record pointing to the server

Installation

Important things to note for this section:

  • All commands need to be run as root unless noted otherwise!
  • Remember to modify paths and domain names where necessary!

Let’s Encrypt

If it’s not already there, install certbot:

apt update && apt install certbot

Then get the certificate for your domain (you should stop any running web server or use another challenge if you get errors):

certbot certonly --standalone --standalone-supported-challenges http-01 -d mqtt.example.com
Update: Permission Errors

I’ve recently had problems after updating certbot because some permission stuff had changed. The solution to this is to add a post-renew hook to certbot.

Create a file with the following content at /etc/letsencrypt/renewal-hooks/deploy/mosquitto.sh (source):

DOMAIN=mqtt.example.com
CERTIFICATE_DIR=/etc/mosquitto/certs

# RENEWED_DOMAINS, CERTIFICATE_DIR and RENEWED_LINEAGE will be set by certbot
if [ "${RENEWED_DOMAINS}" = "${DOMAIN}" ]; then
	cp ${RENEWED_LINEAGE}/fullchain.pem ${CERTIFICATE_DIR}/server.pem
	cp ${RENEWED_LINEAGE}/privkey.pem ${CERTIFICATE_DIR}/server.key

	chown mosquitto: ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key

	chmod 0600 ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key

	pkill -HUP -x mosquitto
fi

After saving the file, the last step is to make it executable and run it once because we just received the certificate:

chmod +x /etc/letsencrypt/renewal-hooks/deploy/mosquitto.sh
RENEWED_DOMAINS=mqtt.example.com RENEWED_LINEAGE=/etc/letsencrypt/live/mqtt.example.com /etc/letsencrypt/renewal-hooks/deploy/mosquitto.sh

Mosquitto

Since we’re using Debian/Ubuntu, the installation is almost as easy as always:

apt update
apt install mosquitto mosquitto-clients
systemctl stop mosquitto

The service was stopped immediately after installation because it’s on a public server and it needs to be configured first. On Debian this can be done the hacky way (by editing /etc/mosquitto/mosquitto.conf) or the clean way. I will use the latter.

By default, the /etc/mosquitto/mosquitto.conf file includes the following line:

include_dir /etc/mosquitto/conf.d

This makes it load all the files with a name matching *.conf in the specified directory, so the configuration file can be any way you want.

Configuration

Let’s first remove all sample files in the config directory and then create a new config:

rm /etc/mosquitto/conf.d/*

The new config should be placed at /etc/mosquitto/conf.d/custom.conf and contain the following:

allow_anonymous false
password_file /etc/mosquitto/pwfile

listener 1883 localhost

listener 8883
certfile /etc/mosquitto/certs/server.pem
keyfile /etc/mosquitto/certs/server.key

See the official configuration docs if you need more options (or don’t understand some I used above).

Authentication

You might have noticed the password_file parameter in the example configuration. This contains the usernames and passwords that are allowed to connect to the server. Let’s create it:

vi /etc/mosquitto/pwfile

The format of the password file is one username and password per line, separated by a colon (:).

user:password
u53r:p455w0rd

Now let’s use mosquitto_passwd to encrypt the password file:

mosquitto_passwd -U /etc/mosquitto/pwfile

If you look into the file after running the command above, you’ll notice that the passwords have been encrypted.

Firewall

If you use ufw (you should), you’ll have to run the following command to enable Mosquitto to receive connections:

ufw allow 8883

Testing

Now it’s time to start the service and test it:

systemctl start mosquitto
systemctl status mosquitto

After the service is running properly, the easiest way to test it is using a remote GUI tool like MQTT.fx, mqtt-spy or one of the other ones available. By using this method (opposed to localhost only testing) you make sure that the firewall and ssl config is working correctly.

Operating

Here are some things you might come across when running a MQTT broker.

Adding users

You can add additional users to the password file by using the following command:

mosquitto_passwd -b /path/to/passwordfile user password

Deleting users

You can remove a user from the password file by using the following command:

mosquitto_passwd -D /path/to/passwordfile user

Editing a user

  1. Delete user
  2. Create user
  3. :)

Reloading configuration changes

After editing the password file, the changes are not immediately applied on the server. To apply any configuration changes, use the following command:

systemctl restart mosquitto

Conclusion

You should now have a running MQTT broker at the domain name you have configured. If you have any problems or questions, don’t hesitate to contact me or to use a search engine of your choice.

Have a nice day.