Monitoring Your Homelab with Grafana and Prometheus
Stop guessing what is happening inside your servers. This guide sets up Grafana and Prometheus to monitor your Proxmox nodes and Docker containers in real time.
If you have been running a homelab for a while, you reach a point where guessing what is happening inside your servers gets old. Is that Proxmox node running hot? Which Docker container is hogging memory? Is your network link saturated? Without monitoring, you are flying blind.
Grafana and Prometheus fix that. Together they give you a proper dashboard showing real-time metrics from your Proxmox nodes, Docker containers, and anything else you care about. Once it is set up, you will wonder how you managed without it.
This guide covers a complete monitoring stack using Docker Compose, pulling metrics from Proxmox nodes via node_exporter and Docker containers via cAdvisor, then visualising everything in Grafana.
How It Works
Before diving in, it helps to understand what each component does:
- Prometheus is the database. It scrapes metrics from various exporters on a schedule and stores them as time-series data.
- node_exporter runs on each server you want to monitor and exposes hardware and OS metrics (CPU, memory, disk, network) that Prometheus collects.
- cAdvisor exposes per-container metrics (CPU, memory, network, disk I/O) from Docker. Prometheus scrapes this too.
- Grafana is the dashboard. It connects to Prometheus as a data source and lets you build and import visual dashboards.
The flow is simple: exporters expose metrics, Prometheus collects them, Grafana displays them.
Step 1: Set Up the Directory Structure
On your monitoring VM, create a folder for the stack:
mkdir -p ~/monitoring/prometheus
cd ~/monitoringYou will need two files before starting: a Docker Compose file and a Prometheus configuration file.
Step 2: Create the Prometheus Config
Prometheus needs to know where to scrape metrics from. Create the config file:
nano ~/monitoring/prometheus/prometheus.ymlPaste the following, replacing the IP addresses with your actual server IPs:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node_exporter'
static_configs:
- targets:
- '192.168.1.101:9100' # Proxmox node 1
- '192.168.1.102:9100' # Proxmox node 2
- '192.168.1.103:9100' # Proxmox node 3
- '192.168.1.104:9100' # Proxmox node 4
labels:
environment: 'homelab'
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']Step 3: Create the Docker Compose File
nano ~/monitoring/docker-compose.ymlservices:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
user: "1000:1000"
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
ports:
- "9090:9090"
networks:
- monitoring
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
user: "1000:1000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=changeme
- GF_USERS_ALLOW_SIGN_UP=false
ports:
- "3000:3000"
networks:
- monitoring
depends_on:
- prometheus
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
privileged: true
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
ports:
- "8080:8080"
networks:
- monitoring
volumes:
prometheus_data:
grafana_data:
networks:
monitoring:
driver: bridgeStep 4: Install node_exporter on Each Proxmox Node
node_exporter runs directly on the host, not in a container. You need to install it on each Proxmox node you want to monitor. Run the following on each node via SSH:
# Download the latest node_exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
# Extract it
tar xvf node_exporter-1.8.2.linux-amd64.tar.gz
# Move the binary
sudo mv node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/
# Clean up
rm -rf node_exporter-1.8.2.linux-amd64*Now create a systemd service so it runs automatically on boot:
sudo nano /etc/systemd/system/node_exporter.service[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
Type=simple
User=nobody
ExecStart=/usr/local/bin/node_exporter
Restart=on-failure
[Install]
WantedBy=multi-user.targetEnable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable node_exporter
sudo systemctl start node_exporterVerify it is working:
curl http://localhost:9100/metrics | head -20You should see a wall of metrics. Repeat this on every Proxmox node you want to monitor.
Step 5: Start the Monitoring Stack
Back on your monitoring VM:
cd ~/monitoring
docker compose up -dCheck everything started correctly:
docker compose psAll three containers (prometheus, grafana, cadvisor) should show as running. Give it 30 seconds, then check that Prometheus is scraping your targets by opening the Prometheus web interface:
http://YOUR_VM_IP:9090/targetsEach target should show State: UP. If any show DOWN, double-check the IP addresses in prometheus.yml and that node_exporter is running on those hosts.
Step 6: Set Up Grafana
Open Grafana in your browser:
http://YOUR_VM_IP:3000Log in with the admin credentials you set in the Compose file. The first thing to do is add Prometheus as a data source.
Add Prometheus as a Data Source
- Go to Connections in the left sidebar
- Click Data sources
- Click Add data source
- Select Prometheus
- Set the URL to
http://prometheus:9090(using the container name since they are on the same Docker network) - Click Save and test
You should see a green confirmation message. Grafana can now query Prometheus.
Import Pre-Built Dashboards
Rather than building dashboards from scratch, import community dashboards. Grafana's dashboard library has excellent ones ready to go.
For node_exporter (server hardware metrics):
- Go to Dashboards and click New, then Import
- Enter dashboard ID 1860 (Node Exporter Full) and click Load
- Select your Prometheus data source
- Click Import
For cAdvisor (Docker container metrics):
- Import dashboard ID 14282 (Cadvisor Exporter)
- Select your Prometheus data source and import
Within minutes you should have a full dashboard showing CPU, memory, disk, and network metrics for every node and container in your homelab.
Step 7: Configure Alerting (Optional)
Dashboards are useful, but alerts are what make monitoring genuinely valuable. Grafana can notify you when something goes wrong, via email, Telegram, Slack, and more.
To set up a Telegram alert:
- Go to Alerting in the left sidebar
- Click Contact points
- Click Add contact point
- Choose Telegram as the integration
- Enter your Telegram bot token and chat ID
- Click Test to verify it works, then Save
You can then create alert rules on any panel, for example alerting if CPU usage stays above 90% for more than 5 minutes, or if disk space drops below 10%.
Useful Management Commands
# View logs
docker compose logs -f prometheus
docker compose logs -f grafana
# Restart the stack
docker compose restart
# Stop everything
docker compose down
# Update images
docker compose pull
docker compose up -d
# Check Prometheus targets
curl http://localhost:9090/api/v1/targets | python3 -m json.toolWhat You Should Have Now
- Prometheus collecting metrics from all your Proxmox nodes every 15 seconds
- cAdvisor feeding Docker container metrics into Prometheus
- Grafana dashboards showing CPU, memory, disk, and network in real time
- 30 days of metric history stored on disk
- Optional Telegram alerts when things go wrong
Once you have this running, you start noticing things you never would have caught otherwise. Which container is slowly leaking memory over a week. Which Proxmox node runs 5 degrees hotter than the others. When your disk is going to fill up. That kind of visibility changes how you manage a homelab.
Next Steps
- Add more exporters — there are exporters for almost everything. Useful ones for a homelab include pihole-exporter, Unifi exporter, and Speedtest Tracker
- Increase retention — change
--storage.tsdb.retention.time=30dto keep longer history, or add--storage.tsdb.retention.size=10GBto cap it by disk usage - Expose via reverse proxy — rather than accessing Grafana on port 3000, put it behind Nginx Proxy Manager with a proper domain and SSL certificate