Yep — you can mix static targets with service discovery (SD) so you don’t have to hand-edit IPs every time. Here are the 2 SD methods that work great in a Proxmox homelab, plus how to combine them.
TL;DR
-
Keep a couple of static must-scrape targets.
-
Add file_sd (simple local YAML/JSON list you can update without touching main config).
-
Optionally add dns_sd (Prometheus discovers hosts from your DNS; great if you use OPNsense/Unbound).
Option A — file_sd_configs (recommended for homelab)
Maintain a separate file listing targets. Easy to script and reload.
prometheus.yml
scrape_configs:
Static fallback (always scrape these)
- job_name: ‘nodes-static’
static_configs:
- targets: [‘192.168.10.5:9100’] labels: role: ‘hypervisor’
Dynamic list from files (add/remove hosts here)
- job_name: ‘nodes-file-sd’
file_sd_configs:
- files:
- /etc/prometheus/targets/nodes.yml refresh_interval: 30s
- files:
/etc/prometheus/targets/nodes.yml
- targets:
- '192.168.10.20:9100' # Ubuntu server
- '192.168.10.21:9100' # Debian server
labels:
role: 'server'
- targets:
- '192.168.10.30:9100' # NAS
labels:
role: 'storage'
Edit
nodes.ymlto add/remove machines. Prometheus will pick changes automatically (every 30s) — no full restart needed.
Option B — dns_sd_configs (uses your DNS)
Let Prometheus resolve a record (A/AAAA or SRV) and scrape all returned endpoints.
A/AAAA record (simplest)
Create a DNS record (e.g., nodes.lan) that returns multiple IPs.
yaml
CopyEdit
scrape_configs: - job_name: 'nodes-dns-a' dns_sd_configs: - names: ['nodes.lan'] # returns multiple A/AAAA records type: 'A' port: 9100 refresh_interval: 30s
SRV record (more flexible; per-target ports)
Create SRV like _node-exporter._tcp.lan pointing to each node and its port.
yaml
CopyEdit
scrape_configs: - job_name: 'nodes-dns-srv' dns_sd_configs: - names: ['_node-exporter._tcp.lan'] type: 'SRV' refresh_interval: 30s
In OPNsense → Unbound, you can add A/AAAA or SRV records so adding a new node is just a DNS change.
Mix them together (static + file_sd + dns_sd)
Use all three; Prometheus will dedupe by the target address.
yaml
CopyEdit
scrape_configs: - job_name: 'nodes' scrape_interval: 15s # 1) Static “must have” targets static_configs: - targets: ['192.168.10.5:9100'] # Proxmox # 2) File-based list maintained by you/scripts file_sd_configs: - files: ['/etc/prometheus/targets/nodes.yml'] refresh_interval: 30s # 3) DNS-based discovery (A/AAAA or SRV) dns_sd_configs: - names: ['nodes.lan'] type: 'A' port: 9100 refresh_interval: 30s
(Optional) Useful relabeling
Tag instances with a friendly name or drop stray targets.
yaml
CopyEdit
- job_name: 'nodes' file_sd_configs: - files: ['/etc/prometheus/targets/nodes.yml'] relabel_configs: # If you put a custom label in file_sd (e.g., role), it’s already attached. # Here’s an example to copy the target address to a clean "instance" label: - source_labels: [__address__] target_label: instance regex: '([^:]+):.*' replacement: '$1' # Example: drop anything that isn't on port 9100 - source_labels: [__address__] regex: '.+:9100' action: keep
Reloading config safely
-
Best: enable HTTP reload and POST to it:
-
Add
--web.enable-lifecycleto Prometheus start flags. -
curl -X POST http://<prometheus-ip>:9090/-/reload
-
-
If you didn’t enable that:
systemctl restart prometheus