|

Setting up Proactive VPS Management

To learn more about Local AI topics, check out related posts in the Local AI Series 

Have questions, ideas to share, or just want to connect? I’d love to hear from you! Check out my About Page to learn more about me or connect with me.

Have questions, ideas to share, or just want to connect? I’d love to hear from you! Check out my About Page to learn more about me or connect with me.

If you are anything like me, it all started with one Virtual Private Server (VPS) and before you close your eyes, you have many of them split between the cloud and your local environment. I use Docker containers for most of my work, and this past weekend one of the VPS was shut down because of a runaway CPU Utilization spiked at over 95% – it was an easy restore – I just had to start it again, but caused some disruption of course!

So what do you need:

  1. Malware Detection: Filesystem scanners (like Hostinger’s Monarx or standalone security agents) to ensure high CPU isn’t caused by a compromised script, webshell, or crypto-miner.
  2. Resource Monitor (and logger): A time-series metric collector to record CPU, memory, and I/O history per container so you can inspect what spiked after the fact.
  3. Centralized VPS/Container Manager: A single interface (like Portainer with remote Agents) to manage containers, review logs, and control stacks across all your cloud and local VPS instances from one dashboard.
  4. Centralized Prometheus/Grafana: A unified monitoring setup to pull performance metrics across all your distributed nodes into a single, comprehensive dashboard.

While malware scanners handle security and Portainer handles container management, you need a dedicated telemetry stack for historical resource logging.

Installing cAdvisor + Prometheus + Grafana via Docker Compose

This stack uses cAdvisor to collect container metrics, Prometheus to store them over time, and Grafana to visualize CPU trends and set up alerts.

Step 1: Create the Project Directory

Connect to your VPS via SSH or terminal and create a dedicated directory for your monitoring configuration:

Bash

mkdir -p /your-folder/monitoring
cd /your-folder/monitoring

Step 2: Configure Prometheus

Create prometheus.yml to instruct Prometheus to scrape metrics from cAdvisor every 15 seconds:

Bash

cat > prometheus.yml <<'EOF'
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']
EOF

Step 3: Create the Docker Compose Deployment

Create docker-compose.yml to define the three monitoring services:

Bash

cat > docker-compose.yml <<'EOF'
services:
  cadvisor:
    image: ghcr.io/google/cadvisor:latest
    container_name: cadvisor
    restart: unless-stopped
    command:
      - --docker_only=true
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker:/var/lib/docker:ro
    networks:
      - monitoring

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.retention.time=30d
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    ports:
      - "127.0.0.1:9090:9090"
    networks:
      - monitoring

  grafana:
    image: grafana/grafana-oss:latest
    container_name: grafana
    restart: unless-stopped
    volumes:
      - grafana-data:/var/lib/grafana
    ports:
      - "127.0.0.1:3000:3000"
    networks:
      - monitoring

volumes:
  prometheus-data:
  grafana-data:

networks:
  monitoring:
EOF

Step 4: Start the Stack & Access the Dashboard Securely

Launch the containers in detached mode:

Bash

docker compose up -d
docker compose ps
ON YOUR LAPTOP: (Not on your server!) Do the following:

To keep management ports hidden from the public internet, open a secure SSH tunnel from your local computer:

Bash

ssh -L 3000:127.0.0.1:3000 root@YOUR_VPS_IP

Open your web browser to [http://127.0.0.1:3000](http://127.0.0.1:3000). Sign in with the default credentials (admin / admin) and set a new password when prompted.

Connecting Grafana to Prometheus & Tracking CPU Spikes

  1. In Grafana, navigate to ConnectionsData SourcesAdd Data Source.
  2. Select Prometheus.
  3. Set the Connection URL to http://prometheus:9090 and click Save & Test.

To build a panel that tracks the exact CPU percentage utilized by each container, create a Grafana visualization using this PromQL query:

  1. Open Grafana at http://127.0.0.1:3000.
  2. In the left menu, open Explore.
  3. Select your Prometheus data source.
  4. Paste the query into the query editor and click Run queries:

sum by (name) (
  rate(container_cpu_usage_seconds_total{name!=""}[5m])
) * 100

For a permanent graph, go to Dashboards → New → New dashboard → Add visualization, select Prometheus, paste the same query, then click Apply and save the dashboard. If it returns no data, check that the Prometheus target for cadvisor:8080 is healthy.

With this query running, the next time a container triggers a sudden workload or runaway loop, you won’t have to guess—you can open Grafana, look back at the exact time of the spike, and identify the responsible container right away.

Once setup you will be able to access something like this:

cAdvisor is running and Prometheus is successfully scraping it, Grafana will show CPU utilization history for each container.

Important details:

  • History starts when Prometheus begins collecting metrics; it cannot show CPU usage from before installation.
  • The Compose file I provided keeps approximately 30 days of Prometheus data.
  • The query displays average CPU usage over the selected Grafana time range.
  • It shows container CPU usage, but not necessarily VPS CPU steal (%st). Keep checking host-level metrics separately if you need to distinguish container load from physical CPU contention.
  • In Grafana, use the time selector in the upper-right corner to view the last hour, day, week, or another range.