Eclipse Mosquitto es un broker MQTT ligero y de código abierto que implementa las versiones 3.1.1 y 5.0 del protocolo. Es la opción habitual para recoger datos de sensores, domótica y dispositivos IoT, porque consume muy pocos recursos y funciona con cualquier cliente MQTT. En este tutorial instalarás Mosquitto en Ubuntu 24.04, crearás usuarios con contraseña, limitarás qué topics puede usar cada uno con una ACL y expondrás el broker a Internet solo por el puerto cifrado 8883 con un certificado de Let's Encrypt.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Con 1 GB de RAM es suficiente para miles de conexiones ligeras.
- Un usuario no root con privilegios
sudo. - UFW activo con el acceso SSH permitido.
- Un dominio o subdominio (en esta guía,
mqtt.your_domain) con un registro DNS A que apunte a la IP pública del servidor. Es necesario para obtener el certificado TLS. - El puerto 80/tcp libre durante la emisión del certificado.
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 mosquitto_pub y mosquitto_sub:
sudo apt update
sudo apt install mosquitto mosquitto-clients
El paquete habilita e inicia el servicio automáticamente. Comprueba que está activo:
sudo 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 ...
Sin configuración adicional, Mosquitto 2.0 solo escucha en localhost:1883 y acepta clientes anónimos. Haz una prueba rápida. Abre una segunda sesión SSH y suscríbete a un topic:
mosquitto_sub -h localhost -t 'prueba/#' -v
Desde la primera sesión, publica un mensaje:
mosquitto_pub -h localhost -t 'prueba/hola' -m 'funciona'
En la sesión del suscriptor aparecerá:
prueba/hola funciona
Pulsa Ctrl+C para cerrar el suscriptor.
Paso 2: Crear usuarios con contraseña
A partir de aquí el broker exigirá usuario y contraseña. Crea el archivo de contraseñas con un primer usuario, por ejemplo sensor1. La opción -c crea el archivo, así que úsala solo la primera vez:
sudo mosquitto_passwd -c /etc/mosquitto/passwd sensor1
Añade un segundo usuario, panel, que usará una aplicación para leer los datos:
sudo mosquitto_passwd /etc/mosquitto/passwd panel
Introduce una contraseña robusta para cada uno cuando te la pida. Las contraseñas se guardan con hash, no en texto plano.
Mosquitto vuelve a leer este archivo con su propio usuario sin privilegios cuando recarga la configuración, así que ajusta el propietario y los permisos:
sudo chown mosquitto:mosquitto /etc/mosquitto/passwd
sudo chmod 600 /etc/mosquitto/passwd
Paso 3: Definir permisos por topic con una ACL
La lista de control de acceso (ACL) decide qué topics puede leer o escribir cada usuario. Sin ella, cualquier usuario autenticado podría publicar en cualquier topic. Crea el archivo:
sudo nano /etc/mosquitto/acl
Añade estas reglas:
# sensor1 solo publica sus propias lecturas y recibe comandos
user sensor1
topic write sensores/sensor1/#
topic read comandos/sensor1
# panel lee todas las lecturas y puede enviar comandos
user panel
topic read sensores/#
topic write comandos/#
# Cada usuario puede leer y escribir bajo dispositivos/<su usuario>/
pattern readwrite dispositivos/%u/#
Las líneas user aplican las reglas topic que las siguen a ese usuario, y pattern aplica a todos, sustituyendo %u por el nombre de usuario. Todo lo que no está permitido explícitamente queda denegado.
Ajusta los permisos igual que con el archivo de contraseñas:
sudo chown mosquitto:mosquitto /etc/mosquitto/acl
sudo chmod 600 /etc/mosquitto/acl
Paso 4: Obtener un certificado TLS de Let's Encrypt
MQTT sin cifrar envía usuarios, contraseñas y datos en claro, así que el acceso desde Internet debe ir por TLS. Instala Certbot y abre temporalmente el puerto 80 para la validación:
sudo apt install certbot
sudo ufw allow 80/tcp
Solicita el certificado en modo standalone, que levanta un servidor web temporal:
sudo certbot certonly --standalone -d mqtt.your_domain
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/mqtt.your_domain/fullchain.pem
Key is saved at: /etc/letsencrypt/live/mqtt.your_domain/privkey.pem
Mosquitto no puede leer directamente /etc/letsencrypt/live/, que solo es accesible para root. La solución recomendada es un hook de despliegue que copie los certificados a /etc/mosquitto/certs en cada renovación y recargue el broker. Crea el script:
sudo nano /etc/letsencrypt/renewal-hooks/deploy/mosquitto.sh
#!/usr/bin/env bash
set -euo pipefail
DOMAIN="mqtt.your_domain"
if [[ "${RENEWED_LINEAGE:-}" == "/etc/letsencrypt/live/${DOMAIN}" ]]; then
install -d -m 750 -o mosquitto -g mosquitto /etc/mosquitto/certs
install -m 644 -o mosquitto -g mosquitto "${RENEWED_LINEAGE}/fullchain.pem" /etc/mosquitto/certs/fullchain.pem
install -m 600 -o mosquitto -g mosquitto "${RENEWED_LINEAGE}/privkey.pem" /etc/mosquitto/certs/privkey.pem
systemctl reload mosquitto || true
fi
Hazlo ejecutable y lánzalo una vez a mano, pasando la variable que Certbot define en las renovaciones:
sudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/mosquitto.sh
sudo RENEWED_LINEAGE=/etc/letsencrypt/live/mqtt.your_domain /etc/letsencrypt/renewal-hooks/deploy/mosquitto.sh
sudo ls -l /etc/mosquitto/certs
-rw-r--r-- 1 mosquitto mosquitto 2876 ... fullchain.pem
-rw------- 1 mosquitto mosquitto 241 ... privkey.pem
Certbot renueva el certificado solo mediante su temporizador de systemd, pero el modo standalone necesita el puerto 80 abierto en cada renovación. Si prefieres no dejarlo abierto permanentemente, usa un plugin DNS de Certbot para tu proveedor.
Paso 5: Configurar los listeners de Mosquitto
El archivo principal /etc/mosquitto/mosquitto.conf ya incluye los archivos de /etc/mosquitto/conf.d/ y activa la persistencia en /var/lib/mosquitto/. No lo modifiques; crea un archivo propio:
sudo nano /etc/mosquitto/conf.d/broker.conf
# Opciones globales
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl
# MQTT sin cifrar solo para clientes locales
listener 1883 localhost
# MQTT sobre TLS para clientes remotos
listener 8883
certfile /etc/mosquitto/certs/fullchain.pem
keyfile /etc/mosquitto/certs/privkey.pem
tls_version tlsv1.2
allow_anonymous, password_file y acl_file se aplican a todos los listeners porque per_listener_settings está desactivado por defecto. Las opciones de certificado afectan solo al listener que las precede, en este caso el 8883. tls_version tlsv1.2 fija la versión mínima, así que también se aceptan clientes TLS 1.3.
Reinicia el servicio para aplicar los nuevos listeners:
sudo systemctl restart mosquitto
Comprueba que escucha en los dos puertos:
sudo ss -tlnp | grep mosquitto
LISTEN 0 100 127.0.0.1:1883 0.0.0.0:* users:(("mosquitto",pid=4121,fd=5))
LISTEN 0 100 0.0.0.0:8883 0.0.0.0:* users:(("mosquitto",pid=4121,fd=6))
LISTEN 0 100 [::]:8883 [::]:* users:(("mosquitto",pid=4121,fd=7))
Si el servicio no arranca, el motivo aparece en el registro:
sudo journalctl -u mosquitto -n 30 --no-pager
Paso 6: Abrir el firewall
Permite solo el puerto cifrado. El 1883 escucha en localhost y no debe abrirse:
sudo ufw allow 8883/tcp
sudo ufw status
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80/tcp ALLOW Anywhere
8883/tcp ALLOW Anywhere
Paso 7: Probar la autenticación, la ACL y TLS
Primero comprueba que el acceso anónimo está bloqueado:
mosquitto_pub -h localhost -t 'prueba/hola' -m 'anon'
Connection error: Connection Refused: not authorised.
Ahora suscríbete como panel por TLS. La opción --capath /etc/ssl/certs hace que el cliente valide el certificado de Let's Encrypt con las CA del sistema. Sustituye panel_password por la contraseña que elegiste:
mosquitto_sub -h mqtt.your_domain -p 8883 --capath /etc/ssl/certs \
-u panel -P 'panel_password' -t 'sensores/#' -v
En otra sesión, publica una lectura como sensor1:
mosquitto_pub -h mqtt.your_domain -p 8883 --capath /etc/ssl/certs \
-u sensor1 -P 'sensor1_password' -t 'sensores/sensor1/temperatura' -m '21.7'
El suscriptor recibe el mensaje:
sensores/sensor1/temperatura 21.7
Prueba ahora a publicar como sensor1 en un topic que la ACL no le permite:
mosquitto_pub -h mqtt.your_domain -p 8883 --capath /etc/ssl/certs \
-u sensor1 -P 'sensor1_password' -t 'sensores/sensor2/temperatura' -m '99'
El comando termina sin error, porque con QoS 0 el broker descarta en silencio las publicaciones no autorizadas, pero el suscriptor no recibe nada. Así se comporta la ACL de Mosquitto.
Notaevita pasar contraseñas con
-Pen servidores compartidos, porque quedan en el historial del shell y son visibles en la lista de procesos. En esta guía se usan solo para probar.
Paso 8: Conectar un dispositivo desde Python
La mayoría de dispositivos y aplicaciones usan una librería MQTT. Este ejemplo usa paho-mqtt 2.x en un entorno virtual para simular un sensor que publica cada 10 segundos:
sudo apt install python3-venv
python3 -m venv ~/mqtt-venv
~/mqtt-venv/bin/pip install paho-mqtt
Crea el script:
nano ~/sensor.py
import json
import random
import time
import paho.mqtt.client as mqtt
BROKER = "mqtt.your_domain"
USUARIO = "sensor1"
PASSWORD = "sensor1_password"
def on_connect(client, userdata, flags, reason_code, properties):
print(f"Conectado: {reason_code}")
client.subscribe("comandos/sensor1")
def on_message(client, userdata, msg):
print(f"Comando recibido en {msg.topic}: {msg.payload.decode()}")
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="sensor1")
client.username_pw_set(USUARIO, PASSWORD)
client.tls_set() # valida el certificado con las CA del sistema
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, 8883)
client.loop_start()
try:
while True:
lectura = {"temperatura": round(random.uniform(19, 24), 1)}
client.publish("sensores/sensor1/temperatura", json.dumps(lectura), qos=1)
time.sleep(10)
except KeyboardInterrupt:
client.loop_stop()
client.disconnect()
Ejecútalo con el suscriptor de panel del paso anterior todavía abierto:
~/mqtt-venv/bin/python ~/sensor.py
Conectado: Success
El suscriptor mostrará una lectura nueva cada 10 segundos, por ejemplo sensores/sensor1/temperatura {"temperatura": 22.4}.
Solución de problemas
Connection Refused: not authorised: usuario o contraseña incorrectos, o el archivo/etc/mosquitto/passwdno pertenece amosquitto. Revisa los permisos del paso 2 y reinicia el servicio.Error: A TLS error occurredo fallo de verificación del certificado: te estás conectando por IP o por un nombre distinto al del certificado. Usa exactamentemqtt.your_domain.- El servicio no arranca tras editar
broker.conf: una opción mal escrita detiene Mosquitto.sudo journalctl -u mosquitto -n 30indica la línea exacta. - Los mensajes no llegan pero no hay errores: casi siempre es la ACL. Comprueba que el topic de publicación encaja en alguna regla
topic writeopatternde ese usuario, respetando mayúsculas y barras.
Conclusión
Tienes un broker Mosquitto en Ubuntu 24.04 que exige autenticación, limita cada usuario a sus topics y solo acepta conexiones remotas cifradas con un certificado que se renueva de forma automática. Como siguientes pasos, puedes añadir un listener WebSocket (protocol websockets) para clientes web, conectar un bridge hacia otro broker con la sección connection de la configuración, o almacenar las lecturas en una base de datos de series temporales con un consumidor como Telegraf o Node-RED.
