Deployment guide

Mochi MQTT

Overview

Mochi MQTT is a fully featured, self-contained MQTT broker written in Go. It speaks MQTT v5 and v3.1.1 and is a popular embeddable broker for Internet of Things fleets, telemetry pipelines and application message buses.

Upstream ships Mochi as a Go library. Its stock example server runs with an allow-all authentication hook and a world-readable HTTP statistics dashboard. This SecureAnyCloud image is different: it is a thin, secure-by-default broker built from the pinned Mochi source (v2.7.9).

The broker requires a per-VM username and password generated on first boot, and it rejects anonymous and wrong-credential connections. It exposes only the authenticated MQTT listener on TCP 1883. There is no WebSocket listener and no world-open stats dashboard.

What you get:

  • Mochi MQTT v2.7.9, built from source into a single static binary at /usr/local/bin/mochi-mqtt-server
  • MQTT v5 and v3.1.1 support on TCP port 1883
  • A per-VM broker username and password generated at first boot (openssl rand)
  • Anonymous and wrong-credential connections rejected at connect (default-deny auth ledger)
  • mosquitto-clients (mosquitto_pub, mosquitto_sub) for testing and scripting
  • The broker running as an unprivileged mochi system user under systemd hardening
  • Opt-in TLS on port 8883
  • 24/7 SecureAnyCloud support

Prerequisites

You need:

  • An Azure VM launched from the SecureAnyCloud Mochi MQTT image. A Standard_B2s is ample.
  • A network security group (NSG) that allows inbound TCP 22 (SSH management) and TCP 1883 (MQTT) from your own device and IoT networks. Restrict the source ranges: even though the broker is authenticated, do not expose it to the whole internet. For production, prefer TLS on TCP 8883 (see Step 6).
  • An SSH session to the VM as azureuser.
1

Verify the broker is running

The broker starts automatically once first boot has generated the per-VM credentials. Run the following commands to check it:

systemctl is-active mochi-mqtt.service
systemctl status mochi-mqtt.service --no-pager | head -n 7 ss -tln | grep ':1883' file /usr/local/bin/mochi-mqtt-server | head -n 1

The service should report active (running), with a listener bound to *:1883.

2

Read the per-VM credentials

Each VM generates its own broker username and password on first boot and writes them to a root-only file. Two VMs launched from this image never share a password. Read the file with:

sudo cat /stage/scripts/mochi-mqtt-credentials.log

Your MQTT clients use the MOCHI_MQTT_USER and MOCHI_MQTT_PASSWORD lines as their credentials.

3

Confirm it is secure by default

Check that the broker refuses unauthenticated and wrong-password clients. Neither command below carries the correct credential, so the broker must reject both.

OUT_ANON=$(mosquitto_pub -h localhost -t demo -m hi 2>&1 || true) case "$OUT_ANON" in *[Rr]efused*|*"not authori"*) echo 'anonymous connection was correctly rejected' ;; *) echo 'unexpected: anonymous connection was accepted' ;; esac
OUT_BAD=$(mosquitto_pub -h localhost -u sac -P wrong-password -t demo -m hi 2>&1 || true) case "$OUT_BAD" in *[Rr]efused*|*"not authori"*) echo 'wrong-credential connection was correctly rejected' ;; *) echo 'unexpected: wrong-credential connection was accepted' ;; esac

Both lines report a correct rejection. The broker ships with no working default credential of any kind.

4

Authenticated publish/subscribe round-trip

Read the per-VM password into a shell variable, subscribe to a topic tree and publish to it. The subscriber receives every matching message.

PASS=$(sudo grep '^MOCHI_MQTT_PASSWORD=' /stage/scripts/mochi-mqtt-credentials.log | cut -d= -f2-)
# Subscribe in the background (bounded), publish three messages, then show what arrived: timeout 6 mosquitto_sub -h localhost -u sac -P "$PASS" -t 'sensors/#' -v -q 1 & sleep 1 mosquitto_pub -h localhost -u sac -P "$PASS" -t sensors/room1/temp -m 21.4 -q 1 mosquitto_pub -h localhost -u sac -P "$PASS" -t sensors/room1/humidity -m 48 -q 1 mosquitto_pub -h localhost -u sac -P "$PASS" -t sensors/door/state -m open -q 1 wait

