Mosquitto MQTT Broker Advanced Configuration
Eclipse Mosquitto is a lightweight, open-source MQTT broker that forms the backbone of IoT communication stacks on Linux. This guide covers advanced Mosquitto configuration including TLS encryption, multiple authentication backends, ACL rules for topic-level authorization, broker bridging, WebSocket support, and persistence for reliable message delivery.
Prerequisites
- Ubuntu 20.04/22.04 or CentOS 8/Rocky Linux 8+
- Root or sudo access
opensslinstalled (for TLS certificate generation)- A domain name (for production TLS)
- Port 1883 (MQTT), 8883 (MQTT/TLS), and 9001 (WebSocket) available
Install Mosquitto
Ubuntu/Debian:
# Add official Mosquitto PPA for the latest version
sudo add-apt-repository ppa:mosquitto-dev/mosquitto-ppa -y
sudo apt update
sudo apt install -y mosquitto mosquitto-clients
sudo systemctl enable mosquitto
sudo systemctl start mosquitto
# Verify version
mosquitto -v # Ctrl+C to stop
mosquitto --version
CentOS/Rocky Linux:
sudo dnf install -y epel-release
sudo dnf install -y mosquitto
sudo systemctl enable --now mosquitto
Backup and clear the default config:
sudo cp /etc/mosquitto/mosquitto.conf /etc/mosquitto/mosquitto.conf.bak
# Use /etc/mosquitto/conf.d/ for modular configuration
TLS Encryption Setup
Enable encrypted MQTT connections (MQTT over TLS on port 8883):
# Create a CA and server certificate
sudo mkdir -p /etc/mosquitto/certs
cd /etc/mosquitto/certs
# Generate CA key and certificate
sudo openssl genrsa -out ca.key 4096
sudo openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
-subj "/C=US/ST=State/O=MyOrg/CN=MQTT CA"
# Generate server key and certificate request
sudo openssl genrsa -out server.key 2048
sudo openssl req -new -key server.key -out server.csr \
-subj "/C=US/ST=State/O=MyOrg/CN=mqtt.example.com"
# Sign the server certificate with the CA
sudo openssl x509 -req -days 3650 -in server.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
sudo chown mosquitto:mosquitto /etc/mosquitto/certs/*.{key,crt}
sudo chmod 600 /etc/mosquitto/certs/*.key
Configure TLS in Mosquitto:
cat > /etc/mosquitto/conf.d/tls.conf << 'EOF'
# TLS listener
listener 8883
protocol mqtt
# Certificate files
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
# Require client certificates (optional - for mutual TLS)
# require_certificate true
# TLS version
tls_version tlsv1.2
# Allow TLS 1.3
# tls_version tlsv1.3
# Disable unencrypted connections on port 1883 (comment out to allow both)
# listener 1883
# Remove the default listener if you want TLS-only:
EOF
sudo systemctl restart mosquitto
Test TLS connection:
# Subscribe with TLS (using CA cert for verification)
mosquitto_sub -h localhost -p 8883 \
--cafile /etc/mosquitto/certs/ca.crt \
-t "test/#" -v
# Publish with TLS
mosquitto_pub -h localhost -p 8883 \
--cafile /etc/mosquitto/certs/ca.crt \
-t "test/hello" -m "Hello TLS"
Authentication Backends
Password file authentication:
# Create password file
sudo touch /etc/mosquitto/passwd
sudo chown mosquitto:mosquitto /etc/mosquitto/passwd
sudo chmod 600 /etc/mosquitto/passwd
# Add users
sudo mosquitto_passwd -b /etc/mosquitto/passwd iotdevice devicepassword
sudo mosquitto_passwd -b /etc/mosquitto/passwd homeassistant hapassword
sudo mosquitto_passwd -b /etc/mosquitto/passwd nodered nrpassword
# View users (hashed, not plain text)
sudo cat /etc/mosquitto/passwd
Configure password file authentication:
cat > /etc/mosquitto/conf.d/auth.conf << 'EOF'
# Disable anonymous access
allow_anonymous false
# Password file
password_file /etc/mosquitto/passwd
EOF
sudo systemctl restart mosquitto
# Test authentication
mosquitto_pub -h localhost -p 1883 \
-u iotdevice -P devicepassword \
-t "test/auth" -m "authenticated"
Plugin-based authentication (mosquitto-auth-plug):
# Install mosquitto-auth-plug for MySQL/Redis/HTTP backends
# This requires compiling from source or using a pre-built package
# Alternative: use mosquitto-plugin-auth for newer versions
# Check plugin availability:
mosquitto --help 2>&1 | grep plugin
# HTTP-based authentication (delegates to an auth service)
cat >> /etc/mosquitto/conf.d/auth.conf << 'EOF'
# HTTP auth backend (requires mosquitto-auth-plug or similar)
# auth_plugin /usr/lib/mosquitto_auth_plug.so
# auth_opt_backends http
# auth_opt_http_ip 127.0.0.1
# auth_opt_http_port 3000
# auth_opt_http_getuser_uri /auth/user
# auth_opt_http_superuser_uri /auth/superuser
# auth_opt_http_aclcheck_uri /auth/acl
EOF
ACL Rules and Topic Authorization
ACL files control which users can publish/subscribe to which topics:
cat > /etc/mosquitto/acl << 'EOF'
# Format:
# user <username>
# topic [read|write|readwrite] <topic>
# Home Assistant - read all, write sensors only
user homeassistant
topic readwrite homeassistant/#
topic read home/#
# Node-RED - can read everything, write to processed topics
user nodered
topic read home/#
topic read homeassistant/#
topic write processed/#
topic write alerts/#
# IoT device - can only write to its own topics
user iotdevice
topic write home/device001/#
topic read home/device001/commands
# IoT device 2 with variable topic (using %c for client ID)
# user iotdevice_template
# topic write home/%c/# # %c = MQTT client ID
# topic write home/%u/# # %u = username
# Pattern-based ACL for all users
# pattern read $SYS/# # Allow reading Mosquitto sys stats
EOF
sudo chown mosquitto:mosquitto /etc/mosquitto/acl
sudo chmod 640 /etc/mosquitto/acl
Add ACL file reference to config:
echo "acl_file /etc/mosquitto/acl" | sudo tee -a /etc/mosquitto/conf.d/auth.conf
sudo systemctl restart mosquitto
WebSocket Support
Enable WebSocket for browser-based MQTT clients:
cat > /etc/mosquitto/conf.d/websockets.conf << 'EOF'
# WebSocket listener (for browser clients)
listener 9001
protocol websockets
# WebSocket with TLS (WSS)
listener 9443
protocol websockets
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
EOF
sudo systemctl restart mosquitto
# Test with mosquitto_sub (WebSocket mode)
mosquitto_sub -h localhost -p 9001 -t "test/#" -v \
-u iotdevice -P devicepassword
Browser-based client (JavaScript MQTT.js):
<!-- Include MQTT.js via CDN -->
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script>
const client = mqtt.connect('wss://mqtt.example.com:9443', {
username: 'nodered',
password: 'nrpassword',
rejectUnauthorized: false // Only for self-signed certs in dev
});
client.on('connect', () => {
console.log('Connected to MQTT broker');
client.subscribe('home/#', { qos: 1 });
});
client.on('message', (topic, payload) => {
console.log(`${topic}: ${payload.toString()}`);
});
</script>
Broker Bridging
Bridge two Mosquitto brokers to relay messages between them (e.g., local IoT broker to cloud broker):
cat > /etc/mosquitto/conf.d/bridge.conf << 'EOF'
# Bridge to a remote MQTT broker (e.g., cloud MQTT)
connection cloud-bridge
address cloud-mqtt.example.com:8883
# Topics to bridge
# local-prefix → remote-prefix
# Direction: both = bidirectional, in = remote→local, out = local→remote
topic sensors/# out 1 home/ remote/home/
topic commands/# in 1 remote/ home/
# Authentication for remote broker
remote_username cloud_device
remote_password cloudpassword
# TLS for bridge connection
bridge_cafile /etc/mosquitto/certs/cloud-ca.crt
bridge_tls_version tlsv1.2
# Keep alive and reconnect settings
keepalive_interval 60
connection_messages true
restart_timeout 5
# QoS level for bridged messages
bridge_attempt_unsubscribe false
EOF
sudo systemctl restart mosquitto
# Verify bridge is connected
mosquitto_sub -h localhost -p 1883 -u homeassistant -P hapassword \
-t '$SYS/broker/connection/cloud-bridge/state' -C 1
# Should return: 1 (connected)
Persistence Configuration
Configure message persistence for durable delivery:
cat > /etc/mosquitto/conf.d/persistence.conf << 'EOF'
# Enable persistence
persistence true
persistence_location /var/lib/mosquitto/
# Persistence file name
persistence_file mosquitto.db
# Autosave interval (seconds, 0 = save on disconnect only)
autosave_interval 300
# Maximum QoS 2 message inflight limit
max_inflight_messages 20
# Maximum queued messages per client
max_queued_messages 100
# Retain messages persist across restarts when persistence is enabled
# Retained messages are written to the persistence file
EOF
sudo chown -R mosquitto:mosquitto /var/lib/mosquitto
sudo systemctl restart mosquitto
Monitoring and Logging
cat > /etc/mosquitto/conf.d/logging.conf << 'EOF'
# Log destinations
log_dest file /var/log/mosquitto/mosquitto.log
log_dest stdout
# Log types
log_type error
log_type warning
log_type notice
log_type information
# log_type debug # Very verbose, only for troubleshooting
# Log timestamp
log_timestamp true
log_timestamp_format %Y-%m-%dT%H:%M:%S
EOF
sudo mkdir -p /var/log/mosquitto
sudo chown mosquitto:mosquitto /var/log/mosquitto
Monitor via $SYS topics:
# Subscribe to all system stats
mosquitto_sub -h localhost -p 1883 \
-u homeassistant -P hapassword \
-t '$SYS/#' -v &
# Key $SYS topics to watch:
# $SYS/broker/clients/connected - Active connections
# $SYS/broker/messages/received - Total messages in
# $SYS/broker/messages/sent - Total messages out
# $SYS/broker/bytes/received - Bytes received
# $SYS/broker/bytes/sent - Bytes sent
# $SYS/broker/subscriptions/count - Active subscriptions
# $SYS/broker/load/messages/+ - Message load averages
# View real-time stats
mosquitto_sub -h localhost -p 1883 \
-u homeassistant -P hapassword \
-t '$SYS/broker/clients/connected' \
-t '$SYS/broker/messages/received' \
-v
Troubleshooting
"Connection refused" on port 1883:
# Check if Mosquitto is running
sudo systemctl status mosquitto
sudo journalctl -u mosquitto -n 30
# Check listening ports
ss -tlnp | grep -E "1883|8883|9001"
# Verify config syntax
sudo mosquitto -c /etc/mosquitto/mosquitto.conf --test-options
Authentication failures:
# Test with explicit credentials
mosquitto_pub -h localhost -p 1883 -u testuser -P testpass -t test -m msg -d
# Check if anonymous access is properly disabled
grep allow_anonymous /etc/mosquitto/conf.d/auth.conf
# Verify password file format
sudo cat /etc/mosquitto/passwd | head -5
# Should look like: username:$7$...(bcrypt hash)
ACL errors - "Not authorized":
# Enable debug logging temporarily
echo "log_type all" | sudo tee /etc/mosquitto/conf.d/debug.conf
sudo systemctl restart mosquitto
# Watch logs for ACL denials
sudo tail -f /var/log/mosquitto/mosquitto.log | grep -i "denied\|acl\|auth"
# Remove debug config when done
sudo rm /etc/mosquitto/conf.d/debug.conf
sudo systemctl restart mosquitto
TLS handshake failures:
# Test TLS with OpenSSL
openssl s_client -connect localhost:8883 -CAfile /etc/mosquitto/certs/ca.crt
# Check certificate expiry
openssl x509 -in /etc/mosquitto/certs/server.crt -noout -dates
# Verify CA chain
openssl verify -CAfile /etc/mosquitto/certs/ca.crt /etc/mosquitto/certs/server.crt
Conclusion
Advanced Mosquitto configuration transforms a basic MQTT broker into a secure, production-grade messaging backbone for IoT deployments. TLS encryption protects data in transit, ACL rules enforce the principle of least privilege for each device and service, WebSocket support enables browser-based dashboards, and broker bridging connects on-premises sensors to cloud platforms. Deploy Mosquitto with persistence enabled to ensure QoS 1 and 2 messages survive broker restarts.


