Pidiylab Logo

Pidiylab Title

Secure Mosquitto MQTT on Raspberry Pi Using TLS & ACLs

Published:

Updated:

Author:

Secure mosquitto mqtt on raspberry pi using tls & acls

Disclaimer

As an affiliate, we may earn a commission from qualifying purchases. We get commissions for purchases made through links on this website from Amazon and other third parties.

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, and openssl 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:

ModelCPURAM OptionsSuitable Use Case
Pi Zero W1GHz, single-core512MBTesting only
Pi 3B+1.4GHz, quad-core1GBBasic secure MQTT broker
Pi 41.5GHz, quad-core2–8GBProduction 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/DirectoryPurpose
/etc/mosquitto/mosquitto.confMain config file
/etc/mosquitto/conf.d/Drop-in config fragments
/etc/mosquitto/passwdEncrypted password file
/etc/mosquitto/aclAccess control list file
/var/log/mosquitto/mosquitto.logLog file for errors and events
/usr/sbin/mosquittoThe 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:

  1. Create the CA (once):
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 1024 -out ca.crt
  1. Create server key and CSR:
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
  1. 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 MessageLikely CauseFix
Connection RefusedWrong port, TLS mismatchUse correct port and TLS settings
Not authorizedACLs don’t matchUpdate ACL file with right topic/user
Unknown CAClient doesn’t trust your CAProvide CA file with connection
TLS handshake failedWrong certs or missing filesCheck paths and file permissions
Broken pipeClient dropped without disconnectMay 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:

  1. Flash firmware (Arduino, PlatformIO, or MicroPython)
  2. Load root CA into flash
  3. Set Wi-Fi and broker IP
  4. Use WiFiClientSecure with 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:

  1. Generate new key and cert pair.
  2. Replace files in /etc/mosquitto/certs/.
  3. 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

Was this helpful?

Yes
No
Thanks for your feedback!

About the author

Latest Posts

Pi DIY Lab