Setting up an encrypted MQTT server on Debian/Ubuntu using mosquitto.
Table of Contents
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
- Delete user
- Create user
- :)
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.