Raspberry Pi as a Network Monitor: Complete Setup Guide with SNMP, Grafana & Alerts
Turn a Raspberry Pi into a full network monitoring station — polling SNMP devices, storing metrics in InfluxDB, visualizing with Grafana, and sending alerts. Step-by-step with real configs.
Why Use a Raspberry Pi as a Network Monitor?
A Raspberry Pi 4 draws about 3–5W of power. Running 24/7, that costs roughly ₹200–₹300 per year in electricity. Compare that to a dedicated server or a commercial NMS appliance, and the economics are obvious.
Over the past few years I've deployed Raspberry Pi-based monitoring stations in several small-to-medium network environments — everything from factory floors to remote railway relay rooms — and they've been rock solid. This guide documents exactly how to set one up from scratch.
What you'll build:
- SNMP poller that queries switches, routers, and IoT devices every 60 seconds
- InfluxDB time-series database to store all metrics
- Grafana dashboard to visualize bandwidth, CPU, memory, and uptime
- Alerting via email or Telegram when thresholds are breached
Hardware Requirements
| Component | Recommended | Minimum | |-----------|-------------|---------| | Raspberry Pi | Pi 4 (4GB RAM) | Pi 3B+ | | Storage | 32GB Class 10 microSD | 16GB | | Power | Official Pi 4 USB-C adapter | Any 5V/3A supply | | Network | Ethernet (not WiFi) | WiFi works | | OS | Raspberry Pi OS Lite (64-bit) | 32-bit Bullseye |
For anything monitoring more than 50 devices, use the Pi 4 with 4GB RAM. The Pi 3B+ will work for small networks (under 20 devices) but will struggle with Grafana rendering.
Step 1: Prepare the Raspberry Pi
Flash the OS
Download Raspberry Pi OS Lite (64-bit, Bookworm) and flash it using Raspberry Pi Imager. In the imager settings before flashing:
- Enable SSH
- Set hostname:
netmon - Set username/password
- Configure WiFi only if you have no ethernet
Initial System Setup
# Update everything first
sudo apt update && sudo apt upgrade -y
# Set timezone (important for time-series data)
sudo timedatectl set-timezone Asia/Kolkata
# Install essential tools
sudo apt install -y curl wget git htop net-tools snmp snmp-mibs-downloader
# Enable SNMP MIBs (disabled by default on Debian/Pi OS)
sudo sed -i 's/^mibs :$/# mibs :/' /etc/snmp/snmp.confVerify SNMP is Working
Test that you can reach a device on your network:
# Test basic SNMP connectivity to a switch/router
snmpwalk -v2c -c public 192.168.1.1 1.3.6.1.2.1.1.1.0
# Expected output:
# SNMPv2-MIB::sysDescr.0 = STRING: Cisco IOS Software...
# (or whatever device description your device has)If this works, SNMP is functional. If you get "No response", check:
- SNMP is enabled on the device
- Community string is correct (
publicis default but many devices change it) - Firewall on the device allows UDP port 161 from your Pi's IP
Step 2: Install InfluxDB
InfluxDB is a time-series database purpose-built for metrics. It stores millions of data points efficiently and integrates natively with Grafana.
# Add InfluxDB repository
curl https://repos.influxdata.com/influxdata-archive_compat.key | \
gpg --dearmor | sudo tee /usr/share/keyrings/influxdata-keyring.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/influxdata-keyring.gpg] \
https://repos.influxdata.com/debian stable main" | \
sudo tee /etc/apt/sources.list.d/influxdata.list
sudo apt update && sudo apt install -y influxdb2
# Start and enable
sudo systemctl enable --now influxdb
# Verify it's running
sudo systemctl status influxdbConfigure InfluxDB
Open the web interface at http://<pi-ip>:8086 and complete the setup wizard:
- Organization name:
techsystemlab(or your org) - Bucket name:
network_metrics - Retention:
30d(30 days is good for a Pi's storage)
After setup, generate an API token (Data → API Tokens → Generate All Access Token) and save it — you'll need it for the poller script.
Step 3: Write the SNMP Poller
This Python script polls all your network devices every 60 seconds and writes metrics to InfluxDB.
sudo apt install -y python3-pip python3-venv
mkdir -p /opt/netmon && cd /opt/netmon
python3 -m venv venv
source venv/bin/activate
pip install influxdb-client pysnmpCreate the poller script:
sudo nano /opt/netmon/snmp_poller.py#!/usr/bin/env python3
"""
SNMP Network Monitor — polls devices and writes to InfluxDB
"""
import time
import logging
from datetime import datetime, timezone
from pysnmp.hlapi import (
getCmd, SnmpEngine, CommunityData, UdpTransportTarget,
ContextData, ObjectType, ObjectIdentity
)
from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
handlers=[
logging.FileHandler('/var/log/netmon.log'),
logging.StreamHandler()
]
)
log = logging.getLogger(__name__)
# ── Configuration ─────────────────────────────────────────────────────────────
INFLUX_URL = "http://localhost:8086"
INFLUX_TOKEN = "YOUR_INFLUXDB_TOKEN_HERE" # paste token from InfluxDB UI
INFLUX_ORG = "techsystemlab"
INFLUX_BUCKET = "network_metrics"
POLL_INTERVAL = 60 # seconds
# Device list — add all your switches, routers, APs
DEVICES = [
{"host": "192.168.1.1", "community": "public", "name": "core-router", "type": "router"},
{"host": "192.168.1.2", "community": "public", "name": "core-switch", "type": "switch"},
{"host": "192.168.1.10", "community": "public", "name": "access-sw-1", "type": "switch"},
{"host": "192.168.1.11", "community": "public", "name": "access-sw-2", "type": "switch"},
{"host": "192.168.1.20", "community": "public", "name": "wifi-ap-1", "type": "ap"},
]
# OIDs to poll per device
OID_MAP = {
"sysUpTime": "1.3.6.1.2.1.1.3.0", # centiseconds since last reboot
"ifInOctets_1": "1.3.6.1.2.1.2.2.1.10.1", # bytes in on interface 1
"ifOutOctets_1":"1.3.6.1.2.1.2.2.1.16.1", # bytes out on interface 1
"ifInOctets_2": "1.3.6.1.2.1.2.2.1.10.2", # bytes in on interface 2
"ifOutOctets_2":"1.3.6.1.2.1.2.2.1.16.2", # bytes out on interface 2
}
# ── SNMP helper ────────────────────────────────────────────────────────────────
def snmp_get(host: str, community: str, oid: str) -> int | None:
error_indication, error_status, _, var_binds = next(
getCmd(
SnmpEngine(),
CommunityData(community, mpModel=1), # v2c
UdpTransportTarget((host, 161), timeout=2, retries=1),
ContextData(),
ObjectType(ObjectIdentity(oid)),
)
)
if error_indication or error_status:
return None
for var_bind in var_binds:
try:
return int(var_bind[1])
except (TypeError, ValueError):
return None
return None
# ── Main polling loop ──────────────────────────────────────────────────────────
def poll_devices(write_api):
now = datetime.now(timezone.utc)
points = []
for device in DEVICES:
host = device["host"]
community = device["community"]
name = device["name"]
dev_type = device["type"]
log.info(f"Polling {name} ({host})")
for metric, oid in OID_MAP.items():
value = snmp_get(host, community, oid)
if value is None:
log.warning(f" {metric}: no response")
continue
point = (
Point("snmp_metric")
.tag("device", name)
.tag("type", dev_type)
.tag("host", host)
.field(metric, value)
.time(now)
)
points.append(point)
log.info(f" {metric} = {value}")
# Write reachability (1 = up, 0 = down)
reachable = 1 if snmp_get(host, community, OID_MAP["sysUpTime"]) is not None else 0
points.append(
Point("device_reachability")
.tag("device", name)
.tag("type", dev_type)
.tag("host", host)
.field("up", reachable)
.time(now)
)
if points:
write_api.write(bucket=INFLUX_BUCKET, org=INFLUX_ORG, record=points)
log.info(f"Wrote {len(points)} points to InfluxDB")
def main():
client = InfluxDBClient(url=INFLUX_URL, token=INFLUX_TOKEN, org=INFLUX_ORG)
write_api = client.write_api(write_options=SYNCHRONOUS)
log.info("SNMP poller started")
while True:
try:
poll_devices(write_api)
except Exception as e:
log.error(f"Poll error: {e}")
time.sleep(POLL_INTERVAL)
if __name__ == "__main__":
main()Run as a systemd Service
sudo nano /etc/systemd/system/netmon-poller.service[Unit]
Description=SNMP Network Monitor Poller
After=network.target influxdb.service
Wants=influxdb.service
[Service]
Type=simple
User=pi
WorkingDirectory=/opt/netmon
ExecStart=/opt/netmon/venv/bin/python3 /opt/netmon/snmp_poller.py
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now netmon-poller
sudo systemctl status netmon-poller
# Watch logs
journalctl -u netmon-poller -fStep 4: Install Grafana
# Add Grafana repository
curl -fsSL https://apt.grafana.com/gpg.key | \
sudo gpg --dearmor -o /usr/share/keyrings/grafana.gpg
echo "deb [signed-by=/usr/share/keyrings/grafana.gpg] \
https://apt.grafana.com stable main" | \
sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update && sudo apt install -y grafana
sudo systemctl enable --now grafana-serverAccess Grafana at http://<pi-ip>:3000 — default login is admin / admin. Change the password immediately.
Add InfluxDB as a Data Source
- Go to Connections → Data Sources → Add data source
- Select InfluxDB
- Set:
- Query language: Flux
- URL:
http://localhost:8086 - Organization:
techsystemlab - Token: (paste your InfluxDB token)
- Default Bucket:
network_metrics
- Click Save & Test — you should see "datasource is working"
Create Your First Dashboard Panel
In a new dashboard, add a panel with this Flux query for interface traffic:
from(bucket: "network_metrics")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "snmp_metric")
|> filter(fn: (r) => r._field == "ifInOctets_1")
|> filter(fn: (r) => r.device == "core-router")
|> derivative(unit: 1s, nonNegative: true)
|> map(fn: (r) => ({ r with _value: r._value * 8.0 })) // convert to bits/sThis gives you bits-per-second in on interface 1 of the core router. Create matching panels for ifOutOctets_1 and repeat for each device.
Step 5: Set Up Alerts
Email Alerts via Grafana
In Grafana, go to Alerting → Contact points → Add contact point:
- Name:
email-alerts - Integration: Email
- Addresses: your email
Then create an alert rule:
- Query: device reachability (
up == 0) - Condition:
is below 1for 2 minutes - Send to:
email-alerts
Telegram Alerts (Better for Mobile)
Create a Telegram bot via @BotFather and get your bot token and chat ID. Add a contact point:
- Integration: Telegram
- BOT API Token:
your-telegram-bot-token - Chat ID:
your-chat-id
You'll get instant Telegram messages when devices go down.
Step 6: Add SNMPv3 Support
For production environments, never use SNMPv2c with community strings. Here's how to add SNMPv3 devices:
from pysnmp.hlapi import UsmUserData, usmHMACSHAAuthProtocol, usmAesCfb128Protocol
def snmp_get_v3(host: str, username: str, auth_pass: str, priv_pass: str, oid: str):
error_indication, error_status, _, var_binds = next(
getCmd(
SnmpEngine(),
UsmUserData(
username,
authKey=auth_pass,
privKey=priv_pass,
authProtocol=usmHMACSHAAuthProtocol,
privProtocol=usmAesCfb128Protocol,
),
UdpTransportTarget((host, 161), timeout=2, retries=1),
ContextData(),
ObjectType(ObjectIdentity(oid)),
)
)
if error_indication or error_status:
return None
for var_bind in var_binds:
try:
return int(var_bind[1])
except (TypeError, ValueError):
return None
return NoneAdd SNMPv3 devices to your DEVICES list with "version": "v3" and handle them separately in the polling loop.
Performance Tuning for Large Networks
If you're monitoring 50+ devices, the serial polling loop becomes too slow. Switch to concurrent polling:
import asyncio
from concurrent.futures import ThreadPoolExecutor
async def poll_all_devices_concurrent(devices, write_api):
loop = asyncio.get_event_loop()
with ThreadPoolExecutor(max_workers=10) as executor:
tasks = [
loop.run_in_executor(executor, poll_single_device, device, write_api)
for device in devices
]
await asyncio.gather(*tasks)With 10 concurrent threads and a 2-second timeout per OID, you can poll 50 devices in under 15 seconds — well within the 60-second interval.
Common Issues and Fixes
"No SNMP response" from device
# Test connectivity manually
snmpget -v2c -c public -t 3 <device-ip> 1.3.6.1.2.1.1.3.0
# Check if UDP 161 is reachable
nmap -sU -p 161 <device-ip>
# Verify community string — many devices use "private" for write, "public" for readInfluxDB disk usage growing too fast
Reduce the retention policy:
# In InfluxDB UI: Data → Buckets → Edit your bucket → Retention → 7d
# Or via CLI:
influx bucket update --name network_metrics --retention 168h # 7 daysGrafana showing no data
Check the time range in the top right — make sure it covers the period you've been polling. Also verify your Flux query field names match what's actually in InfluxDB (use the Data Explorer in InfluxDB UI to browse what was written).
Frequently Asked Questions
Can a Raspberry Pi 4 handle monitoring 100 devices?
Yes, with concurrent polling. Serial polling of 100 devices at 2s timeout each would take 200+ seconds per cycle — too slow for 60s intervals. With 20 concurrent threads, 100 devices poll in about 10–15 seconds. RAM usage is typically 400–600MB for InfluxDB + Grafana + poller on a Pi 4 with 4GB RAM.
What's the difference between this and LibreNMS on a Pi?
LibreNMS is a full-featured auto-discovery NMS with device templates, alerting, and a web UI. It's great but heavy — it requires MySQL, Apache, and PHP, and runs sluggishly on a Pi 3. The custom stack here (InfluxDB + Grafana + Python) is lighter, more flexible, and easier to extend. LibreNMS is better if you need automatic device discovery and pre-built device templates.
Can I monitor Windows servers and Linux hosts too?
Yes. Install snmpd on Linux hosts and enable SNMP on Windows via Services. For Linux, edit /etc/snmp/snmpd.conf:
# /etc/snmp/snmpd.conf (minimal working config)
rocommunity public 192.168.1.100 # allow read from Pi's IP only
syslocation Server Room
syscontact admin@yourcompany.comThen restart: sudo systemctl restart snmpd. You can now poll CPU load (1.3.6.1.4.1.2021.10.1.3.1), memory (1.3.6.1.4.1.2021.4.*), and disk usage (1.3.6.1.4.1.2021.9.*).
How do I back up the monitoring data?
# Back up InfluxDB data
influx backup /mnt/usb-backup/influxdb-$(date +%Y%m%d)
# Or export a specific bucket as CSV
influx query 'from(bucket:"network_metrics") |> range(start:-7d)' \
--raw > /mnt/usb-backup/metrics-$(date +%Y%m%d).csvSchedule with cron: 0 2 * * * /home/pi/backup-metrics.sh
Conclusion
A Raspberry Pi with InfluxDB and Grafana gives you a professional-grade network monitoring station for under ₹5,000 in hardware. The Python SNMP poller is simple enough to understand and modify, and Grafana's alerting handles notifications reliably.
The setup I've described here is exactly what runs in a few of our client deployments — factory floors and remote substations where a full server isn't practical but reliable monitoring is essential.
Related: SNMPv3 Secure Configuration and Testing | SNMP Traps and Alert Receiver Setup | Open Source Tools for SNMP Monitoring