
Instalando un broker MQTT doméstico (II)
En el artículo anterior explicaba que quería usar un thin client Fujitsu Futro S450 como broker MQTT permanente para mi entorno local. Expliqué cómo hice varias actualizaciones al hardware para que pudiese correr un broker MQTT de forma más o menos holgada y por poco dinero. Y así quedó el tema. En el artículo de hoy explicaré los pasos para el cambio de sistema operativo y la instalación de la primera versión del broker MQTT, que dejaré funcionando con su configuración por defecto.
Un nuevo sistema operativo para el Futro S450
Me gusta Linux, no lo puedo evitar. Desde siempre. Me da igual una distribución u otra. Como comenté, ya había instalado Lubuntu 14.04 en el Futro S450, por lo que no debería haber problema para correo sobre él la última versión Long Term Support (LTS) de Ubuntu Server. No necesito interfaz gráfico (ni lo quiero, con tan pocos recursos).
Descargar la ISO de Ubuntu Server 16.04.1
El procesador del Futro S450 es de 64 bits, así que el primer paso para la instalación es la descarga de la ISO de Ubuntu Server 16.04.1 en su versión de 64 bits. Desde https://www.ubuntu.com/download/server se puede descargar la imagen ISO, aunque recomiendo el Torrent que va bastante más rápido (el torrent también se descarga de ese enlace).

Una vez tengamos la ISO descargada, o bien creamos un CD arrancable (Ubuntu Server cabe en uno) o bien creamos una versión arrancable en cualquier memoria USB. El Futro S450 no tiene CD y, aunque se puede utilizar un CD externo USB, es mucho más cómodo volcar la ISO directamente a un pendrive. Yo usé uno de 8 GB que tenía por ahí. Perderá los datos, así que aseguraros que es un lápiz USB de estos que se usan para andar por casa sin nada importante dentro.
Crear un USB arrancable de Ubuntu Server 16.04.1
En Linux hay multitud de formas de crear un USB arrancable a partir de una imagen ISO. Con comandos de toda la vida de Linux, como dd o cat, o con herramientas gráficas. Hacía tiempo que no creaba un USB de arranque a partir de una ISO, pero la última vez lo hice en Linux y utilicé la utilidad Unetbootin. Esta vez hice lo mismo, pero por alguna razón Unetbootin no estampa correctamente la ISO sobre el pendrive y el Futro S450 no lo detecta como un disco de arranque. Me di cuenta tras varios intentos. Así que opté por crear el USB a partir de la ISO de otra forma: utilizando la herramienta Discos de Ubuntu, que es la distribución que uso ahora mismo en mi estación de trabajo.



Los pasos son:
- Introducir el USB en el cual se quiere grabar la ISO.
- Abrir la herramienta Discos y seleccionar de la izquierda el volumen correspondiente a ese pendrive (es importante, a ver si vas a volcar la ISO sobre tu disco duro en lugar de sobre el pendrive, jeje).
- Arriba a la derecha en la ventana, expandir el menú y seleccionar «Restaurar imagen de disco».
- Seleccionar la imagen ISO de Ubuntu Server que hemos descargado.
Y ya está. Te preguntará catorce veces para asegurarse de que vuelcas la ISO en el pendrive y no en otro lado y luego pedirá la clave de root. Finalmente aceptamos para crear la imagen sobre el disco USB. Aparecerá una barra de progreso que nos indicará cuándo ha finalizado.
Arrancar e instalar Ubuntu Server 16.04.1
Una vez creado correctamente el USB de arranque, la instalación no tiene ninguna diferencia por el hecho de que sea un thin client la máquina destino. Únicamente hay que poner cuidado de seleccionar el arranque desde USB. Para ello, simplemente hay que insertar el USB de arranque en el Futro S450 y al arrancar hay que pulsar <F12> y aparecerá el menú de arranque. Sólo hay que seleccionar el USB y pulsar <Enter>. Y la instalación comenzará como es habitual.



