The Internet of Things generates an enormous volume of data — temperature readings, motion events, GPS coordinates, power consumption metrics — all streaming continuously from sensors and edge devices. Most organizations default to managed cloud platforms like AWS IoT Core or Azure IoT Hub, only to discover that per-message pricing scales painfully as device fleets grow. A self-hosted IoT infrastructure on an Ubuntu VPS gives you complete control over your data pipeline, from MQTT message ingestion through time-series storage to real-time dashboards, at a fraction of the cost.

Running your own IoT backend on a VPS means no per-message fees, no vendor lock-in, and full data sovereignty. Whether you're managing a building automation system with a few hundred sensors, an agricultural monitoring network spread across fields, or an industrial fleet of thousands of edge devices, an Ubuntu VPS provides the foundation for a production-grade IoT stack. This guide walks through the complete architecture: installing and securing an MQTT broker, building a data ingestion pipeline, storing time-series data efficiently, visualizing metrics in Grafana, and scaling your infrastructure as your device fleet grows.

MassiveGRID Ubuntu VPS includes: Ubuntu 24.04 LTS pre-installed · Proxmox HA cluster with automatic failover · Ceph 3x replicated NVMe storage · Independent CPU/RAM/storage scaling · 12 Tbps DDoS protection · 4 global datacenter locations · 100% uptime SLA · 24/7 human support rated 9.5/10

Deploy a self-managed VPS — from $1.99/mo
Need dedicated resources? — from $19.80/mo
Want fully managed hosting? — we handle everything

Why Self-Host IoT Infrastructure

Managed IoT platforms charge per message, per device, and per rule evaluation. At small scale this seems reasonable, but costs compound rapidly. Self-hosting on a VPS eliminates these variable costs entirely and offers three critical advantages:

Self-hosting also means you choose every component in the stack. Want to swap InfluxDB for TimescaleDB? Route messages through Node-RED instead of Telegraf? Add custom edge processing logic? There are no platform restrictions — just standard open-source tools running on your Ubuntu VPS.

VPS vs AWS IoT Core / Azure IoT Hub — Cost Comparison

The economics of self-hosted IoT infrastructure become dramatically clear at scale. Here is a realistic comparison for a fleet of 500 devices, each publishing a sensor reading every 30 seconds (1,440 messages/device/day):

Cost Factor AWS IoT Core Azure IoT Hub (S1) Self-Hosted VPS
Messages/day 720,000 720,000 720,000
Messages/month ~21.6 million ~21.6 million ~21.6 million
Messaging cost ~$21.60/mo ($1/million msgs) ~$50/mo (S1 unit per 400K msgs/day) $0 (included)
Device registry ~$0.50/mo Included in tier $0 (included)
Rule engine / routing ~$3.24/mo Included in tier $0 (Telegraf/custom)
Time-series storage ~$15–40/mo (Timestream) ~$25–50/mo (ADX) $0 (InfluxDB on VPS)
Dashboard ~$9/mo (Managed Grafana) ~$10/mo (Azure dashboards) $0 (Grafana on VPS)
Total monthly cost ~$50–75/mo ~$85–110/mo $1.99–$9.99/mo

At 5,000 devices the gap widens further — managed platforms can exceed $500/month while a VPS with 4 vCPU and 8 GB RAM handles the load comfortably for under $20/month. The savings are not marginal; they are an order of magnitude.

IoT Stack Architecture

A production IoT data pipeline on Ubuntu follows a clean, layered architecture. Each component has a single responsibility and communicates with its neighbors through well-defined interfaces:

IoT Devices (sensors, edge gateways)
        │
        ▼
┌─────────────────────┐
│  Mosquitto MQTT      │  ← Message broker (pub/sub)
│  Broker (port 8883)  │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│  Telegraf            │  ← Data collection agent
│  (MQTT consumer)     │     Parses, transforms, routes
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│  InfluxDB            │  ← Time-series database
│  (data retention)    │     Downsampling, retention policies
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│  Grafana             │  ← Visualization + alerting
│  (dashboards)        │     Real-time dashboards, threshold alerts
└─────────────────────┘

This architecture is modular. You can replace any layer independently — swap Telegraf for a custom Python consumer, add Node-RED for visual flow programming, or insert Apache Kafka for high-throughput buffering. The MQTT broker sits at the center, decoupling devices from backend processing.

Prerequisites — Ubuntu VPS Sizing by Device Count

Choosing the right VPS size depends on how many devices you plan to connect and how frequently they publish data. Mosquitto is remarkably lightweight — a single-threaded broker can handle tens of thousands of connections on minimal resources. The heavier components are your database and dashboard layers.

With MassiveGRID's independent resource scaling, you can start small and add CPU, RAM, or storage independently as your fleet grows — no need to migrate to a larger plan or reprovision the server.

