← All Articles

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.

dockermonitoringprometheusgrafana

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

Setting Up Grafana

Add Prometheus as a data source:

  1. Go to Connections > Data Sources > Add data source
  2. Select Prometheus
  3. URL: http://prometheus:9090
  4. Click Save & Test

Import a dashboard: Instead of building from scratch, import a community dashboard. The most popular ones for this stack:

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:

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.