Setup Mosquitto With SSL Using Docker On AWS
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:
- using OwnTrack's generate-CA.sh script
- using Let's Encrypt certbot
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
});