Pruebas de brokers

Configurar entornos MQTT de desarrollo, staging y producción

Cómo separar los entornos MQTT de desarrollo, staging y producción: broker por entorno, prefijos de topic, credenciales y ACL propias, promoción y smoke tests.

Actualizado · 8 min de lectura

Configurar entornos MQTT de desarrollo, staging y producción

La forma más limpia de usar MQTT en desarrollo, staging y producción se resume rápido: da a cada entorno su propio broker (o instancia aislada de broker) y sus propias credenciales, mantén los nombres de topic idénticos entre entornos y cambia solo la configuración (URL, usuario, contraseña) cuando el código pasa de uno a otro. Todo lo demás en esta guía consiste en que eso sea aburrido y seguro.

Para qué sirve cada entorno

DesarrolloStagingProducción
PropósitoIteración rápida, experimentosRelease candidate, pruebas de integración y de cargaDispositivos y clientes reales
BrokerDocker local o un endpoint de pruebas compartidoMismo tipo de broker y misma configuración que producciónDedicado y monitorizado
DatosFalsos, desechablesRealistas, generados o anonimizadosReales
Quién se conectaDesarrolladores, simuladoresCI, dispositivos de prueba, QAFlota y servicios de backend
CredencialesPor desarrollador o un usuario de desarrollo compartidoPor servicio, solo de stagingPor servicio y por dispositivo
TLSOpcionalObligatorio, igual que en producciónObligatorio

Staging solo es útil si se comporta como producción. Un broker de staging sin TLS, sin autenticación o con ACL totalmente abiertas dejará pasar releases que fallan el primer día en producción.

Tres formas de separar los entornos

ModeloCómo funcionaIdeal paraCuidado con
Un broker por entornoHosts o instancias separados; topics idénticosProducción, y cualquier equipo que pueda permitírseloMás endpoints que gestionar
Broker compartido, topics con prefijodev/..., stg/... en un broker, ACL por entornoDesarrollo y staging con poco presupuestoUna ACL mal configurada filtra datos entre entornos; capacidad compartida
HíbridoProducción aislada; desarrollo y staging comparten brokerLa mayoría de equipos pequeños y medianosMantén las credenciales de producción totalmente fuera del broker compartido

Elijas lo que elijas, producción nunca comparte broker con las pruebas. Una prueba de carga, un simulador desbocado o un mensaje retenido publicado por error no deberían poder llegar a dispositivos reales.

Prefijos de topic bien hechos

Con un broker por entorno, no pongas el entorno en el topic. factory/line1/temp es el mismo topic en staging y en producción, así que suscripciones, dashboards, reglas y ficheros ACL se pueden promover sin tocarlos.

Cuando los entornos comparten broker, el prefijo es obligatorio, y debe añadirse en un único lugar. El peor patrón son las comprobaciones de entorno repartidas por el código (if env == "prod": topic = ...). Construye cada topic con un helper que anteponga el prefijo configurado, y deja el prefijo vacío cuando el entorno tenga su propio broker:

mqtt-config.mjs
import mqtt from "mqtt";

export const ENV = process.env.APP_ENV ?? "dev";
const url = process.env.MQTT_URL;
const prefix = process.env.MQTT_TOPIC_PREFIX ?? "";   // "" si el entorno tiene su propio broker

if (!url) throw new Error("MQTT_URL is not set");

export const topic = (t) => (prefix ? `${prefix}/${t}` : t);

export function connect(name) {
  return mqtt.connect(url, {
    clientId: `${name}-${ENV}-${Math.random().toString(16).slice(2, 8)}`,
    username: process.env.MQTT_USER,
    password: process.env.MQTT_PASS,
    protocolVersion: 5,
    reconnectPeriod: 2000,
  });
}
uso
import { connect, topic } from "./mqtt-config.mjs";

const client = connect("ingest");
client.on("connect", () => client.subscribe(topic("factory/+/temp"), { qos: 1 }));

Incluir el entorno en el client ID también hace legibles los logs del broker: ves de inmediato que ingest-stg-3fa9c1 es un servicio de staging. En un broker de desarrollo compartido, da a cada desarrollador un prefijo personal como testmqtt/dev-alice para que los experimentos nunca colisionen; los detalles están en nombrar topics de prueba para que nunca colisionen.

Credenciales y ACL por entorno

Cada entorno tiene sus propios usuarios, y una credencial de un entorno debe ser inútil en otro. Nombra a los usuarios por servicio y entorno (ingest-stg, ingest-prod) para que una credencial filtrada o mal usada salte a la vista en los logs.

En un broker compartido de desarrollo y staging, las ACL son lo que realmente mantiene separados los entornos. Un fichero ACL de Mosquitto para ese caso:

acl (broker compartido de desarrollo + staging)
user ingest-dev
topic read dev/telemetry/#
topic write dev/cmd/#

user ingest-stg
topic read stg/telemetry/#
topic write stg/cmd/#

Verifica la separación en lugar de darla por hecha: conéctate con el usuario de desarrollo e intenta suscribirte a stg/#. Con MQTT 5 el broker devuelve un código de fallo en el SUBACK (0x87 Not authorized); con MQTT 3.1.1 recibes 0x80 o simplemente ningún mensaje. Probar los permisos ACL de MQTT muestra cómo automatizar estas pruebas negativas.