In normal use, run the subscriber in one terminal and publish from another. The topic filter sensors/# matches every topic under sensors/.

5

Connect from a remote MQTT client

From another machine, connect to the VM's public IP on port 1883 with the per-VM credentials. You can find the public IP on the VM's Overview page in the Azure portal. Make sure your NSG allows inbound TCP 1883 from that machine's address.

$ mosquitto_sub -h YOUR-VM-PUBLIC-IP -p 1883 -u sac -P 'YOUR-PASSWORD' -t 'sensors/#' -v $ mosquitto_pub -h YOUR-VM-PUBLIC-IP -p 1883 -u sac -P 'YOUR-PASSWORD' -t sensors/room1/temp -m 21.4

Any standard MQTT v5 or v3.1.1 client library (Paho, MQTT.js and others) connects the same way. Supply the host, port 1883, the broker username and the per-VM password.

6

Enable TLS (optional, recommended for production)

The broker supports TLS on a separate port. Provide a certificate and key, point the broker at them, then open TCP 8883 in your NSG instead of 1883.

The example below uses a self-signed certificate. For production, use a CA-issued certificate.

# Generate a self-signed certificate (replace the CN with your DNS name): $
sudo openssl req -x509 -newkey rsa:2048 -nodes -days 825 \
  -keyout /etc/mochi-mqtt/tls.key -out /etc/mochi-mqtt/tls.crt \
  -subj "/CN=your-broker.example.com" $
sudo chown mochi:mochi /etc/mochi-mqtt/tls.key /etc/mochi-mqtt/tls.crt $
sudo chmod 0640 /etc/mochi-mqtt/tls.key
# Point the broker at the cert/key and the TLS port, then restart: $
sudo tee -a /etc/mochi-mqtt/mochi.env >/dev/null <<'EOF' MOCHI_MQTT_TCP_ADDR=:8883 MOCHI_MQTT_TLS_CERT=/etc/mochi-mqtt/tls.crt MOCHI_MQTT_TLS_KEY=/etc/mochi-mqtt/tls.key EOF $
sudo systemctl restart mochi-mqtt.service
# Clients then connect over TLS on 8883: $ mosquitto_pub -h YOUR-VM-PUBLIC-IP -p 8883 --cafile ca.crt -u sac -P 'YOUR-PASSWORD' -t demo -m hi
7

Components and file layout

Run the commands below to inspect the installed components:

ls -l /usr/local/bin/mochi-mqtt-server systemctl is-enabled mochi-mqtt.service id mochi
ls -la /etc/mochi-mqtt/

The image uses the following paths and ports:

  • Broker binary: /usr/local/bin/mochi-mqtt-server (static Go binary, Mochi v2.7.9)
  • Broker credentials (env): /etc/mochi-mqtt/mochi.env (mode 0600 root:root)
  • Human-readable credentials: /stage/scripts/mochi-mqtt-credentials.log (mode 0600 root:root)
  • systemd service: /etc/systemd/system/mochi-mqtt.service (runs as mochi)
  • First-boot rotation: /etc/systemd/system/mochi-mqtt-firstboot.service
  • MQTT port: TCP 1883 (TLS opt-in on 8883)

Security notes

  • No default credential. The image ships with no working broker credential. Each VM generates its own username and password on first boot, so no two VMs from this image share one. There is no "default" account to change, because none exists.
  • Default-deny authentication. The broker authorises exactly one configured user. Anonymous connections and any other username and password are rejected at connect.
  • Restrict network exposure. Even though the broker is authenticated, limit inbound 1883 (or 8883) to the source ranges that need it. Prefer TLS for any traffic that crosses an untrusted network.
  • Rotate the password when you need to. Edit MOCHI_MQTT_PASSWORD in /etc/mochi-mqtt/mochi.env, update /stage/scripts/mochi-mqtt-credentials.log, then run sudo systemctl restart mochi-mqtt.service.
  • Keep the VM patched. The image tracks Ubuntu security updates through unattended-upgrades.

Support

SecureAnyCloud images come with 24/7 support. For questions about this Mochi MQTT image or help with your deployment, contact the SecureAnyCloud support team.

Deploy on Azure

Launch Mochi MQTT Broker on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure