Network Monitor

More Raspberry Pi Projects

Project 4 — Network Monitoring with Grafana

What you will build A live monitoring dashboard showing system metrics, network activity, Pi-hole stats, and sensor readings
Difficulty Intermediate — installation is straightforward, dashboard building takes experimentation
Time to complete 2 – 3 hours for the core stack, plus time for building dashboards
What you will need Raspberry Pi 4 (2 GB+ recommended), internet connection, optional: DHT22 or DS18B20 temperature sensor

What Is the TIG Stack?

Grafana on its own is just a visualisation tool — it draws charts but doesn't collect or store data. To monitor your Pi you need a complete data pipeline, commonly called the TIG stack:

The TIG monitoring pipeline
🖥️systemCPU, RAM, disk
🌐networkbytes in/out
🚫Pi-holeDNS queries, blocks
🌡️DHT22temp, humidity
📡pinglatency, uptime
▼ collected every 10 seconds
TelegrafAgent that collects metrics from dozens of sources using plugins — runs on the Pi and pushes data into InfluxDBagent only
▼ stored as time-series data
InfluxDBTime-series database optimised for storing metrics — fast writes, efficient compression, built-in data retention policies:8086
▼ queried on demand
GrafanaWeb dashboard — queries InfluxDB and renders live charts, graphs, gauges, alerts, and tables:3000
Example dashboard — what you will see
CPU Usage12%average
CPU Temp61°Con-chip
Memory38%1.5 / 4 GB
Disk54%used
Net In2.3MB/s
Net Out0.8MB/s
DNS Blocks23%of queries
Uptime14d7h 22m

What You Will Need

🍓 Raspberry Pi 4 2 GB RAM minimum. InfluxDB is the hungriest component — it runs comfortably on 2 GB but appreciates 4 GB if you're storing months of data.
💾 SSD (recommended) InfluxDB does many small writes. Running it on a microSD card will significantly shorten the card's life. An external SSD is strongly recommended.
🌡️ Sensor (optional) DHT22 (temperature + humidity, ~£4) or DS18B20 (temperature probe, ~£3) add a satisfying real-world dimension to the dashboard.
🚫 Pi-hole (optional) If you completed Course 1 Project 2, you can pull Pi-hole DNS stats directly into Grafana for a great combined dashboard.
🌐 Static local IP Set a DHCP reservation for your Pi in your router so its local IP address never changes — makes bookmarking the dashboard reliable.
🔑 SSH access All installation is done via SSH. Grafana's web UI is accessed from any browser on your local network once it's running.

Step 1 — Install InfluxDB

InfluxDB 2.x has a simpler setup than the older v1 branch and includes a built-in web UI for exploring your data. We'll use v2:

# Add the InfluxDB repository
pi@raspberrypi:~$ wget -q https://repos.influxdata.com/influxdata-archive_compat.key
pi@raspberrypi:~$ echo '23a1c8836f0afc5ed24e0486339d7cc8f6790b83886c4c96995b88a061c5bb5d influxdata-archive_compat.key' | sha256sum -c && \
  cat influxdata-archive_compat.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg > /dev/null

pi@raspberrypi:~$ echo 'deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg] https://repos.influxdata.com/debian stable main' | \
  sudo tee /etc/apt/sources.list.d/influxdata.list

pi@raspberrypi:~$ sudo apt update
pi@raspberrypi:~$ sudo apt install -y influxdb2 influxdb2-cli
pi@raspberrypi:~$ sudo systemctl enable --now influxdb
pi@raspberrypi:~$ sudo systemctl status influxdb
● influxdb.service - InfluxDB is an open-source, distributed, time series database
     Active: active (running)

Set up InfluxDB via the web UI

Open http://raspberrypi.local:8086 in your browser (or use the Pi's IP address). You'll see the initial setup wizard:

  • Username / Password — create your admin account
  • Organisation name — e.g. homelab
  • Bucket nametelegraf (Telegraf will write here by default)
  • Retention — how long to keep data. 30d is a good starting point; increase to 365d if you have an SSD with plenty of space
  • Copy the API token — shown at the end of setup. Save it — you'll need it for Telegraf and Grafana.
Copy and save the API token shown during setup — it is displayed only once. If you lose it, you can generate a new one from the InfluxDB UI under Data → API Tokens → Generate API Token.

Step 2 — Install and Configure Telegraf

pi@raspberrypi:~$ sudo apt install -y telegraf

