Monitoring a VPS is not optional once you have more than one server or a production application. Prometheus collects metrics from your servers and applications. Grafana visualizes them in dashboards. Together, they give you a real-time view of CPU, memory, disk, network, and application-level metrics with configurable alerting. This guide covers installing both on a single VPS, configuring exporters, building dashboards, and setting up alerts that catch problems before users do.
Why Prometheus + Grafana on a VPS
Managed monitoring services (Datadog, New Relic) start at $15–$30 per host per month. Prometheus and Grafana are open source and free. On a 2 GB VPS, the full stack (Prometheus, Grafana, Node Exporter, and Alertmanager) consumes approximately 300–500 MB of RAM and handles up to 50 monitored targets without performance degradation.
| Component | Memory Usage | CPU (Idle) | Disk (30 days retention) |
|---|---|---|---|
| Prometheus | 150–250 MB | 2–5% | 2–5 GB |
| Grafana | 80–120 MB | 1–2% | 100 MB |
| Node Exporter | 10–20 MB | <1% | Minimal |
| Alertmanager | 20–30 MB | <1% | Minimal |
| Total | 260–420 MB | 3–8% | 2–5 GB |
Step 1: Install Prometheus
# Download and install Prometheus
cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.52.0/prometheus-2.52.0.linux-amd64.tar.gz
tar xzf prometheus-2.52.0.linux-amd64.tar.gz
sudo mv prometheus-2.52.0.linux-amd64 /opt/prometheus
# Create a system user
sudo useradd --no-create-home --shell /bin/false prometheus
# Set ownership
sudo chown -R prometheus:prometheus /opt/prometheus
Create a minimal configuration at /opt/prometheus/prometheus.yml:
# /opt/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093']
# Rule files for alerting
rule_files:
- "rules/*.yml"
# Scrape configurations
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
Create a systemd service at /etc/systemd/system/prometheus.service:
[Unit]
Description=Prometheus
After=network.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/opt/prometheus/prometheus \
--config.file=/opt/prometheus/prometheus.yml \
--storage.tsdb.path=/opt/prometheus/data \
--storage.tsdb.retention.time=30d \
--web.console.templates=/opt/prometheus/consoles \
--web.console.libraries=/opt/prometheus/console_libraries
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
sudo systemctl status prometheus
Step 2: Install Node Exporter (System Metrics)
Node Exporter exposes CPU, memory, disk, and network metrics from the Linux kernel:
cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.linux-amd64.tar.gz
tar xzf node_exporter-1.8.1.linux-amd64.tar.gz
sudo cp node_exporter-1.8.1.linux-amd64/node_exporter /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false node_exporter
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter
Create systemd service at /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.cpu \
--collector.diskstats \
--collector.filesystem \
--collector.meminfo \
--collector.netdev \
--collector.loadavg
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
Step 3: Install Grafana
# Add Grafana repository (Ubuntu/Debian)
sudo apt install -y software-properties-common
sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
sudo apt update
sudo apt install grafana -y
sudo systemctl enable --now grafana-server
sudo systemctl status grafana-server
Grafana runs on port 3000. Default credentials are admin/admin. Change the password immediately after login.
Step 4: Add Prometheus as a Data Source in Grafana
In the Grafana UI (http://your-vps:3000):
- Navigate to Configuration → Data Sources → Add data source.
- Select Prometheus.
- Set URL to
http://localhost:9090. - Click Save & Test.
Step 5: Import a Pre-Built Dashboard
Grafana has a community dashboard library. Import the popular Node Exporter Full dashboard (ID 1860):
- Navigate to Dashboards → Import.
- Enter 1860 in the Grafana.com dashboard ID field.
- Select your Prometheus data source.
- Click Import.
You will see CPU usage, memory, disk I/O, network traffic, and system load in real time.
Step 6: Configure Alerting
Create alert rules in /opt/prometheus/rules/vps.yml:
# /opt/prometheus/rules/vps.yml
groups:
- name: vps_alerts
rules:
# Disk space alert
- alert: DiskSpaceLow
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 90
for: 5m
labels:
severity: warning
annotations:
summary: "Memory usage above 90% on {{ $labels.instance }}"
description: "Memory usage is {{ $value }}%."
# CPU alert
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 10m
labels:
severity: warning
annotations:
summary: "CPU usage above 80% for 10 minutes on {{ $labels.instance }}"
description: "CPU usage is {{ $value }}%."
# System load alert
- alert: HighSystemLoad
expr: node_load15 / count without(cpu, mode) (node_cpu_seconds_total{mode="idle"}) > 1.5
for: 5m
labels:
severity: critical
annotations:
summary: "System load too high on {{ $labels.instance }}"
description: "15-minute load average is {{ $value }} times the number of CPUs."
# Target down alert
- alert: TargetDown
expr: up == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Target {{ $labels.instance }} is down"
description: "{{ $labels.job }} on {{ $labels.instance }} has been unreachable for 2 minutes."
Reload Prometheus to pick up the new rules:
sudo systemctl reload prometheus
Step 7: Set Up Alert Notifications
Configure Alertmanager for email notifications at /opt/prometheus/alertmanager.yml:
# /opt/prometheus/alertmanager.yml
global:
smtp_smarthost: 'smtp.gmail.com:587'
smtp_from: '[email protected]'
smtp_auth_username: '[email protected]'
smtp_auth_password: 'your-app-password'
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'email'
receivers:
- name: 'email'
email_configs:
- to: '[email protected]'
Securing the Stack
- Reverse proxy with TLS: Put Grafana behind Nginx with SSL. Grafana on port 3000 over HTTP is fine on localhost, but expose it with HTTPS.
- Authentication: Grafana has built-in auth. Prometheus has no built-in auth — use Nginx basic auth or OAuth2 proxy in front of it.
- Firewall: Only expose ports 80/443 (Nginx) and 22 (SSH). Prometheus (9090), Grafana (3000), and Node Exporter (9100) should be accessible only from localhost or via the reverse proxy.
- Data retention: The
--storage.tsdb.retention.time=30dflag limits Prometheus data storage to 30 days. Adjust based on your disk size. On a 20 GB VPS, 30 days is safe for up to 10 monitored targets.
For a VPS with adequate resources to run this monitoring stack alongside your applications, compare VPS plans with suitable RAM and storage. For more on performance optimization and server management, explore our performance tuning guides.


Leave a Reply
You must be logged in to post a comment.