FTC disclosure: This article contains affiliate links. If you purchase through these links, we may earn a commission at no additional cost to you.
Documentation basis: This rewrite is grounded in the Proxmox external metric server documentation, the Prometheus getting-started documentation, and the Grafana fundamentals documentation. The goal is to explain exporter, retention, and dashboard roles clearly before anyone starts scraping metrics.
How to Monitor Proxmox with Grafana and Prometheus: Build a Small Metrics Stack That Surfaces Host Pressure
Monitor Proxmox with Prometheus and Grafana by exposing node metrics, storing time series cleanly, and building dashboards that show host pressure before performance drifts.

Proxmox monitoring becomes more useful once you treat it as a history problem, not just a dashboard problem. A live web UI can show current CPU or RAM use, but it does not automatically preserve the trend lines that explain why a node keeps feeling slow during backups, replication, or noisy-neighbor bursts.
A small metrics stack solves that by separating responsibilities: exporters expose host data, Prometheus stores time-series history, and Grafana turns that history into graphs and alerts a human can review quickly.
This page helps a homelab operator choose a lightweight monitoring path for Proxmox and understand which components matter before adding dashboards, alerts, and longer-term retention.

Create the user and token
SSH into one Proxmox node as root and create a dedicated user:
pveum user add prometheus@pve --comment "Prometheus metrics collector"
pveum aclmod / -user prometheus@pve -role PVEAuditor
pveum user token add prometheus@pve monitoring -privsep 0
That last command prints the token value once. Save it immediately in your password manager or a local secrets file that is not committed anywhere.
Your final credential set will look like this:
- User:
prometheus@pve - Token name:
monitoring - Token value:
your-long-token-value
Verify the idea, not just the command
The goal here is simple:
- the user has the
PVEAuditorrole - the permission path is
/ - the token exists and can read cluster information
If you are newer to Proxmox permissions, this is the same principle I recommend in my SSH hardening guide: give services only the access they need, then stop.
Step 2 - Create the monitoring stack files
Why this matters
Before you run containers, it helps to make the stack layout predictable. Otherwise, a week from now you will be staring at a folder called monitoring-final-v2-actual and wondering what past-you was trying to prove.
Create a working directory on your Docker host:
mkdir -p ~/proxmox-monitoring/prometheus
mkdir -p ~/proxmox-monitoring/grafana/provisioning/datasources
mkdir -p ~/proxmox-monitoring/pve
cd ~/proxmox-monitoring
Now create this docker-compose.yml file:
services:
pve-exporter:
image: prompve/prometheus-pve-exporter:latest
container_name: pve-exporter
restart: unless-stopped
ports:
- "127.0.0.1:9221:9221"
volumes:
- ./pve/pve.yml:/etc/prometheus/pve.yml:ro
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --web.enable-lifecycle
ports:
- "9090:9090"
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
depends_on:
- pve-exporter
grafana:
image: grafana/grafana-oss:latest
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources:ro
depends_on:
- prometheus
volumes:
prometheus_data:
grafana_data:
A couple of notes:
- I bind the exporter to
127.0.0.1:9221so it is not exposed to the whole LAN by default. - Prometheus and Grafana can be exposed to your LAN, but I still recommend putting them behind a reverse proxy later if you want remote access. If you need that piece, my Nginx Proxy Manager guide walks through the basics.
Step 3 - Configure the Proxmox exporter
Why this matters
The exporter is the translator between Prometheus and Proxmox. Prometheus cannot scrape the Proxmox API directly in the format Grafana expects for these dashboards. The exporter handles that translation for you.
Create ~/proxmox-monitoring/pve/pve.yml:
default:
user: prometheus@pve
token_name: monitoring
token_value: YOUR_LONG_TOKEN_VALUE
verify_ssl: false
Replace YOUR_LONG_TOKEN_VALUE with the actual token value from Step 1.
What could go wrong
If your Proxmox node uses a self-signed certificate, verify_ssl: false is usually the quickest beginner path. Long term, I prefer trusted certificates, but there is no point pretending every homelab starts there.
If you already use valid certificates, set this instead:
verify_ssl: true
Step 4 - Configure Prometheus scraping
Why this matters
Prometheus needs to know where metrics live, how often to collect them, and how to label them. This is where a lot of "Grafana shows nothing" problems actually start.
Create ~/proxmox-monitoring/prometheus/prometheus.yml:
global:
scrape_interval: 30s
evaluation_interval: 30s
scrape_configs:
- job_name: prometheus
static_configs:
- targets:
- localhost:9090
- job_name: pve
static_configs:
- targets:
- 192.168.1.10
metrics_path: /pve
params:
module: [default]
cluster: ['1']
node: ['1']
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: pve-exporter:9221
Replace 192.168.1.10 with the IP or hostname of your Proxmox node.
If you have a cluster, list each Proxmox node under targets:
- targets:
- 192.168.1.10
- 192.168.1.11
- 192.168.1.12
This configuration follows the exporter project pattern where Prometheus sends the Proxmox node as the target parameter and the exporter does the API call on its behalf.
Step 5 - Provision the Grafana datasource
Why this matters
You can add the datasource by hand in the UI. I still prefer provisioning it in a file because it makes rebuilds painless. If you redeploy the stack later, Grafana comes back with the datasource ready instead of making you click through the same screens again.
Create ~/proxmox-monitoring/grafana/provisioning/datasources/prometheus.yml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: true
Step 6 - Start the stack
Why this matters
Now we move from configuration to proof. The point is not just to start containers. The point is to confirm each layer works before you pile the next layer on top.
Launch the stack:
cd ~/proxmox-monitoring
docker compose up -d
Check container status:
docker compose ps
Then follow the logs if something looks off:
docker compose logs -f pve-exporter
docker compose logs -f prometheus
docker compose logs -f grafana
Verify the exporter first
From the Docker host, test the exporter endpoint:
curl -s http://127.0.0.1:9221/metrics | head
You should see exporter self-metrics. Then test the Proxmox-backed endpoint through Prometheus later, but this quick check confirms the container is alive.
Verify Prometheus targets
Open Prometheus at http://YOUR-DOCKER-HOST:9090/targets.
You want to see the pve target as UP. If it is DOWN, do not move to Grafana yet. Fix the scrape first.
This step saves time because Grafana is just a mirror here. If Prometheus has nothing, Grafana will faithfully visualize nothing (which is a very honest failure mode, to be fair).
Step 7 - Import the Proxmox Grafana dashboard
Why this matters
Grafana without a dashboard is just a very polished blank page. The easiest starting point is the public Proxmox dashboard with ID 10347 from Grafana Labs.
Open Grafana at http://YOUR-DOCKER-HOST:3000.
Default login:
- Username:
admin - Password:
admin
Grafana will ask you to change the password on first login.
Then import dashboard ID 10347:
- Go to Dashboards
- Click New -> Import
- Enter
10347 - Choose the
Prometheusdatasource - Finish the import
That dashboard is a good beginner starting point because it covers:
- node CPU and memory
- storage allocation and usage
- guest CPU, memory, disk IO, and network IO
- historical trends that the Proxmox UI does not keep front and center
Step 8 - Check that the graphs mean something
Why this matters
A dashboard full of moving lines feels impressive, but the real question is whether it helps you catch useful problems. I like to do a quick sanity test right after setup.
Try one or two controlled changes:
# On a busy VM or container host
apt update
# Or generate a little disk activity on a test VM
fio --name=randread --rw=randread --bs=4k --size=256M --runtime=60 --time_based
Then watch whether:
- CPU changes on the correct node
- IO appears where you expect
- guest graphs line up with your test workload
If the graphs move in the wrong place, you probably have a target or instance-label mismatch.
Common mistakes
1. Using an admin account instead of a monitoring account
You do not need full admin rights for metrics. Use PVEAuditor and keep it boring.
2. Importing the dashboard before Prometheus targets are up
This wastes time. Always verify http://YOUR-HOST:9090/targets first.
3. Forgetting to replace the Proxmox target IP in prometheus.yml
I have seen people copy a config, stand up the stack, and then wonder why Grafana is still blank. It turns out they were scraping somebody else's example IP. Computers are ruthless about details.
4. Leaving the exporter open on all interfaces
Bind it to 127.0.0.1 unless you have a good reason not to. Metrics endpoints should not be casually exposed.
5. Blaming Grafana for a Prometheus problem
If Prometheus does not scrape the exporter successfully, Grafana cannot rescue the situation. Check the stack in this order:
- Proxmox token and permissions
- exporter container logs
- Prometheus target status
- Grafana datasource
- imported dashboard settings
Troubleshooting checklist
If the dashboard shows no data, walk through these checks in order:
# Is the exporter container running?
docker compose ps
# Does the exporter respond locally?
curl -s http://127.0.0.1:9221/metrics | head
# Can Prometheus see the config you expect?
docker compose exec prometheus cat /etc/prometheus/prometheus.yml
# Reload Prometheus after config changes if needed
curl -X POST http://localhost:9090/-/reload
Then confirm in the UI:
- Prometheus -> Status -> Targets ->
pveis UP - Grafana -> Connections -> Data sources ->
Prometheusis healthy - Imported dashboard is using the same datasource you configured
If you want a broader monitoring foundation after this, my article on homelab monitoring with Prometheus and Grafana expands the stack beyond Proxmox specifically. And if you are building Docker-based services next, these Docker Compose best practices will save you some future cleanup.
FAQ
Do I need to run Grafana and Prometheus on the Proxmox host itself?
No. In most homelabs, I prefer a separate VM or Docker host. It keeps the monitoring stack isolated and makes maintenance easier.
Can I use a password instead of an API token?
Yes, but I do not recommend it if token auth is available. Tokens are cleaner, easier to rotate, and generally a better habit.
Should I monitor every Proxmox node separately?
Yes. If you have multiple nodes, add each node as a target in Prometheus so you get complete node-level visibility.
What if my Proxmox node uses a self-signed certificate?
Use verify_ssl: false in pve.yml as the short-term fix. Long term, trusted certificates are the better answer.
Is this enough for alerting too?
It is enough to get started with visibility. Once the data is flowing, you can add Prometheus alert rules or an Alertmanager stack later.
What to learn next
Once you have Proxmox metrics working, the next useful improvements are:
- add node exporter on important Linux VMs for OS-level metrics
- monitor your backup jobs and storage pool health
- put Grafana behind HTTPS and SSO
- build a few simple alerts for disk exhaustion, host memory pressure, and guest downtime
For official references, keep these handy:
- prometheus-pve-exporter GitHub project
- Grafana dashboard 10347 for Proxmox via Prometheus
- Prometheus configuration documentation
If you came into this feeling overwhelmed by the terminology, that is normal. The trick is to stop treating monitoring like one giant product and start treating it like a small chain of jobs. Proxmox exposes data. The exporter translates it. Prometheus stores it. Grafana shows it. Once that clicks, the setup becomes much easier to manage.
And once you have historical graphs for your cluster, a whole category of weird homelab problems stops feeling mysterious. Which is nice, because the homelab will always invent new ways to be weird.
article_topic // How to Monitor Proxmox with Grafana and Prometheus
Start building a smarter homelab.
Join readers learning Proxmox, networking, storage, backups, and self-hosting without breaking everything.
Enter your email address to receive the Homelab Addiction newsletter.
Beginner-friendly
No gatekeeping. Just clear, actionable guides.
1 useful email / week
Practical tips, real-world setups, and lessons learned.
Zero hype, practical only
What works, what breaks, and how to fix it.
Reply to any email with what you're building.
I read and reply to as many as I can.
— The Homelab Addiction Operator
support // the lab
Found this guide useful?
If it saved you time or a rebuild, you can support more practical homelab guides.