How to Monitor VPS Performance with Grafana and Prometheus

How to Monitor VPS Performance with Grafana and Prometheus

UptimeRobot tells you if your site is up or down. Netdata shows you what’s happening right now. But Grafana + Prometheus answers the harder questions: Why did the server slow down last Tuesday at 2 AM? What was the memory trend over the past 30 days before the OOM crash? Which API endpoint is consuming the most CPU over time?

This guide sets up a complete Prometheus + Grafana monitoring stack on your VPS: metric collection with Node Exporter, long-term storage in Prometheus, beautiful dashboards in Grafana, and alerting when things go wrong.

The Monitoring Stack

Component Role
Node Exporter Exposes Linux server metrics (CPU, RAM, disk, network) as HTTP endpoints
Prometheus Time-series database that scrapes and stores metrics
Grafana Visualization layer β€” turns Prometheus data into dashboards
Alertmanager Routes alerts (email, Telegram, PagerDuty) when thresholds are breached

πŸ’‘ Resource note: The full stack uses ~300–500 MB RAM. Run it on a dedicated monitoring VPS or alongside other apps on a 4 GB+ plan. View VPS Plans β†’


Step 1: Install Node Exporter (on each server to monitor)

NODE_EXPORTER_VERSION="1.8.2"

wget https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz
tar xvfz node_exporter-*.tar.gz
sudo mv node_exporter-*/node_exporter /usr/local/bin/
sudo useradd -rs /bin/false node_exporter
sudo nano /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
After=network.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter \
  --collector.systemd \
  --collector.processes
Restart=always

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

# Verify metrics are being exported
curl http://localhost:9100/metrics | head -20

Secure Node Exporter (don’t expose publicly)

# Node Exporter should only be accessible locally or via SSH tunnel
# Add to UFW: allow only from Prometheus server IP
sudo ufw allow from PROMETHEUS_SERVER_IP to any port 9100

Step 2: Install Prometheus

PROMETHEUS_VERSION="2.54.1"

wget https://github.com/prometheus/prometheus/releases/download/v${PROMETHEUS_VERSION}/prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz
tar xvfz prometheus-*.tar.gz
sudo mv prometheus-*/prometheus /usr/local/bin/
sudo mv prometheus-*/promtool  /usr/local/bin/

sudo useradd -rs /bin/false prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /var/lib/prometheus

Configure Prometheus

sudo nano /etc/prometheus/prometheus.yml
global:
  scrape_interval:     15s   # How often to collect metrics
  evaluation_interval: 15s   # How often to evaluate alert rules

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - localhost:9093

rule_files:
  - "/etc/prometheus/alerts/*.yml"

scrape_configs:
  # Monitor the Prometheus server itself
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Monitor this VPS (local Node Exporter)
  - job_name: 'vps-main'
    static_configs:
      - targets: ['localhost:9100']
        labels:
          server: 'main-vps'
          location: 'usa'

  # Monitor additional VPS instances
  - job_name: 'vps-hk'
    static_configs:
      - targets: ['HK_VPS_IP:9100']
        labels:
          server: 'hk-vps'
          location: 'hong-kong'

  - job_name: 'vps-backup'
    static_configs:
      - targets: ['BACKUP_VPS_IP:9100']
        labels:
          server: 'backup-vps'
          location: 'usa'

Create Prometheus systemd service

sudo nano /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus Monitoring
After=network.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 \
  --storage.tsdb.retention.time=30d \
  --web.listen-address=127.0.0.1:9090
Restart=always

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

Step 3: Install Grafana

sudo apt install -y apt-transport-https software-properties-common wget
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update && sudo apt install grafana -y

sudo systemctl enable grafana-server
sudo systemctl start grafana-server

Expose Grafana via Nginx with SSL

