Server kamu down jam 2 pagi, dan yang kasih tahu bukan alerting system kamu — tapi user yang nge-DM "mas, appnya error". Kalau pernah ngalamin ini, berarti kamu butuh monitoring tools untuk self-hosted infrastructure yang proper, bukan sekadar uptime command yang kamu jalanin manual.
Artikel ini bahas setup monitoring yang gue pakai sendiri di VPS-VPS gue: dari metrics collection, alerting, sampai dashboard yang bisa dibuka dari HP. Semua self-hosted, semua gratis, dan semua bisa kamu replikasi dalam satu sore.
Kenapa Monitoring Self-Hosted Itu Nyebelin Kalau Salah Setup
Problem pertama: banyak orang install Prometheus + Grafana, terus bingung kenapa dashboard-nya kosong. Atau install Netdata, tapi alert-nya nggak pernah nyampe karena konfigurasi notifikasi salah.
Problem kedua: monitoring tools yang "enterprise-ready" sering overly complex untuk kebutuhan solo dev atau tim kecil. Kamu nggak butuh 47 microservice hanya untuk tahu apakah RAM kamu penuh.
Jadi gue bakal kasih stack yang proporsional: cukup powerful untuk production, cukup simpel untuk di-maintain sendiri.
Stack yang Gue Pakai: Prometheus + Grafana + Alertmanager
Ini stack paling battle-tested untuk WordPress object cache dan monitoring tools untuk self-hosted infrastructure. Bukan yang paling mudah di-setup pertama kali, tapi paling fleksibel jangka panjang.
Komponen:
- Prometheus — scrape dan simpan metrics
- Node Exporter — expose system metrics dari host
- Grafana — dashboard dan visualisasi
- Alertmanager — routing alert ke Telegram/email
Gue pakai Docker Compose supaya gampang di-manage. Ini docker-compose.yml yang langsung jalan:
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=15d'
ports:
- '9090:9090'
restart: unless-stopped
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
ports:
- '9100:9100'
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=gantipasswordini
- GF_USERS_ALLOW_SIGN_UP=false
ports:
- '3000:3000'
restart: unless-stopped
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
ports:
- '9093:9093'
restart: unless-stopped
volumes:
prometheus_data:
grafana_data:
Buat file prometheus.yml di folder yang sama:
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']
rule_files:
- 'alert_rules.yml'
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100']
Jalankan dengan:
docker compose up -d
Setelah ini, Grafana bisa diakses di http://IP_SERVER:3000. Login dengan admin dan password yang kamu set di environment variable tadi.
Setup Alert ke Telegram (Ini yang Paling Penting)
Dashboard cantik nggak ada gunanya kalau kamu nggak tahu server down. Gue pakai Telegram karena notification-nya reliable dan bisa diakses dari HP tanpa install app tambahan.
Pertama, buat Telegram bot:
- Chat
@BotFatherdi Telegram - Kirim
/newbot, ikuti instruksi - Simpan token yang dikasih
- Buat grup atau channel, tambahkan bot-nya
- Cari chat ID-nya via
https://api.telegram.org/bot<TOKEN>/getUpdates
Buat file alertmanager.yml:
route:
group_by: ['alertname']
group_wait: 30s
group_interval: 5m
repeat_interval: 1h
receiver: 'telegram'
receivers:
- name: 'telegram'
telegram_configs:
- bot_token: 'TOKEN_BOT_KAMU'
chat_id: -1001234567890
message: |
{{ range .Alerts }}
*{{ .Annotations.summary }}*
{{ .Annotations.description }}
Status: {{ .Status }}
{{ end }}
parse_mode: 'Markdown'
Terus buat alert_rules.yml untuk define kapan alert dikirim:
groups:
- name: node_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: "CPU usage tinggi di {{ $labels.instance }}"
description: "CPU usage sudah {{ $value | printf \"%.2f\" }}% selama 5 menit terakhir."
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
for: 2m
labels:
severity: critical
annotations:
summary: "RAM hampir penuh di {{ $labels.instance }}"
description: "Memory usage: {{ $value | printf \"%.2f\" }}%"
- alert: DiskSpaceLow
expr: (node_filesystem_avail_bytes{mountpoint=\"/\"} / node_filesystem_size_bytes{mountpoint=\"/\"}) * 100 < 15
for: 1m
labels:
severity: critical
annotations:
summary: "Disk hampir penuh di {{ $labels.instance }}"
description: "Sisa disk: {{ $value | printf \"%.2f\" }}%"
Restart Alertmanager setelah update config:
docker compose restart alertmanager prometheus
Gotcha yang Gue Kena
Beberapa hal yang bikin gue buang waktu berjam-jam:
1. Port node-exporter nggak bisa diakses dari container Prometheus
Kalau kamu jalanin node-exporter di host network tapi Prometheus di Docker network, mereka nggak bisa saling reach dengan localhost. Solusinya: di prometheus.yml, ganti target ke IP internal Docker host:
scrape_configs:
- job_name: 'node'
static_configs:
- targets: ['172.17.0.1:9100'] # Docker bridge gateway
Atau lebih clean: tambahkan network_mode: host ke service node-exporter dan gunakan host.docker.internal kalau kamu di Docker Desktop. Di Linux production, pakai IP gateway-nya langsung.
2. Telegram chat_id salah format
Group chat ID di Telegram selalu negatif (contoh: -1001234567890). Kalau kamu pakai angka positif, alert nggak akan nyampe dan error message-nya nggak obvious. Cek ulang via API getUpdates.
3. Grafana dashboard kosong setelah restart
Kalau kamu nggak pakai volume yang persistent dan container restart, semua dashboard hilang. Pastikan grafana_data volume sudah di-define dan di-mount dengan benar. Atau export dashboard JSON-nya dan simpan di repo.
4. Prometheus storage habis
Default retention Prometheus adalah 15 hari. Di VPS dengan disk kecil, ini bisa jadi masalah. Gue set --storage.tsdb.retention.size=5GB di command Prometheus untuk limit berdasarkan ukuran, bukan waktu:
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=15d'
- '--storage.tsdb.retention.size=5GB'
Alternatif: Netdata untuk yang Mau Cepat
Kalau Prometheus + Grafana terasa terlalu banyak moving parts, Netdata adalah alternatif yang jauh lebih cepat di-setup. Install satu command, langsung dapat dashboard real-time dengan ratusan metrics.
bash <(curl -Ss https://my-netdata.io/kickstart.sh)
Netdata jalan di port 19999 dan langsung kasih visualisasi CPU, RAM, disk, network, bahkan per-process metrics tanpa konfigurasi tambahan.
Kekurangannya: untuk alerting yang sophisticated dan long-term storage, Netdata versi gratis punya limitasi. Tapi untuk quick health check dan troubleshooting real-time, ini yang paling cepat.
Monitoring Uptime dengan Uptime Kuma
Prometheus + Grafana bagus untuk system metrics, tapi untuk monitoring apakah endpoint HTTP kamu up atau down, gue pakai Uptime Kuma.
# Tambahkan ke docker-compose.yml yang sama
uptime-kuma:
image: louislam/uptime-kuma:latest
container_name: uptime-kuma
volumes:
- uptime_kuma_data:/app/data
ports:
- '3001:3001'
restart: unless-stopped
Uptime Kuma punya UI yang clean, support monitoring HTTP, TCP, ping, DNS, dan bisa kirim notifikasi ke Telegram, Discord, Slack, dan puluhan channel lain. Setup-nya lewat web UI, nggak perlu edit config file.
Buat status page publik juga bisa — berguna kalau kamu punya user yang mau tahu status service kamu tanpa harus tanya langsung.
Mengamankan Dashboard dari Internet
Jangan expose port Grafana (3000) atau Prometheus (9090) langsung ke internet tanpa proteksi. Minimal dua opsi:
Opsi 1: Basic Auth via Nginx
server {
listen 80;
server_name monitoring.domain-kamu.com;
location / {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
}
}
Buat password file:
sudo htpasswd -c /etc/nginx/.htpasswd adminuser
Opsi 2: Tailscale
Cara yang lebih clean: jangan expose port sama sekali. Pasang Tailscale di server dan laptop kamu, akses monitoring lewat Tailscale IP. Zero-config, end-to-end encrypted.
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Setelah itu kamu bisa akses http://100.x.x.x:3000 dari mana saja selama device kamu ada di Tailscale network yang sama.
Yang Gue Lakuin Selanjutnya
Setup di atas sudah cukup untuk cover 80% kebutuhan monitoring tools untuk self-hosted infrastructure di skala solo dev atau tim kecil. Tapi ada beberapa hal yang masih gue explore:
- Loki + Promtail — centralized log aggregation yang terintegrasi dengan Grafana. Sekarang gue masih
docker logsmanual, yang jelas nggak scalable. - cAdvisor — untuk metrics per-container Docker yang lebih detail dari node-exporter.
- Grafana alerting — migrasi dari Alertmanager ke this guide Grafana unified alerting yang lebih modern.
Kalau kamu baru mulai, urutan yang gue rekomendasikan:
- Install Uptime Kuma dulu — paling cepat, langsung ada value.
- Tambahkan Netdata untuk real-time system metrics.
- Baru migrate ke Prometheus + Grafana kalau kamu butuh long-term data dan custom alerting.
Jangan langsung pasang semua sekaligus — kamu bakal overwhelmed dengan konfigurasi dan akhirnya nggak ada yang bener-bener jalan.