Grafana + Prometheus Metrics

← Self-Hosting · Foundations 8 of 8 · Replaces: guessing why the server feels slow

What You'll Build

The same monitoring tools that real companies use, running on your home server:

node-exporter  ──►  Prometheus  ──►  Grafana
(reads CPU, RAM,     (saves a reading    (turns the history
 disk, network)       every 15 seconds)   into dashboards)

This is also great practice for IT and security jobs — "set up Prometheus and Grafana" is a real skill employers ask for.

Ports: Grafana 3003, Prometheus 9090 · Time: 45 minutes · Difficulty: Medium

Step 1: Tell Prometheus What to Collect

mkdir -p ~/stacks/monitoring && cd ~/stacks/monitoring
nano prometheus.yml
# How often to take a reading from every target
global:
  scrape_interval: 15s

# The list of things to read metrics from
scrape_configs:
  - job_name: "prometheus"            # Prometheus monitoring itself
    static_configs:
      - targets: ["localhost:9090"]

  - job_name: "homeserver"            # the server's hardware, via node-exporter
    static_configs:
      - targets: ["node-exporter:9100"]

Step 2: The Three-Container Stack

nano compose.yaml
services:
  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    restart: unless-stopped
    command: ["--path.rootfs=/host"]   # read the real server, not the container
    pid: host
    volumes:
      - /:/host:ro,rslave

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    ports:
      - "9090:9090"
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.retention.time=30d"      # keep 30 days of history
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    ports:
      - "3003:3000"                              # 3000 is taken by Homepage
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  prometheus-data:
  grafana-data:
docker compose up -d

Check Prometheus at http://192.168.1.50:9090 → Status → Targets. Both targets should say UP.

Step 3: Connect Grafana to Prometheus

  1. Open http://192.168.1.50:3003. Log in with admin / admin; you're forced to set a new password.
  2. Connections → Data sources → Add data source → Prometheus.
  3. Prometheus server URL: http://prometheus:9090 (containers in the same stack find each other by name) → Save & test.

Step 4: Import a Ready-Made Dashboard

  1. Dashboards → New → Import.
  2. Enter dashboard ID 1860 ("Node Exporter Full", from grafana.com) → Load.
  3. Pick your Prometheus data source → Import.

You now have graphs of CPU, memory, disk space and speed, network traffic, and temperatures (if your hardware reports them). Star it so it's on your Grafana home page.

Step 5: Alert When the Disk Is Nearly Full

  1. Alerting → Contact points → Add: choose your notification method (the same ntfy topic from Uptime Kuma works via a Webhook).
  2. Alerting → Alert rules → New alert rule. Query (switch to Code mode):
# Percentage of disk space USED on the root filesystem
100 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} * 100)
  1. Condition: IS ABOVE 85, evaluate every 5m for 15m, send to your contact point → Save.

Troubleshooting

What's Next?

The foundations are done. Time for the fun part — the apps:

Browse the Self-Hosted Apps →