Network Monitor
More Raspberry Pi Projects
Project 4 — Network Monitoring with Grafana
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:
What You Will Need
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 name —
telegraf(Telegraf will write here by default) - Retention — how long to keep data.
30dis a good starting point; increase to365dif 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.
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:8086 → Data 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 ID | Name | What it shows |
|---|---|---|
10578 | Telegraf: system dashboard | CPU, memory, disk, network — Flux compatible |
15650 | Raspberry Pi Monitoring | Pi-specific metrics including CPU temperature |
14952 | Pi-hole Exporter | DNS 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
/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(or365 daysif 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
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).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./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.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.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).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
| Task | Command / URL |
|---|---|
| InfluxDB web UI | http://raspberrypi.local:8086 |
| Grafana web UI | http://raspberrypi.local:3000 |
| Restart Telegraf | sudo systemctl restart telegraf |
| View Telegraf log | sudo journalctl -u telegraf -f |
| Restart InfluxDB | sudo systemctl restart influxdb |
| Restart Grafana | sudo systemctl restart grafana-server |
| Test InfluxDB health | curl 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 login | admin / admin (change on first login) |
| Fix ping permissions | sudo setcap cap_net_raw+ep /usr/bin/telegraf |
| List all InfluxDB buckets | influx bucket list |
| View InfluxDB data (CLI) | influx query 'from(bucket:"telegraf") |> range(start:-1h) |> limit(n:5)' |
| Community dashboards | grafana.com/grafana/dashboards |
| Telegraf plugin reference | docs.influxdata.com/telegraf/latest/plugins |