Skip to content
Learni
View all tutorials
IoT & DevOps

How to Secure Mosquitto MQTT Broker in 2026

Lire en français

Introduction

In 2026, IoT architectures demand ultra-secure, scalable MQTT brokers. Mosquitto, the lightest and most performant open-source broker, leads with native MQTT 5.0 support, persistent storage, and inter-broker bridges. This expert tutorial guides you step-by-step to deploy a production-ready Mosquitto: Linux installation, advanced configuration with password authentication, granular ACLs, TLS 1.3 encryption, persistence, and Docker Compose orchestration.

Why it matters: In a zero-trust world, a poorly secured broker exposes your devices to MITM or DoS attacks. We provide complete, immediately testable configs while avoiding expert-level pitfalls. By the end, your broker will handle 100k+ QoS2 connections without breaking a sweat, ready for Kubernetes or edge computing. (142 words)

Prerequisites

  • Ubuntu 24.04 LTS or Debian 12 server (4 GB RAM minimum for load testing).
  • Advanced MQTT knowledge (QoS, topic wildcards, retained messages).
  • OpenSSL 3+ installed (sudo apt install openssl).
  • Docker 27+ and Docker Compose 2.29+ for containerized deployment.
  • Tools: mosquitto_pub/sub (installed with the broker), jq for JSON parsing.

Installing Mosquitto

install-mosquitto.sh
#!/bin/bash
sudo apt update
sudo apt install -y software-properties-common
dist="$(lsb_release -cs)"
wget -O - https://repo.eclipse.org/content/repositories/dev_mosquitto/com/eclipse-mosquitto/repo/${dist}-main/public.key | sudo tee /etc/apt/trusted.gpg.d/mosquitto-${dist}.asc > /dev/null
sudo add-apt-repository -y "deb https://repo.eclipse.org/content/repositories/dev_mosquitto/com/eclipse-mosquitto/repo/${dist}-main/ ${dist} main"
sudo apt update
sudo apt install -y mosquitto mosquitto-clients
sudo systemctl stop mosquitto
sudo systemctl disable mosquitto

This script installs the latest dev version of Mosquitto (2.0.18+ in 2026) from the official Eclipse repo for full MQTT 5.0 support. It disables the systemd service for manual configuration. Avoid outdated distro packages that lack features like shared subscriptions.

Basic Configuration and Listener

Now, test the bare broker. Run the installation code, then in one terminal use mosquitto_sub -h localhost -t test/topic, and publish with mosquitto_pub -h localhost -t test/topic -m 'Hello MQTT'. The broker listens on 1883 by default (unsecured).

Basic Mosquitto Configuration

/etc/mosquitto/mosquitto.conf
persistence true
persistence_location /var/lib/mosquitto/
log_dest file /var/log/mosquitto/mosquitto.log
log_type all
log_timestamp true
log_timestamp_format %Y-%m-%dT%T%z
max_queued_messages 10000
max_queued_bytes 1048576
allow_anonymous false
listener 1883 localhost
listener 8883
protocol mqtt
max_connections 100000

This config enables persistence (messages survive restarts), detailed logging with ISO timestamps, and two listeners: 1883 local-only for testing, 8883 for standard MQTT. Limit queues to prevent OOM under load. allow_anonymous false enforces auth from the start.

Starting and Basic Testing

