rumqttd MQTT Broker on Ubuntu 24.04 on Azure User Guide
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
cloudimgbroker credential rotated at first boot into/etc/rumqttd/rumqttd.toml - Anonymous and wrong-credential connections rejected by the broker
rumqttd.servicerunning as an unprivilegedrumqttduser- 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

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

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.

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

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, thensudo systemctl restart rumqttd. - Enable TLS by adding a
[v4.2]server block with atlssection (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.