How to Install Prometheus on Ubuntu 24.04 VPS — Production-Grade Monitoring
Prometheus is the de-facto open-source standard for infrastructure and application metrics. Pull-based scraping, a powerful query language (PromQL), an embedded time-series database, and a massive ecosystem of exporters make it the foundation of most modern observability stacks. This guide walks you through installing Prometheus on an Ubuntu 24.04 LTS VPS from the official GitHub binary — no Docker, no package manager surprises — and hardening it for real production workloads with scrape configs, recording rules, alert rules, remote_write to long-term storage, and an authenticated reverse proxy.
Running on a VPS? A Starter VPS with 2 vCPU and 4 GB RAM comfortably scrapes 10-50 targets with 15-day local retention.
Table of Contents
What is Prometheus?
Prometheus is an open-source monitoring system that collects metrics by periodically scraping HTTP endpoints exposed by your applications and infrastructure. Originally developed at SoundCloud and now a graduated CNCF project, Prometheus defines the pull-based metrics model that powers observability across Kubernetes, cloud-native microservices, and classic VMs.
A Prometheus deployment typically has four moving parts. The Prometheus server scrapes targets, stores samples in its local time-series database (TSDB), and evaluates rules. Exporters are lightweight agents that translate subsystem state into Prometheus-format metrics — node_exporter for Linux hosts, blackbox_exporter for HTTP/TCP/ICMP probes, postgres_exporter for databases, and hundreds more. Alertmanager receives fired alerts from Prometheus and routes them to Slack, email, PagerDuty, or webhooks with deduplication and silencing. Grafana provides dashboards on top of PromQL queries.
Prometheus is purpose-built for operational monitoring: high-cardinality numeric time series, second-resolution scrapes, and reliable behavior during partial outages. Each server is self-contained, which means no single point of failure — if your central monitoring dies, each Prometheus keeps running independently.
Why Run Prometheus on Your Own VPS?
Running Prometheus yourself instead of paying for a hosted observability SaaS offers several advantages:
- Flat, predictable cost — A VPS costs the same whether you ingest 1M or 100M samples per day. Hosted platforms charge per active series, per GB ingested, and per query, and the bills grow faster than your metrics do.
- Data locality — Your metrics never leave your infrastructure. This matters for regulated workloads (healthcare, finance, EU PII) and for debugging where you need access to raw samples without paying for "high cardinality" tiers.
- No per-metric labeling taxes — Hosted platforms charge for unique label combinations. On your own Prometheus, a
pod="foo-abc123"label is free. - Full PromQL access — Query the raw TSDB without rate limits or query-complexity caps.
- Integration with on-prem tooling — Scrape private networks, VPN-only endpoints, and legacy systems without cloud-to-on-prem connectors.
- Portability — Your
prometheus.yml, rules files, and dashboards are standard YAML/JSON and move between providers trivially.
Prometheus VPS Sizing on CloudCore
| Plan | vCPU | RAM | NVMe | Scrape Scale | Retention Sweet Spot | Price |
|---|---|---|---|---|---|---|
| Starter | 2 | 4 GB | 50 GB | 10-50 targets, 50k series | 15 days local | EUR 7.99/mo |
| Standard | 4 | 8 GB | 100 GB | 100-300 targets, 250k series | 15-30 days local | EUR 14.99/mo |
| Professional | 6 | 12 GB | 200 GB | 500+ targets, 1M series | 30 days local + remote_write | EUR 19.99/mo |
| Enterprise | 8 | 16 GB | 400 GB | 2k+ targets, 3M series | 30 days local + HA pair | EUR 34.99/mo |
Prerequisites
Before you begin, make sure you have:
- A VPS running Ubuntu 24.04 LTS with root or sudo access
- SSH access (PuTTY on Windows, or native terminal on macOS/Linux)
- At least 2 vCPU and 4 GB RAM for the Starter scale
- At least 50 GB of free disk space for the TSDB
- A domain name pointed at your VPS if you plan to use HTTPS via the reverse proxy
ssh root@your-server-ipStep 1: Update System Packages
Start by updating the package index and upgrading installed packages. This ensures that you have the latest security patches and that apt dependencies for Nginx, Certbot, and build tooling resolve cleanly later.
sudo apt update && sudo apt upgrade -yInstall a few utilities we will need throughout the guide:
sudo apt install -y curl wget tar ufwIf the kernel was updated, reboot before continuing:
sudo rebootStep 2: Create a Dedicated Prometheus User
Running Prometheus as root is a bad idea. Create a dedicated system user that owns the binary, configuration, and data directories. The --no-create-home and --shell /bin/false flags ensure the account cannot be used for interactive login.
sudo groupadd --system prometheus
sudo useradd --system --no-create-home --shell /bin/false --gid prometheus prometheusCreate the directories Prometheus expects:
sudo mkdir -p /etc/prometheus /var/lib/prometheus /etc/prometheus/rules /etc/prometheus/file_sd
sudo chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheusDirectory layout summary:
/etc/prometheus— Configuration (prometheus.yml, rule files, service discovery)/etc/prometheus/rules— Recording and alerting rule files/etc/prometheus/file_sd— File-based service discovery targets/var/lib/prometheus— TSDB data directory/usr/local/bin— Binaries (prometheus,promtool)
Step 3: Download and Install the Prometheus Binary
Prometheus publishes statically linked binaries on GitHub releases. This is the recommended install path — Ubuntu's apt package lags significantly behind upstream and often ships broken defaults.
Fetch the current stable release (replace the version if a newer one is out):
cd /tmp
PROM_VERSION="2.54.1"
wget https://github.com/prometheus/prometheus/releases/download/v${PROM_VERSION}/prometheus-${PROM_VERSION}.linux-amd64.tar.gz
tar xvf prometheus-${PROM_VERSION}.linux-amd64.tar.gz
cd prometheus-${PROM_VERSION}.linux-amd64Install the binaries and default assets:
sudo install -o prometheus -g prometheus -m 0755 prometheus /usr/local/bin/prometheus
sudo install -o prometheus -g prometheus -m 0755 promtool /usr/local/bin/promtool
sudo cp -r consoles console_libraries /etc/prometheus/
sudo chown -R prometheus:prometheus /etc/prometheus/consoles /etc/prometheus/console_librariesVerify the install:
/usr/local/bin/prometheus --versionExpected output:
prometheus, version 2.54.1 (branch: HEAD, revision: ...)
build user: root@...
build date: ...
go version: go1.22.7
platform: linux/amd64Step 4: Configure prometheus.yml
The main configuration file defines global settings, scrape jobs, rule files, alerting targets, and remote_write destinations. Create it at /etc/prometheus/prometheus.yml:
sudo tee /etc/prometheus/prometheus.yml > /dev/null <<'EOF' global: scrape_interval: 15s evaluation_interval: 15s external_labels: cluster: "primary" replica: "A"rule_files: - "/etc/prometheus/rules/*.yml"
alerting: alertmanagers: - static_configs: - targets: - "127.0.0.1:9093"
scrape_configs: - job_name: "prometheus" static_configs: - targets: ["127.0.0.1:9090"]
- job_name: "node" static_configs: - targets: ["127.0.0.1:9100"] labels: env: "production" role: "app-server"
- job_name: "blackbox_http" metrics_path: /probe params: module: [http_2xx] static_configs: - targets: - https://vps-server.host - https://status.vps-server.host relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 127.0.0.1:9115
- job_name: "file_sd_apps" file_sd_configs: - files: - /etc/prometheus/file_sd/*.json refresh_interval: 30s EOF sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml
Key sections explained:
global.scrape_interval— How often Prometheus scrapes each target. 15s is the standard starting point. Drop to 10s for tighter alerting at the cost of more RAM and disk; raise to 30s-60s for cost-sensitive deployments.global.external_labels— Labels applied to all samples leaving this Prometheus (federation, remote_write, alerts). Required for distinguishing replicas in HA pairs.rule_files— Glob of files containing recording and alerting rules.alerting.alertmanagers— Where fired alerts are pushed. You will install Alertmanager separately.scrape_configs— Each job is a set of targets Prometheus polls. Theblackbox_httpexample shows the classic relabel dance for blackbox-style exporters.
sudo -u prometheus /usr/local/bin/promtool check config /etc/prometheus/prometheus.ymlExpected output:
Checking /etc/prometheus/prometheus.yml
SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntaxStep 5: Create the systemd Service
Write the unit file that supervises Prometheus, restarts it on crash, and ties it into Ubuntu's boot process.
sudo tee /etc/systemd/system/prometheus.service > /dev/null <<'EOF' [Unit] Description=Prometheus Monitoring Server Documentation=https://prometheus.io/docs/ Wants=network-online.target After=network-online.target[Service] User=prometheus Group=prometheus Type=simple Restart=on-failure RestartSec=5s ExecStart=/usr/local/bin/prometheus \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/var/lib/prometheus \ --storage.tsdb.retention.time=15d \ --storage.tsdb.retention.size=40GB \ --web.console.templates=/etc/prometheus/consoles \ --web.console.libraries=/etc/prometheus/console_libraries \ --web.listen-address=127.0.0.1:9090 \ --web.external-url=https://prometheus.yourdomain.com \ --web.enable-lifecycle
Hardening
NoNewPrivileges=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/var/lib/prometheus PrivateTmp=true PrivateDevices=true ProtectKernelTunables=true ProtectControlGroups=true LockPersonality=true
[Install] WantedBy=multi-user.target EOF
Flag highlights:
--storage.tsdb.retention.time=15d— Keep 15 days of data locally. Combined withretention.size, whichever limit hits first triggers compaction.--storage.tsdb.retention.size=40GB— Hard cap on on-disk data size. Keeps you from filling the root partition.--web.listen-address=127.0.0.1:9090— Bind only to localhost. The reverse proxy in Step 10 handles external access.--web.external-url— Required for correct absolute URLs when behind a proxy at a subdomain.--web.enable-lifecycle— Lets you hot-reload config withcurl -X POST http://127.0.0.1:9090/-/reload.
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
sudo systemctl status prometheusExpected status output:
● prometheus.service - Prometheus Monitoring Server
Loaded: loaded (/etc/systemd/system/prometheus.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-04-16 10:00:00 UTC; 5s ago
Main PID: 2345 (prometheus)
Tasks: 9
Memory: 62.0MVerify the HTTP endpoint:
curl -s http://127.0.0.1:9090/-/healthyExpected output:
Prometheus Server is Healthy.Step 6: Install node_exporter
Without exporters, Prometheus has nothing to scrape. node_exporter is the canonical agent for Linux hosts — it exposes CPU, memory, disk, filesystem, network, and kernel metrics on port 9100.
Create a dedicated user and download the binary:
sudo useradd --system --no-create-home --shell /bin/false node_exporter
cd /tmp NE_VERSION="1.8.2" wget https://github.com/prometheus/node_exporter/releases/download/v${NE_VERSION}/node_exporter-${NE_VERSION}.linux-amd64.tar.gz tar xvf node_exporter-${NE_VERSION}.linux-amd64.tar.gz sudo install -o node_exporter -g node_exporter -m 0755 \ node_exporter-${NE_VERSION}.linux-amd64/node_exporter /usr/local/bin/node_exporter
Create the systemd unit:
sudo tee /etc/systemd/system/node_exporter.service > /dev/null <<'EOF' [Unit] Description=Prometheus Node Exporter Wants=network-online.target After=network-online.target[Service] User=node_exporter Group=node_exporter Type=simple Restart=on-failure ExecStart=/usr/local/bin/node_exporter \ --web.listen-address=127.0.0.1:9100 \ --collector.systemd \ --collector.processes
[Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable --now node_exporter
Confirm metrics are flowing:
curl -s http://127.0.0.1:9100/metrics | head -20You should see lines like node_cpu_seconds_total{cpu="0",mode="idle"} .... Since prometheus.yml already scrapes 127.0.0.1:9100, the target will appear in the Prometheus UI at Status -> Targets within 15 seconds.
For remote hosts, repeat the install and add each to the node job:
- job_name: "node"
static_configs:
- targets:
- "127.0.0.1:9100"
- "10.0.0.15:9100"
- "10.0.0.16:9100"For uptime monitoring, install blackbox_exporter alongside node_exporter to probe HTTP endpoints, TCP ports, and DNS.
Step 7: Add Recording Rules
Recording rules precompute expensive or frequently used PromQL expressions and save the results as new time series. They reduce dashboard load time and make alerting rules simpler.
Create /etc/prometheus/rules/recording.yml:
sudo tee /etc/prometheus/rules/recording.yml > /dev/null <<'EOF' groups: - name: node-recording interval: 30s rules: - record: instance:node_cpu_utilization:ratio expr: | 1 - avg by (instance) ( rate(node_cpu_seconds_total{mode="idle"}[5m]) )- record: instance:node_memory_utilization:ratio expr: | 1 - ( node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes )
- record: instance:node_filesystem_free:ratio expr: | node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}
- record: instance:node_network_receive_bytes:rate5m expr: | sum by (instance) ( rate(node_network_receive_bytes_total{device!~"lo|docker.*"}[5m]) ) EOF sudo chown prometheus:prometheus /etc/prometheus/rules/recording.yml
Naming follows the Prometheus convention: level:metric:operation. instance:node_cpu_utilization:ratio means "aggregated at the instance level, derived from node_cpu, expressed as a ratio."
Validate and reload:
sudo -u prometheus /usr/local/bin/promtool check rules /etc/prometheus/rules/recording.yml
curl -X POST http://127.0.0.1:9090/-/reloadStep 8: Add Alert Rules
Alerting rules evaluate PromQL expressions on a schedule and fire alerts to Alertmanager when conditions are met. Alertmanager then handles delivery.
Create /etc/prometheus/rules/alerts.yml:
sudo tee /etc/prometheus/rules/alerts.yml > /dev/null <<'EOF' groups: - name: node-alerts interval: 30s rules: - alert: InstanceDown expr: up{job="node"} == 0 for: 2m labels: severity: critical annotations: summary: "Instance {{ $labels.instance }} is down" description: "{{ $labels.instance }} has been unreachable for more than 2 minutes."- alert: HighCPUUsage expr: instance:node_cpu_utilization:ratio > 0.90 for: 10m labels: severity: warning annotations: summary: "High CPU on {{ $labels.instance }}" description: "CPU utilization is {{ $value | humanizePercentage }} (>90%) for 10 minutes."
- alert: HighMemoryUsage expr: instance:node_memory_utilization:ratio > 0.92 for: 10m labels: severity: warning annotations: summary: "High memory on {{ $labels.instance }}" description: "Memory utilization is {{ $value | humanizePercentage }} (>92%) for 10 minutes."
- alert: DiskSpaceLow expr: instance:node_filesystem_free:ratio < 0.10 for: 15m labels: severity: warning annotations: summary: "Low disk on {{ $labels.instance }} {{ $labels.mountpoint }}" description: "Only {{ $value | humanizePercentage }} free on {{ $labels.mountpoint }}."
- alert: DiskWillFillIn4Hours expr: predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[1h], 4*3600) < 0 for: 30m labels: severity: critical annotations: summary: "Disk will fill within 4 hours on {{ $labels.instance }}" description: "At the current write rate, {{ $labels.mountpoint }} will be full in <4h."
- alert: PrometheusConfigReloadFailed expr: prometheus_config_last_reload_successful == 0 for: 5m labels: severity: warning annotations: summary: "Prometheus config reload failed" description: "The last configuration reload did not succeed." EOF sudo chown prometheus:prometheus /etc/prometheus/rules/alerts.yml
Validate and reload:
sudo -u prometheus /usr/local/bin/promtool check rules /etc/prometheus/rules/*.yml
curl -X POST http://127.0.0.1:9090/-/reloadAlerts will appear in the Prometheus UI at Alerts, cycling through inactive -> pending -> firing states as the for duration elapses. To deliver them, install Alertmanager and point the alerting.alertmanagers block in prometheus.yml at it.
Step 9: Forward Metrics with remote_write
Local TSDB storage is ideal for short-term retention and fast queries, but for long-term retention (months to years), horizontal scale, or HA, you want to forward samples to a dedicated long-term store. Prometheus supports this via remote_write.
Popular remote_write backends include:
- Grafana Mimir — Horizontally scalable, multi-tenant, CNCF project (fork of Cortex).
- Thanos — Object-storage-backed, deduplicates HA pairs, widely deployed.
- VictoriaMetrics — Resource-efficient, PromQL-compatible, simplest to operate.
remote_write block to /etc/prometheus/prometheus.yml:remote_write:
- url: "https://mimir.yourdomain.com/api/v1/push"
name: "mimir-primary"
basic_auth:
username: "tenant-1"
password_file: /etc/prometheus/mimir_password
queue_config:
capacity: 10000
max_samples_per_send: 2000
batch_send_deadline: 5s
min_shards: 1
max_shards: 50
metadata_config:
send: true
send_interval: 1m
write_relabel_configs:
- source_labels: [__name__]
regex: "go_.|process_."
action: dropKey settings:
queue_config— Tune shard count and batch size for throughput.max_shards: 50lets Prometheus parallelize writes under burst.write_relabel_configs— Drop noisy/uninteresting metrics before they leave the scraper. The example drops Go runtime metrics to save ingest cost.basic_auth.password_file— Never put secrets inline in YAML. Store them in a0600-permissioned file owned byprometheus.
echo -n "your-mimir-tenant-password" | sudo tee /etc/prometheus/mimir_password > /dev/null
sudo chown prometheus:prometheus /etc/prometheus/mimir_password
sudo chmod 0600 /etc/prometheus/mimir_passwordValidate and reload:
sudo -u prometheus /usr/local/bin/promtool check config /etc/prometheus/prometheus.yml
curl -X POST http://127.0.0.1:9090/-/reloadMonitor the queue with these metrics in the Prometheus UI:
prometheus_remote_storage_samples_pending— Samples waiting in the queue. Should trend near 0.prometheus_remote_storage_samples_dropped_total— Incremented on failure. Should be flat.prometheus_remote_storage_shards— Current active shard count.
Step 10: Secure with an Nginx Reverse Proxy
Prometheus has no built-in authentication. Since the systemd unit binds it to 127.0.0.1, it is not reachable from the internet — but you still need a way to view the UI and run queries from your browser. Put Nginx in front with TLS and HTTP basic auth.
Install Nginx and Certbot
sudo apt install -y nginx apache2-utils certbot python3-certbot-nginxCreate a Password File
sudo htpasswd -c /etc/nginx/.prometheus-htpasswd adminYou will be prompted for a password. To add more users later, drop the -c flag.
Configure the Nginx Server Block
sudo tee /etc/nginx/sites-available/prometheus > /dev/null <<'EOF' server { listen 80; server_name prometheus.yourdomain.com; return 301 https://$host$request_uri; }server { listen 443 ssl http2; server_name prometheus.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/prometheus.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/prometheus.yourdomain.com/privkey.pem;
# Security headers add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Content-Type-Options nosniff; add_header X-Frame-Options DENY; add_header Referrer-Policy strict-origin-when-cross-origin;
# Block the federation and admin endpoints from public access location ~ ^/(api/v1/admin|-/reload|-/quit) { return 403; }
location / { auth_basic "Prometheus"; auth_basic_user_file /etc/nginx/.prometheus-htpasswd;
proxy_pass http://127.0.0.1:9090; 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;
proxy_read_timeout 120s; proxy_send_timeout 120s; } } EOF
sudo ln -sf /etc/nginx/sites-available/prometheus /etc/nginx/sites-enabled/ sudo nginx -t
Issue the TLS Certificate
sudo certbot --nginx -d prometheus.yourdomain.com
sudo systemctl reload nginxOpen the Firewall
sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enableYou can now visit https://prometheus.yourdomain.com, enter the basic-auth credentials, and explore the UI. PromQL queries run against the local TSDB; the Status -> Targets page confirms that scraping is healthy; and the Alerts page reflects the rules defined in Step 8.
To pair this with dashboards, install Grafana on the same VPS (or a separate one) and add Prometheus as a data source pointing at https://prometheus.yourdomain.com with the basic-auth credentials.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
Failed to start Prometheus: opening storage failed: lock DB directory | Previous process still running or stale lock | sudo systemctl stop prometheus, then rm /var/lib/prometheus/lock if the PID is gone |
Targets stuck in DOWN state | Firewall blocking scrape port or exporter not bound to scrapeable interface | Check curl <target>:<port>/metrics from the Prometheus host; adjust UFW with sudo ufw allow from <prom-ip> to any port 9100 |
out of order sample errors in logs | Clock skew between Prometheus and target, or duplicate scrape jobs | Install chrony: sudo apt install chrony; verify each target appears only once in scrape_configs |
| High RAM usage | Too many active series (cardinality explosion) | Run topk(20, count by (__name__)({__name__=~".+"})) in Prometheus UI to find offenders; drop with metric_relabel_configs |
remote_write queue backing up | Remote endpoint slower than scrape rate | Increase max_shards; drop unnecessary metrics with write_relabel_configs; scale the remote backend |
| Alerts never fire despite matching expr | for: duration not elapsed, or Alertmanager unreachable | Check Alerts page for pending state; curl 127.0.0.1:9093/-/healthy to verify Alertmanager |
| Reload returns 403/404 | --web.enable-lifecycle missing, or reverse proxy blocks /-/reload | Keep --web.enable-lifecycle in the unit and run reloads from localhost, not through Nginx |
TSDB compaction lag (prometheus_tsdb_compactions_failed_total > 0) | Insufficient disk IOPS or RAM pressure | Upgrade to a higher CloudCore tier; reduce retention; move /var/lib/prometheus to NVMe |
Viewing Logs
Stream Prometheus logs in real time:
sudo journalctl -u prometheus -fGet the last 100 lines:
sudo journalctl -u prometheus -n 100 --no-pagerCheck config reload status:
curl -s http://127.0.0.1:9090/api/v1/status/config | headFAQ
What are the minimum system requirements for Prometheus?
Prometheus runs comfortably on a 2 vCPU / 4 GB RAM VPS for monitoring 10-50 targets. RAM usage scales with active series — plan for roughly 3 KB per active series. Disk usage averages 1-2 bytes per sample after compression, so 15-day retention on 100k active series at 15-second scrape intervals consumes around 20 GB. CPU is rarely the bottleneck below ~500k series; above that, rule evaluation and recording rules start dominating.
Should I use Prometheus with remote_write or store data locally?
For a single server or homelab, local TSDB storage with 15-30 day retention is sufficient and simpler to operate. For HA (two replicas scraping the same targets), multi-tenant workloads, or long-term storage (months to years), forward samples via remote_write to Mimir, Thanos, or VictoriaMetrics. remote_write lets you keep Prometheus as a lightweight scraper while offloading storage and query federation to a purpose-built TSDB. Most teams run both: 15 days local for fast queries, plus remote_write for compliance-grade long-term retention.
How is Prometheus different from VictoriaMetrics?
Prometheus is the reference implementation of the pull-based metrics model with PromQL, scraping, alerting, and local TSDB. VictoriaMetrics is a drop-in compatible TSDB that accepts Prometheus remote_write, uses 7-10x less RAM and 70% less disk for the same dataset, and supports MetricsQL (a PromQL superset with extra functions). VictoriaMetrics does not replace Prometheus's scraping logic — most teams run Prometheus for scraping and rule evaluation, and VictoriaMetrics (or a cluster of vmagent + vmstorage) for long-term storage.
Do I need Alertmanager to use alert rules?
Yes. Prometheus evaluates alerting rules and fires alerts, but it delegates routing, grouping, silencing, inhibition, and delivery (email, Slack, PagerDuty, OpsGenie, webhooks) to Alertmanager. Without Alertmanager, alerts appear in the Prometheus UI but never reach a human. You can install Alertmanager on the same VPS or a separate one — see our Alertmanager install guide.
Can Prometheus monitor Windows servers?
Yes, using windows_exporter (the Windows equivalent of node_exporter). It exposes CPU, memory, disk, network, IIS, MSSQL, Active Directory, and Windows service metrics on port 9182 by default. Add it as a scrape target in prometheus.yml just like node_exporter. The collector flags let you enable only the subsystems you care about to reduce cardinality.
How do I visualize Prometheus metrics?
The built-in Prometheus UI is functional for ad-hoc PromQL queries and debugging but not dashboards. Install Grafana and add Prometheus as a data source to build rich dashboards with panels, variables, annotations, and alerts. The Grafana community maintains thousands of pre-built dashboards — the "Node Exporter Full" dashboard (ID 1860) is the canonical starting point for host-level monitoring and works immediately after completing this guide.
How do I handle high-cardinality labels?
Cardinality explosion is the #1 operational issue with Prometheus. Labels like user_id, request_id, or session_id create a new time series per unique value and quickly exhaust RAM. Mitigation: never put unbounded strings in labels, use metric_relabel_configs to drop offending metrics at scrape time, and regularly audit with topk(20, count by (__name__)({__name__=~".+"})) in the UI. For logs (which are naturally high-cardinality), use Loki instead.
Next Steps
Now that Prometheus is running on your VPS, here are recommended next steps to build a complete observability stack:
- Install Grafana — Add Prometheus as a data source and import the "Node Exporter Full" dashboard (ID 1860) to visualize everything node_exporter produces. Build custom dashboards on top of your recording rules for fast queries.
- Install Alertmanager — Deliver your alert rules to Slack, email, PagerDuty, or webhooks. Configure routing trees, silences, and inhibition to keep on-call sane.
- Install Loki — Pair Prometheus metrics with logs using Grafana's purpose-built log aggregator. Promtail ships logs from every host and queries run through the same Grafana UI.
- Install VictoriaMetrics — If
remote_writeoverhead or local TSDB disk usage becomes a concern, VictoriaMetrics is the simplest long-term storage option with dramatically lower resource footprint.
- Install Mimir — For multi-tenant, horizontally scalable metrics storage backed by object storage (S3, GCS, R2), Mimir is the Grafana Labs successor to Cortex. Use when you outgrow single-node remote_write backends.
- Install node_exporter on every host — You already installed it locally; roll it out to every VPS in your fleet so Prometheus has a complete picture.
- Install blackbox_exporter — Add synthetic HTTP/TCP/ICMP probes for external endpoints, SSL certificate expiry checks, and DNS monitoring. Essential for SLA dashboards and customer-facing uptime.
- Read the official Prometheus documentation — The upstream docs cover PromQL in depth, federation patterns, HA deployment topologies, and exporter development. Essential reading as you scale.
Running DataMammoth? Managed Monitoring is Included>
Every CloudCore VPS comes with opt-in managed monitoring — Prometheus, Grafana, Alertmanager, and node_exporter pre-configured against your fleet, with dashboards and alert rules tuned for production workloads.>
- Zero-touch node_exporter rollout across every VPS in your account
- Hosted Grafana dashboards, no separate install
- Slack/email alerts pre-wired to your support contacts
- 30-day metric retention on every plan, 1-year on Enterprise>
Browse VPS Plans — Starter plans from EUR 7.99/month.