Place the config in /etc/mosquitto/mosquitto.conf, create dirs with sudo mkdir -p /var/lib/mosquitto /var/log/mosquitto, and set ownership sudo chown -R mosquitto:mosquitto /var/{lib,log}/mosquitto. Start it: sudo -u mosquitto mosquitto -c /etc/mosquitto/mosquitto.conf. Test pub/sub – expect an auth error (that's good!).

Generating the Password File

gen-passwords.sh
#!/bin/bash
sudo mkdir -p /etc/mosquitto/auth
sudo touch /etc/mosquitto/auth/passwordfile
sudo chown mosquitto:mosquitto /etc/mosquitto/auth/passwordfile
sudo -u mosquitto mosquitto_passwd -c /etc/mosquitto/auth/passwordfile admin 'SecurePass2026!'
sudo -u mosquitto mosquitto_passwd /etc/mosquitto/auth/passwordfile iotdevice 'DeviceToken123'
sudo chmod 600 /etc/mosquitto/auth/passwordfile

Generates a hashed password file with mosquitto_passwd (SHA512 PBKDF2). Adds two users: admin (management) and iotdevice (publish/sub). Strict 600 permissions for security. Never store plaintext in production; rotate regularly.

Integrating Password Authentication

Update mosquitto.conf with password_file /etc/mosquitto/auth/passwordfile. Restart: pkill mosquitto ; sudo -u mosquitto mosquitto -c /etc/mosquitto/mosquitto.conf. Test: mosquitto_pub -h localhost -p 1883 -u iotdevice -P 'DeviceToken123' -t sensors/temp -m '23.5'. Success! Without creds, connection refused.

Advanced ACL Configuration

/etc/mosquitto/auth/aclfile
# ACL pour admin : full access
user admin
pattern readwrite %/

# IoT devices : publish sur sensors/, sub sur $SYS/ et actuators/
user iotdevice
pattern write sensors/+
pattern read $SYS/broker/#
p topic read actuators/#

# Groupe devices : wildcards
pattern write home/+/#
pattern read home/%u/#

# Deny all else
pattern readwrite $SYS

Hierarchical ACLs: admin gets full access via %/. iotdevice publishes to sensors/+ (one level), reads sysinfo and actuators. %u injects username for per-user topics. Test with mosquitto_sub -u iotdevice -P 'DeviceToken123' -t 'sensors/invalid' -v – denied! Add acl_file /etc/mosquitto/auth/aclfile to conf.

Applying ACLs and Testing

Add acl_file to mosquitto.conf, set ownership sudo chown mosquitto:mosquitto /etc/mosquitto/auth/aclfile, and restart. Expert tests:

  • Admin pub/sub everywhere: OK.
  • Iotdevice pub sensors/temp: OK; pub home/bad: denied.
Monitor /var/log/mosquitto/mosquitto.log for Access Refused.

Generating Self-Signed TLS Certificates

gen-tls-certs.sh
#!/bin/bash
sudo mkdir -p /etc/mosquitto/certs
cd /etc/mosquitto/certs
sudo openssl req -newkey rsa:4096 -days 365 -nodes -x509 -keyout mosquitto.key -out mosquitto.crt -subj '/C=FR/ST=Paris/L=Paris/O=Learni/OU=IoT/CN=localhost'
sudo openssl dhparam -out dhparam.pem 4096
sudo chown -R mosquitto:mosquitto /etc/mosquitto/certs
sudo chmod 600 /etc/mosquitto/certs/{mosquitto.key,dhparam.pem}
sudo chmod 644 /etc/mosquitto/certs/mosquitto.crt

Generates a self-signed RSA 4096-bit CA (TLS 1.3 compatible) and DH params for Perfect Forward Secrecy. In production, use Let's Encrypt or EJBCA. Critical permissions: private key 600. Verify: openssl x509 -in mosquitto.crt -text -noout.

Enabling TLS on Listener 8883

Add to mosquitto.conf:

listener 8883
protocol mqtt
cafile /etc/mosquitto/certs/mosquitto.crt
certfile /etc/mosquitto/certs/mosquitto.crt
keyfile /etc/mosquitto/certs/mosquitto.key
dhparam /etc/mosquitto/certs/dhparam.pem
require_certificate false
use_identity_as_username true

Restart. Test TLS: mosquitto_pub -h localhost -p 8883 --capath /etc/ssl/certs -u iotdevice -P 'DeviceToken123' -t sensors/temp -m '24.0'. Check logs for TLS-PSK or cipher errors.

Bridge Configuration to Remote Broker

/etc/mosquitto/bridge.conf
connection bridge-to-aws
address aws-iot-endpoint:8883
bridge_hostname mqtt-aws
bridge_username AWS_IOT_USER
bridge_password AWS_IOT_TOKEN
tls_version tlsv1.3
bridge_cafile /etc/mosquitto/certs/aws-ca.crt
bridge_certfile /etc/mosquitto/certs/client.crt
bridge_keyfile /etc/mosquitto/certs/client.key
remote_username mosq-aws
remote_password bridgepass
topic sensors/# out 1 bridge-mqtt-aws/ sensors/ {{"qos":1,"retain":true}}
topic actuators/# in 2 bridge-mqtt-aws/ actuators/

Bridge out/in: forwards sensors/# to AWS IoT (QoS1, retain), subs actuators QoS2. Mutual TLS for security. Include via include_dir /etc/mosquitto/conf.d with sudo ln -s /etc/mosquitto/bridge.conf /etc/mosquitto/conf.d/. Scales for clustering.

Production Docker Deployment

For high availability, use Docker. Generate secrets via docker secret create mosquitto_pw /etc/mosquitto/auth/passwordfile.

Docker Compose for HA Mosquitto

docker-compose.yml
version: '3.8'
services:
  mosquitto:
    image: eclipse-mosquitto:2.0
    restart: always
    ports:
      - '1883:8883'
      - '8883:8883'
    volumes:
      - ./mosquitto.conf:/mosquitto/config/mosquitto.conf:ro
      - ./auth:/mosquitto/config/auth:ro
      - ./certs:/mosquitto/config/certs:ro
      - mosquitto_data:/mosquitto/data
      - mosquitto_log:/mosquitto/log
    environment:
      - TZ=Europe/Paris
    networks:
      - iot-net
volumes:
  mosquitto_data:
  mosquitto_log:
networks:
  iot-net:
    driver: bridge

Production Compose: persistent volumes, read-only configs, TZ for logs. Scale with replicas in Swarm. Run docker compose up -d. Monitor with Prometheus via Mosquitto plugin.

Best Practices

  • Rotate credentials: Monthly cron script for mosquitto_passwd + ACL updates.
  • Monitoring: Enable $SYS/broker/clients/active + Prometheus exporter.
  • Load testing: Use mqtt-benchmark for 10k conn/s.
  • Backup: Rsync /var/lib/mosquitto + mosquitto_db_dump.
  • Zero-trust: Mutual TLS + PSK for low-power devices.

Common Errors to Avoid

  • Forgetting sudo chown mosquitto on configs: crashes with 'Permission denied'.
  • ACL without user prefix: applies globally, exposes everything.
  • TLS without DH params: falls back to insecure ciphers (log: 'no shared cipher').
  • No max_connections: DoS via exhaustion (default 1000 too low).

Next Steps

Dive into MQTT 5.0 shared subscriptions with our Learni IoT training. Resources: Mosquitto Docs, MQTT Explorer for debugging, Eclipse GitHub repo for C plugins.