No voy a detallar la instalación de Ubuntu Server porque no es el propósito de este artículo; además Internet está plagada de manuales. Simplemente comentaré dos peculiaridades que yo he configurado. Por un lado, el particionado. Finalmente utilicé la unidad USB de 16 GB que tenía por casa, así que el Futro S450 ha quedado con una Compact Flash de 4 GB y un USB de 16GB. He configurado las particiones de la siguiente forma:
Compact Flash -> 1 partición ext4 de 4 GB -> Montada en / USB -> 1 participación swap de 4 GB USB -> 1 partición ext4 de 12 GB -> Montada en /var
De tal forma que aquella rama que pueda tener un mayor crecimiento, por logs y por el propio almacenamiento del broker MQTT quede en el USB que tiene más espacio.



Y por otro lado, necesitaré un servidor SSH que me permita acceder remotamente ya que tal y como tengo pensado colocar el Futro S450 estará alto, sin teclado, ni ratón ni monitor. Así que durante el proceso de instalación, cuando se pregunta si se desea instalar un conjunto predefinido de paquetes, he deseleccionado todo excepto «OpenSSH server», que dejará sshd escuchando en el puerto 22 al finalizar la instalación.
Configurar la red de forma estática
Por defecto, Ubuntu Server 16.04.1 configura la red para obtener su configuración a través de DHCP. Para un servidor, o se tiene configurado bien el servidor DHCP para asignar siempre la misma IP a la misma interfaz de red o si no no es la opción óptima, por lo que cambiaremos esta configuración para que la red esté definida estáticamente.



