How to Monitor Your Homelab with Prometheus and Grafana
Prometheus scrapes metrics. Grafana makes them pretty. Together they give you dashboards that actually tell you what's happening on your homelab.
At some point, “is it up?” stops being enough. You want to know CPU usage over the last 24 hours. You want to see memory pressure before it causes an OOM kill. You want a dashboard that lights up red before your disk fills up — not after.
Prometheus and Grafana are the standard answer for this in the homelab world, and for good reason. They’re open source, they run fine on low-end hardware, and once they’re set up, they mostly take care of themselves.
What Each Piece Does
Prometheus is a time-series database and metrics scraper. It pulls metrics from endpoints (called “exporters”) on a schedule and stores them. You don’t push data to Prometheus — it reaches out and pulls it.
Grafana is the visualization layer. It connects to Prometheus (and other data sources) and lets you build dashboards with graphs, gauges, tables, and alert panels. The dashboards look professional with almost no configuration.
Node Exporter is a Prometheus exporter that runs on each host you want to monitor. It exposes system metrics — CPU, memory, disk, network, load average — at a /metrics endpoint.
cAdvisor does the same thing but for Docker containers. It exposes per-container CPU, memory, and network metrics.
Setting It Up with Docker Compose
The easiest way to run this whole stack is a single docker-compose.yml. Create a directory for it and add this:
version: "3.8"
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
ports:
- "9090:9090"
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=changeme
restart: unless-stopped
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
ports:
- "9100:9100"
restart: unless-stopped
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8080:8080"
restart: unless-stopped
volumes:
prometheus_data:
grafana_data:
Then create prometheus.yml in the same directory:
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
Run docker compose up -d and give it a minute to start.
Accessing the Stack
- Prometheus at
http://your-server-ip:9090— check Status > Targets to confirm everything is being scraped - Grafana at
http://your-server-ip:3000— log in with admin / changeme (change this immediately)
Setting Up Grafana
Add Prometheus as a data source:
- Go to Connections > Data Sources > Add data source
- Select Prometheus
- URL:
http://prometheus:9090 - Click Save & Test
Import a dashboard: Instead of building from scratch, import a community dashboard. The most popular ones for this stack:
- Node Exporter Full — Dashboard ID
1860— covers everything about your host hardware - Docker and System Monitoring — Dashboard ID
893— good container overview
Go to Dashboards > New > Import, enter the ID, select your Prometheus data source, and import. You’ll have production-quality dashboards in 30 seconds.
Adding More Hosts
To monitor additional machines, run node-exporter on each one:
docker run -d \
--name node-exporter \
--restart unless-stopped \
-p 9100:9100 \
-v /proc:/host/proc:ro \
-v /sys:/host/sys:ro \
prom/node-exporter \
--path.procfs=/host/proc \
--path.sysfs=/host/sys
Then add that host to your Prometheus scrape config and reload Prometheus.
Setting Up Alerts
Grafana can send alerts to Discord, Slack, Telegram, or email when metrics cross thresholds. Go to Alerting > Contact Points to configure a notification channel, then set alert rules on any dashboard panel.
Useful alerts to start with:
- Disk usage over 80%
- Memory usage over 90%
- Container down (cadvisor stops reporting a container you care about)
- CPU sustained above 95% for 5+ minutes
The Practical Value
Once this is running, you stop guessing. You see that your backup job pegs CPU every night at 2am. You notice that one container leaks memory slowly over a week. You catch a disk filling up with enough time to do something about it.
That’s the actual benefit — not the pretty graphs, but the awareness. You know what normal looks like, which means you notice when something isn’t normal.
The whole stack runs comfortably on 512MB RAM. It’s one of the best uses of spare resources in any homelab.