Setting up MQTT broker with SSL, the easy/lazy way.
In my current setup I’m running Home assistant
via Docker, all the services/add-ons running share /usr/share/hassio/ subfolders as a mount into the docker container.
For ssl this is /usr/share/hassio/ssl, I’m already running NginxProxyManager
which handles the certs for HTTP, via LetsEncrypt, for me.
So rather than setting it up manually I’m simply going to reuse the cert NginxProxyManager created.
creating the cert
This should be fairly straight forward. Via the webinterface of NginxProxyManager, this should look something like http://192.168.178.x:81/nginx/proxy.
Add a proxy host, input the domain name, point it to anywhere, shouldn’t really matter. Do keep it enabled otherwise the cert will not be updated.
finding the cert
All cert live in /usr/share/hassio/ssl which is also the path which is mounted to the containers. This means you can actually use certs from other containers!
root@fractal:/home/patrick# ls -alh /usr/share/hassio/ssl/nginxproxymanager/live
total 80K
drwx------ 19 root root 4,0K nov 14 18:24 .
drwxr-xr-x  9 root root 4,0K feb 15 11:55 ..
drwxr-xr-x  2 root root 4,0K feb  3 12:57 npm-1
drwxr-xr-x  2 root root 4,0K feb  3 12:57 npm-2
drwxr-xr-x  2 root root 4,0K feb  3 13:52 npm-3
drwxr-xr-x  2 root root 4,0K feb  3 13:52 npm-4
...
As you can see these are not easily recognised by name, diving into the directory;
root@fractal:/home/patrick# ls -alh /usr/share/hassio/ssl/nginxproxymanager/live/npm-1/
total 12K
drwxr-xr-x  2 root root 4,0K feb  3 12:57 .
drwx------ 19 root root 4,0K nov 14 18:24 ..
lrwxrwxrwx  1 root root   29 feb  3 12:57 cert.pem -> ../../archive/npm-1/cert5.pem
lrwxrwxrwx  1 root root   30 feb  3 12:57 chain.pem -> ../../archive/npm-1/chain5.pem
lrwxrwxrwx  1 root root   34 feb  3 12:57 fullchain.pem -> ../../archive/npm-1/fullchain5.pem
lrwxrwxrwx  1 root root   32 feb  3 12:57 privkey.pem -> ../../archive/npm-1/privkey5.pem
To “easily” check the domain (CN/common name) simply use openssl.
root@fractal:/home/patrick# openssl x509 -noout -subject -in /usr/share/hassio/ssl/nginxproxymanager/live/npm-1/cert.pem 
subject=CN = my.domainname.com
Since we’ve just created a new one we can simply go by date and get the latest. Please do validate it is the correct one.
Config
Within Home assistant -> supervisor -> Mosquitto Broker -> configuration
Look for and replace or add;
certfile: fullchain.pem
keyfile: privkey.pem
Please note, we omit the
/usr/share/hassio, sincesslis mount to/sslin the container.
Mosquitto is wrapped in a
run.shscripts which checks if the files exist and PREPENDS/ssl/
# Enable SSL if exists configs
if [ -e "/ssl/$CAFILE" ] && [ -e "/ssl/$CERTFILE" ] && [ -e "/ssl/$KEYFILE" ]; then
    echo "$SSL_CONFIG" >> /etc/mosquitto.conf
else
    bashio::log.warning "SSL not enabled - No valid certs found!"
fi
for more info see
/usr/share/hassio/addons/core/mosquitto/data/run.sh
So the config becomes:
certfile: nginxproxymanager/live/npm-19/fullchain.pem
keyfile: nginxproxymanager/live/npm-19/privkey.pem
Save, restart the container, and check the log if it comes up AND if the 8883 port is included
Alternatives
Connect to 443 directly
I actually tried this, using MQTT Explorer to connect directly to NginxProxyManager on 443 but this doesn’t work.
NginxProxy as a proxy for mqtt
Sadly this isn’t as easy as you might think, but you would have to be able to add an additional port to NginxProxyManager. So some clarification, you would need to add the 8883, the MQTT SSL port, to NginxProxyManager docker container. That might not seem that big of an issue, take (for example) Portainer, edit the container, add the port, BUT, with each update (and possibly restart) Home Assistant will remove it again.
WS/WSS
Could we use WS or WSS via NginxProxy alone? Yes of course, will I? NO, I’m going to connect to it from a microcontroller on which I don’t intent to implement websocket.