Installing Mosquitto MQTT Broker

Eclipse Mosquitto is the standard open-source MQTT broker — lightweight, reliable, and capable of handling production workloads. Install it on Ubuntu 24.04:

# Install Mosquitto broker and client tools
sudo apt update
sudo apt install -y mosquitto mosquitto-clients

# Enable and start the service
sudo systemctl enable mosquitto
sudo systemctl start mosquitto

# Verify it's running
sudo systemctl status mosquitto

By default, Mosquitto listens on port 1883 (unencrypted) and accepts anonymous connections. This is fine for initial testing but must be locked down before production use. Create a basic configuration file:

# /etc/mosquitto/conf.d/default.conf

# Listener configuration
listener 1883 0.0.0.0

# Logging
log_dest file /var/log/mosquitto/mosquitto.log
log_type all

# Connection limits
max_connections 10000
max_queued_messages 1000

# Persistence
persistence true
persistence_location /var/lib/mosquitto/

# Message size limit (default 256MB is too high for IoT)
message_size_limit 10240

Restart Mosquitto to apply the configuration:

sudo systemctl restart mosquitto

Securing MQTT with TLS, Authentication, and ACLs

An unsecured MQTT broker exposed to the internet is a serious risk — anyone who discovers the port can subscribe to all topics and publish arbitrary commands. Production deployments require three layers of security:

TLS Encryption

Enable TLS to encrypt all MQTT traffic. You will need SSL certificates — see our guide on installing SSL certificates on Ubuntu VPS for obtaining certificates via Let's Encrypt:

# /etc/mosquitto/conf.d/tls.conf

# Disable unencrypted listener
listener 8883 0.0.0.0

# TLS configuration
cafile /etc/letsencrypt/live/mqtt.yourdomain.com/chain.pem
certfile /etc/letsencrypt/live/mqtt.yourdomain.com/fullchain.pem
keyfile /etc/letsencrypt/live/mqtt.yourdomain.com/privkey.pem

# Require TLS 1.2 minimum
tls_version tlsv1.2

Password Authentication

Create a password file and require authentication for all connections:

# Create password file with first user
sudo mosquitto_passwd -c /etc/mosquitto/passwd sensor_gateway_01

# Add additional users
sudo mosquitto_passwd -b /etc/mosquitto/passwd sensor_gateway_02 'strong_password_here'
sudo mosquitto_passwd -b /etc/mosquitto/passwd dashboard_reader 'another_password'
sudo mosquitto_passwd -b /etc/mosquitto/passwd telegraf_consumer 'telegraf_password'

# Add to Mosquitto config
# password_file /etc/mosquitto/passwd
# allow_anonymous false

Access Control Lists (ACLs)

ACLs restrict which users can publish or subscribe to specific topics:

# /etc/mosquitto/acl.conf

# Sensor gateways can publish to their own device topics
user sensor_gateway_01
topic write sensors/building-a/#

user sensor_gateway_02
topic write sensors/building-b/#

# Telegraf can read all sensor data
user telegraf_consumer
topic read sensors/#
topic read devices/#

# Dashboard reader for status topics
user dashboard_reader
topic read sensors/#
topic read devices/+/status

Add the ACL file to your configuration with acl_file /etc/mosquitto/acl.conf and restart Mosquitto. For a comprehensive security approach, refer to our Ubuntu VPS security hardening guide covering firewalls, fail2ban, SSH hardening, and more.

Testing with MQTT Clients

Before connecting real devices, verify your broker works correctly using command-line tools and a graphical client.

Command-Line Testing with mosquitto_pub and mosquitto_sub

Open two terminal sessions. In the first, subscribe to a topic:

# Subscribe to all sensor topics (TLS + authentication)
mosquitto_sub -h mqtt.yourdomain.com -p 8883 \
  --cafile /etc/letsencrypt/live/mqtt.yourdomain.com/chain.pem \
  -u telegraf_consumer -P 'telegraf_password' \
  -t 'sensors/#' -v

In the second terminal, publish a test message:

# Publish a sensor reading
mosquitto_pub -h mqtt.yourdomain.com -p 8883 \
  --cafile /etc/letsencrypt/live/mqtt.yourdomain.com/chain.pem \
  -u sensor_gateway_01 -P 'gateway_password' \
  -t 'sensors/building-a/floor-1/temperature' \
  -m '{"value": 22.5, "unit": "celsius", "timestamp": 1740700800}'

You should see the message appear in the subscriber terminal immediately. If not, check Mosquitto's log file at /var/log/mosquitto/mosquitto.log for authentication or ACL errors.

MQTT Explorer

For a graphical view of your topic hierarchy and message flow, install MQTT Explorer on your workstation. It connects to your broker and displays the full topic tree, message payloads, and publish/subscribe statistics in real time — invaluable for debugging topic structures and verifying device connectivity.