VPS

VPS Monitoring Setup with Prometheus and Grafana

Updated: October 2, 2026  ·  ~12 min read
Grafana dashboard showing VPS CPU RAM Disk metrics

Why Monitor Your VPS

When your website or application slows down or crashes, the first question is: "What happened?" Without monitoring, you're flying blind — forced to SSH in and run top or df -h manually, with no historical context to understand what led up to the problem.

Prometheus + Grafana is the most widely adopted self-hosted monitoring stack in production environments. It installs on any VPS for free and gives you deeper visibility than expensive SaaS monitoring tools.

MetricToolWhy It Matters
CPU usageNode Exporter → PrometheusCatch spikes before users notice
RAM free/usedNode Exporter → PrometheusPlan upgrades based on real data
Disk I/O & usageNode Exporter → PrometheusPrevent disk-full that corrupts databases
Network trafficNode Exporter → PrometheusDetect unusual traffic or early DDoS
Custom app metricsClient library → PrometheusTrack request rate and error rates

Prometheus + Grafana Architecture

Before installing, understand the components:

Basic architecture: Target VPS (Node Exporter:9100) → Prometheus:9090 → Grafana:3000 — this guide runs everything on a single VPS, suitable for 2+ GB RAM instances.

Installing Prometheus

Download and install Prometheus on Ubuntu 22.04:

# Create a dedicated system user
sudo useradd --no-create-home --shell /bin/false prometheus

# Create directories
sudo mkdir /etc/prometheus /var/lib/prometheus

# Download Prometheus (check latest version at github.com/prometheus/prometheus)
PROM_VER="2.53.0"
wget https://github.com/prometheus/prometheus/releases/download/v${PROM_VER}/prometheus-${PROM_VER}.linux-amd64.tar.gz
tar -xzf prometheus-${PROM_VER}.linux-amd64.tar.gz
cd prometheus-${PROM_VER}.linux-amd64/

# Copy binaries
sudo cp prometheus /usr/local/bin/
sudo cp promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool

# Copy config files
sudo cp -r consoles/ /etc/prometheus/
sudo cp -r console_libraries/ /etc/prometheus/
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus

Create the initial config file

sudo nano /etc/prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']

Create a systemd service

sudo nano /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
  --config.file /etc/prometheus/prometheus.yml \
  --storage.tsdb.path /var/lib/prometheus/ \
  --web.console.templates=/etc/prometheus/consoles \
  --web.console.libraries=/etc/prometheus/console_libraries \
  --storage.tsdb.retention.time=30d

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable prometheus
sudo systemctl start prometheus
sudo systemctl status prometheus

Installing Node Exporter

Node Exporter collects OS-level metrics — CPU, RAM, Disk, Network:

NODE_VER="1.8.1"
wget https://github.com/prometheus/node_exporter/releases/download/v${NODE_VER}/node_exporter-${NODE_VER}.linux-amd64.tar.gz
tar -xzf node_exporter-${NODE_VER}.linux-amd64.tar.gz
sudo cp node_exporter-${NODE_VER}.linux-amd64/node_exporter /usr/local/bin/

sudo useradd --no-create-home --shell /bin/false node_exporter

sudo nano /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable node_exporter
sudo systemctl start node_exporter

Verify Node Exporter is running: curl http://localhost:9100/metrics | head -20

Configuring Prometheus Scrape Jobs

The prometheus.yml config above already targets localhost:9100. Verify Node Exporter is being scraped by visiting the Prometheus UI:

Open browser: http://YOUR_VPS_IP:9090 → Status → Targets → the node endpoint should show UP

Try these example queries in the Prometheus UI Expression box:

# CPU usage (%)
100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# RAM used (bytes)
node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes

# Disk usage (%)
(node_filesystem_size_bytes - node_filesystem_free_bytes) / node_filesystem_size_bytes * 100

Installing Grafana

Grafana can be installed from the official apt repository:

sudo apt-get install -y apt-transport-https software-properties-common wget
wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/grafana.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list

sudo apt-get update
sudo apt-get install -y grafana

sudo systemctl daemon-reload
sudo systemctl enable grafana-server
sudo systemctl start grafana-server

Open http://YOUR_VPS_IP:3000 in your browser → log in with admin / admin → you'll be prompted to change the password immediately.

Creating Your First Dashboard