Telegraf is configured through a single TOML file. The default config file is large (it has hundreds of commented-out plugins). Create a clean, focused config instead:

pi@raspberrypi:~$ sudo nano /etc/telegraf/telegraf.conf

Replace the contents with:

# ── Global agent settings ──────────────────────────────────────────
[agent]
  interval          = "10s"    # collect metrics every 10 seconds
  round_interval    = true
  metric_batch_size = 1000
  flush_interval    = "10s"

# ── Output: write to InfluxDB 2 ────────────────────────────────────
[[outputs.influxdb_v2]]
  urls         = ["http://localhost:8086"]
  token        = "PASTE_YOUR_INFLUXDB_TOKEN_HERE"
  organization = "homelab"
  bucket       = "telegraf"

# ── Input: CPU usage ───────────────────────────────────────────────
[[inputs.cpu]]
  percpu           = true
  totalcpu         = true
  collect_cpu_time = false
  report_active    = false

# ── Input: Memory ──────────────────────────────────────────────────
[[inputs.mem]]

# ── Input: Disk usage ──────────────────────────────────────────────
[[inputs.disk]]
  ignore_fs = ["tmpfs", "devtmpfs", "devfs", "iso9660", "overlay", "aufs", "squashfs"]

# ── Input: Disk I/O ────────────────────────────────────────────────
[[inputs.diskio]]

# ── Input: Network interfaces ──────────────────────────────────────
[[inputs.net]]
  interfaces = ["eth0"]   # change to wlan0 if using Wi-Fi

# ── Input: System (uptime, load, processes) ────────────────────────
[[inputs.system]]

# ── Input: Raspberry Pi CPU temperature ────────────────────────────
[[inputs.file]]
  files            = ["/sys/class/thermal/thermal_zone0/temp"]
  name_override    = "cpu_temperature"
  data_format      = "value"
  data_type        = "integer"

# ── Input: Ping / latency (checks 8.8.8.8 and 1.1.1.1) ────────────
[[inputs.ping]]
  urls   = ["8.8.8.8", "1.1.1.1"]
  count  = 3
  method = "native"

Give Telegraf permission to ping

pi@raspberrypi:~$ sudo setcap cap_net_raw+ep /usr/bin/telegraf
pi@raspberrypi:~$ sudo systemctl enable --now telegraf
pi@raspberrypi:~$ sudo systemctl status telegraf
● telegraf.service - Telegraf
     Active: active (running)

Verify data is flowing into InfluxDB

Open http://raspberrypi.local:8086Data Explorer. Select the telegraf bucket, then the cpu measurement. If you see data points, Telegraf is working.

Step 3 — Install Grafana

# Add the Grafana APT repository
pi@raspberrypi:~$ sudo mkdir -p /etc/apt/keyrings/
pi@raspberrypi:~$ wget -q -O /etc/apt/keyrings/grafana.gpg https://apt.grafana.com/gpg.key
pi@raspberrypi:~$ echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | \
  sudo tee /etc/apt/sources.list.d/grafana.list

pi@raspberrypi:~$ sudo apt update
pi@raspberrypi:~$ sudo apt install -y grafana

pi@raspberrypi:~$ sudo systemctl enable --now grafana-server
pi@raspberrypi:~$ sudo systemctl status grafana-server
● grafana-server.service - Grafana instance
     Active: active (running)

Open http://raspberrypi.local:3000 in a browser. Log in with the default credentials: admin / admin. You'll be prompted to change the password on first login.

Step 4 — Connect Grafana to InfluxDB

  • In Grafana, go to Connections → Data Sources → Add data source
  • Select InfluxDB
  • Set Query Language to Flux (the InfluxDB 2 query language)
  • Set URL to http://localhost:8086
  • Under InfluxDB Details, enter your Organisation (homelab), Bucket (telegraf), and paste your Token
  • Click Save & Test — you should see a green ✓

Step 5 — Build Your First Dashboard

Using a community dashboard template

The fastest way to get a great-looking dashboard is to import one from grafana.com/grafana/dashboards. Recommended starting points:

Dashboard IDNameWhat it shows
10578Telegraf: system dashboardCPU, memory, disk, network — Flux compatible
15650Raspberry Pi MonitoringPi-specific metrics including CPU temperature
14952Pi-hole ExporterDNS queries, block rate, top blocked domains

To import: Dashboards → Import → enter the ID → select your InfluxDB data source → Import.

Writing your first Flux query manually

