VPNSmith
self-host-vpnINFO

Monitorizar tu VPN VPS con Prometheus + Grafana (2026)

Stack monitoring completa: node_exporter, wireguard_exporter, dashboards Grafana, alertas uptime/throughput, integración Discord webhook. Setup 30 min.

Por Eric Gerard · Fondateur · VPNSmith — Spécialiste self-host VPN & VPS GDPR6 min de lecturaFoto vía Unsplash

Tu túnel WireGuard funciona. Pero te preguntas: ¿cuántos Mbps consume en horas punta? ¿Qué peers se conectan cuándo? ¿El VPS Contabo aguanta realmente sus 200 Mbps anunciados? Podrías abrir un terminal y tail -f journalctl en cada duda, o instalar una stack Prometheus + Grafana en 30 minutos que te da las respuestas visualmente, alerta sobre incidentes, y guarda el histórico.

Esta guía implementa el setup que usamos nosotros mismos en Contabo VPS S desde hace 14 meses. node_exporter para el sistema, wireguard_exporter para los peers, Prometheus para el almacenamiento, Grafana para la visu, Alertmanager + webhook Discord para alertas.

Arquitectura

Todo corre en el mismo VPS Contabo. Tres procesos systemd:

  • node_exporter (puerto 9100): métricas sistema (CPU, RAM, disco, red)
  • wireguard_exporter (puerto 9586): métricas peers WireGuard
  • prometheus (puerto 9090): scrape de exporters cada 15s, retención 30 días
  • grafana (puerto 3000): dashboards
  • alertmanager (puerto 9093): reglas de alerta + webhook Discord

Coste: ~250 MB RAM, ~3% CPU permanente en VPS 4 vCPU. Ningún impacto perceptible en el túnel.

Paso 1 — Instalar node_exporter

sudo useradd --no-create-home --shell /usr/sbin/nologin node_exporter

cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
tar xzf node_exporter-1.8.2.linux-amd64.tar.gz
sudo cp node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter

Servicio systemd /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 --web.listen-address=127.0.0.1:9100

[Install]
WantedBy=multi-user.target

Importante: bind en 127.0.0.1 — sin exposición pública.

sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
curl -s http://127.0.0.1:9100/metrics | head -20

Paso 2 — Instalar prometheus-wireguard-exporter

El exporter que usamos: github.com/MindFlavor/prometheus_wireguard_exporter (Rust, binario ~3 MB).

cd /tmp
wget https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/download/3.6.6/prometheus_wireguard_exporter_3.6.6_linux_amd64.tar.gz
tar xzf prometheus_wireguard_exporter_3.6.6_linux_amd64.tar.gz
sudo cp prometheus_wireguard_exporter /usr/local/bin/
sudo chmod +x /usr/local/bin/prometheus_wireguard_exporter

Servicio /etc/systemd/system/wireguard_exporter.service:

[Unit]
Description=WireGuard Prometheus Exporter
After=network.target wg-quick@wg0.service
Requires=wg-quick@wg0.service

[Service]
User=root
ExecStart=/usr/local/bin/prometheus_wireguard_exporter -a 127.0.0.1 -p 9586 -n /etc/wireguard/wg0.conf
Restart=on-failure

[Install]
WantedBy=multi-user.target

El flag -n /etc/wireguard/wg0.conf permite al exporter usar nombres de peers (comentados en el .conf) como labels Prometheus.

sudo systemctl daemon-reload
sudo systemctl enable --now wireguard_exporter
curl -s http://127.0.0.1:9586/metrics | grep wireguard_

Paso 3 — Instalar Prometheus

sudo useradd --no-create-home --shell /usr/sbin/nologin prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus /var/lib/prometheus

cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.55.1/prometheus-2.55.1.linux-amd64.tar.gz
tar xzf prometheus-2.55.1.linux-amd64.tar.gz
sudo cp prometheus-2.55.1.linux-amd64/prometheus /usr/local/bin/
sudo cp prometheus-2.55.1.linux-amd64/promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool

Config /etc/prometheus/prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets:
            - 127.0.0.1:9093

rule_files:
  - "alert_rules.yml"

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:
          instance: vps-contabo-nuremberg

  - job_name: wireguard
    static_configs:
      - targets: [127.0.0.1:9586]
        labels:
          instance: vps-contabo-nuremberg

Reglas de alerta /etc/prometheus/alert_rules.yml:

groups:
  - name: vpn_alerts
    interval: 30s
    rules:
      - alert: HighCPU
        expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        annotations:
          summary: "CPU > 80% en {{ $labels.instance }}"

      - alert: WireGuardPeerDown
        expr: time() - wireguard_latest_handshake_seconds > 600
        for: 5m
        annotations:
          summary: "WG peer {{ $labels.peer }} sin handshake desde >10min"

      - alert: HighBandwidth
        expr: rate(node_network_transmit_bytes_total{device="eth0"}[5m]) * 8 > 180000000
        for: 10m
        annotations:
          summary: "Bandwidth > 180 Mbps en eth0 — acercándose al límite Contabo"

      - alert: DiskAlmostFull
        expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 15
        for: 10m
        annotations:
          summary: "Disco < 15% libre en {{ $labels.instance }}"

Servicio /etc/systemd/system/prometheus.service:

[Unit]
Description=Prometheus
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

