From 05630eb4d46491e8bb2b327bedcf294e5c0861b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Sun, 8 Feb 2026 21:02:28 +0100 Subject: [PATCH] grafana: add Proxmox dashboard Dashboard for monitoring Proxmox VMs: - Summary stats: VMs running/stopped, node CPU/memory, uptime - VM status table with name, status, CPU%, memory%, uptime - VM CPU usage over time - VM memory usage over time - Network traffic (RX/TX) per VM - Disk I/O (read/write) per VM - Storage usage gauges and capacity table - VM filter to focus on specific VMs Filters out template VMs, shows only actual guests. Co-Authored-By: Claude Opus 4.5 --- services/grafana/dashboards/proxmox.json | 605 +++++++++++++++++++++++ 1 file changed, 605 insertions(+) create mode 100644 services/grafana/dashboards/proxmox.json diff --git a/services/grafana/dashboards/proxmox.json b/services/grafana/dashboards/proxmox.json new file mode 100644 index 0000000..ffba8a0 --- /dev/null +++ b/services/grafana/dashboards/proxmox.json @@ -0,0 +1,605 @@ +{ + "uid": "proxmox-homelab", + "title": "Proxmox - Homelab", + "tags": ["proxmox", "virtualization", "homelab"], + "timezone": "browser", + "schemaVersion": 39, + "version": 1, + "refresh": "30s", + "time": { + "from": "now-6h", + "to": "now" + }, + "templating": { + "list": [ + { + "name": "vm", + "type": "query", + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "query": "label_values(pve_guest_info{template=\"0\"}, name)", + "refresh": 2, + "includeAll": true, + "multi": true, + "current": {"text": "All", "value": "$__all"} + } + ] + }, + "panels": [ + { + "id": 1, + "title": "VMs Running", + "type": "stat", + "gridPos": {"h": 4, "w": 4, "x": 0, "y": 0}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "count(pve_up{id=~\"qemu/.*\"} * on(id) pve_guest_info{template=\"0\"} == 1)", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [{"color": "green", "value": null}] + } + } + }, + "options": { + "reduceOptions": {"calcs": ["lastNotNull"]}, + "colorMode": "value", + "graphMode": "none" + } + }, + { + "id": 2, + "title": "VMs Stopped", + "type": "stat", + "gridPos": {"h": 4, "w": 4, "x": 4, "y": 0}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "count(pve_up{id=~\"qemu/.*\"} * on(id) pve_guest_info{template=\"0\"} == 0)", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [ + {"color": "green", "value": null}, + {"color": "yellow", "value": 1}, + {"color": "red", "value": 3} + ] + }, + "noValue": "0" + } + }, + "options": { + "reduceOptions": {"calcs": ["lastNotNull"]}, + "colorMode": "value", + "graphMode": "none" + } + }, + { + "id": 3, + "title": "Node CPU", + "type": "gauge", + "gridPos": {"h": 4, "w": 4, "x": 8, "y": 0}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "pve_cpu_usage_ratio{id=~\"node/.*\"} * 100", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + {"color": "green", "value": null}, + {"color": "yellow", "value": 70}, + {"color": "red", "value": 90} + ] + } + } + }, + "options": { + "reduceOptions": {"calcs": ["lastNotNull"]}, + "showThresholdLabels": false, + "showThresholdMarkers": true + } + }, + { + "id": 4, + "title": "Node Memory", + "type": "gauge", + "gridPos": {"h": 4, "w": 4, "x": 12, "y": 0}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "pve_memory_usage_bytes{id=~\"node/.*\"} / pve_memory_size_bytes{id=~\"node/.*\"} * 100", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + {"color": "green", "value": null}, + {"color": "yellow", "value": 70}, + {"color": "red", "value": 90} + ] + } + } + }, + "options": { + "reduceOptions": {"calcs": ["lastNotNull"]}, + "showThresholdLabels": false, + "showThresholdMarkers": true + } + }, + { + "id": 5, + "title": "Node Uptime", + "type": "stat", + "gridPos": {"h": 4, "w": 4, "x": 16, "y": 0}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "pve_uptime_seconds{id=~\"node/.*\"}", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "unit": "s", + "thresholds": { + "mode": "absolute", + "steps": [{"color": "blue", "value": null}] + } + } + }, + "options": { + "reduceOptions": {"calcs": ["lastNotNull"]}, + "colorMode": "value", + "graphMode": "none" + } + }, + { + "id": 6, + "title": "Templates", + "type": "stat", + "gridPos": {"h": 4, "w": 4, "x": 20, "y": 0}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "count(pve_guest_info{template=\"1\"})", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "thresholds": { + "mode": "absolute", + "steps": [{"color": "purple", "value": null}] + } + } + }, + "options": { + "reduceOptions": {"calcs": ["lastNotNull"]}, + "colorMode": "value", + "graphMode": "none" + } + }, + { + "id": 7, + "title": "VM Status", + "type": "table", + "gridPos": {"h": 10, "w": 24, "x": 0, "y": 4}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "pve_guest_info{template=\"0\", name=~\"$vm\"}", + "format": "table", + "instant": true, + "refId": "info" + }, + { + "expr": "pve_up{id=~\"qemu/.*\"} * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"}", + "format": "table", + "instant": true, + "refId": "status" + }, + { + "expr": "pve_cpu_usage_ratio{id=~\"qemu/.*\"} * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"} * 100", + "format": "table", + "instant": true, + "refId": "cpu" + }, + { + "expr": "pve_memory_usage_bytes{id=~\"qemu/.*\"} * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"} / on(id) pve_memory_size_bytes * 100", + "format": "table", + "instant": true, + "refId": "mem" + }, + { + "expr": "pve_uptime_seconds{id=~\"qemu/.*\"} * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"}", + "format": "table", + "instant": true, + "refId": "uptime" + } + ], + "fieldConfig": { + "defaults": {}, + "overrides": [ + { + "matcher": {"id": "byName", "options": "Name"}, + "properties": [{"id": "custom.width", "value": 150}] + }, + { + "matcher": {"id": "byName", "options": "Status"}, + "properties": [ + {"id": "custom.width", "value": 80}, + {"id": "mappings", "value": [ + {"type": "value", "options": {"0": {"text": "Stopped", "color": "red"}}}, + {"type": "value", "options": {"1": {"text": "Running", "color": "green"}}} + ]}, + {"id": "custom.cellOptions", "value": {"type": "color-text"}} + ] + }, + { + "matcher": {"id": "byName", "options": "CPU %"}, + "properties": [ + {"id": "unit", "value": "percent"}, + {"id": "decimals", "value": 1}, + {"id": "custom.width", "value": 80}, + {"id": "custom.cellOptions", "value": {"type": "gauge", "mode": "basic"}}, + {"id": "min", "value": 0}, + {"id": "max", "value": 100}, + {"id": "thresholds", "value": {"mode": "absolute", "steps": [{"color": "green", "value": null}, {"color": "yellow", "value": 50}, {"color": "red", "value": 80}]}} + ] + }, + { + "matcher": {"id": "byName", "options": "Memory %"}, + "properties": [ + {"id": "unit", "value": "percent"}, + {"id": "decimals", "value": 1}, + {"id": "custom.width", "value": 100}, + {"id": "custom.cellOptions", "value": {"type": "gauge", "mode": "basic"}}, + {"id": "min", "value": 0}, + {"id": "max", "value": 100}, + {"id": "thresholds", "value": {"mode": "absolute", "steps": [{"color": "green", "value": null}, {"color": "yellow", "value": 70}, {"color": "red", "value": 90}]}} + ] + }, + { + "matcher": {"id": "byName", "options": "Uptime"}, + "properties": [ + {"id": "unit", "value": "s"}, + {"id": "custom.width", "value": 100} + ] + }, + { + "matcher": {"id": "byName", "options": "ID"}, + "properties": [{"id": "custom.width", "value": 90}] + } + ] + }, + "options": { + "showHeader": true, + "sortBy": [{"displayName": "Name", "desc": false}] + }, + "transformations": [ + { + "id": "joinByField", + "options": {"byField": "name", "mode": "outer"} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Time 1": true, + "Time 2": true, + "Time 3": true, + "Time 4": true, + "Value #info": true, + "id 1": true, + "id 2": true, + "id 3": true, + "id 4": true, + "instance": true, + "instance 1": true, + "instance 2": true, + "instance 3": true, + "instance 4": true, + "job": true, + "job 1": true, + "job 2": true, + "job 3": true, + "job 4": true, + "name 1": true, + "name 2": true, + "name 3": true, + "name 4": true, + "node": true, + "tags": true, + "template": true, + "type": true + }, + "indexByName": { + "name": 0, + "id": 1, + "Value #status": 2, + "Value #cpu": 3, + "Value #mem": 4, + "Value #uptime": 5 + }, + "renameByName": { + "name": "Name", + "id": "ID", + "Value #status": "Status", + "Value #cpu": "CPU %", + "Value #mem": "Memory %", + "Value #uptime": "Uptime" + } + } + } + ] + }, + { + "id": 8, + "title": "VM CPU Usage", + "type": "timeseries", + "gridPos": {"h": 8, "w": 12, "x": 0, "y": 14}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "pve_cpu_usage_ratio{id=~\"qemu/.*\"} * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"} * 100", + "legendFormat": "{{name}}", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "custom": { + "lineWidth": 1, + "fillOpacity": 10, + "showPoints": "never" + } + } + }, + "options": { + "legend": {"displayMode": "list", "placement": "bottom"}, + "tooltip": {"mode": "multi", "sort": "desc"} + } + }, + { + "id": 9, + "title": "VM Memory Usage", + "type": "timeseries", + "gridPos": {"h": 8, "w": 12, "x": 12, "y": 14}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "pve_memory_usage_bytes{id=~\"qemu/.*\"} * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"}", + "legendFormat": "{{name}}", + "refId": "A" + } + ], + "fieldConfig": { + "defaults": { + "unit": "bytes", + "min": 0, + "custom": { + "lineWidth": 1, + "fillOpacity": 10, + "showPoints": "never" + } + } + }, + "options": { + "legend": {"displayMode": "list", "placement": "bottom"}, + "tooltip": {"mode": "multi", "sort": "desc"} + } + }, + { + "id": 10, + "title": "VM Network Traffic", + "type": "timeseries", + "gridPos": {"h": 8, "w": 12, "x": 0, "y": 22}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "rate(pve_network_receive_bytes{id=~\"qemu/.*\"}[5m]) * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"}", + "legendFormat": "{{name}} RX", + "refId": "A" + }, + { + "expr": "-rate(pve_network_transmit_bytes{id=~\"qemu/.*\"}[5m]) * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"}", + "legendFormat": "{{name}} TX", + "refId": "B" + } + ], + "fieldConfig": { + "defaults": { + "unit": "Bps", + "custom": { + "lineWidth": 1, + "fillOpacity": 10, + "showPoints": "never" + } + } + }, + "options": { + "legend": {"displayMode": "list", "placement": "bottom"}, + "tooltip": {"mode": "multi", "sort": "desc"} + } + }, + { + "id": 11, + "title": "VM Disk I/O", + "type": "timeseries", + "gridPos": {"h": 8, "w": 12, "x": 12, "y": 22}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "rate(pve_disk_read_bytes{id=~\"qemu/.*\"}[5m]) * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"}", + "legendFormat": "{{name}} Read", + "refId": "A" + }, + { + "expr": "-rate(pve_disk_write_bytes{id=~\"qemu/.*\"}[5m]) * on(id) group_left(name) pve_guest_info{template=\"0\", name=~\"$vm\"}", + "legendFormat": "{{name}} Write", + "refId": "B" + } + ], + "fieldConfig": { + "defaults": { + "unit": "Bps", + "custom": { + "lineWidth": 1, + "fillOpacity": 10, + "showPoints": "never" + } + } + }, + "options": { + "legend": {"displayMode": "list", "placement": "bottom"}, + "tooltip": {"mode": "multi", "sort": "desc"} + } + }, + { + "id": 12, + "title": "Storage Usage", + "type": "bargauge", + "gridPos": {"h": 6, "w": 12, "x": 0, "y": 30}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "pve_disk_usage_bytes{id=~\"storage/.*\"} / pve_disk_size_bytes{id=~\"storage/.*\"} * 100", + "legendFormat": "{{id}}", + "refId": "A", + "instant": true + } + ], + "fieldConfig": { + "defaults": { + "unit": "percent", + "min": 0, + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + {"color": "green", "value": null}, + {"color": "yellow", "value": 70}, + {"color": "red", "value": 85} + ] + } + } + }, + "options": { + "reduceOptions": {"calcs": ["lastNotNull"]}, + "orientation": "horizontal", + "displayMode": "gradient", + "showUnfilled": true + }, + "transformations": [ + { + "id": "renameByRegex", + "options": { + "regex": "storage/pve1/(.*)", + "renamePattern": "$1" + } + } + ] + }, + { + "id": 13, + "title": "Storage Capacity", + "type": "table", + "gridPos": {"h": 6, "w": 12, "x": 12, "y": 30}, + "datasource": {"type": "prometheus", "uid": "prometheus"}, + "targets": [ + { + "expr": "pve_disk_size_bytes{id=~\"storage/.*\"}", + "format": "table", + "instant": true, + "refId": "size" + }, + { + "expr": "pve_disk_usage_bytes{id=~\"storage/.*\"}", + "format": "table", + "instant": true, + "refId": "used" + }, + { + "expr": "pve_disk_size_bytes{id=~\"storage/.*\"} - pve_disk_usage_bytes{id=~\"storage/.*\"}", + "format": "table", + "instant": true, + "refId": "free" + } + ], + "fieldConfig": { + "defaults": { + "unit": "bytes" + }, + "overrides": [ + { + "matcher": {"id": "byName", "options": "Storage"}, + "properties": [{"id": "unit", "value": "none"}] + } + ] + }, + "options": { + "showHeader": true + }, + "transformations": [ + { + "id": "joinByField", + "options": {"byField": "id", "mode": "outer"} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Time 1": true, + "Time 2": true, + "instance": true, + "instance 1": true, + "instance 2": true, + "job": true, + "job 1": true, + "job 2": true + }, + "renameByName": { + "id": "Storage", + "Value #size": "Total", + "Value #used": "Used", + "Value #free": "Free" + } + } + }, + { + "id": "renameByRegex", + "options": { + "regex": "storage/pve1/(.*)", + "renamePattern": "$1" + } + } + ] + } + ] +}