LinuxmonitoringTested on real hardware

Node Exporter + pve-exporter for Proxmox Metrics

Install prometheus-node-exporter on every Proxmox node and prometheus-pve-exporter with a read-only API token — the two endpoints Prometheus needs for full host and cluster metrics.

Distrosproxmox, debian
Shellbash
Updated
Script
bash
# ── Run on each Proxmox node. Placeholder: <TOKEN-SECRET> is printed
# ── by the pveum command in step 2 — copy it into pve.yml.
# ── Full stack walkthrough: /blog/node-exporter-grafana-proxmox/

# 1. Host metrics — Debian's packaged node exporter (port 9100)
apt update && apt install -y prometheus-node-exporter
systemctl enable --now prometheus-node-exporter

# 2. Read-only API user + token for the PVE exporter
pveum user add pve-exporter@pve --comment "Prometheus PVE exporter"
pveum acl modify / --users pve-exporter@pve --roles PVEAuditor
pveum user token add pve-exporter@pve monitoring --privsep 0
# ^ COPY the printed token secret now — it is shown only once

# 3. Install prometheus-pve-exporter (isolated via pipx)
apt install -y pipx
PIPX_HOME=/opt/pipx PIPX_BIN_DIR=/usr/local/bin pipx install prometheus-pve-exporter

# 4. Exporter config — paste the token secret from step 2
mkdir -p /etc/prometheus
cat > /etc/prometheus/pve.yml <<'EOF'
default:
  user: pve-exporter@pve
  token_name: monitoring
  token_value: <TOKEN-SECRET>
  verify_ssl: false
EOF
chmod 600 /etc/prometheus/pve.yml

# 5. Run it as a service (port 9221)
cat > /etc/systemd/system/pve-exporter.service <<'EOF'
[Unit]
Description=Prometheus Proxmox VE exporter
After=network.target

[Service]
ExecStart=/usr/local/bin/pve_exporter --config.file /etc/prometheus/pve.yml
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now pve-exporter

# 6. Smoke test both endpoints
curl -s localhost:9100/metrics | head -3
curl -s "localhost:9221/pve?target=localhost" | head -3

Prerequisites

  • Proxmox VE 8.x/9.x node(s), root shell
  • A Prometheus server to scrape the endpoints (the full stack guide)

Prometheus scrape config

Add both jobs on your Prometheus server — substitute your node addresses (10.0.0.x are placeholders):

- job_name: node
  static_configs:
    - targets: ['10.0.0.11:9100', '10.0.0.12:9100']

- job_name: pve
  static_configs:
    - targets: ['10.0.0.11']
  metrics_path: /pve
  params:
    module: [default]
  relabel_configs:
    - source_labels: [__address__]
      target_label: __param_target
    - source_labels: [__param_target]
      target_label: instance
    - target_label: __address__
      replacement: 10.0.0.11:9221

Notes

  • PVEAuditor is read-only — the exporter can see everything and change nothing
  • --privsep 0 gives the token the user’s full (audit-only) permissions
  • One pve-exporter per cluster is enough (it reads cluster-wide state); node-exporter goes on every node
  • Dashboards and the reasoning behind each piece: the companion guide