Eclipse Mosquitto es un broker MQTT ligero y muy extendido en proyectos IoT y de domótica. Una instalación por defecto sirve para pruebas, pero expuesta a Internet necesita cifrado, autenticación y control de qué puede leer o escribir cada cliente. En este tutorial configurarás Mosquitto en Ubuntu 24.04 con TLS de Let's Encrypt en el puerto 8883, usuarios con contraseña, listas de control de acceso (ACL) por topic, MQTT sobre WebSockets seguros y, opcionalmente, un puente hacia otro broker.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo.
  • Un dominio o subdominio (en esta guía your_domain) con un registro DNS A apuntando a la IP del servidor.
  • El puerto 80 libre para que Certbot pueda validar el dominio.
  • UFW activo con SSH permitido.

Paso 1: Instalar Mosquitto

Ubuntu 24.04 incluye Mosquitto 2.0 en sus repositorios. Instala el broker y los clientes de línea de comandos:

sudo apt update
sudo apt install mosquitto mosquitto-clients

El servicio arranca automáticamente. Comprueba su estado:

systemctl status mosquitto --no-pager
● mosquitto.service - Mosquitto MQTT Broker
     Loaded: loaded (/usr/lib/systemd/system/mosquitto.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-09-24 09:40:11 UTC; 8s ago

El archivo principal /etc/mosquitto/mosquitto.conf ya activa la persistencia en /var/lib/mosquitto/, envía el log a /var/log/mosquitto/mosquitto.log e incluye todos los archivos .conf de /etc/mosquitto/conf.d/. No lo modificarás: toda tu configuración irá en conf.d.

Paso 2: Obtener un certificado de Let's Encrypt

Con un certificado de una autoridad pública, los clientes validan el broker usando los certificados raíz del sistema y no tienes que distribuir una CA propia. Instala Certbot y abre el puerto 80 para la validación:

sudo apt install certbot
sudo ufw allow 80/tcp

Solicita el certificado en modo standalone, en el que Certbot levanta un servidor web temporal:

sudo certbot certonly --standalone -d your_domain
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/your_domain/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/your_domain/privkey.pem

Mosquitto se ejecuta con el usuario mosquitto, que no puede leer /etc/letsencrypt/live. En lugar de cambiar los permisos de ese directorio, crea un hook de despliegue que copie el certificado a /etc/mosquitto/certs y reinicie el broker en cada renovación:

sudo nano /etc/letsencrypt/renewal-hooks/deploy/mosquitto.sh
#!/usr/bin/env bash
set -euo pipefail

domain="your_domain"

# Solo actuar cuando se renueva el certificado del broker
if [ "${RENEWED_LINEAGE}" != "/etc/letsencrypt/live/${domain}" ]; then
    exit 0
fi

install -o mosquitto -g mosquitto -m 0644 "${RENEWED_LINEAGE}/fullchain.pem" /etc/mosquitto/certs/fullchain.pem
install -o mosquitto -g mosquitto -m 0600 "${RENEWED_LINEAGE}/privkey.pem" /etc/mosquitto/certs/privkey.pem
systemctl restart mosquitto

Hazlo ejecutable y ejecútalo una vez a mano para copiar el certificado actual:

sudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/mosquitto.sh
sudo RENEWED_LINEAGE=/etc/letsencrypt/live/your_domain /etc/letsencrypt/renewal-hooks/deploy/mosquitto.sh
sudo ls -l /etc/mosquitto/certs/*.pem
-rw-r--r-- 1 mosquitto mosquitto 2864 Sep 24 09:45 /etc/mosquitto/certs/fullchain.pem
-rw------- 1 mosquitto mosquitto  241 Sep 24 09:45 /etc/mosquitto/certs/privkey.pem

Paso 3: Crear los usuarios

Crea el archivo de contraseñas con el primer usuario, admin. La opción -c crea el archivo y lo sobrescribiría si ya existiera, así que úsala solo esta vez:

sudo mosquitto_passwd -c /etc/mosquitto/passwd admin

Añade el resto de usuarios sin -c. En este ejemplo, un sensor y una aplicación de panel que solo lee datos:

sudo mosquitto_passwd /etc/mosquitto/passwd sensor01
sudo mosquitto_passwd /etc/mosquitto/passwd dashboard

Cada comando pide la contraseña dos veces. Las contraseñas se guardan con hash, nunca en claro. Ajusta los permisos para que solo root y el grupo mosquitto puedan leer el archivo:

sudo chown root:mosquitto /etc/mosquitto/passwd
sudo chmod 640 /etc/mosquitto/passwd

Para eliminar un usuario más adelante, usa sudo mosquitto_passwd -D /etc/mosquitto/passwd nombre_usuario y reinicia Mosquitto.

Paso 4: Definir las ACL

Las ACL limitan a qué topics puede suscribirse o publicar cada usuario. Crea el archivo:

sudo nano /etc/mosquitto/acl
# Administrador: acceso total, incluidas las estadísticas del broker
user admin
topic readwrite #
topic read $SYS/#

# Panel: solo lee lecturas de sensores
user dashboard
topic read sensores/#
topic write comandos/#

# Reglas para todos los usuarios: %u se sustituye por el nombre de usuario.
# Cada sensor solo publica en su propia rama y solo lee sus comandos.
pattern write sensores/%u/#
pattern read comandos/%u/#

Reglas a tener en cuenta:

  • Las líneas topic se aplican al último user declarado encima. Las líneas pattern se aplican a todos los usuarios.
  • El comodín # no incluye los topics que empiezan por $SYS, por eso admin necesita su propia regla.
  • Lo que no está permitido explícitamente queda denegado.

Ajusta los permisos igual que el archivo de contraseñas:

sudo chown root:mosquitto /etc/mosquitto/acl
sudo chmod 640 /etc/mosquitto/acl

Paso 5: Configurar los listeners

Vas a definir tres puntos de escucha: MQTT sin cifrar solo en localhost (para servicios del propio servidor, como Home Assistant o Node-RED), MQTT con TLS en el 8883 y MQTT sobre WebSockets con TLS en el 8084 para clientes web. Crea el archivo:

sudo nano /etc/mosquitto/conf.d/broker.conf
# Autenticación y ACL comunes a todos los listeners
per_listener_settings false
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl

# Persistencia y límites
autosave_interval 300
max_queued_messages 1000
max_packet_size 262144

# MQTT sin cifrar, solo accesible desde el propio servidor
listener 1883 localhost

# MQTT sobre TLS
listener 8883
certfile /etc/mosquitto/certs/fullchain.pem
keyfile /etc/mosquitto/certs/privkey.pem

# MQTT sobre WebSockets con TLS
listener 8084
protocol websockets
certfile /etc/mosquitto/certs/fullchain.pem
keyfile /etc/mosquitto/certs/privkey.pem
OpciónFunción
per_listener_settings falseAplica la autenticación y las ACL a todos los listeners por igual.
allow_anonymous falseRechaza clientes sin usuario y contraseña.
autosave_interval 300Guarda la base de persistencia en disco cada 300 segundos, además de al detener el servicio.
max_queued_messages 1000Mensajes máximos en cola por cliente desconectado con sesión persistente.
max_packet_size 262144Rechaza paquetes de más de 256 KB.

Reinicia Mosquitto y comprueba que escucha en los tres puertos:

sudo systemctl restart mosquitto
sudo ss -tlnp | grep mosquitto
LISTEN 0      100        127.0.0.1:1883       0.0.0.0:*    users:(("mosquitto",pid=6120,fd=5))
LISTEN 0      100          0.0.0.0:8883       0.0.0.0:*    users:(("mosquitto",pid=6120,fd=7))
LISTEN 0      100          0.0.0.0:8084       0.0.0.0:*    users:(("mosquitto",pid=6120,fd=9))

Si el servicio no arranca, el motivo aparece al final del log:

sudo tail -n 20 /var/log/mosquitto/mosquitto.log

Abre los puertos cifrados en el firewall. El 1883 queda cerrado al exterior porque solo escucha en localhost:

sudo ufw allow 8883/tcp
sudo ufw allow 8084/tcp

Paso 6: Probar TLS, autenticación y ACL

Desde tu equipo (o desde el propio servidor), abre un suscriptor con el usuario dashboard. La opción --capath /etc/ssl/certs hace que el cliente valide el certificado con las raíces del sistema:

mosquitto_sub -h your_domain -p 8883 --capath /etc/ssl/certs -u dashboard -P 'dashboard_password' -t 'sensores/#' -v

En otra terminal, publica una lectura como sensor01 en su propia rama:

mosquitto_pub -h your_domain -p 8883 --capath /etc/ssl/certs -u sensor01 -P 'sensor01_password' -t sensores/sensor01/temperatura -m 21.5

El suscriptor recibe el mensaje:

sensores/sensor01/temperatura 21.5

Ahora comprueba que la ACL funciona: sensor01 intenta publicar en la rama de otro sensor.

mosquitto_pub -h your_domain -p 8883 --capath /etc/ssl/certs -u sensor01 -P 'sensor01_password' -t sensores/sensor02/temperatura -m 99

El suscriptor no recibe nada: Mosquitto descarta en silencio las publicaciones no autorizadas. Por último, prueba que un cliente sin credenciales es rechazado:

mosquitto_pub -h your_domain -p 8883 --capath /etc/ssl/certs -t prueba -m hola
Connection error: Connection Refused: not authorised.
Error: The connection was refused.

Para el listener de WebSockets, los clientes web (por ejemplo con la librería MQTT.js) se conectan a wss://your_domain:8084 con los mismos usuarios.

Paso 7: Crear un puente hacia otro broker (opcional)

Un puente (bridge) reenvía topics entre dos brokers. Es habitual en una pasarela local que envía sus lecturas a un broker central. Esta configuración va en el broker local que inicia la conexión, no en el central. Crea el archivo:

sudo nano /etc/mosquitto/conf.d/bridge.conf
connection central
address central.example.com:8883
bridge_capath /etc/ssl/certs
remote_clientid gateway01
remote_username gateway01
remote_password your_bridge_password
cleansession false

# Envía las lecturas locales al central con el prefijo edificio1/
topic sensores/# out 1 "" edificio1/
# Recibe del central los comandos para esta pasarela
topic comandos/# in 1 "" edificio1/

El formato de topic es patrón dirección QoS prefijo-local prefijo-remoto. Con esta configuración, sensores/sensor01/temperatura se publica en el central como edificio1/sensores/sensor01/temperatura. En el broker central, el usuario gateway01 necesita permisos de escritura en edificio1/sensores/# y de lectura en edificio1/comandos/#.

Reinicia y revisa el log:

sudo systemctl restart mosquitto
sudo grep -i bridge /var/log/mosquitto/mosquitto.log | tail -n 5
1727171234: Connecting bridge central (central.example.com:8883)

Paso 8: Monitorizar el broker con $SYS

Mosquitto publica estadísticas en los topics $SYS/# cada 10 segundos. Consulta el número de clientes conectados con el usuario admin (la opción -C 1 sale tras recibir un mensaje):

mosquitto_sub -h localhost -p 1883 -u admin -P 'admin_password' -t '$SYS/broker/clients/connected' -C 1 -v
$SYS/broker/clients/connected 3

Otros topics útiles:

TopicQué indica
$SYS/broker/versionVersión del broker.
$SYS/broker/messages/receivedMensajes recibidos desde el arranque.
$SYS/broker/load/messages/received/1minMedia de mensajes recibidos por minuto.
$SYS/broker/store/messages/countMensajes retenidos o en cola almacenados.

Solución de problemas

Connection Refused: not authorised con credenciales correctas: el usuario no existe en /etc/mosquitto/passwd o Mosquitto no puede leer el archivo. Comprueba los permisos (root:mosquitto, 640) y reinicia el servicio tras añadir usuarios.

Error TLS certificate verify failed: el cliente se conecta por IP en lugar de por your_domain, o no tiene las raíces de confianza. Usa siempre el nombre del certificado y --capath /etc/ssl/certs (o --cafile con la ruta del bundle de tu sistema).

Mosquitto no arranca tras editar la configuración: una opción mal escrita o un archivo de certificado ilegible. El log /var/log/mosquitto/mosquitto.log indica la línea exacta del error.

Un cliente publica pero nadie recibe los mensajes: casi siempre es una ACL. Revisa que la regla cubre el topic exacto y recuerda que las líneas topic pertenecen al user anterior.

Conclusión

Tu broker Mosquitto acepta solo conexiones cifradas desde el exterior, exige usuario y contraseña, limita los topics de cada cliente mediante ACL, sirve a clientes web por WebSockets seguros y renueva su certificado automáticamente. El listener local sin cifrar queda disponible para servicios del propio servidor.

Como siguientes pasos puedes:

  • Conectar Home Assistant o Node-RED al listener local 127.0.0.1:1883.
  • Guardar las lecturas de los sensores en una base de datos de series temporales y visualizarlas en Grafana.
  • Pasar a autenticación con certificados de cliente (require_certificate) para dispositivos que no deben usar contraseña.