
Monitoring your VPS is essential for any production workload. This guide walks you through setting up Grafana and Prometheus — the most powerful open-source monitoring stack available today. You will have a beautiful dashboard displaying real-time CPU, RAM, disk, and network metrics, with automated alerting configured in under an hour.
What Are Grafana and Prometheus
Before diving into installation, here is how these components work together:
- Prometheus — a time-series database that scrapes metrics from exporters at a defined interval (default every 15 seconds) and stores them in its internal time-series format
- Node Exporter — a lightweight agent installed on your server that collects OS-level metrics such as CPU usage, memory, disk I/O, and network traffic, exposing them on port 9100
- Grafana — a visualization platform that connects to Prometheus as a data source and renders beautiful dashboards, with built-in support for alert rules and notification channels
Data flow: Node Exporter (port 9100) → Prometheus scrape (port 9090) → Grafana visualize (port 3000)
Requirements
Ensure the following before starting:
- Ubuntu 20.04 LTS or 22.04 LTS VPS
- At least 1 GB RAM (2 GB recommended for comfortable performance)
- Ports required: 9090 (Prometheus), 3000 (Grafana), 9100 (Node Exporter — internal only)
- Root or sudo access
Install Prometheus
Download the Prometheus binary from GitHub Releases and configure a systemd service:
# Create a dedicated system user
sudo useradd --no-create-home --shell /bin/false prometheus
# Download Prometheus
PROM_VER="2.52.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 and config files
sudo cp prometheus /usr/local/bin/
sudo cp promtool /usr/local/bin/
sudo mkdir /etc/prometheus /var/lib/prometheus
sudo cp -r consoles/ console_libraries/ /etc/prometheus/
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheusCreate the systemd service file:
sudo nano /etc/systemd/system/prometheus.service[Unit]
Description=Prometheus Monitoring
After=network.target
[Service]
User=prometheus
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=0.0.0.0:9090
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable prometheus
sudo systemctl start prometheus
sudo systemctl status prometheusEssential PromQL Queries to Know
PromQL (Prometheus Query Language) is how you pull specific metrics from Prometheus for display in Grafana panels. The pre-built dashboard covers most needs, but knowing a few core queries lets you build custom panels and alert rules:
| Metric | PromQL Query | What It Shows |
|---|---|---|
| CPU Usage % | 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) | CPU % used in the last 5 minutes |
| RAM Usage % | (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 | Percentage of RAM currently in use |
| Disk Free % | (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 | Free disk space on the root partition |
| Network In | rate(node_network_receive_bytes_total{device="eth0"}[5m]) | Inbound traffic in bytes per second |
Even when using Dashboard ID 1860, understanding these query patterns is valuable for building custom panels and writing targeted alert rules.
Install Node Exporter
Node Exporter collects OS metrics and makes them available for Prometheus to scrape:
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_exportersudo nano /etc/systemd/system/node_exporter.service[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable node_exporter
sudo systemctl start node_exporterConfigure Prometheus Scrape Config
Edit /etc/prometheus/prometheus.yml so Prometheus knows to scrape from Node Exporter:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']sudo systemctl restart prometheus
# Verify at http://YOUR_VPS_IP:9090/targets
# Both targets should show status UPInstall Grafana
Use the official Grafana APT repository for convenient updates:
sudo apt-get 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-get update
sudo apt-get install -y grafana
sudo systemctl daemon-reload
sudo systemctl enable grafana-server
sudo systemctl start grafana-serverOpen your browser and navigate to http://YOUR_VPS_IP:3000. Log in with username admin and password admin. Grafana will immediately prompt you to set a new password.
Connect Grafana to Prometheus Data Source
- Go to Configuration → Data Sources
- Click Add data source and select Prometheus
- Set the URL to
http://localhost:9090 - Click Save & Test — you should see "Data source is working"
Import Dashboard Node Exporter Full (ID 1860)
Grafana.com hosts a pre-built dashboard for Node Exporter with hundreds of ready-made panels:
- Go to Dashboards → Import
- Enter Dashboard ID: 1860
- Click Load
- Select the Prometheus data source you created
- Click Import
You will instantly see a comprehensive dashboard showing CPU usage, memory utilization, disk I/O, network bandwidth, and hundreds more metrics — no PromQL queries required.
Adding Application-specific Exporters
Node Exporter covers OS-level metrics only. When your VPS runs specific services, additional exporters extend visibility down to the application layer:
- MySQL / MariaDB Exporter — tracks query throughput, slow queries, and connection pool usage
- Nginx Exporter — monitors request rate, active connections, and error rate via the stub_status module
- Blackbox Exporter — probes HTTP and TCP endpoints to verify that websites respond correctly; ideal for external health checks
- Redis Exporter — reports hit rate, memory usage, and connected client counts for Redis cache instances
Each exporter exposes metrics on its own port. Add a corresponding entry in the scrape_configs section of prometheus.yml:
# Add Nginx Exporter to scrape_configs
- job_name: 'nginx'
static_configs:
- targets: ['localhost:9113']
# Add MySQL Exporter to scrape_configs
- job_name: 'mysql'
static_configs:
- targets: ['localhost:9104']Set Up Alert Rules and Notification Channels
Configure alerts to notify you when CPU or memory usage exceeds a threshold:
Email Alerting
# Edit /etc/grafana/grafana.ini
[smtp]
enabled = true
host = smtp.gmail.com:587
user = [email protected]
password = your_app_password
from_address = [email protected]Telegram Alerting
- Create a Telegram Bot via @BotFather and obtain your Bot Token
- Go to Alerting → Contact Points → New contact point
- Select Telegram, enter your Bot Token and Chat ID
- Create an Alert Rule in any dashboard panel — for example: CPU > 85% for 5 minutes
Pro tip: Use Dashboard ID 1860 "Node Exporter Full" from Grafana.com — this pre-built dashboard contains over 200 metric graphs and requires zero PromQL configuration. It is the fastest way to get full VPS visibility up and running.
Managing Prometheus Data Retention and Backups
Prometheus stores time-series data in /var/lib/prometheus, and this directory grows over time. Planning storage from the start prevents disk-full incidents:
Adjusting the Retention Period
The systemd service configured earlier sets a 30-day retention. You can tune this based on available disk space:
# Inside prometheus.service — adjust retention as needed
--storage.tsdb.retention.time=15d # 15 days (~2–3 GB for one server)
--storage.tsdb.retention.time=90d # 90 days (~6–9 GB for one server)
--storage.tsdb.retention.size=10GB # hard size cap — auto-purges oldest dataBacking Up Prometheus Data
The cleanest approach is to trigger a snapshot via the Prometheus admin API and then sync it to off-site storage:
# Create a snapshot (requires --web.enable-admin-api flag in prometheus.service)
curl -XPOST http://localhost:9090/api/v1/admin/tsdb/snapshot
# List available snapshots
ls /var/lib/prometheus/snapshots/
# Sync to a remote backup server
rsync -avz /var/lib/prometheus/snapshots/ backup@backupserver:/prometheus-backup/Back up at least once per week and also export Grafana Dashboard JSON (Share → Export → Save to file) — Dashboard configuration is stored in Grafana's own database, not in Prometheus data.
Firewall and Security Hardening
Only expose the Grafana port publicly. Node Exporter and Prometheus should never be accessible from the internet:
sudo ufw allow 3000/tcp # Grafana only — expose this port
# Do NOT open ports 9090 or 9100 to the public — they expose sensitive data
sudo ufw reloadFor additional security, place Grafana behind an Nginx reverse proxy with HTTPS and basic authentication, or restrict access by IP using UFW rules.
Get a VPS to Run Your Monitoring Stack
AsiaGB VPS with 2 GB RAM or more runs Grafana, Prometheus, and Node Exporter smoothly — with 99% Uptime guarantee and high-speed SSD storage starting at 500 THB/month.
View VPS Plans