If you want to build panels from scratch, here are Flux queries for the most useful metrics:

// CPU usage — average across all cores
from(bucket: "telegraf")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "cpu" and
                     r._field == "usage_percent" and
                     r.cpu == "cpu-total")
  |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)
// CPU temperature (divide millidegrees by 1000 to get °C)
from(bucket: "telegraf")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "cpu_temperature")
  |> map(fn: (r) => ({r with _value: float(v: r._value) / 1000.0}))
// Network bytes received per second on eth0
from(bucket: "telegraf")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "net" and
                     r._field == "bytes_recv" and
                     r.interface == "eth0")
  |> derivative(unit: 1s, nonNegative: true)
// Memory used percentage
from(bucket: "telegraf")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "mem" and
                     r._field == "used_percent")
  |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)

Step 6 — Add Pi-hole Metrics (if installed)

If you set up Pi-hole in Course 1, you can pull its statistics directly into Grafana. Pi-hole exposes a simple API that Telegraf can poll.

Add this section to your Telegraf config:

pi@raspberrypi:~$ sudo nano /etc/telegraf/telegraf.conf
# ── Input: Pi-hole DNS stats ────────────────────────────────────────
[[inputs.http]]
  urls         = ["http://localhost/admin/api.php"]
  name_override = "pihole"
  data_format  = "json"
  interval     = "60s"   # poll Pi-hole every 60 seconds
  [inputs.http.tags]
    source = "pihole"
pi@raspberrypi:~$ sudo systemctl restart telegraf

This pulls Pi-hole's summary stats (total queries, queries blocked, block percentage, unique domains, unique clients, and more) into InfluxDB, ready to chart in Grafana.

A Flux query for the block rate:

from(bucket: "telegraf")
  |> range(start: -24h)
  |> filter(fn: (r) => r._measurement == "pihole" and
                     r._field == "ads_percentage_today")
  |> last()

Step 7 — Add a Temperature Sensor (optional)

DHT22 — temperature and humidity via Python

The DHT22 connects to a GPIO pin and provides both temperature and humidity readings. Because it requires a Python library, the easiest approach is a small Python script that writes directly to InfluxDB.

pi@raspberrypi:~$ pip3 install --break-system-packages adafruit-circuitpython-dht influxdb-client
pi@raspberrypi:~$ nano /home/pi/dht22_to_influx.py
import time, board, adafruit_dht
from influxdb_client import InfluxDBClient, Point, WriteOptions

# ── Config ──────────────────────────────────────────────────────
TOKEN  = "YOUR_INFLUXDB_TOKEN"
ORG    = "homelab"
BUCKET = "telegraf"
URL    = "http://localhost:8086"
GPIO   = board.D4       # DHT22 data pin — connected to GPIO 4

# ── Setup ───────────────────────────────────────────────────────
sensor = adafruit_dht.DHT22(GPIO)
client = InfluxDBClient(url=URL, token=TOKEN, org=ORG)
write  = client.write_api()

while True:
    try:
        temp     = sensor.temperature
        humidity = sensor.humidity
        if temp is not None:
            point = (
                Point("environment")
                .tag("sensor", "dht22")
                .field("temperature_c", temp)
                .field("humidity_pct",  humidity)
            )
            write.write(bucket=BUCKET, org=ORG, record=point)
    except RuntimeError:
        pass    # DHT22 occasionally misfires — safe to ignore
    time.sleep(30)

Run it as a systemd service so it starts on boot:

pi@raspberrypi:~$ sudo nano /etc/systemd/system/dht22.service
[Unit]
Description=DHT22 sensor to InfluxDB
After=network.target influxdb.service

[Service]
User=pi
ExecStart=/usr/bin/python3 /home/pi/dht22_to_influx.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
pi@raspberrypi:~$ sudo systemctl daemon-reload
pi@raspberrypi:~$ sudo systemctl enable --now dht22

Step 8 — Set Up Grafana Alerts

Grafana can notify you when a metric exceeds a threshold — useful for catching an overheating Pi, a full disk, or internet downtime.

  • In any panel, click the panel title → Edit
  • Switch to the Alert tab → Create alert rule from this panel
  • Set a condition, e.g. CPU temperature above 75°C
  • Under Notifications, configure a contact point — Grafana supports email, Telegram, Discord, Slack, PagerDuty, and more
  • For email: go to Alerting → Contact Points → New → Email and enter your email address
