Tutorial

How to Install and Secure the Mosquitto MQTT Messaging Broker on Ubuntu 18.04 [Quickstart]

How to Install and Secure the Mosquitto MQTT Messaging Broker on Ubuntu 18.04 [Quickstart]

Introduction

MQTT is a machine-to-machine messaging protocol, designed to provide lightweight publish/subscribe communication to “Internet of Things” devices. Mosquitto is a popular MQTT server (or broker, in MQTT parlance) that has great community support and is easy to install and configure.

In this condensed quickstart tutorial we’ll install and configure Mosquitto, and use Let’s Encrypt SSL certificates to secure our MQTT traffic. If you need more in-depth coverage of any of the steps, please review the following tutorials:

Prerequisites

Before starting this tutorial, you will need:

  • An Ubuntu 18.04 server with a non-root, sudo-enabled user and basic firewall set up, as detailed in this Ubuntu 18.04 server setup tutorial
  • A domain name pointed at your server. This tutorial will use the placeholder mqtt.example.com throughout
  • Port 80 must be unused on your server. If you’re installing Mosquitto on a machine with a web server that occupies this port, you’ll need to use a different method to fetch certificates, such as Certbot’s webroot mode.

Step 1 — Installing the Software

First we will install a custom software repository to get the latest version of Certbot, the Let’s Encrypt client:

  1. sudo add-apt-repository ppa:certbot/certbot

Press ENTER to accept, then install the software packages for Mosquitto and Certbot:

  1. sudo apt install certbot mosquitto mosquitto-clients

Next we’ll fetch our SSL certificate.

Step 2 — Downloading an SSL Certificate

Open up port 80 in your firewall:

  1. sudo ufw allow 80

Then run Certbot to fetch the certificate. Be sure to substitute your server’s domain name here:

  1. sudo certbot certonly --standalone --preferred-challenges http -d mqtt.example.com

You will be prompted to enter an email address and agree to the terms of service. After doing so, you should see a message telling you the process was successful and where your certificates are stored.

We’ll configure Mosquitto to use these certificates next.

Step 3 — Configuring Mosquitto

First we’ll create a password file that Mosquitto will use to authenticate connections. Use mosquitto_passwd to do this, being sure to substitute your own preferred username:

  1. sudo mosquitto_passwd -c /etc/mosquitto/passwd your-username

You will be prompted twice for a password.

Now open up a new configuration file for Mosquitto:

  1. sudo nano /etc/mosquitto/conf.d/default.conf

This will open an empty file. Paste in the following:

/etc/mosquitto/conf.d/default.conf
allow_anonymous false
password_file /etc/mosquitto/passwd

listener 1883 localhost

listener 8883
certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem

listener 8083
protocol websockets
certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem

Be sure to substitute the domain name you used in Step 2 for mqtt.example.com. Save and close the file when you are finished.

This file does the following:

  • Disables anonymous logins
  • Uses our password file to enable password authentication
  • Sets up a unsecured listener on port 1883 for localhost only
  • Sets up a secure listener on port 8883
  • Sets up a secure websocket-based listener on port 8083

Restart Mosquitto to pick up the configuration changes:

  1. sudo systemctl restart mosquitto

Check to make sure the service is running again:

  1. sudo systemctl status mosquitto
Output
● mosquitto.service - LSB: mosquitto MQTT v3.1 message broker Loaded: loaded (/etc/init.d/mosquitto; generated) Active: active (running) since Mon 2018-07-16 15:03:42 UTC; 2min 39s ago Docs: man:systemd-sysv-generator(8) Process: 6683 ExecStop=/etc/init.d/mosquitto stop (code=exited, status=0/SUCCESS) Process: 6699 ExecStart=/etc/init.d/mosquitto start (code=exited, status=0/SUCCESS) Tasks: 1 (limit: 1152) CGroup: /system.slice/mosquitto.service └─6705 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

The status should be active (running). If it’s not, check your configuration file and restart again. Some more information may be available in Mosquitto’s log file:

  1. sudo tail /var/log/mosquitto/mosquitto.log