sudo nano /etc/nginx/sites-available/grafana
server {
    listen 80;
    server_name monitor.yourdomain.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name monitor.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/monitor.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/monitor.yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
sudo ln -s /etc/nginx/sites-available/grafana /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d monitor.yourdomain.com

Step 4: Configure Grafana

First login

  1. Open https://monitor.yourdomain.com
  2. Login with admin / admin β†’ change password immediately

Add Prometheus as a data source

  1. Grafana β†’ Connections β†’ Data sources β†’ Add data source
  2. Select Prometheus
  3. URL: http://localhost:9090
  4. Click Save & test β€” should show “Successfully queried the Prometheus API”

Import the Node Exporter Full dashboard

  1. Grafana β†’ Dashboards β†’ Import
  2. Enter dashboard ID: 1860 (Node Exporter Full β€” most popular community dashboard)
  3. Select your Prometheus data source
  4. Click Import

You now have a professional server monitoring dashboard showing CPU usage, memory, disk I/O, network traffic, system load, and more β€” all with historical data going back 30 days. βœ…


Step 5: Create Custom Dashboards

Key PromQL queries for VPS monitoring

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

# Memory usage percentage
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

# Disk usage percentage for root partition
(1 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})) * 100

# Network receive rate (bytes per second)
rate(node_network_receive_bytes_total{device="eth0"}[5m])

# Number of open file descriptors
node_filefd_allocated

# Load average (1-minute)
node_load1

Step 6: Set Up Alerting

Install Alertmanager

ALERTMANAGER_VERSION="0.27.0"

wget https://github.com/prometheus/alertmanager/releases/download/v${ALERTMANAGER_VERSION}/alertmanager-${ALERTMANAGER_VERSION}.linux-amd64.tar.gz
tar xvfz alertmanager-*.tar.gz
sudo mv alertmanager-*/alertmanager /usr/local/bin/
sudo mv alertmanager-*/amtool /usr/local/bin/
sudo mkdir -p /etc/alertmanager
sudo nano /etc/alertmanager/alertmanager.yml
global:
  smtp_from: 'alerts@yourdomain.com'
  smtp_smarthost: 'smtp.gmail.com:587'
  smtp_auth_username: 'alerts@yourdomain.com'
  smtp_auth_password: 'your-app-password'

route:
  group_by: ['alertname', 'server']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'email-alerts'

receivers:
  - name: 'email-alerts'
    email_configs:
      - to: 'you@yourdomain.com'
        send_resolved: true

Create alert rules

sudo mkdir -p /etc/prometheus/alerts
sudo nano /etc/prometheus/alerts/vps.yml
groups:
  - name: vps_alerts
    rules:
      # High CPU alert
      - 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 is {{ $value }}% (threshold: 85%)"

      # High memory alert
      - alert: HighMemoryUsage
        expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "High memory usage on {{ $labels.instance }}"
          description: "Memory usage is {{ $value }}%"

      # Disk space alert
      - alert: DiskSpaceLow
        expr: (1 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"})) * 100 > 80
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Low disk space on {{ $labels.instance }}"
          description: "Disk is {{ $value }}% full"

      # Server down alert
      - alert: ServerDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Server {{ $labels.instance }} is down"
sudo systemctl restart prometheus

Step 7: Add Telegram Alerting

sudo nano /etc/alertmanager/alertmanager.yml
receivers:
  - name: 'telegram-alerts'
    telegram_configs:
      - bot_token: 'YOUR_TELEGRAM_BOT_TOKEN'
        chat_id: YOUR_CHAT_ID
        message: |
          🚨 *{{ .Status | toUpper }}*: {{ .CommonLabels.alertname }}
          Server: {{ .CommonLabels.instance }}
          {{ .CommonAnnotations.description }}

Step 8: Monitor Multiple Servers

The real power of Prometheus is monitoring your entire infrastructure from one place. Install Node Exporter on every VPS, add them to prometheus.yml, and they all appear in your Grafana dashboards with server labels for easy filtering.

# In prometheus.yml, add each new server:
  - job_name: 'client-server-1'
    static_configs:
      - targets: ['CLIENT_IP:9100']
        labels:
          server: 'client-1'
          environment: 'production'

Create a Grafana variable called $server to filter dashboards by server β€” switch between monitoring your USA VPS, HK VPS, and client servers with a single dropdown.


Final Thoughts

Prometheus + Grafana is the industry standard for infrastructure monitoring precisely because it scales from one VPS to thousands of servers without changing the architecture. The 30-day metric retention lets you analyze trends and diagnose past incidents. The alerting pipeline ensures you’re notified before problems become outages.

Fast β€’ Reliable β€’ Affordable VPS - DO It Now!

Get top VPS hosting with VPS.DO’s fast, low-cost plans. Try risk-free with our 7-day no-questions-asked refund and start today!