If you set up the mail server in Projects 2 and 3, you can configure Grafana to send alerts through your own Postfix server. In Grafana's SMTP settings (/etc/grafana/grafana.ini), set the host to localhost:587 with your mail user's credentials.

Step 9 — Set a Data Retention Policy

InfluxDB will keep your data forever by default, which will eventually fill your disk. Set a retention policy to automatically delete old data:

  • In the InfluxDB web UI: Load Data → Buckets → telegraf → Settings
  • Set Delete Data to 30 days (or 365 days if on an SSD)
  • Save — InfluxDB will automatically purge data older than this threshold

If you want long-term trends without the storage cost, use Telegraf's aggregator plugins to downsample older data (e.g. keep 10-second granularity for 7 days, then 1-minute averages for 6 months).

Troubleshooting

⚠ Telegraf starts but no data appears in InfluxDB
Check the Telegraf log: sudo journalctl -u telegraf -n 50. The most common cause is a wrong API token — look for 401 Unauthorized in the log. Copy the token from InfluxDB (Data → API Tokens) and re-paste it into telegraf.conf, then restart Telegraf. Also check the organisation name matches exactly (it's case-sensitive).
⚠ Grafana shows "Data source connected and labels found. No results" in panels
The Flux query is probably filtering for a measurement or field name that doesn't match what Telegraf actually wrote. Go to the InfluxDB web UI → Data Explorer → select your bucket and browse the measurements and field names that actually exist. Copy the exact names into your Flux query.
⚠ CPU temperature reads as a huge number (e.g. 55000 instead of 55°C)
The kernel's thermal zone file reports temperature in millidegrees. Divide by 1000 in your Flux query using map(fn: (r) => ({r with _value: float(v: r._value) / 1000.0})), or apply a unit transformation in the Grafana panel options under Standard options → Unit → select Temperature → Celsius and set the display min/max sensibly.
⚠ InfluxDB is consuming too much memory
InfluxDB 2 can be memory-hungry. Set a query memory limit in /etc/influxdb/config.toml: add [query-controller] max-memory-bytes = 104857600 (100 MB). Also set a retention policy on your bucket — unbounded data grows the WAL and cache indefinitely. Restart InfluxDB after changes.
⚠ Ping plugin errors — "socket: operation not permitted"
The Telegraf process doesn't have permission to create raw sockets for ICMP pings. Run: sudo setcap cap_net_raw+ep /usr/bin/telegraf. If Telegraf was updated via apt, the capability gets reset — add a post-install hook or set method = "exec" in the ping plugin to use the system ping binary instead.
⚠ Grafana can't connect to InfluxDB — "Failed to call resource" or "502 Bad Gateway"
InfluxDB is not running or not reachable on port 8086. Check: sudo systemctl status influxdb and curl http://localhost:8086/health. If InfluxDB is running but Grafana can't reach it, ensure the URL in Grafana's data source settings is exactly http://localhost:8086 (no trailing slash, not https unless you've set up TLS).
⚠ DHT22 readings are intermittent or "None"
The DHT22 is a notoriously noisy sensor that occasionally fails to respond. The Python script already handles RuntimeError silently — just let it retry on the next 30-second interval. If failures are frequent: (1) check the wiring — data pin needs a 4.7–10 kΩ pull-up resistor to 3.3V; (2) ensure no other process is accessing the same GPIO pin; (3) consider switching to a DS18B20 (1-Wire) sensor which is far more reliable for pure temperature readings.

Quick Reference

TaskCommand / URL
InfluxDB web UIhttp://raspberrypi.local:8086
Grafana web UIhttp://raspberrypi.local:3000
Restart Telegrafsudo systemctl restart telegraf
View Telegraf logsudo journalctl -u telegraf -f
Restart InfluxDBsudo systemctl restart influxdb
Restart Grafanasudo systemctl restart grafana-server
Test InfluxDB healthcurl http://localhost:8086/health
Telegraf config file/etc/telegraf/telegraf.conf
InfluxDB config/etc/influxdb/config.toml
Grafana config/etc/grafana/grafana.ini
Grafana default loginadmin / admin (change on first login)
Fix ping permissionssudo setcap cap_net_raw+ep /usr/bin/telegraf
List all InfluxDB bucketsinflux bucket list
View InfluxDB data (CLI)influx query 'from(bucket:"telegraf") |> range(start:-1h) |> limit(n:5)'
Community dashboardsgrafana.com/grafana/dashboards
Telegraf plugin referencedocs.influxdata.com/telegraf/latest/plugins