MQTT needs an always-on broker with a public IP address – exactly what a VPS provides. Mosquitto on a 2 vCPU / 2GB RAM VPS handles 10,000+ concurrent MQTT connections comfortably. You need TLS on port 8883, per-device authentication and firewall rules. A VPS costs £4-8/month regardless of how many messages your devices send.
Why MQTT needs a VPS
MQTT works on a publish/subscribe model: devices publish data to a broker, and anything that wants that data subscribes to the relevant topic. The broker must be reachable from both devices and subscribers – which means it needs a stable, public IP address and a port open to the internet.
Running a broker at home doesn’t work reliably: most home broadband connections sit behind carrier-grade NAT (CGNAT) with no fixed IP, and the router goes offline when someone reboots it. A VPS solves both problems with a guaranteed uptime SLA and a fixed public address.
Mosquitto: the right broker for a VPS
Eclipse Mosquitto is the standard choice for self-hosted MQTT. It is written in C, has a tiny memory footprint (typically under 10MB at idle), and handles hundreds of thousands of connections on modest hardware. It ships in the Ubuntu package manager and is well-documented with an active community.
The alternatives – HiveMQ Community, EMQX, VerneMQ – are designed for enterprise-scale deployments and carry significantly more overhead. For the device counts most projects on this site involve (from a handful to a few thousand), Mosquitto is the right choice.
VPS sizing for MQTT
| Device count | Message rate | Minimum VPS | Recommended VPS |
|---|---|---|---|
| 1-100 devices | Low (1 msg/min each) | 1 vCPU, 512MB RAM | 2 vCPU, 2GB RAM |
| 100-1,000 devices | Moderate (1 msg/30s each) | 2 vCPU, 1GB RAM | 2 vCPU, 4GB RAM |
| 1,000-10,000 devices | Moderate | 4 vCPU, 4GB RAM | 4 vCPU, 8GB RAM |
| 10,000+ devices | Any | Consider clustering | Separate broker VM |
The limiting factor at scale is usually open file descriptors (each MQTT connection uses one) rather than CPU or RAM. The default Linux limit of 1,024 open files needs raising to support more than about 900 simultaneous connections. The full guide covers this.
Run ulimit -n on your VPS to see the current file descriptor limit. Set it to 65535 in /etc/security/limits.conf before going live with more than a few hundred devices.
Installing Mosquitto on Ubuntu
sudo apt update && sudo apt install -y mosquitto mosquitto-clients
# Enable and start
sudo systemctl enable mosquitto --now
# Check it is running
mosquitto_sub -h localhost -t test/# -v &
mosquitto_pub -h localhost -t test/hello -m "working"
That confirms a basic local connection. The next step is TLS and authentication before opening port 8883 to the internet.
TLS and authentication: non-negotiable
Plain MQTT on port 1883 sends credentials and message content in cleartext. Anyone on the same network path can read your sensor data and inject fake readings. TLS on port 8883 encrypts the entire connection. Per-device username and password authentication means a compromised device credential can be revoked without affecting the rest of the fleet.
The MQTT Security guide covers the full setup: Let’s Encrypt certificates, password file generation, and topic-level ACL rules that restrict which device can publish to which topics.
MQTT over cellular (4G/5G): the CGNAT problem
Devices on cellular connections are almost always behind carrier-grade NAT. They cannot be reached from outside, but they can make outbound connections. MQTT’s TCP connection is always initiated by the device (client to broker), which means MQTT works perfectly well over cellular – the device connects out to your VPS’s public IP on port 8883, and the broker responds.
If MQTT connections drop frequently on 4G, the cause is usually the carrier’s NAT timeout expiring during idle periods. Set the MQTT keepalive to 60 seconds or less to prevent this.
VPS for MQTT vs cloud MQTT services
| Self-hosted VPS (Mosquitto) | HiveMQ Cloud | AWS IoT Core | |
|---|---|---|---|
| Monthly cost (100 devices) | £4-8 flat | Free tier then per-device | ~£1-5 + per-message fees |
| Monthly cost (1,000 devices) | £4-8 flat | £30-50+ | £15-60+ depending on frequency |
| Control | Full root access | API-managed only | AWS console |
| Data ownership | Yours | Vendor holds data | Vendor holds data |
| Vendor dependency | None | High | High |
Connecting devices to your Mosquitto broker
Any MQTT client library works: Paho (Python, Java, C), Arduino PubSubClient, umqtt for MicroPython on ESP32, MQTTX for testing. The connection parameters are consistent across all clients:
# Python (paho-mqtt)
import paho.mqtt.client as mqtt
client = mqtt.Client(client_id="sensor-01", protocol=mqtt.MQTTv311)
client.tls_set(ca_certs="/path/to/ca.pem")
client.username_pw_set("sensor-01", "device-password")
client.connect("your-vps-domain.com", 8883, keepalive=60)
client.publish("sensors/factory1/temperature", "21.4")
Common MQTT problems and how a VPS solves them
Problem: devices lose connection on 4G frequently. Cause: carrier NAT timeout. Solution: set MQTT keepalive to 60 seconds or less. This sends a small keepalive packet before the NAT session expires. The VPS always has an active port open (51820 for WireGuard, 8883 for MQTT); the device side needs only the keepalive setting.
Problem: MQTT broker goes down when the home router reboots. Cause: running the broker at home means it depends on home internet uptime. Solution: run Mosquitto on a VPS – it is independent of home internet and has a guaranteed uptime SLA.
Problem: device data is visible to anyone who knows the broker address. Cause: no TLS, no authentication. Solution: TLS on port 8883 encrypts the connection; per-device passwords prevent unauthorised access; ACL rules restrict which device can see which topics.
Problem: MQTT broker is unreachable after power cut at home. Cause: VPS broker has its own power supply at the data centre. A VPS is not affected by home power issues.
MQTT topic design for IoT fleets
A well-designed topic hierarchy scales without reorganisation. The recommended pattern for UK industrial and commercial IoT:
sensors/{site}/{device-id}/{measurement}
# Examples:
sensors/factory-a/motor-1/temperature
sensors/building-b/room-302/co2
sensors/vehicle/van-123/gps
alerts/{site}/{device-id}/{alert-type}
This structure lets wildcard subscriptions work efficiently: sensors/factory-a/# subscribes to everything at factory A; sensors/+/+/temperature subscribes to all temperature readings across all sites and devices. Design the hierarchy before deployment, as changing it later requires updating every device’s publish topic.
What to run alongside Mosquitto
Mosquitto handles the message transport layer. Most projects add:
- Node-RED to subscribe to MQTT topics and route data to databases or trigger automations. See VPS for Node-RED.
- InfluxDB + Grafana for time-series storage and dashboards. See Grafana + InfluxDB guide.
- ThingsBoard as an all-in-one platform (MQTT broker, rules engine, dashboards). See ThingsBoard guide.
Frequently asked questions
What is the minimum VPS spec for Mosquitto?
Mosquitto runs on 1 vCPU and 256MB RAM for small deployments. For any production use with more than 50 devices, 2 vCPU and 1GB RAM is the recommended minimum. The bottleneck is usually file descriptors and network connections, not CPU or memory.
Does MQTT work over cellular (4G/5G)?
Yes. MQTT clients initiate outbound TCP connections to the broker, which works through any NAT including carrier-grade NAT. Set the MQTT keepalive interval to 60 seconds or less to prevent the connection dropping due to NAT timeout.
Is port 1883 or 8883 for MQTT?
Port 1883 is plain MQTT (no encryption). Port 8883 is MQTT over TLS (encrypted). You should always use port 8883 for any broker exposed to the internet. Port 1883 should be firewall-blocked or bound to localhost only on a production VPS.
How many devices can one Mosquitto broker handle?
Mosquitto has been tested with over 100,000 concurrent connections on appropriate hardware. For the majority of projects on this site, a single VPS with Mosquitto handles the full device fleet comfortably. Clustering becomes relevant above roughly 50,000 concurrent connections.
Do I need a domain name for my MQTT broker?
You can connect to a VPS by its IP address directly. However, a domain name makes TLS certificates straightforward (Let’s Encrypt requires a domain), and makes it easy to change the underlying VPS without updating every device. A domain is strongly recommended for any deployment beyond initial testing.
What is the difference between MQTT 3.1.1 and MQTT 5?
MQTT 5 adds features including message expiry, shared subscriptions and enhanced authentication. Mosquitto 2.x supports both. Most IoT devices use MQTT 3.1.1 as it is more widely supported by client libraries. Use MQTT 3.1.1 unless you specifically need MQTT 5 features.