Configuración por entorno

Mantén un fichero de configuración por entorno y cárgalo al arrancar; el código no cambia.

.env.dev
APP_ENV=dev
MQTT_URL=mqtt://broker.connectmq.com:1883
MQTT_USER=username
MQTT_PASS=password
MQTT_TOPIC_PREFIX=testmqtt/dev-alice
.env.staging
APP_ENV=staging
MQTT_URL=mqtts://<your-staging-host>:8883
MQTT_USER=ingest-stg
MQTT_PASS=<desde tu gestor de secretos>
MQTT_TOPIC_PREFIX=

Los valores de producción viven solo en el gestor de secretos del despliegue de producción, nunca en el repositorio ni en los jobs de prueba de CI. Añade una protección al setup de pruebas para que un error no pueda apuntar la suite a producción:

test/setup.mjs
import { ENV } from "../mqtt-config.mjs";

if (ENV === "prod" || ENV === "production") {
  throw new Error("Refusing to run tests against production");
}

Los dispositivos necesitan la misma disciplina. El firmware no debería llevar el broker fijo en el código; el entorno se asigna durante el aprovisionamiento junto con las credenciales del dispositivo, de modo que un dispositivo de staging no pueda acabar en la flota de producción. Consulta aprovisionamiento de dispositivos MQTT.

Promover la configuración del broker

La configuración del broker (listeners, TLS, límites, ficheros ACL) debe pasar por los entornos igual que el código:

  1. Guarda la configuración del broker en git como una plantilla más valores por entorno (hostnames, rutas de certificados, límites). El generador de configuración de Mosquitto es una forma rápida de obtener un fichero inicial correcto.
  2. Revisa los cambios de ACL como si fueran código: un solo # en la línea equivocada lo abre todo.
  3. Aplica el cambio en desarrollo, luego en staging, ejecuta las pruebas y solo entonces promueve el mismo commit a producción.
  4. Compara staging con producción antes de cada release. Cualquier diferencia que no sea un hostname, un secreto o un límite de capacidad es un bug esperando a ocurrir.

Smoke test en cada entorno

Tras cada despliegue, ejecuta una ida y vuelta completa con las credenciales de ese entorno. El mismo script sirve en todas partes:

smoke.sh
#!/usr/bin/env bash
set -euo pipefail
: "${MQTT_HOST:?}" "${MQTT_USER:?}" "${MQTT_PASS:?}"
T="${MQTT_TOPIC_PREFIX:-testmqtt}/smoke/$(date +%s)"
OUT=$(mktemp)
mosquitto_sub -h "$MQTT_HOST" -p 8883 --capath /etc/ssl/certs \
  -u "$MQTT_USER" -P "$MQTT_PASS" -t "$T" -C 1 -W 10 > "$OUT" &
sleep 1
mosquitto_pub -h "$MQTT_HOST" -p 8883 --capath /etc/ssl/certs \
  -u "$MQTT_USER" -P "$MQTT_PASS" -t "$T" -m ok -q 1
wait
grep -qx ok "$OUT" && echo "smoke test passed on $MQTT_HOST"

-W 10 hace que el suscriptor termine con error si no llega nada en diez segundos, así que un entorno roto hace fallar el pipeline en lugar de bloquearlo. Para una versión más completa, consulta un script de smoke test MQTT; para una comprobación manual, conéctate con el cliente MQTT online usando las credenciales del entorno.

Errores frecuentes

  • Las mismas credenciales en todas partes. Una contraseña de desarrollo filtrada se convierte en un incidente de producción.
  • Staging sin TLS ni autenticación. Los fallos de certificados y permisos aparecen entonces por primera vez en producción.
  • Comprobaciones de entorno en la lógica de negocio. Promueve configuración, no ramas de código.
  • Datos de prueba retenidos en un broker compartido. Bórralos tras las pruebas o las siguientes ejecuciones leerán un estado obsoleto.
  • Dispositivos de staging olvidados. El hardware de pruebas que apunta a producción por una configuración antigua contamina los datos reales.

Antes de salir en vivo, repasa el checklist de producción MQTT contra el propio entorno de producción, no contra staging.

Brokers separados, credenciales separadas, topics idénticos y un único lugar donde cambia la configuración: con estas cuatro reglas, llevar una release de desarrollo a staging y a producción es un cambio de configuración y un smoke test, no una migración.

Preguntas frecuentes

¿Deben compartir desarrollo, staging y producción un mismo broker MQTT?

Producción debe tener su propio broker o instancia aislada. Desarrollo y staging pueden compartir un broker si cada entorno tiene sus propias credenciales, su propio prefijo de topic y ACL que los separen, aunque las instancias separadas son más fáciles de razonar.

¿El nombre del entorno debe formar parte del topic MQTT?

Solo cuando los entornos comparten broker. Con un broker por entorno, mantén los topics idénticos en todas partes para promover código y dashboards sin cambios. Si necesitas un prefijo, añádelo en un único lugar del código del cliente.

¿Cómo evito que las pruebas publiquen en producción?

Da las credenciales de producción solo a los servicios de producción, mantenlas fuera de los jobs de prueba de CI y añade una protección en el setup de pruebas que se niegue a ejecutar si el entorno o la URL del broker configurados son los de producción.