If all is well, use ufw to allow the two new ports through the firewall:

  1. sudo ufw allow 8883
  2. sudo ufw allow 8083

Now that Mosquitto is set up, we’ll configure Certbot to restart Mosquitto after renewing our certificates.

Step 4 — Configuring Certbot Renewals

Certbot will automatically renew our SSL certificates before they expire, but it needs to be told to restart the Mosquitto service after doing so.

Open the Certbot renewal configuration file for your domain name:

  1. sudo nano /etc/letsencrypt/renewal/mqtt.example.com.conf

Add the following renew_hook option on the last line:

/etc/letsencrypt/renewal/mqtt.example.com.conf
renew_hook = systemctl restart mosquitto

Save and close the file, then run a Certbot dry run to make sure the syntax is ok:

  1. sudo certbot renew --dry-run

If you see no errors, you’re all set. Let’s test our MQTT server next.

Step 5 – Testing Mosquitto

We installed some command line MQTT clients in Step 1. We can subscribe to the topic test on the localhost listener like so:

  1. mosquitto_sub -h localhost -t test -u "your-user" -P "your-password"

And we can publish with mosquitto_pub:

  1. mosquitto_pub -h localhost -t test -m "hello world" -u "your-user" -P "your-password"

To subscribe using the secured listener on port 8883, do the following:

  1. mosquitto_sub -h mqtt.example.com -t test -p 8883 --capath /etc/ssl/certs/ -u "your-username" -P "your-password"

And this is how you publish to the secured listener:

  1. mosquitto_pub -h mqtt.example.com -t test -m "hello world" -p 8883 --capath /etc/ssl/certs/ -u "your-username" -P "your-password"

Note that we’re using the full hostname instead of localhost. Because our SSL certificate is issued for mqtt.example.com, if we attempt a secure connection to localhost we’ll get an error saying the hostname does not match the certificate hostname.

To test the websocket functionality, we’ll use a public, browser-based MQTT client. Open the Eclipse Paho javascript client utility in your browser and fill out the connection information as follows:

  • Host is the domain for your Mosquitto server, mqtt.example.com
  • Port is 8083
  • ClientId can be left to the default randomized value
  • Path can be left to the default value of /ws
  • Username is your Mosquitto username from Step 3
  • Password is the password you chose in Step 3

The remaining fields can be left to their default values.

After pressing Connect, the client will connect to your server. You can publish and subscribe using the Subscribe and Publish Message panes below the Connection pane.

Conclusion

We’ve now set up and tested a secure, password-protected and SSL-encrypted MQTT server. This can serve as a robust and secure messaging platform for your IoT, home automation, or other projects.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
4 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

I have encountered few errors when dealing with the certifications.

Command: sudo certbot certonly --standalone --preferred-challenges http -d mqtt.example.com Error: Problem binding to port 80: Could not bind to IPv4 or IPv6.

Command: sudo certbot renew --dry-run Errors: Attempting to renew cert (mqtt.example.com) from /etc/letsencrypt/renewal/mqtt.example.com.conf produced an unexpected error: Problem binding to port 80: Could not bind to IPv4 or IPv6… Skipping. Dry run: skipping deploy hook command: systemctl restart mosquitto

You have to stop the webservice. For me it was “service apache2 stop”

Everything working fine except for the Eclipse Paho javascript client. The “Connect” button throws an error on the javascript console: Uncaught ReferenceError: connectionToggle is not defined And obviously the connection does not take place.

Everything works smoothly apart from I can’t connect securely on port 8883. I get a “Error: A TLS error occurred.”. It works over 1883 using the domain but not 8883. /etc/ssl/certs/ is empty should something be in here?

When renewing the SSL certs, the mosquitto restart commands fails because it doesn’t wait the process to start again, you need to use (not a clean way of restarting but at least it works…)

renew_hook = systemctl stop mosquitto;sleep 1;systemctl start mosquitto

the sleep commands makes the magic here. If you find any other way of doing it, please share it.

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel