Rm
Streaming & Messaging Azure

rumqttd MQTT Broker on Ubuntu 24.04 on Azure User Guide

| Product: rumqttd MQTT Broker on Ubuntu 24.04 LTS on Azure

Overview

rumqttd is a fast, lightweight MQTT broker written in Rust, from the rumqtt project (Apache-2.0). The cloudimg image ships rumqttd 0.20.0 as a single static binary managed by systemd, configured to require authentication on every connection. A unique broker credential is generated on the VM's first boot, so no two deployments share a password and nothing is baked into the image.

What is included:

  • rumqttd 0.20.0 (pinned static musl binary, Apache-2.0) at /usr/local/bin/rumqttd
  • mosquitto-clients (mosquitto_pub, mosquitto_sub) for testing
  • MQTT v3.1.1 listener on TCP 1883
  • Per-VM cloudimg broker credential rotated at first boot into /etc/rumqttd/rumqttd.toml
  • Anonymous and wrong-credential connections rejected by the broker
  • rumqttd.service running as an unprivileged rumqttd user
  • Hardened, fully patched Ubuntu 24.04 LTS base
  • 24/7 cloudimg support

Prerequisites

  • An Azure VM launched from this cloudimg image (recommended size Standard_B2s or larger)
  • A network security group (NSG) allowing inbound TCP 22 (SSH) and TCP 1883 (MQTT) from only the client/device networks that need them
  • SSH access as azureuser

Restrict TCP 1883 in your NSG to your device and application subnets. Do not expose the broker to the whole internet.

Step 1: Verify the broker is running

SSH in as azureuser, then confirm the service is active and listening on 1883:

sudo systemctl status rumqttd.service --no-pager -n 0
sudo ss -tln | grep 1883
/usr/local/bin/rumqttd --version

Expected output:

● rumqttd.service - rumqttd MQTT broker (cloudimg)
     Loaded: loaded (/etc/systemd/system/rumqttd.service; enabled; preset: enabled)
     Active: active (running)
       Docs: https://www.cloudimg.co.uk/guides/rumqttd-on-ubuntu-24-04-azure/
   Main PID: 1477 (rumqttd)
LISTEN 0      1024         0.0.0.0:1883      0.0.0.0:*
rumqttd 0.20.0

rumqttd.service active (running), listening on TCP 1883, rumqttd 0.20.0

Step 2: Read the per-VM broker credential

The cloudimg username and its randomly generated password are written to a root-only credentials file at first boot:

sudo cat /stage/scripts/rumqttd-credentials.log

Expected output (your password will differ — it is unique to this VM):

# rumqttd — Per-VM Credentials
# MQTT v3.1.1 broker, port 1883. Anonymous connections are rejected.
RUMQTTD_USER=cloudimg
RUMQTTD_PASSWORD=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
RUMQTTD_HOST=<your-vm-ip>
RUMQTTD_PORT=1883

Per-VM cloudimg credential in a 0600 root-only file; password unique to this VM

Step 3: Publish and subscribe

Use the generated credential to prove an end-to-end publish/subscribe round-trip. This snippet subscribes for two messages, then publishes them:

PASS=$(sudo grep '^RUMQTTD_PASSWORD=' /stage/scripts/rumqttd-credentials.log | cut -d= -f2-)
mosquitto_sub -h 127.0.0.1 -p 1883 -u cloudimg -P "$PASS" -t 'demo/#' -C 2 -W 5 -v &
sleep 1
mosquitto_pub -h 127.0.0.1 -p 1883 -u cloudimg -P "$PASS" -t demo/temp -m '22.5'
mosquitto_pub -h 127.0.0.1 -p 1883 -u cloudimg -P "$PASS" -t demo/state -m 'online'
wait

Expected output — the subscriber receives both messages:

demo/temp 22.5
demo/state online

From a remote client, replace 127.0.0.1 with the VM's IP and open TCP 1883 in your NSG first.

Authenticated pub/sub round-trip: subscriber on demo/# receives demo/temp and demo/state

Step 4: Anonymous connections are rejected

The broker refuses any connection without the correct credential. A publish with no username fails:

if mosquitto_pub -h 127.0.0.1 -p 1883 -t demo/temp -m 'nope' 2>/dev/null; then
  echo 'UNEXPECTED: anonymous accepted'
else
  echo 'anonymous connection correctly rejected'
fi

Expected output:

anonymous connection correctly rejected

Anonymous publish rejected by the broker — authentication is enforced

Step 5: Components

Component Path
Broker binary /usr/local/bin/rumqttd
Config /etc/rumqttd/rumqttd.toml (mode 0640 root:rumqttd)
Config template /usr/local/share/cloudimg/rumqttd.toml.template
systemd unit /etc/systemd/system/rumqttd.service
First-boot unit /etc/systemd/system/rumqttd-firstboot.service
Credentials /stage/scripts/rumqttd-credentials.log (mode 0600 root:root)
Service user rumqttd (unprivileged, nologin)

The authentication table lives in the config under [v4.1.connections.auth]:

[v4.1]
name = "v4-1"
listen = "0.0.0.0:1883"

    [v4.1.connections.auth]
    cloudimg = "<per-VM-password>"

Step 6: Security hardening

  • Restrict the NSG so TCP 1883 only reaches your device and application subnets.
  • Add more users by adding username = "password" lines under [v4.1.connections.auth] in /etc/rumqttd/rumqttd.toml, then sudo systemctl restart rumqttd.
  • Enable TLS by adding a [v4.2] server block with a tls section (cert + key paths) listening on 8883, per the rumqttd documentation.
  • Patch regularly: sudo apt-get update && sudo apt-get upgrade && sudo reboot.
  • Rotate the password by editing the auth table and restarting the service.

Licensing

rumqttd is distributed under the Apache-2.0 licence by the rumqtt project — free to use. cloudimg provides the pre-built, hardened image and commercial support separately. Questions: support@cloudimg.co.uk.