Sometimes you are lucky enough to have to learn a new cool technology for a project that you are working on. I’m working on the MakeTimeFlow building a juicy IOT device that helps me flow between lots of projects and boosts my executive functioning. I was using an https API endpoint to capture data, but this was heavy and slowing the devices down, and I also wanted to be able to have multiple ways that users could enter their data (device, desktop, app) so I needed some kind of pub/sub solution - and MQTT was waiting. These are my notes on working with this.

Install Mosquitto on Mac

brew install mosquitto

Mosquitto comes with useful command line tools for publishing and subscribing to topics

mosquitto_sub -h localhost -t test
mosquitto_pub -h localhost -t test -m "hello world"

Install Mosquitto securely on the server

I based this on this great Digital Ocean tutorial. I’m using an Ubuntu 20.04 server so some things have changed.

Mosquitto is available as a snap, but it currently makes it a lot harder to work with with the documentation for learning (for example it places files not in /etc/mosquitto but in /var/snap/mosquitto/common). You can still install it with apt-get

As root

sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt-get update
sudo apt-get install mosquitto mosquitto-clients

I like to test that it is working, so I login another terminal and in one do sub and the other pub:

mosquitto_sub -h localhost -t test
mosquitto_pub -h localhost -t test -m "hello world"

Make sure users have to authenticate.

sudo vim /etc/mosquitto/confi.d/default.conf
allow_anonymous false
password_file /etc/mosquitto/passwd

Create an account for you to test with.

sudo mosquitto_passwd -c /etc/mosquitto/passwd username

Now these should no longer work:

mosquitto_sub -h localhost -t test

But this should work:

mosquitto_sub -h localhost -t test -u "username" -P "password"
mosquitto_pub -h localhost -t test -m "hello world" -u "username" -P "password"

Setup Nginx to proxy MQTT requests

I followed this helpful guidance.

sudo vim /etc/mosquitto/confi.d/default.conf

Add in the bind_address to bind it only to localhost

allow_anonymous false
password_file /etc/mosquitto/passwd

bind_address localhost

I have not figured out how to do this for the websockets protocol yet, but I suspect it will be similar.

#listener 8083
#protocol websockets

Now the key next step is to update nginx.conf (note: not the normal sites-avaiable/site.conf)

sudo vim /etc/nginx/nginx.conf

Add this at the bottom (i.e. below the http { } )

stream {
        upstream mosquitto {
                server localhost:1883;
        }

        server {
            listen 8883 ssl;
            proxy_pass mosquitto;
            ssl_certificate /etc/letsencrypt/live/app.maketimeflow.com/fullchain.pem; # managed by Certbot
            ssl_certificate_key /etc/letsencrypt/live/app.maketimeflow.com/privkey.pem; # managed by Certbot
            #include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
            #ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
        }
}

Make sure mosquitto is running, restart nginx and make sure they are all running.

sudo systemctl restart mosquitto.service
systemctl status mosquitto.service
sudo systemctl restart nginx.service
systemctl status nginx.service

Now you should have a mosquitto reachable server through nginx.

I could not get my local mosquitto_pub and _sub commands to work, but mqtt.fx could connect with SSL/TLS > “CA signed server certificate” enabled.

Setting up access

In the future I will use an auth plugin, for now I am learning about the built in auth methods.

File based ACL

Add in a line to your .conf

acl_file /etc/mosquitto/acl

Now for the acl file you can create a root, and then have all other users have access only to their flow

user youradminuser
topic readwrite #

pattern readwrite flow/%u/#

You can test this now, by pub and sub as admin and as users in allow and “denied” topics. You can monitor this by watching the logs:

tail -f /var/log/mosquitto/mosquitto.log

After adding new users or changing the acl, you can just reload (not restart) the service!

sudo systemctl reload mosquitto.service

Appendix

Trying to get the local commands to connect

mosquitto_pub -h example.com -t test -m “hello again” -p 8883 -u “username” -P “password” -d

To convert pem to crt https://stackoverflow.com/questions/13732826/convert-pem-to-crt-and-key

openssl x509 -outform der -in your-cert.pem -out your-cert.crt

https://upcloud.com/community/tutorials/install-secure-mqtt-broker-ubuntu/

Get the trust ca from a website

openssl s_client -connect app.example.com:443