Mosquitto + Node-RED on Ubuntu 24.04 on Azure User Guide
Overview
This image pairs Eclipse Mosquitto, the lightweight open source MQTT message broker, with Node-RED, the flow based low code programming tool, on a single Ubuntu 24.04 LTS VM. It is the canonical IoT starter stack: devices publish telemetry to Mosquitto, and Node-RED subscribes, transforms and routes those messages visually.
The integration is pre wired and proven at every boot. Node-RED's broker connection already points at the local Mosquitto with this VM's own generated credentials, a demo flow round trips a real message through the broker on first boot, and both the broker password and the editor admin password are unique to your VM.
What is included:
- Eclipse Mosquitto 2.0.18 MQTT broker on port
1883, authentication required (anonymous access disabled) - Node-RED 5.0.4 on Node.js 22 LTS, run as a dedicated systemd service bound to loopback
- nginx on port
80fronting the flow editor (websocket proxied), with an unauthenticated/healthendpoint for probes - A demo flow, already deployed: an inject node publishes to topic
cloudimg/demothrough the real broker, and a subscriber node receives it, shows it in the debug sidebar and appends it to a log file - Per VM credentials generated on first boot: the broker user
cloudimgand the editor useradmin, both written to a root only file - Licence texts for both components shipped in the image under
/usr/share/cloudimg/licenses/mosquitto-node-red/ - 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is comfortable for this stack; scale up for very high message rates or heavy flows. NSG inbound: allow 22/tcp from your management network, 80/tcp for the flow editor, and 1883/tcp for MQTT devices (restrict the source ranges to your device networks).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Mosquitto Node-RED by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Then Review + create -> Create. After the VM deploys, open port 1883 for your MQTT devices (Step 2 shows the CLI form).
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name mosquitto-node-red \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name mosquitto-node-red --port 80 --priority 1010
az vm open-port --resource-group <your-rg> --name mosquitto-node-red --port 1883 --priority 1020
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
systemctl is-active mosquitto node-red nginx
All three report active:
active
active
active

Step 5 - Retrieve your credentials
Both passwords are generated uniquely on the first boot of your VM and written to a root only file:
sudo cat /root/mosquitto-node-red-credentials.txt
The file contains the broker credentials (MOSQUITTO_USER / MOSQUITTO_PASSWORD, broker user cloudimg) and the flow editor credentials (NODE_RED_ADMIN_USER / NODE_RED_ADMIN_PASSWORD, editor user admin), plus ready to copy connection examples. Store both passwords somewhere safe.
Step 6 - Check the health endpoint
nginx serves an unauthenticated health endpoint for load balancers and probes:
curl -s http://localhost/health
It returns ok.
Step 7 - Publish and subscribe through the broker
The broker requires authentication; anonymous connections are rejected. Read the generated password into a variable, then round trip a message:
MQPASS=$(sudo grep '^MOSQUITTO_PASSWORD=' /root/mosquitto-node-red-credentials.txt | cut -d= -f2-)
mosquitto_sub -h localhost -u cloudimg -P "$MQPASS" -t 'demo/greeting' -C 1 -W 10 &
sleep 1
mosquitto_pub -h localhost -u cloudimg -P "$MQPASS" -t 'demo/greeting' -m "hello from the shell"
wait
The subscriber prints the published message:
hello from the shell
Anonymous access is off. An unauthenticated client is refused:
$ mosquitto_pub -h localhost -t test -m x
Connection error: Connection Refused: not authorised.

Step 8 - Open the flow editor
Browse to http://<vm-public-ip>/ and sign in as admin with the NODE_RED_ADMIN_PASSWORD from Step 5.

The editor opens on the MQTT Demo flow that ships with the image. Both MQTT nodes show a green connected badge: Node-RED is already authenticated against the local Mosquitto with this VM's generated credentials, with no configuration needed.

Click the button on the Send test message inject node to publish a message to cloudimg/demo through the real broker; the subscribe cloudimg/demo node receives it and shows it in the debug sidebar.
Step 9 - Watch an MQTT message arrive in Node-RED
Prove the end to end chain from the shell. The demo flow appends every message it receives on cloudimg/demo to /var/lib/node-red/mqtt-inbox.log:
MQPASS=$(sudo grep '^MOSQUITTO_PASSWORD=' /root/mosquitto-node-red-credentials.txt | cut -d= -f2-)
mosquitto_pub -h localhost -u cloudimg -P "$MQPASS" -t cloudimg/demo -m "sensor reading 21.5"
sleep 2
sudo tail -n 1 /var/lib/node-red/mqtt-inbox.log
The last line of the log is the message you just published:
sensor reading 21.5
The same message appears live in the editor's debug sidebar:


