MQTT Broker on Digital Ocean

MQTT Broker on Digital Ocean

"In the previous episode..."

I wrote a short post on MQTT and VerneMQ some months ago and promised a follow-up. Here it is.

Scope of the post

In this post I'll explain how to set up a VerneMQ server on a Ubuntu virtual machine on DigitalOcean. We will use LetsEncrypt to enable ssl connection and setup users and topics for the VerneMQ server.

Some tools and prerequisites

Mosquitto

When you are setting up a MQTT server (or doing andthing with MQTT really) it's nice to have an easy way to test your setup. Mosquitto is a nice tool to do just that.

Using the command-line tools mosquitto-pub and mosquitto-sub saved me some gray hair. I strongly advise that you download and install it!

Eclipse Mosquitto
Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices

You will need a domain

We are going to use LetsEncrypt and certbot to generate ssl certificates. For that you need a domain.

You will also need to add that domain to your DigitalOcean droplet. If you don't have a domain that is already using DigitalOceans name servers ns1.digitalocean.com, ns2.digitalocean.com and ns3.digitalocean.com, you will need to change your domain to used them.  Follow the instructions of your domain shop to change DNS. When you have done so it might take up to 48 hours for the change to propagate.

The virtual machine

First we need a machine in the ☁️ for our VerneMQ server. I like DigitalOcean, but you could use any cloud provider. If you use my referal link you will get $50 in credit over 30 days.

When you have registered a user and signed into DigitalOcean, create a new project and add a droplet (DigitalOcean's name for a cloud server) to it.

Choose Ubuntu (it's the default), and the most modest spec ($5/month).

Remember to add your SSH key to the droplet. That makes it easy and safe to log into it using SSH.

Creating a droplet
The cheapest virtual machine will suffice

Logging into the droplet

Once the droplet is created find it in your project. The IP address of the droplet should appear quite clearly on the page of the droplet. Copy it and use it to SSH into it. Again, this requires that you added a SSH key when you created the droplet.

ssh root@<your.drolet.ip.address>
root@your.drolet.ip.address:~#

Installing VerneMQ

I covered installing VerneMQ in my last post, but here's the recap:

Download the file wget https://github.com/vernemq/vernemq/releases/download/1.9.2/vernemq-1.9.2.bionic.x86_64.deb . Depending on when your are reading this, that might not be the most up-to-date version. You can find all versions of VerneMQ on https://vernemq.com/downloads/.

The installation guide for VerneMQ is very nice. I'll just recap it here.

Once the file is downloaded you can install by running dpkg install vernemq-1.9.2.bionic.x86_64.deb.

Verfy the installation

Next, run dpkg -s vernemq | grep Status.

If VerneMQ has been installed successfully Status: install ok installed is returned.

Start VerneMQ

Once you've installed VerneMQ, start it on your node:

service vernemq start

SSL, please

I wanted to use a secure connection to the VerneMQ server. LetsEncrypt and certbot to the rescue! 🤖

Install Certbot

First install certbot on the droplet. Assuming you chose Ubuntu just follow the instructions on the certbot hompage.

Generate a certificate

When certbot is installed we can generate a certificate. That can be done with the following command: sudo certbot certonly --standalone

You will be guided through som steps, including providing the domain for the certificate. This domain should be the one you intend to use for the droplet and MQTT server.

Move the certificates

I read a post about another guy setting up VerneMQ with SSL. He recommended moving the cert and key to /etc/vernemq/ and changing the owner to vernemq. This might not be needed, but I don't think there is any harm in it and you avoid having to give read rights to your letsencrypt folder.

You can do it with the following commands:

cp /etc/letsencrypt/live/your.domain.name/*.pem /etc/vernemq/

chown vernemq:vernemq /etc/vernemq/*.pem

Configure VerneMq

Now we need to add some listeners so VerneMQ knows it should expect requests through ssl, and on other ports. We also need to point to the cert file, key file and ca file for SSL to work. I added/edited the following lines in /etc/vernemq/vernemq.conf. Note the line numbers may differ in your vernemq.conf

237 listener.tcp.local = 127.0.0.1:1883
238 listener.tcp.default = <droplet_ip>:1883
239 listener.ssl.default = <droplet_ip>:8883
285 listener.http.local = 127.0.0.1:8888
286 listener.http.default = <droplet_ip>:8888
335 listener.https.certfile = /etc/vernemq/cert.pem
356 listener.vmqs.keyfile = /etc/vernemq/privkey.pem
363 listener.https.keyfile = /etc/vernemq/privkey.pem

Add users

I also wanted to restrict read and write access to VerneMQ to specific users. This is easily done by using the vmq-passwd command-line tool and/or editing /etc/vernemq/vmq.passwd file.

I ended up writing the user names and passwords in my favorite editor and pasting it all into vmq.passwd before running vmq-passwd -U /etc/vernemq/vmq.passwd to encrypt the passwords in the file. There should be one username and password per line, separated by a : .

user1:password1
user2:password2

vmq-passwd -U /etc/vernemq/vmq.passwd

Please make sure that your usernames and passwords does not contain any : 's.  Also, make sure that you don't have any trailing spaces. I spent way to much time on this step... 🙄

Add topics

Now it's time to add the MQTT topics that you will publish and subscribe to. That's done by editing the /etc/vernemq/vmq.acl file. Again, the official VerneMQ documentation explains this quite nicely.

TLDR;
You can grant read and/or write to anonymous users and/or named users. I added a subscriber user and a publisher user.

user subscriber
topic read topicname1/#
topic read anothertopic/#

user publisher
topic write topicname1/#
topic write anothertopic/#

☠️☠️☠️ Trailing spaces will be part of the topic name ☠️☠️☠️

Restart VerneMQ

To make sure that all of these changes takes effect please restart VerneMQ

vernemq restart

Test with mosquitto

Assuming you did install mosquitto, you can now try to subscribe to one of your topics.

In terminal 1
mosquitto_sub -h <yourdomian.com> -u <verne-mq-user> -p 8883 -t <your-topic> -P <user-password> --cafile /etc/ssl/certs/cacert.pem

and publish to it in terminal 2
mosquitto_pub -h <yourdomian.com> -u <verne-mq-user> -P <user-password> -p 8883 -t <your-topic> -m "HI!" --cafile /etc/ssl/certs/cacert.pem

If you are on Linux you can use the --capath /etc/ssl/certs option instead. For people on Mac: you either have to export the root certificates from the Keychain tool or download them.

If everything works you should see the message "HI!" in terminal 1.  🎉🎉🎉

Now write code!

Hopefully you are all setup to write som acctual code that leverages MQTT. I recommend you write that code in Elixir, using the Tortoise MQTT library 😀

Until next time 🤙