[Install]
WantedBy=multi-user.target
sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml /etc/prometheus/alert_rules.yml
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus

Paso 4 — Instalar Grafana

sudo apt install -y apt-transport-https software-properties-common
sudo mkdir -p /etc/apt/keyrings/
wget -q -O - https://apt.grafana.com/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/grafana.gpg
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana

Edita /etc/grafana/grafana.ini para bind solo en localhost:

[server]
http_addr = 127.0.0.1
http_port = 3000
sudo systemctl enable --now grafana-server

Paso 5 — Acceder a Grafana de forma segura

En lugar de abrir puerto 3000 públicamente, túnel SSH desde tu laptop:

ssh -L 3000:127.0.0.1:3000 eric@vpn.example.com

Luego abre http://127.0.0.1:3000 en navegador local. Login admin / admin (cambia inmediatamente).

Alternativa: acceder vía el túnel WireGuard. Si tu VPS es 10.66.66.1 lado VPN, hit http://10.66.66.1:3000 desde cualquier peer conectado. Ningún puerto expuesto al Internet público.

Paso 6 — Configurar la datasource Prometheus

En Grafana:

  1. Settings → Data Sources → Add → Prometheus
  2. URL: http://127.0.0.1:9090
  3. Save & Test → "Data source is working"

Paso 7 — Importar dashboards

Dashboards listos:

  • Node Exporter Full: ID 1860 en grafana.com
  • WireGuard: ID 12557 o más reciente

En Grafana: Dashboards → Import → pegar ID → elegir datasource Prometheus → Import.

Paso 8 — Alertas Discord vía webhook

Instalar Alertmanager:

cd /tmp
wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz
tar xzf alertmanager-0.27.0.linux-amd64.tar.gz
sudo cp alertmanager-0.27.0.linux-amd64/alertmanager /usr/local/bin/
sudo cp alertmanager-0.27.0.linux-amd64/amtool /usr/local/bin/
sudo useradd --no-create-home --shell /usr/sbin/nologin alertmanager
sudo mkdir -p /etc/alertmanager /var/lib/alertmanager
sudo chown alertmanager:alertmanager /etc/alertmanager /var/lib/alertmanager

Config /etc/alertmanager/alertmanager.yml:

global:
  resolve_timeout: 5m

route:
  receiver: discord

receivers:
  - name: discord
    webhook_configs:
      - url: 'https://discord.com/api/webhooks/XXXXXXX/YYYYYYY?wait=true'
        send_resolved: true

Genera el webhook Discord: Server Settings → Integrations → Webhooks → New Webhook.

Servicio /etc/systemd/system/alertmanager.service:

[Unit]
Description=Alertmanager
After=network.target

[Service]
User=alertmanager
Group=alertmanager
Type=simple
ExecStart=/usr/local/bin/alertmanager \
  --config.file=/etc/alertmanager/alertmanager.yml \
  --storage.path=/var/lib/alertmanager \
  --web.listen-address=127.0.0.1:9093

[Install]
WantedBy=multi-user.target
sudo chown alertmanager:alertmanager /etc/alertmanager/alertmanager.yml
sudo systemctl daemon-reload
sudo systemctl enable --now alertmanager

Queries útiles para un VPN VPS

En Grafana, estas queries son las más útiles día a día:

Bandwidth WireGuard total (Mbps):

rate(wireguard_sent_bytes_total[5m]) * 8 / 1e6 + rate(wireguard_received_bytes_total[5m]) * 8 / 1e6

Top 5 peers por bytes recibidos (24h):

topk(5, increase(wireguard_received_bytes_total[24h]))

Último handshake por peer (humanizado):

time() - wireguard_latest_handshake_seconds

CPU utilización %:

100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

Disk usage %:

100 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100

Backup y retención

Prometheus mantiene 30 días por defecto. Más allá, sube la retención (añade disco) o downsample con Thanos / VictoriaMetrics (overkill para VPS personal).

/var/lib/prometheus/ consume ~50-100 MB por día. A 30 días, ~2-3 GB máx. Tu VPS Contabo tiene 50 GB NVMe, margen amplio.

Hardening adicional

  • fail2ban en Grafana: crea filtro para intentos login. 5× fallos → ban 15 min.
  • Reverse proxy con auth básica: Caddy o Nginx delante de Grafana si quieres exponer dashboard a colaborador sin SSH tunnel. Pero prefiere siempre el túnel WireGuard si es posible.
  • TLS: si expones Grafana fuera del LAN/túnel, certbot + Caddy en 5 minutos.

Veredicto

Con esta stack tienes visu en tiempo real de todo lo que pasa en tu VPN VPS. Ves inmediatamente cuando un peer hace 200 GB en una noche, cuando el CPU spike, cuando un peer no handshakea desde 1h.

Son 30 minutos de setup una vez, y 14 meses de paz con un Contabo VPS S que aguanta sus 200 Mbps sin sorpresas.

Para arrancar:

El VPS que usamos: /go/contabo — 4,99 €/mes, 200 Mbps, jurisdicción Alemania GDPR. Nuestra reseña completa Contabo VPS tras 14 meses de uso continuo.

★ Datacenter Nuremberg GDPR · ✓ IPv4 dédiée incluse · 200+ Mbps garantis

Probar Contabo30 jours satisfait ou remboursé