Let Mosquitto MQTT broker piggyback on Nginx's Let's Encrypt certificates

This article documents a method to let Mosquitto MQTT broker use the same certificates as Blocks with NGINX if deployed on the same server and accessed with the same domain name. This allows us to get the certificates automatically updated from the Lets Encrypt Nginx cert bot.

It assumes a working server with certificates handled by NGINX, as described in the Blocks "net-install" here, and Mosquitto installed on the server.

The article Add certificates for the Mosquitto MQTT broker secure connections describes the general setup to add TLS, and the article MQTT gives some context about MQTT and the Mosquitto broker.

Config file

We use a Mosquitto config file in /etc/mosquitto/conf.d with the following content:

 
user mosquitto 
password_file /etc/mosquitto/conf.d/pixi-pwd
listener 1883 localhost

listener 8883

keyfile /etc/mosquitto/certs/privkey.pem
certfile /etc/mosquitto/certs/fullchain.pem
cafile /etc/mosquitto/certs/fullchain.pem

Password file is described in the tls-article linked above and the 1883 listener is only required if one want the blocks server use local host with no encryption (probably a little bit more efficient)

To use the same certs as NGINX, symlink the relevant NGINX certs into /etc/mosquitto/certs like this:

:!: The path to the Let's Encrypt certs will vary depending on the domain name in use.

 
ln -s /etc/letsencrypt/live/pixilab.net/cert.pem /etc/mosquitto/certs/cert.pem 
ln -s /etc/letsencrypt/live/pixilab.net/chain.pem /etc/mosquitto/certs/chain.pem 
ln -s /etc/letsencrypt/live/pixilab.net/fullchain.pem /etc/mosquitto/certs/fullchain.pem 
ln -s /etc/letsencrypt/live/pixilab.net/privkey.pem /etc/mosquitto/certs/privkey.pem
 

Once this is done, restart Mosquitto:

 systemctl restart mosquitto 

Automatically restart Mosquitto after any Certbot renewal

To achieve this, use Certbot’s deploy hooks.

Create a script in the deploy hook directory:

 nano /etc/letsencrypt/renewal-hooks/deploy/restart-mosquitto.sh 

Add the following shell script content:

 #!/bin/bash
echo "[+] Let's Encrypt certificate deployed. Restarting Mosquitto..."

#Restart the Mosquitto service
if systemctl restart mosquitto; then
echo "[+] Mosquitto restarted successfully."
else
echo "[!] Failed to restart Mosquitto." >&2
exit 1
fi

Make the script executable:

 chmod +x /etc/letsencrypt/renewal-hooks/deploy/restart-mosquitto.sh 

Verify functionality

To verify that everything works, force Certbot to renew the certificates:

 certbot renew --force-renewal 

Then check that Mosquitto restarted automatically:

 journalctl -u mosquitto --since "5 minutes ago" 

You should see some startup logging from Mosquitto as a result.

After the process finishes, Mosquitto should continue to work with TLS connections.