Introduction
So you’re setting up a Mosquitto MQTT broker on a Raspberry Pi with TLS and ACLs? Smart move. MQTT’s great for lightweight messaging, but out of the box, it’s about as secure as leaving your front door open with a welcome mat that says “Hack me.” That’s where TLS encryption and ACLs come in. These two are like the deadbolt and peephole for your message broker — they stop snoopers and limit who gets to see what.
I ran this on a Pi 4B using Raspberry Pi OS Lite. I locked down access using an ACL file that maps users to specific topics, then wrapped everything in TLS with a CA-signed certificate chain. Clients using ESP32 and Node-RED talked to it using encrypted payloads and client certs. You could do the same — just don’t skip any steps or you’ll end up debugging port errors longer than you’d like.
Ready to get the broker secured and clients filtered? Let’s dig into what hardware you need and how to prep it.
Key Takeaways
- Use TLS (with valid certs) to encrypt MQTT traffic.
- Configure ACLs to lock down topic access per user or client.
- Avoid anonymous access; use password files or client certs.
- Debug with
journalctl,mosquitto.log, andopenssl s_client. - Monitor broker health using
$SYS/topics and external dashboards.
Hardware and OS Setup for MQTT
Raspberry Pi Model Selection
Not every Raspberry Pi is created equal. If you’re just handling a few MQTT clients on your LAN, a Raspberry Pi Zero W might squeak by. But the moment you throw in TLS, you’re asking that tiny CPU to do encryption math. That’s like asking a hamster to solve algebra.
Go with a Raspberry Pi 3B+ or Pi 4. Both have better networking, USB ports for expandability, and enough RAM to avoid swap-induced slowdowns. If you’re using TLS + ACLs + logging, anything under 1GB RAM becomes a bottleneck.
Compatible Raspberry Pi Models:
| Model | CPU | RAM Options | Suitable Use Case |
|---|---|---|---|
| Pi Zero W | 1GHz, single-core | 512MB | Testing only |
| Pi 3B+ | 1.4GHz, quad-core | 1GB | Basic secure MQTT broker |
| Pi 4 | 1.5GHz, quad-core | 2–8GB | Production or multi-client |
Operating System Options
You’ve got choices, and like pizza toppings, some are better than others. The go-to is Raspberry Pi OS Lite — it’s stable, headless, and doesn’t waste cycles on a GUI. Alternatives like DietPi are even leaner, while Ubuntu Server ARM is good if you’re already used to systemd on Ubuntu.
Make sure SSH is enabled and Wi-Fi or Ethernet is configured before you detach the monitor. You don’t want to end up blind after first boot.
Popular OS Choices:
- Raspberry Pi OS Lite – clean, lightweight, stable
- DietPi – ultra minimal, great for resource efficiency
- Ubuntu Server – if you want full Ubuntu ecosystem
Basic Networking
If your IP changes every time the Pi reboots, you’re going to have a bad time. Set a static IP either through your router or in the Pi’s dhcpcd.conf. This way, your clients don’t chase a moving target.
Make sure your hostname is something descriptive — not just “raspberrypi” unless you want conflicts down the road. I like “mqtt-pi” because, well, it tells me what the Pi does.
Commands you’ll use:
hostnamectl set-hostname mqtt-pi
sudo nano /etc/dhcpcd.conf # for static IP
Once that’s sorted, you’re ready to install Mosquitto.
Installing Mosquitto on Raspberry Pi
Using apt to Install Mosquitto
No need to compile from source unless you’re feeling fancy. The Mosquitto package in the Raspberry Pi OS repository is good enough for TLS and ACL support.
Run this in the terminal:
sudo apt update
sudo apt install mosquitto mosquitto-clients
sudo systemctl enable mosquitto
sudo systemctl start mosquitto
This installs both the broker and handy client tools like mosquitto_pub and mosquitto_sub — great for testing without writing a single line of code.
Check the service:
sudo systemctl status mosquitto
If it says “active (running)”, you’re in business. If it says “dead”, well, you’re not.
Directory Structure and Files
Here’s where Mosquitto likes to hang out on a Pi:
| File/Directory | Purpose |
|---|---|
/etc/mosquitto/mosquitto.conf | Main config file |
/etc/mosquitto/conf.d/ | Drop-in config fragments |
/etc/mosquitto/passwd | Encrypted password file |
/etc/mosquitto/acl | Access control list file |
/var/log/mosquitto/mosquitto.log | Log file for errors and events |
/usr/sbin/mosquitto | The actual broker binary |
Instead of cramming all config into one file, you can keep things tidy using include_dir /etc/mosquitto/conf.d/ in the main mosquitto.conf. Then create files like listener.conf, tls.conf, and acl.conf inside conf.d.
Want to see if the broker listens?
netstat -tulpen | grep 1883
If you see something like tcp6 0 0 :::1883, it’s working. If not, fix your config before going further.
Configuring MQTT Topics and Clients
Client ID and Session Behavior
Every MQTT client needs a Client ID. It’s how the broker knows who’s talking. Think of it like caller ID — no ID, no memory of who you are.
If you connect with clean_session=true, the broker forgets everything about you the moment you disconnect. Use this if you’re testing or you don’t care about missed messages. But for real deployments, set clean_session=false and give the client a fixed ID. That way, QoS 1 and 2 messages get stored if the connection drops.
Example:
mosquitto_sub -h mqtt-pi.local -t sensor/temperature -i "client01" --id client01 --clean-session false
Keep Alive and Reconnect Options
The keep alive value is a timeout in seconds. If the broker doesn’t hear from the client within that window, it assumes the client went belly-up and sends out the Last Will and Testament if defined.
Set a keep alive that makes sense. Something like 60 seconds is standard. Some clients can reconnect automatically, but if you’re using raw tools, you’ll have to handle that yourself.
Topic Structures and Wildcards
Topic names aren’t just for show — they define access, ACLs, and how organized your message tree is.
Use slashes to structure them:
home/livingroom/temperature
home/kitchen/humidity
devices/pi1/status
Wildcards make subscriptions flexible:
+is for single-level (e.g.home/+/temperature)#is for multi-level (e.g.devices/#)
A few good practices:
- Avoid spaces — MQTT doesn’t like them.
- Use lowercase.
- Use consistent separators (
/not_or-). - Keep it hierarchical.
Test it:
mosquitto_pub -t home/livingroom/temp -m 23.4
mosquitto_sub -t home/# # catches everything under home
Access Control Lists (ACLs)
What ACLs Control in Mosquitto
Out of the box, Mosquitto’s like a wide-open freeway. Any client can connect, subscribe, publish — total chaos. ACLs (Access Control Lists) let you control which users can access which topics, and what they’re allowed to do.
Each ACL rule can:
- Allow or deny read, write, or readwrite access
- Target specific topics, clients, or users
- Use wildcards for broader rules
No ACL = every topic is open to everyone. Don’t do that.
Creating ACL Rules
First, make sure you turn off anonymous access in your main config:
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl
Then create the acl file. Here’s what that might look like:
user sensor1
topic read home/livingroom/temperature
user actuator1
topic write home/livingroom/lights
pattern readwrite devices/%u/#
That last line is sneaky useful. %u matches the username, so if a user logs in as sensor1, they get access to devices/sensor1/#.
Restart the broker after edits:
sudo systemctl restart mosquitto
Example ACL Scenarios
1. Read-only Client
user readonly
topic read sensors/temperature
2. Write-only Actuator
user relay1
topic write controls/relay1
3. Full Admin Access
user admin
topic readwrite #
You can also deny access explicitly by omitting permissions. If no rule matches, the default is DENY — unless you override that (bad idea, don’t).
Adding TLS Encryption
Understanding TLS in Mosquitto
TLS isn’t just a checkbox. It’s what keeps your MQTT messages from being intercepted, spoofed, or tampered with. When enabled, TLS encrypts everything between the broker and clients — from topic names to payloads.
To make TLS work with Mosquitto, you need:
- A CA certificate (root cert)
- A server certificate (for the broker)
- A private key (matches the server cert)
Your clients also need to trust the CA, or the connection fails. That’s the point.
Generating Certificates with OpenSSL
This can get tedious, but it’s crucial. Here’s a step-by-step:
- Create the CA (once):
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 1024 -out ca.crt
- Create server key and CSR:
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
- Sign the server cert:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 500 -sha256
Store all these in /etc/mosquitto/certs/.
mosquitto.conf TLS Settings
Add this to a new file like /etc/mosquitto/conf.d/tls.conf:
listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
tls_version tlsv1.2
require_certificate false
Restart Mosquitto:
sudo systemctl restart mosquitto
Now the broker listens securely on port 8883.
Want to force encryption only? Remove the default listener on port 1883. That way, nobody gets in unless they go through TLS.
Secure Authentication
Password File Setup
If you’re not using certificates, at least use passwords. Mosquitto supports hashed password files created with the mosquitto_passwd utility.
Create a password file:
sudo mosquitto_passwd -c /etc/mosquitto/passwd user1
You’ll be prompted to enter a password. The -c flag creates a new file. To add more users, run the command again without -c.
mosquitto.conf settings:
allow_anonymous false
password_file /etc/mosquitto/passwd
Restart the broker to apply changes:
sudo systemctl restart mosquitto
Now only users in that file can connect.
TLS Client Certificate Authentication
This is the more secure route — and more annoying. Instead of passwords, you give each client its own certificate, and the broker only accepts connections if:
- The client certificate is signed by a trusted CA
- The identity in the cert matches the ACL
Enable cert checking in Mosquitto:
require_certificate true
use_identity_as_username true
This tells Mosquitto to use the CN (Common Name) from the client’s certificate as the username in ACL rules.
Example:
If a client connects using a cert with CN=sensor1, then the ACL must include:
user sensor1
topic read sensors/room1
You can combine cert-based auth with passwords, or force one over the other using listener-specific settings.
Dual-Layer Security
Use both TLS with passwords or certs + ACLs to tighten things up. Even if someone steals a password, without the right cert, they’re still locked out.
Test it using mosquitto_sub:
mosquitto_sub -h mqtt-pi.local -p 8883 --cafile ca.crt --cert client.crt --key client.key -t "home/#" -q 1
If it fails with “not authorized,” check the ACLs. If it fails with “TLS handshake failed,” check the cert paths and CA chain.
Debugging and Logs
Using systemctl and journalctl
The broker might be running fine — or it might be silently crying. Either way, you’ll want to use systemctl and journalctl to see what’s going on behind the scenes.
Check broker status:
sudo systemctl status mosquitto
This gives you a quick summary. If something’s broken, it’ll show “inactive” or “failed.”
To view live logs:
journalctl -u mosquitto -f
This streams the log output as it happens — great for catching ACL errors, TLS failures, and config issues right as they occur.
Enabling Verbose Logging
By default, Mosquitto doesn’t show much. You can tell it to be chattier by editing your config:
log_dest file /var/log/mosquitto/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information
You can stack multiple log_type entries to get everything from client connections to subscription events.
Restart the service and check the log file:
tail -f /var/log/mosquitto/mosquitto.log
Common Errors and Fixes
| Error Message | Likely Cause | Fix |
|---|---|---|
Connection Refused | Wrong port, TLS mismatch | Use correct port and TLS settings |
Not authorized | ACLs don’t match | Update ACL file with right topic/user |
Unknown CA | Client doesn’t trust your CA | Provide CA file with connection |
TLS handshake failed | Wrong certs or missing files | Check paths and file permissions |
Broken pipe | Client dropped without disconnect | May need keep alive tuning |
Use openssl s_client to test the TLS connection manually:
openssl s_client -connect mqtt-pi.local:8883 -CAfile ca.crt
If you see cert info and Verify return code: 0 (ok), you’re good. If not, the cert chain is broken or mismatched.
Integration with IoT Clients
ESP32 and ESP8266 Setup
Both ESP32 and ESP8266 boards are popular in home automation. They can run lightweight MQTT libraries like PubSubClient that let them publish sensor data or receive control messages. The catch? TLS eats RAM. You’ll need to be careful with cert sizes.
Steps:
- Flash firmware (Arduino, PlatformIO, or MicroPython)
- Load root CA into flash
- Set Wi-Fi and broker IP
- Use
WiFiClientSecurewith TLS enabled
Arduino Example:
WiFiClientSecure net;
PubSubClient client(net);
net.setCACert(ca_cert);
client.setServer("mqtt-pi.local", 8883);
You’ll need to convert your CA file into a .h string. That’s tedious, but tools like MQTT-TLS-Fingerprint or built-in converters can help.
MQTT.fx and MQTT Explorer
If you want to test without touching code, use GUI tools like:
- MQTT.fx – Java-based, supports TLS, easy to connect and inspect
- MQTT Explorer – Electron app, lets you view the entire topic tree in real-time
Both support custom CA certs, client certificates, and usernames. Plug in the same settings as your ESP32, and you can monitor your topics while the device publishes.
Subscribing and Publishing
Try this from a Pi terminal:
mosquitto_pub -t "home/bedroom/temp" -m "22.3" --cafile ca.crt --cert client.crt --key client.key -p 8883 -h localhost
Then on another window:
mosquitto_sub -t "home/#" --cafile ca.crt --cert client.crt --key client.key -p 8883 -h localhost
You’ll see the message pass through, encrypted and authenticated.
Maintenance and Security Best Practices
Rotating Certs and Passwords
Don’t set it and forget it. TLS certificates expire, and passwords should rotate on a schedule. If your cert is self-signed, set a calendar reminder — nobody else will.
To rotate:
- Generate new key and cert pair.
- Replace files in
/etc/mosquitto/certs/. - Restart the broker.
Avoid downtime by automating it with a script or using Let’s Encrypt + cron for trusted CAs.
Updating Passwords
sudo mosquitto_passwd /etc/mosquitto/passwd user1
That replaces the old hash with a new one. No restart needed.
Rate Limiting and Fail2Ban
Mosquitto doesn’t rate-limit by default. Use Fail2Ban to watch logs and ban IPs that try brute-force logins.
Add jail:
[mosquitto]
enabled = true
port = 1883,8883
filter = mosquitto
logpath = /var/log/mosquitto/mosquitto.log
Create /etc/fail2ban/filter.d/mosquitto.conf with patterns like:
failregex = .*Client connection from <HOST> failed.*
Monitoring Broker Health
You’re not running a critical system unless you’re monitoring it. Track:
- Number of connected clients
- Unusual disconnections
- Message rates
Use tools like:
- Node-RED for visual stats
- Telegraf + InfluxDB + Grafana for logging
mosquitto_sub -t '$SYS/#'for internal stats
Sample output:
$SYS/broker/clients/connected 6
$SYS/broker/messages/sent 542
$SYS/broker/uptime 3 days, 7 hours
Set alerts if clients drop unexpectedly or message volume spikes.
FAQ
Q: Can I use Mosquitto without TLS in a private LAN?
Yes, but it’s risky. Anyone on the same network can sniff or inject MQTT traffic. TLS adds a layer of protection, even in trusted environments.
Q: Do all clients need their own certificate?
Only if you enable require_certificate and use_identity_as_username. Otherwise, clients can authenticate with username/password over TLS.
Q: What if my ESP8266 runs out of memory when using TLS?
Try reducing cert size, disable unnecessary libraries, or use fingerprint-based verification instead of full cert chain validation.
Q: How do I debug ACL denials?
Check /var/log/mosquitto/mosquitto.log. If it says Not authorized, confirm the user exists, matches the rule, and the topic pattern is valid.
Q: Can I run Mosquitto and Node-RED on the same Pi?
Absolutely. Just make sure they don’t fight over ports and both point to the correct TLS settings and brokers.
References
- Mosquitto Documentation
- Raspberry Pi Docs
- MQTT v3.1.1 Specification (OASIS)
- OpenSSL Man Pages
- Fail2Ban GitHub





