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 · Fundador · VPNSmith - Especialista en VPN self-host y VPS GDPR7 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 un setup de calidad producción para un Contabo Cloud VPS 10. node_exporter para el sistema, wireguard_exporter para los peers, Prometheus para el almacenamiento, Grafana para la visu, Alertmanager + webhook Discord para alertas.

Por qué monitorizar un VPN self-host (y no solo mirar wg show)

Ejecutar wg show en un terminal te da el estado instantáneo: peers conectados, último handshake, total de bytes intercambiados desde el arranque del túnel. Es útil para un debug puntual, pero nunca te dirá cuánto ancho de banda consumiste ayer a las 22h, qué peer monopoliza tu upload desde hace tres días, o si tu latencia París-Nuremberg se ha duplicado silenciosamente por culpa de un peering BGP roto en el upstream Contabo. Para eso necesitas time-series: registrar el valor de una métrica cada 15 segundos, guardar el histórico 30 días, y poder consultar «media de throughput entre 18h y 22h, sobre los últimos 14 días laborables». Eso es exactamente lo que hace Prometheus, y eso es exactamente para lo que existe Grafana por encima.

La otra razón que se subestima a menudo: las alertas proactivas. Sin monitorización, descubres un túnel cortado cuando un peer te manda un mensaje Telegram «ya no funciona en mi casa». Con Alertmanager + un webhook Discord, recibes la notificación en el minuto que sigue a la avería, generalmente antes de que tus usuarios se den cuenta. El tipo de incidentes que esto detecta a tiempo: un OOM del proceso WireGuard tras un peer mal configurado que abre cientos de conexiones paralelas, un disco que se llena silenciosamente por un log rotation roto, o un upstream cortado durante un mantenimiento no anunciado. Sin la monitorización, esos casos son difíciles de diagnosticar.

Por último, es la base de la transparencia para los usuarios. Si alojas un VPN para tu familia o tu empresa, poder mostrarles un dashboard público en solo lectura con uptime + ancho de banda consumido da una credibilidad que nadie ofrece del lado consumer (NordVPN no publica su uptime, ExpressVPN tampoco).

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

Un pasillo de una sala de servidores
Un pasillo de una sala de servidores

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 75 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, para una tranquilidad duradera con un Contabo Cloud VPS 10 y su conexión 200 Mbit/s anunciada.

Para arrancar:

El VPS que recomendamos: Contabo Cloud VPS 10 - 5,50 €/mes, conexión 200 Mbit/s anunciada, jurisdicción Alemania GDPR. Ver nuestra reseña completa Contabo VPS.

★ Datacenter Núremberg GDPR · ✓ IPv4 dedicada incluida · 200+ Mbps garantizados

Aloja tu VPN en tu propio VPS → ContaboAcceso root completo · IPv4 pública · elige tu región

Preguntas frecuentes

¿El monitoring impacta el rendimiento del VPS?
Marginal. node_exporter + wireguard_exporter + prometheus consumen ~80 MB RAM y <1% CPU en Cloud VPS 10 de Contabo. Grafana añade ~150 MB. Todo cabe holgadamente en 8 GB RAM.
¿Hace falta un VPS dedicado para Prometheus?
No para uso personal. Todo puede correr en el mismo VPS que tu túnel WireGuard. Para infra multi-VPS (>5 servidores), separa Prometheus en host dedicado y haz scrape por red.
¿Cómo evitar exponer Grafana en Internet?
Bind Grafana en 127.0.0.1:3000 y accede vía túnel SSH (ssh -L 3000:127.0.0.1:3000 vps). O vía el propio túnel WireGuard (10.66.66.1:3000). Ningún puerto público abierto.