Step 10 - Connect devices and external clients
With port 1883 open in your NSG, any MQTT client can connect using the broker credentials from Step 5:
# From a device or workstation:
mosquitto_pub -h <vm-public-ip> -u cloudimg -P '<MOSQUITTO_PASSWORD>' -t sensors/temperature -m '21.5'
mosquitto_sub -h <vm-public-ip> -u cloudimg -P '<MOSQUITTO_PASSWORD>' -t 'sensors/#' -v
To route a new topic into Node-RED, add an mqtt in node in the editor, select the existing Local Mosquitto broker configuration, set your topic (for example sensors/#) and click Deploy.
To add more broker users, use mosquitto_passwd (without -c, which would recreate the file) and reload:
sudo mosquitto_passwd -b /etc/mosquitto/passwd sensor01 '<new-password>'
sudo systemctl reload mosquitto
Step 11 - Confirm the runtime from the command line
The Node-RED admin API is protected by the same editor login. Obtain a bearer token and query the runtime settings:
NRPASS=$(sudo grep '^NODE_RED_ADMIN_PASSWORD=' /root/mosquitto-node-red-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s --data "client_id=node-red-admin&grant_type=password&scope=*&username=admin&password=${NRPASS}" http://localhost/auth/token | jq -r .access_token)
curl -s -H "Authorization: Bearer ${TOKEN}" http://localhost/settings | jq '{version, httpNodeRoot}'
{
"version": "5.0.4",
"httpNodeRoot": "/api/"
}

Step 12 - Install extra palette nodes
Node-RED has a catalogue of thousands of community nodes for databases, dashboards, cloud services and protocols. Install them from the editor via Menu -> Manage palette -> Install.

After installing nodes from the command line instead (sudo -u node-red npm --prefix /var/lib/node-red install <node>), restart Node-RED so it loads them:
sudo systemctl restart node-red
Server Components
| Component | Version | Detail |
|---|---|---|
| Eclipse Mosquitto | 2.0.18 | MQTT broker on 0.0.0.0:1883, allow_anonymous false, password file auth |
| Node-RED | 5.0.4 | Flow editor + runtime on loopback 127.0.0.1:1880, adminAuth enabled |
| Node.js | 22 LTS | Runtime for Node-RED (NodeSource) |
| nginx | 1.24 | Reverse proxy :80 -> Node-RED, websocket aware, /health endpoint |
| Ubuntu | 24.04 LTS | Fully patched at image capture; unattended upgrades enabled |
Key Paths
| Path | Purpose |
|---|---|
/root/mosquitto-node-red-credentials.txt |
Per VM credentials (root only, generated at first boot) |
/etc/mosquitto/conf.d/cloudimg.conf |
Broker listener + authentication configuration |
/etc/mosquitto/passwd |
Broker password file (mosquitto_passwd format) |
/var/lib/mosquitto/ |
Broker persistence store |
/var/lib/node-red/ |
Node-RED user directory: flows.json, credential store, settings, installed nodes |
/var/lib/node-red/mqtt-inbox.log |
File sink written by the demo flow |
/usr/share/cloudimg/licenses/mosquitto-node-red/ |
Licence texts: Node-RED Apache 2.0; Mosquitto EPL 2.0 / EDL 1.0 (distributed under the EDL 1.0 arm) |
Managing the services
systemctl status mosquitto --no-pager -l | head -n 5
● mosquitto.service - Mosquitto MQTT Broker
Loaded: loaded (/usr/lib/systemd/system/mosquitto.service; enabled; preset: enabled)
Active: active (running)
Restart either component after configuration changes:
sudo systemctl restart mosquitto
sudo systemctl restart node-red
sudo systemctl reload nginx
Enabling HTTPS
nginx terminates plain HTTP on port 80. For public exposure of the editor, add a DNS name for the VM and extend the nginx site with a TLS server block (for example with certbot), or front the VM with an Azure Application Gateway. Keep Node-RED itself bound to loopback so the only public editor surface is the authenticated, TLS terminated proxy. For MQTT over TLS, add a listener 8883 block with certificate paths to /etc/mosquitto/conf.d/cloudimg.conf and open 8883 instead of 1883.
Troubleshooting
The editor rejects your password. Re read NODE_RED_ADMIN_PASSWORD from the credentials file; it is unique to this VM. If you have rotated it, restart Node-RED after editing /var/lib/node-red/settings.js.
MQTT clients cannot connect from outside. Confirm port 1883 is open in the NSG and that your client passes -u cloudimg -P '<password>'. The broker logs to the journal: sudo journalctl -u mosquitto -n 20.
The demo flow shows no messages. Check the broker connection badges in the editor. Both MQTT nodes should read connected; the runtime journal (sudo journalctl -u node-red -n 20) shows the connection log line Connected to broker: node-red-cloudimg@mqtt://127.0.0.1:1883.
First boot state. The one shot mosquitto-node-red-firstboot.service generates all credentials before the runtime starts. Its log is in the journal: sudo journalctl -u mosquitto-node-red-firstboot -n 30.
Security Recommendations
- Restrict NSG source ranges for ports 80 and 1883 to your own networks; do not leave them open to the internet.
- Add TLS (see Enabling HTTPS) before exposing the editor or the broker publicly.
- Create dedicated broker users per device with
mosquitto_passwdinstead of sharing thecloudimgaccount. - Rotate the editor and broker passwords periodically; the credentials file documents both.
- The OS keeps patching itself via unattended upgrades; reboot when
/var/run/reboot-requiredappears.
Support
cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.