Como comentaba, el thin client estará subido a una estantería y sin teclado ni monitor ni nada. Ahora lo tengo por el medio, pero eso se va a acabar en breve. Y como quiero acceder a él por SSH, quiero que siempre tenga una IP fija asignada y conocida por mí (por eso y porque nos hará falta a la hora de generar los certificados para soportar TLS). Para ello, abrimos el fichero /etc/network/interfaces:
sudo vi /etc/network/interfaces
Y modificamos la configuración de la interfaz eth0 para dejarla como sigue:
#Configuración de enp8s0 auto enp8s0 iface enp8s0 inet static address 192.168.1.20 gateway 192.168.1.1 dns-nameservers 8.8.8.8 8.8.4.4
La interfaz enp8s0 es la que a mí me crea Ubuntu automáticamente y corresponde a la interfaz Gigabit Ethernet. La IP 192.168.1.20 es la que quiero que tenga siempre el broker MQTT y 192.168.1.1 es la dirección de la pasarela de red. Para la dirección de la pasarela de red configuramos la misma que la de nuestra red local, que obtendréis con el comando:
route -n | grep "^0.0.0.0" | cut -c 17- | cut -c -16
El campo dns-nameserver especificado usará los servidores de nombre de Google para resolver nombres, que son de público acceso; no es necesario cambiarlos. Los dejaremos así.
A partir de este momento, accederé siempre de forma remota al Futro S450 a través de SSH con el siguiente comando:
ssh manolodd@192.168.1.20
Donde manolodd es el usuario no-root que cree durante la instalación de Ubuntu Server en el thin client y la dirección IP es la del Futro, como acabamos de ver unos párrafos atrás. Así que, salvo que se especifique lo contrario, los comandos de aquí en adelante se ejecutarán sobre el Fujitsu Futro y a él habré accedido previamente vía SSH.
Un broker MQTT para el Fujitsu Futro S450
¿Que broker MQTT instalo?
Existen numerosos brokers MQTT open source que cualquiera puede descargar y configurar. Unos son pesados y mastodónticos y otros ligeros y muy eficientes. Pero unos permiten una escalabilidad vertical y horizontal casi inacabable y otros no escalan más allá de de un simple core de la CPU. Así que, como en casi todas las ocasiones, la decisión vendrá determinada por los requisitos. En mi caso, los comenté en el primer artículo de esta serie: soportará muy poca carga, que sea suficiente, que de servicio sobre TLS y que soporte autenticación de usuarios y ACLs. Y, también, que pueda correr suficientemente bien en un thin client como el Fujitsu Futro S450.
Para este contexto, yo prefiero Mosquitto. Mosquitto MQTT es un broker MQTT que soporta la última especificación de MQTT realizada por OASIS, soporta TLS, tiene un sistema de plugins y pluings interesantes ya creados, soporta MQTT sobre Websockets, ACLs, autenticación… vamos, soporta bastante más de lo que yo requiero para este broker en concreto.
Instalando Mosquitto
Como ya he comentado, Mosquitto se encuentra de serie en los repositorios oficiales de Ubuntu Server 16.04.1. Sin embargo, el repositorio oficial trae una versión bastante anticuada de Mosquitto, por lo que el primer paso que daré será añadir el repositorio de Mosquitto para Ubuntu, con lo siguiente:
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa sudo apt-get update
Y ahora sí, instalamos Mosquitto MQTT broker con la siguiente orden:
sudo apt-get install mosquitto
lo cual, además de instalar Mosquitto, lo arranca y deja funcionando con la configuración por defecto (que en la mayoría de los casos podría ser más que suficiente).
Probando Mosquitto
El puerto por defecto utilizado para MQTT es el 1883. Como no hemos configurado nada al respecto, Mosquitto estará escuchando en dicho puerto; si utilizamos el comando:
netstat -ln --tcp
Su salida nos dará algo como esto:
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:1883 0.0.0.0:* LISTEN tcp6 0 0 :::22 :::* LISTEN tcp6 0 0 :::1883 :::* LISTEN
Donde se puede observar claramente que hay un servicio en el puerto 1883 tanto sobre TCP/IPv4 como sobre TCP/IPv6. Este servicio escuchando es Mosquitto sirviendo MQTT sin TLS.
Ahora que ya sabemos que Mosquitto está preparado, haremos una prueba en remoto, desde otra máquina con Linux. Yo lo haré desde mi estación de trabajo con Ubuntu, en la misma red local. Primero, antes de nada, instalaré en esta máquina el cliente de Mosquitto. Son herramientas muy útiles para hacer tests y ver que el broker está funcionando correctamente.
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa sudo apt-get update sudo apt-get install mosquitto-clients
Y a partir de ahí tendremos dos herramientas para hacer las pruebas como clientes: mosquitto_sub, para suscribirse a un topic concreto de Mosquitto y recibir aquello que se publique; y mosquitto_pub, para conectarse a Mosquitto y publicar un mensaje en un topic determinado. Usaremos ambas herramientas. Haremos una conexión remota hacia el broker con mosquitto_sub, sobre el topic «UnTopicCualquiera» y posteriormente desde otro terminal o desde otra máquina, nos conectaremos al broker para publicar el mensaje «Hola» en el topic «UnTopicCualquiera» del Mosquitto, que será recibido por el cliente que está suscrito a dicho topic.
Nos suscribimos al topic de forma remota:
mosquitto_sub -h 192.168.1.20 -t "UnTopicCualquiera" -v
Vemos que no ocurre nada. El proceso no vuelve a la shell sino que queda esperando a ver si algo se publica en ese topic. Ahora publicamos, de forma remota (desde otro terminal o desde otra máquina), sobre el mismo topic del Mosquitto:
mosquitto_pub -h 192.168.1.20 -t "UnTopicCualquiera" -m Hola
Vemos que el comando se ejecuta y termina, volviendo a la shell. Básicamente se ha conectado al broker MQTT, ha publicado el mensaje en el topic «UnTopicCualquiera» y se ha desconectado. Si vamos a la otra máquina o el otro terminal, donde estaba el cliente que se había suscrito al topic «UnTopicCualquiera», vemos que ha recibido un mensaje que «alguien» (la publicación que se acaba de hacer con mosquitto_pub) ha publicado en ese topic.
mosquitto_sub -h 192.168.1.20 -t "UnTopicCualquiera" -v UnTopicCualquiera Hola
Y sigue ahí, suscrito, esperando más mensajes hasta que pulsemos <Ctrl+C> para acabar el proceso.
Conclusión
Contar con un broker MQTT que haga de ESB con hardware de bajo coste y un bajo consumo de energía es algo muy, muy sencillo. Mosquitto es un broker MQTT muy potente y de alto rendimiento. Con la combinación de un Thin Client de 64 bits y Mosquitto, podemos tener broker MQTT para rato y desde luego tendremos una base hacer aplicaciones muy interesantes IoT (o no), porque es muy sencillo conectar tu aplicación (app móvil, backend, web…) desde cualquier lenguaje de programación, a tu broker MQTT.
En cuanto tenga un hueco, haré un tercer artículo y os explicaré de forma rápida cómo configurar MQTT sobre TLS para poder acceder al broker remoto de forma segura y, si me da tiempo, explicaré también en qué consiste y como se configura el ACL y la autenticación en Mosquitto.
¿Tenéis comentarios? 🙂