Selama ini pemantauan homelab saya cuma berdua: SSH dan menebak. Setiap ada VM yang terasa lambat, saya masuk ke mesin yang salah lebih dulu, buka htop, keluar, lalu coba mesin berikutnya. Begitu komposisinya bertambah jadi satu Docker host, dua node Proxmox, dan beberapa VM lain, cara seperti ini tidak bisa dipertahankan lagi.
Solusinya adalah monitoring stack. Prometheus bertugas mengumpulkan metrik dari semua mesin, Grafana menampilkan metrik tersebut sebagai grafik dan dashboard, dan Alertmanager memberi tahu saya kalau ada nilai yang melewati ambang batas, misalnya disk hampir penuh. Semua komponennya berjalan sebagai container Docker di satu mesin, sedangkan mesin yang dipantau cukup menjalankan satu exporter ringan.
Artikel ini memandu proses setup dari nol sampai jadi, termasuk bagian yang sering dilewati tutorial lain: menarik metrik Proxmox VE langsung dari API-nya menggunakan PVE Exporter. Semua konfigurasi di sini ditulis dan diuji memakai Prometheus 3.15.1 dan Grafana OSS 13.3.0, dua versi stabil per November 2026. Untuk Anda yang baru pertama kali menyentuh Prometheus atau Grafana, cukup ikuti langkahnya secara berurutan karena setiap langkah menyiapkan file yang dibutuhkan langkah berikutnya.
Apa yang Akan Kita Bangun #
Ada enam container yang berjalan di satu jaringan Docker:
| Container | Tugas | Port |
|---|---|---|
| prometheus | Menarik dan menyimpan metrik | 9090 |
| grafana | Dashboard dan visualisasi | 3000 |
| node-exporter | Metrik hardware dan OS | 9100 |
| cadvisor | Metrik per-container Docker | 8080 |
| alertmanager | Pengirim notifikasi alert | 9093 |
| pve-exporter | Metrik Proxmox VE via API | 9221 |
Prometheus bekerja dengan model pull. Setiap 15 detik dia mengunjungi URL /metrics di setiap target, lalu menyimpan angka yang ditemukan. Exporter adalah program kecil yang tugasnya menyediakan angka itu: node-exporter melaporkan CPU, memori, dan disk sebuah mesin; cadvisor melaporkan statistik per-container; dan pve-exporter bertanya ke API Proxmox lalu menerjemahkan jawabannya ke format Prometheus. Grafana sendiri tidak menyimpan apa pun, dia hanya menampilkan hasil query ke Prometheus.
flowchart LR
subgraph SOURCES["Mesin & Layanan (Target Pantau)"]
direction TB
NE["Node Exporter
(Host, VM, PVE Nodes)
:9100"]
CAD["cAdvisor
(Container Docker)
:8080"]
PVE["Proxmox VE Cluster
(API Status)"]
end
PVEEXP["pve-exporter
:9221"]
PVE -->|API Token| PVEEXP
subgraph CORE["Monitoring Stack (Docker)"]
direction TB
PROM["Prometheus
:9090
(Scrape & TSDB)"]
end
NE -->|Pull /metrics| PROM
CAD -->|Pull /metrics| PROM
PVEEXP -->|Pull /pve| PROM
subgraph OUTPUT["Visualisasi & Notifikasi"]
direction TB
GRAF["Grafana
:3000
(Dashboard)"]
AM["Alertmanager
:9093"]
NOTIF["Notifikasi
(Telegram / Discord / Webhook)"]
end
PROM -->|PromQL Query| GRAF
PROM -->|Kirim Alert| AM
AM --> NOTIF
style PROM fill:#e6522c,stroke:#333,stroke-width:1px,color:#fff
style GRAF fill:#f46800,stroke:#333,stroke-width:1px,color:#fff
Persiapan dan Prasyarat #
- Satu mesin Linux dengan Docker dan Docker Compose terpasang. Minimal 2 core CPU dan 4 GB RAM supaya nyaman.
- Akses SSH ke mesin tersebut, serta ke mesin lain yang mau dipantau.
- Minimal satu node Proxmox VE jika ingin mengikuti bagian PVE. Cukup akses web UI, tidak perlu menyentuh CLI Proxmox.
- Waktu sekitar satu jam, sebagian besar untuk mengetik file konfigurasi dan menunggu image terunduh.
Langkah 1. Membuat Struktur Folder Proyek #
mkdir -p monitoring-stack/prometheus monitoring-stack/alertmanager monitoring-stack/grafana/provisioning/datasources
cd monitoring-stackSetiap folder punya satu tugas:
prometheus/menyimpanprometheus.ymldanalert_rules.ymlalertmanager/menyimpanalertmanager.ymlgrafana/provisioning/datasources/bisa diisi file yang mendaftarkan data source Prometheus secara otomatis
Penalaran Teknis: File konfigurasi sengaja diletakkan di luar container. Dengan begitu kita bisa mengeditnya dengan editor biasa lalu me-reload Prometheus tanpa build ulang apa pun.
Langkah 2. Konfigurasi Prometheus #
Buat file prometheus/prometheus.yml dengan isi berikut, dan ganti alamat IP-nya dengan milik Anda:
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
rule_files:
- "alert_rules.yml"
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "node-exporter"
static_configs:
- targets: ["node-exporter:9100", "10.1.1.20:9100", "10.1.1.10:9100", "10.1.1.200:9100", "100.114.62.179:9100"]
- job_name: "cadvisor"
static_configs:
- targets: ["cadvisor:8080"]
- job_name: "pve"
static_configs:
- targets:
- 10.1.1.20 # Proxmox VE node 1
- 10.1.1.10 # Proxmox VE node 2
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 # PVE exporterSatu file kecil lagi supaya Prometheus bisa langsung start. Isinya baru kita lengkapi di Langkah 10:
echo "groups: []" > prometheus/alert_rules.ymlPenalaran Teknis: Ada tiga hal penting di file di atas:
- Di dalam jaringan Docker, container saling menghubungi lewat nama service. Target
node-exporter:9100adalah container dari compose kita sendiri, jadi dia otomatis memantau Docker host-nya. - Target berupa IP adalah mesin lain yang menjalankan node exporter secara native, bukan lewat Docker. Contoh di atas memantau dua node Proxmox di
10.1.1.20dan10.1.1.10, satu VM di10.1.1.200, dan satu mesin kecil yang saya akses lewat VPN (makanya IP-nya diawali100.). Sesuaikan semuanya dengan alamat Anda. - Job
pvememang terlihat aneh, tapi logikanya sederhana. Prometheus tidak pernah menghubungi kedua IP node itu secara langsung. Tiga barisrelabel_configsmenulis ulang alamat scrape sehingga request yang sebenarnya dikirim kepve-exporter:9221, dengan alamat node dibawa sebagai parameter. Satu container pve-exporter jadi melayani semua node Proxmox, dan tiap node tetap punya labelinstancesendiri.
Blok alerting dan rule_files merujuk ke Alertmanager serta file aturan alert yang akan kita buat di langkah-langkah berikutnya.
Langkah 3. Persiapan Node Proxmox #
Di sini ada dua pekerjaan, dan keduanya dilakukan di sisi Proxmox, bukan di Docker. Pertama, tiap node Proxmox memasang node exporter dari repositori Debian. Kedua, kita membuat API token supaya pve-exporter boleh membaca data cluster.
Memasang Node Exporter di Tiap Node #
SSH ke setiap node Proxmox lalu jalankan:
apt update
apt install prometheus-node-exporterPaket ini otomatis berjalan sebagai service systemd dan menyajikan metrik di port 9100. Verifikasi singkat:
systemctl status prometheus-node-exporter
curl -s localhost:9100/metrics | headItulah alasan job node-exporter di prometheus.yml mendaftarkan IP node dengan port 9100. Tidak perlu Docker di sisi Proxmox, paket apt saja sudah cukup.
Membuat User dan API Token #
PVE Exporter mengambil data lewat API Proxmox, jadi dia butuh token dengan izin baca. Berikut langkahnya di web UI:
- Buka Datacenter > Permissions > Users, klik Add. Beri nama
grafanadengan realm Linux PAM, sehingga identitasnya menjadigrafana@pam.

- Lanjut ke Datacenter > Permissions > API Tokens, klik Add. Pilih user
grafana@pam, isi Token ID dengangrafana, dan biarkan opsi Privilege separation tidak dicentang supaya token mewarisi izin user-nya.

-
Setelah dialog tertutup, rahasia token berupa deretan UUID ditampilkan sekali saja. Salin dan simpan dulu karena tidak bisa dilihat lagi nanti.
-
Terakhir, beri izin baca. Buka Datacenter > Permissions > Add > User Permission, isi Path dengan
/, pilih usergrafana@pam, dan role PVEAuditor.

Penalaran Teknis: Izin yang dipasang di level Datacenter (path /) berlaku untuk semua node dalam cluster. Dua node saya ada dalam satu cluster, jadi satu token grafana@pam sudah mencakup 10.1.1.20 dan 10.1.1.10 sekaligus. Kalau node Anda berdiri sendiri-sendiri (tidak di-cluster), ulangi langkah user, token, dan permission ini di masing-masing node.
File Kredensial pve.yml #
Buat file pve.yml di root proyek:
default:
username: grafana@pam
token_name: grafana
token_value: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
verify_ssl: falseGanti token_value dengan rahasia yang tadi disalin. Nilai verify_ssl: false biasanya diperlukan di homelab karena sertifikat Proxmox umumnya self-signed.
Langkah 4. Menulis File Docker Compose #
Buat compose.yml di root proyek. Versi image sudah disesuaikan dengan rilis stabil terbaru, Prometheus v3.15.1 dan Grafana 13.3.0:
services:
prometheus:
image: prom/prometheus:v3.15.1
container_name: prometheus
volumes:
- ./prometheus:/etc/prometheus
- prometheus-data:/prometheus
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.retention.time=15d"
ports:
- "9090:9090"
restart: unless-stopped
networks:
- frontend
grafana:
image: grafana/grafana-oss:13.3.0
container_name: grafana
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=changeme_now
restart: unless-stopped
networks:
- frontend
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
pid: host
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- "--path.rootfs=/rootfs"
ports:
- "9100:9100"
restart: unless-stopped
networks:
- frontend
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8080:8080"
restart: unless-stopped
networks:
- frontend
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
volumes:
- ./alertmanager:/etc/alertmanager
ports:
- "9093:9093"
restart: unless-stopped
networks:
- frontend
pve-exporter:
image: prompve/prometheus-pve-exporter
container_name: pve-exporter
volumes:
- ./pve.yml:/etc/prometheus/pve.yml
ports:
- "9221:9221"
environment:
- PROXMOX_VE_USERNAME=grafana@pam
- PROXMOX_VE_TOKEN_NAME=grafana
- PROXMOX_VE_TOKEN_VALUE=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
restart: unless-stopped
networks:
- frontend
volumes:
prometheus-data:
grafana-data:
networks:
frontend:
external: trueBeberapa hal yang perlu dicatat dari file di atas:
- Ganti
GF_SECURITY_ADMIN_PASSWORDsebelum stack pertama kali dijalankan. - Dua named volume (
prometheus-datadangrafana-data) menjaga data tetap hidup antar restart. Tanpa itu, semua data hilang setiapdocker compose down. - Environment di service
pve-exporterberisi kredensial yang sama denganpve.yml. Kalau keduanya berbeda, environment variable yang menang, jadi pilih salah satu sebagai sumber utama dan jaga tetap sinkron. - Node exporter berjalan dengan
pid: hostdan beberapa mount read-only supaya bisa melihat proses dan filesystem asli host, bukan isi container-nya. Cadvisor butuh mount serupa untuk memeriksa container lain. --storage.tsdb.retention.time=15dberarti Prometheus menyimpan data 15 hari. Kalau disk terbatas, kecilkan nilainya atau tambahkan--storage.tsdb.retention.size.
Tentang jaringan frontend: saya memakai jaringan Docker eksternal yang sudah ada sebelumnya di homelab saya, jaringan yang sama dengan yang dibuat di artikel Traefik saya. Kalau Anda belum punya, buat dulu dengan docker network create frontend, atau hapus saja semua blok networks: di atas dan biarkan Compose membuat jaringan bawaan untuk proyek ini.
Langkah 5. Konfigurasi Alertmanager #
Buat alertmanager/alertmanager.yml:
route:
group_by: ["alertname"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: default-webhook
receivers:
- name: default-webhook
webhook_configs:
- url: http://contoh-webhook-anda/
send_resolved: trueBagian route menentukan bagaimana alert dikelompokkan dan dikirim. Alert dengan nama sama digabung jadi satu notifikasi lewat group_by, ada tunggu 30 detik sebelum pengiriman pertama (group_wait), dan alert yang masih aktif dikirim ulang tiap 4 jam (repeat_interval). Receiver di contoh ini berupa webhook. Nanti bisa diganti dengan Telegram, Discord, atau email, format konfigurasinya ada di dokumentasi resmi Alertmanager.
Selama belum ada alert yang aktif, Alertmanager tidak mengirim apa pun, jadi URL webhook placeholder seperti di atas tidak masalah untuk saat ini.
Langkah 6. Menjalankan Stack #
docker compose up -d
docker compose psHarusnya muncul enam container dengan status Up. Container yang stuck di Restarting hampir selalu berarti ada volume yang mengarah ke file yang tidak ada. Periksa kembali jalurnya, pelakunya paling sering adalah pve.yml yang lupa dibuat.

Langkah 7. Memeriksa Target di Prometheus #
Buka http://localhost:9090/targets (ganti localhost dengan IP mesin kalau Anda browsing dari laptop). Harusnya ada sembilan target hijau: Prometheus sendiri, lima instance node-exporter, cadvisor, dan dua entri pve, satu per node Proxmox. Entri pve menampilkan IP node, bukan IP exporter, sebagai efek dari relabel di Langkah 2.

Target yang DOWN biasanya berarti IP salah, exporter-nya tidak jalan di mesin tersebut, atau ada firewall di antaranya. Klik targetnya untuk melihat pesan error-nya.
Langkah 8. Menghubungkan Grafana ke Prometheus #
Masuk ke http://localhost:3000 dengan user admin dan password yang tadi diset di compose. Buka Connections > Data sources > Add data source, pilih Prometheus, isi URL dengan http://prometheus:9090, lalu klik Save & Test.
http://prometheus:9090, bukan localhost. Grafana berjalan di container-nya sendiri, dan localhost di dalam container itu menunjuk ke Grafana-nya sendiri, bukan ke Prometheus. Ini kesalahan paling umum pemula.

Kalau ingin data source terdaftar otomatis tanpa klik, buat grafana/provisioning/datasources/prometheus.yml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: trueDengan file ini sudah ada sebelum stack pertama kali dijalankan, data source langsung tersedia begitu Grafana start.
Langkah 9. Membangun Dashboard Grafana #
Panel pertama sebaiknya dicoba manual supaya konsep dasarnya paham. Buat dashboard baru lewat Dashboards > New > Add visualization, pilih data source Prometheus, lalu isi query:
rate(node_cpu_seconds_total{mode="idle"}[5m])Query ini menghitung seberapa cepat waktu CPU idle berlalu dalam lima menit terakhir per core. Semakin sibuk mesin, semakin kecil nilainya.
Setelah itu, dashboard komunitas jauh lebih praktis. Buka Dashboards > Import dan masukkan ID berikut:
- 1860, Node Exporter Full (halaman dashboard): tampilan lengkap satu mesin, dari CPU, memori, disk, sampai jaringan. Setelah import, pilih mesinnya dari dropdown Host. Semua mesin di job
node-exportermuncul di sana, baik yang terpasang via apt maupun yang berjalan sebagai container. - 893, Docker and System Monitoring (halaman dashboard): tampilan per-container dari data cadvisor.
- 10347, Proxmox via Prometheus (halaman dashboard): tampilan cluster dan node Proxmox dari data pve-exporter.


Langkah 10. Aturan Alert #
Sekarang lengkapi prometheus/alert_rules.yml yang tadi masih berupa placeholder:
groups:
- name: host-alerts
rules:
- alert: HighCPUUsage
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
description: "CPU usage has been above 85% for 5 minutes on {{ $labels.instance }}."
- alert: LowDiskSpace
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10
for: 10m
labels:
severity: critical
annotations:
summary: "Low disk space on {{ $labels.instance }}"
description: "Root filesystem free space is below 10% on {{ $labels.instance }}."Aturan pertama membalik angka idle tadi menjadi persentase pemakaian CPU per mesin (avg by (instance)), lalu memicu alert kalau nilainya di atas 85%. Kalimat for: 5m artinya kondisi harus bertahan lima menit sebelum alert dianggap sah. Inilah yang mencegah kita diganggu karena lonjakan CPU sesaat. Aturan kedua memantau sisa ruang filesystem root dan masuk kriteria kritis kalau di bawah 10% selama sepuluh menit.
Terapkan tanpa restart:
curl -X POST http://localhost:9090/-/reloadCek http://localhost:9090/alerts, keduanya harus muncul dengan status Inactive. Siklus hidupnya: Inactive (aman), Pending (kondisi terpenuhi tapi durasi for belum genap), lalu Firing (alert dikirim ke Alertmanager).

Kesalahan yang Sering Terjadi #
- Pakai
localhostdi target atau data source. Di dalam jaringan container,localhostmenunjuk ke container itu sendiri. Pakai nama service atau IP mesin. - Melewatkan named volume. Tanpa volume, semua data metrik dan dashboard hilang setiap
docker compose down. - Password default Grafana dibiarkan. Terutama kalau port 3000 bisa dijangkau dari luar.
- Tidak memantau pertumbuhan disk. Prometheus terus menulis data selama 15 hari. Perhatikan ukuran volume
prometheus-data, atau kecilkan retention. - Edit rule tapi tidak reload. Perubahan
alert_rules.ymlbaru berlaku setelah endpoint/-/reloaddipanggil atau container di-restart. - Mencampur angka node exporter dan cadvisor. Yang satu angka host, yang satu angka container. Memori terpakai 90% di cadvisor adalah pemakaian container, bukan mesinnya.
- Alert tanpa
for. Tanpa durasi, lonjakan sesaat langsung jadi notifikasi.
Troubleshooting Cepat #
| Gejala | Kemungkinan penyebab | Cek pertama |
|---|---|---|
Target DOWN di /targets |
Exporter tidak jalan atau IP/port salah | docker compose ps, lalu curl ke /metrics dari sisi Prometheus |
Panel Grafana No data |
URL data source pakai localhost |
Ganti ke http://prometheus:9090 |
| cAdvisor langsung exit | Ada mount yang tidak lengkap | Bandingkan blok volumes dengan contoh di atas |
| pve-exporter restart terus | pve.yml tidak ada atau token salah |
docker logs pve-exporter |
| Alertmanager tidak mau start | YAML tidak valid | docker logs alertmanager, atau validasi dengan amtool check-config |
| Error YAML di Prometheus | Typo di prometheus.yml |
docker logs prometheus, pesannya menyebut baris persisnya |
Pertanyaan yang Sering Diajukan #
Apakah Prometheus dan Grafana gratis? Ya, keduanya open source dan bisa dijalankan di server sendiri tanpa biaya lisensi. Yang Anda bayar hanyalah hardware yang menjalankannya.
Berapa RAM yang dibutuhkan? Untuk skala di artikel ini, 4 GB RAM dan 2 core sudah nyaman. Pemakaian bertambah seiring jumlah target yang dipantau dan panjang retention.
Apakah Grafana bisa jalan tanpa Prometheus? Bisa. Grafana mendukung banyak data source lain seperti Loki, InfluxDB, sampai database SQL. Prometheus hanya salah satu pilihan yang paling umum untuk metrik.
Bagaimana kalau mesin utamanya Windows? Docker Desktop dengan backend WSL 2 bisa menjalankan stack ini. Catatannya, node exporter tidak bisa melaporkan metrik host Windows dengan benar, jadi angka CPU dan memori Windows host-nya tidak akurat.
Berapa lama data disimpan? Di konfigurasi artikel ini 15 hari, sesuai flag --storage.tsdb.retention.time=15d. Naikkan atau turunkan sesuai kapasitas disk. Data lama tidak hilang saat upgrade selama named volume-nya tidak dihapus.
Penutup #
Sekarang semua mesin di homelab, container Docker, sampai cluster Proxmox bisa dipantau dari satu halaman Grafana, dan ada dua alert yang berjaga kalau CPU atau disk bermasalah. Langkah berikutnya yang wajar: ganti receiver webhook Alertmanager dengan notifikasi yang benar-benar Anda baca, tambahkan exporter untuk aplikasi tertentu, dan sesuaikan retention dengan kapasitas disk.
Kalau ada langkah yang macet atau hasilnya berbeda dari yang ditulis, ceritakan di komentar, saya bantu cek.