perkun.eu Services Portfolio Blog About Contact PL
← Blog

1/30/2023

Grafana + InfluxDB + MQTT — IoT dashboard from scratch

TL;DR: Three components of the stack: Mosquitto broker, InfluxDB as the time-series DB, Grafana as the visualization layer. Everything in Docker Compose, ready in 2 hours.

IoT system monitoring starts with a question: how do I know what my sensor was doing two hours ago? Log files aren’t enough, and a relational database overcomplicates time-series queries. This is where the Mosquitto + InfluxDB + Grafana stack comes in — mature, well-documented tools that together create a complete pipeline from sensor to dashboard chart.

Why this stack

InfluxDB is optimized for time series. When a temperature sensor sends a reading every 10 seconds, each record has a timestamp and a value — exactly the schema InfluxDB handles natively. A query for “average temperature over the last hour grouped by 5 minutes” is a single line in the Flux language, whereas in SQL it would require complex time window operations.

Grafana has a native connector for InfluxDB 2.x and hundreds of pre-built dashboards on the marketplace (grafana.com/grafana/dashboards). For popular devices — Zigbee sensors, Shelly, ESP32 — you can often find a ready-to-import dashboard in 30 seconds.

Docker Compose

The full configuration starts three services:

version: '3.8'
services:
  mosquitto:
    image: eclipse-mosquitto:2
    ports:
      - "1883:1883"
    volumes:
      - ./mosquitto/config:/mosquitto/config
      - ./mosquitto/data:/mosquitto/data

  influxdb:
    image: influxdb:2.7
    ports:
      - "8086:8086"
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=haslo_admin
      - DOCKER_INFLUXDB_INIT_ORG=myorg
      - DOCKER_INFLUXDB_INIT_BUCKET=iot
      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=moj_token_api
    volumes:
      - influxdb_data:/var/lib/influxdb2

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=haslo_grafana
    volumes:
      - grafana_data:/var/lib/grafana

volumes:
  influxdb_data:
  grafana_data:

After docker compose up -d, InfluxDB is available on port 8086 and Grafana on port 3000. Mosquitto requires a mosquitto.conf config file with listener 1883 and allow_anonymous true (or user configuration for production).

Node-RED as an MQTT → InfluxDB bridge

Rather than writing your own Python script to subscribe to MQTT and write to InfluxDB, it’s worth using Node-RED. The visual flow-based editor handles both protocols through built-in nodes, and data transformation (JSON parsing, field renaming) happens without a single line of code.

Node-RED can be added to the same docker-compose.yml as a fourth service using the nodered/node-red:latest image. Once you install the node-red-contrib-influxdb nodes and the built-in mqtt in node, you’re ready to go.

Example flow

A typical flow looks like this. The mqtt in node subscribes to the topic sensors/temperatura/salon and receives a payload in the format {"value": 21.3, "humidity": 45}. A function node parses the JSON and transforms the data into InfluxDB format:

const data = JSON.parse(msg.payload);
msg.payload = [
    {
        measurement: "temperatura",
        fields: { value: data.value, humidity: data.humidity },
        timestamp: new Date()
    }
];
return msg;

The influxdb out node writes the data to the iot bucket in the myorg organization. The connection is configured via the URL http://influxdb:8086 and an API token.

Grafana datasource and dashboard

In Grafana, go to Configuration → Data Sources → Add data source → InfluxDB. Select Flux as the query language and enter the URL http://influxdb:8086, organization myorg, bucket iot, and the API token.

Example Flux query for a temperature chart over the last 24 hours:

from(bucket: "iot")
  |> range(start: -24h)
  |> filter(fn: (r) => r._measurement == "temperatura")
  |> filter(fn: (r) => r._field == "value")
  |> aggregateWindow(every: 5m, fn: mean, createEmpty: false)

You can add an alert on the panel: if the temperature exceeds 30°C for 5 minutes — send a notification via email or Telegram.

Summary

The Mosquitto + InfluxDB + Grafana stack runs in production with hundreds of sensors. It requires no external cloud services or subscriptions. Operating costs are server electricity and setup time — everything is open source and self-hosted. For new IoT projects, this is the starting point you should build from.