Provision an EC2 instance on AWS:

Create a new Elastic IP address, and associate it with your instance. Now the certificates docker-machine generated won't be valid. You will have to regenerate the certs.

docker-machine regenerate-certs mqtt-server

This will trigger a Docker daemon restart which will stop running containers, best to do this before you create any containers.

Now that we have an Elastic IP, we want to create a CNAME record, using Route53.

Generating certificates:

Install certbot

Certbot is part of EFF’s effort to encrypt the entire Internet. Secure communication over the Web relies on HTTPS, which requires the use of a digital certificate that lets browsers verify the identity of web servers (e.g., is that really google.com?). Web servers obtain their certificates from trusted third parties called certificate authorities (CAs). Certbot is an easy-to-use client that fetches a certificate from Let’s Encrypt—an open certificate authority launched by the EFF, Mozilla, and others—and deploys it to a web server.

Ubuntu's certbot seems out of date, we can install the official client from an Ubuntu PPA.

sudo add-apt-repository ppa:certbot/certbot

After you need to update the packages:

sudo apt-get update

Finally install the client:

sudo apt-get install certbot

Running certbot

sudo certbot certonly --standalone --preferred-challenges http-01 -d mqtt-test.goliat.dev
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/mqtt-test.goliat.dev/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/mqtt-test.goliat.dev/privkey.pem
   Your cert will expire on 2017-12-25. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"

Setup Automatic Renewals

We can use cron to schedule a check for expiring certificates and renew them using certbot.

sudo crontab -e
####
# run every day at 3:15AM. Check certs, update if expiring
# in less than 30 days, restart mosquitto afterwards
####
15 3 * * * certbot renew --noninteractive --post-hook "systemctl restart mosquitto"

No Docker

sudo apt-get install mosquitto mosquitto-clients
sudo nano /etc/mosquitto/conf.d/default.conf

configuration file:

listener 1883 localhost
listener 8883
cafile /etc/letsencrypt/live/mqtt-test.goliat.dev/chain.pem
certfile /etc/letsencrypt/live/mqtt-test.goliat.dev/cert.pem
keyfile /etc/letsencrypt/live/mqtt-test.goliat.dev/privkey.pem


# log_dest file /var/log/mosquitto.log
# log_type warning

listener 8083
protocol websockets
cafile /etc/letsencrypt/live/mqtt-test.goliat.dev/chain.pem
certfile /etc/letsencrypt/live/mqtt-test.goliat.dev/cert.pem
keyfile /etc/letsencrypt/live/mqtt-test.goliat.dev/privkey.pem

Need to restart afterwards:

sudo systemctl restart mosquitto

Test commands:

mosquitto_pub -h mqtt-test.goliat.dev -t test -m "hello again" -p 8883 --capath /etc/ssl/certs/

mosquitto_sub -h mqtt-test.goliat.dev -t test -p 8883 --capath /etc/ssl/certs/

docker-machine env mqtt-server
eval $(docker-machine env mqtt-server)
docker-machine ssh mqtt-server

Websockets

Ports 9001 or 8083

Connect client:

<script src="https://raw.githubusercontent.com/eclipse/paho.mqtt.javascript/master/src/paho-mqtt.js" />
// host and port overwritten at connect
var mqtt = new Paho.MQTT.Client("yourdomain.com", 9001, "");

mqtt.connect({
    hosts: [ "wss://yourdomain.com:9001/" ],
    useSSL: true
});