Connect Prometheus as a Grafana data source:

  1. In Grafana UI → Connections → Data sources → Add data source → select Prometheus
  2. URL: http://localhost:9090 → Save & test → should show "Data source is working"
  3. Import a ready-made dashboard → Dashboards → Import → enter ID 1860 → Load → select your Prometheus data source → Import
Dashboard ID 1860 is "Node Exporter Full" — the most downloaded dashboard on Grafana.com. It instantly shows CPU, RAM, Disk, Network, and Load Average with no manual query writing.
Panel in Dashboard 1860Data Shown
CPU BasicUser, System, IOWait, Idle %
Memory BasicTotal, Used, Free, Buffers/Cache
Disk Space Used %Usage % per partition
Network TrafficReceived/Transmitted bytes/s
System Load1m, 5m, 15m load average
Disk I/ORead/Write bytes/s

Setting Up CPU/RAM Alerts

Add alert rules to Prometheus to trigger notifications when thresholds are exceeded:

sudo nano /etc/prometheus/alert.rules.yml
groups:
- name: node_alerts
  rules:
  - alert: HighCPU
    expr: 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "High CPU {{ $value }}%"
      description: "Instance {{ $labels.instance }} CPU usage above 85% for 5 minutes"

  - alert: LowMemory
    expr: (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 < 15
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "Low RAM {{ $value }}% available"
      description: "Instance {{ $labels.instance }} has less than 15% available RAM"

  - alert: DiskAlmostFull
    expr: (node_filesystem_size_bytes - node_filesystem_free_bytes) / node_filesystem_size_bytes * 100 > 85
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "Disk {{ $value }}% used"
      description: "Disk on {{ $labels.instance }} ({{ $labels.mountpoint }}) is {{ $value }}% full"

Add the rule file to prometheus.yml:

rule_files:
  - "/etc/prometheus/alert.rules.yml"
sudo systemctl reload prometheus

Security — Firewall and Basic Auth

By default, Prometheus (9090) and Node Exporter (9100) are accessible from any IP. Lock them down:

# Block external access to Prometheus and Node Exporter
sudo ufw deny 9090
sudo ufw deny 9100
# Or allow only your own IP
sudo ufw allow from YOUR_OFFICE_IP to any port 9090
Tip: Use SSH tunneling instead of opening port 9090: ssh -L 9090:localhost:9090 user@YOUR_VPS_IP then open http://localhost:9090 on your local machine. Much safer than exposing the port publicly.

Grafana authentication settings

sudo nano /etc/grafana/grafana.ini

[auth.anonymous]
enabled = false

[security]
admin_password = YOUR_STRONG_PASSWORD

Summary

You now have a complete self-hosted monitoring stack. Here's what was set up:

With this setup, you have the historical data to make informed scaling decisions — no more guessing when to upgrade. If you need a VPS with enough resources to run Prometheus + Grafana alongside your application, see AsiaGB VPS packages.

Need a VPS for Your Monitoring Stack?

AsiaGB VPS features SSD storage, 99% uptime, and Ubuntu 20.04/22.04/24.04 — ready to deploy in minutes.

View VPS Packages

FAQ

What is the difference between Prometheus and Grafana?

Prometheus is a time-series database that collects and stores metrics. Grafana is a visualization platform that reads from Prometheus and renders the data as interactive dashboards. They complement each other perfectly.

What is Node Exporter?

Node Exporter is a lightweight agent that runs on Linux and exposes OS-level metrics via an HTTP endpoint on port 9100. Prometheus scrapes this endpoint periodically to collect CPU, RAM, Disk, and Network data.

How much RAM does this stack need?

Prometheus + Grafana + Node Exporter combined use approximately 400-600 MB of RAM. A VPS with at least 2 GB RAM is recommended for comfortable operation alongside your main workload.

Can I send alerts to Slack or LINE Notify?

Yes — Alertmanager supports Slack natively. For LINE Notify, use a webhook receiver in Alertmanager or configure a notification channel in Grafana Alerting, which has direct LINE Notify support.

Is Dashboard ID 1860 usable right away?

Yes — just import it by ID from Grafana's dashboard library, select Prometheus as the data source, and you get a fully functional CPU, RAM, Disk, and Network dashboard with no manual query configuration.

How long does Prometheus retain data?

The default retention period is 15 days. Extend it with --storage.tsdb.retention.time=30d. Typical disk usage for 30-day retention is 2-5 GB depending on the number of tracked metrics.