VPNSmith
self-host-vpnINFO

Monitorer son VPN VPS avec Prometheus + Grafana (2026)

Stack monitoring complète : node_exporter, wireguard_exporter, dashboards Grafana, alertes uptime/throughput, intégration Discord webhook. Setup 30 min.

Par Eric Gerard · Fondateur · VPNSmith — Spécialiste self-host VPN & VPS GDPR7 min de lecturePhoto via Unsplash

Ton tunnel WireGuard marche. Mais tu te demandes : combien de Mbps il consomme aux heures de pointe ? Quels peers se connectent quand ? Le VPS Contabo tient-il vraiment ses 200 Mbps annoncés ? Tu pourrais ouvrir un terminal et tail -f journalctl à chaque doute, ou installer une stack Prometheus + Grafana en 30 minutes qui te donne les réponses en visuel, alerte sur incidents, et garde l'historique.

Ce guide implémente le setup qu'on utilise nous-mêmes sur Contabo VPS S depuis 14 mois. node_exporter pour le système, wireguard_exporter pour les peers, Prometheus pour le stockage, Grafana pour la visu, Alertmanager + webhook Discord pour les alertes.

Architecture

Tout tourne sur le même VPS Contabo. Trois processus systemd :

  • node_exporter (port 9100) : métriques système (CPU, RAM, disque, réseau)
  • wireguard_exporter (port 9586) : métriques peers WireGuard (handshake, bytes_in/out, last_seen)
  • prometheus (port 9090) : scrape les exporters toutes les 15s, stocke 30 jours
  • grafana (port 3000) : dashboards
  • alertmanager (port 9093) : règles d'alerte + webhook Discord

Coût : ~250 Mo RAM, ~3 % CPU permanent sur un VPS 4 vCPU. Aucun impact perceptible sur le tunnel.

Étape 1 — Installer node_exporter

# Sur le VPS, en sudo
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

Service 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

Important : on bind sur 127.0.0.1 (pas 0.0.0.0) — pas d'exposition publique. Prometheus accédera via localhost.

sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
curl -s http://127.0.0.1:9100/metrics | head -20
# Doit retourner des métriques type "node_cpu_seconds_total"

Étape 2 — Installer prometheus-wireguard-exporter

L'exporter qu'on utilise : github.com/MindFlavor/prometheus_wireguard_exporter (Rust, ~3 Mo binaire, scrape la sortie de wg show).

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

Service /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

Le flag -n /etc/wireguard/wg0.conf permet à l'exporter d'utiliser les noms des peers (commentés dans le .conf) comme labels Prometheus. Plus lisible dans Grafana que des pubkeys nues.

sudo systemctl daemon-reload
sudo systemctl enable --now wireguard_exporter
curl -s http://127.0.0.1:9586/metrics | grep wireguard_
# Doit retourner wireguard_sent_bytes_total, wireguard_received_bytes_total, etc.

Étape 3 — Installer 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

Règles d'alerte /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% on {{ $labels.instance }}"

      - alert: WireGuardPeerDown
        expr: time() - wireguard_latest_handshake_seconds > 600
        for: 5m
        annotations:
          summary: "WG peer {{ $labels.peer }} hasn't handshaken in >10min"

      - alert: HighBandwidth
        expr: rate(node_network_transmit_bytes_total{device="eth0"}[5m]) * 8 > 180000000
        for: 10m
        annotations:
          summary: "Bandwidth > 180 Mbps on eth0 — approaching Contabo limit"

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

Service /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
sudo systemctl status prometheus
# Vérifier qu'il tourne, pas d'erreur de parse

Étape 4 — Installer 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

Édite /etc/grafana/grafana.ini pour binder sur localhost uniquement :

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

Étape 5 — Accéder à Grafana en sécurité

Au lieu d'ouvrir le port 3000 publiquement, tunnel SSH depuis ton laptop :

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

Puis ouvre http://127.0.0.1:3000 dans ton navigateur local. Login admin / admin (change immédiatement).

Alternative : accéder via le tunnel WireGuard. Si ton VPS est 10.66.66.1 côté VPN, fais http://10.66.66.1:3000 depuis n'importe quel peer connecté. Aucun port n'est exposé au public Internet.

Étape 6 — Configurer la datasource Prometheus

Dans Grafana :

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

Étape 7 — Importer les dashboards

Dashboards prêts à l'emploi :

  • Node Exporter Full : ID 1860 sur grafana.com — métriques système complètes
  • WireGuard : ID 12557 ou plus récent — peers, bandwidth, last_seen

Dans Grafana : Dashboards → Import → coller l'ID → choisir la datasource Prometheus → Import.

Pour un dashboard custom dédié VPN VPS, on a publié notre fichier JSON sur GitHub (lien dans le repo VPNSmith). Il contient :

  • Vue d'ensemble : RAM/CPU/disque/uptime
  • Bande passante eth0 (in/out, 1h/24h/7j)
  • Peers WireGuard : nom, dernier handshake, bytes échangés
  • Top peers par consommation
  • Alertes actives

Étape 8 — Alertes Discord via webhook

Installer 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

Configuration /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

Génère le webhook Discord : Server Settings → Integrations → Webhooks → New Webhook. Copie l'URL. Le format brut Prometheus n'est pas joli dans Discord — on utilise donc le pont PrometheusAlert-Discord ou un parser simple qui transforme en embed Discord propre.

Service /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

Métriques utiles pour un VPN VPS

Dans Grafana, ces queries Prometheus sont les plus utiles au quotidien :

Bandwidth WireGuard total (Mbps) :

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

Top 5 peers par bytes reçus (24h) :

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

Dernière handshake par peer (humain) :

time() - wireguard_latest_handshake_seconds

CPU utilisation % :

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 et rétention

Prometheus garde 30 jours par défaut (--storage.tsdb.retention.time=30d). Au-delà, soit tu augmentes la rétention (ajoute du disque), soit tu downsamples avec Thanos ou VictoriaMetrics (overkill pour un VPS perso).

Le /var/lib/prometheus/ consomme ~50-100 Mo par jour pour ce stack. À 30 jours, ~2-3 Go max. Ton VPS Contabo a 50 Go NVMe, large marge.

Hardening additionnel

  • fail2ban sur Grafana : crée un filter pour les tentatives login. Auth ratée 5×→ban 15 min.
  • Reverse proxy avec auth basique : Caddy ou Nginx devant Grafana si tu veux exposer le dashboard à un collègue sans passer par SSH tunnel. Mais préfère toujours le tunnel WireGuard si possible.
  • TLS : si tu exposes Grafana en dehors du LAN/tunnel, certbot + Caddy en 5 minutes.

Verdict

Avec cette stack, tu as une visu en temps réel de tout ce qui passe sur ton VPN VPS. Tu vois immédiatement quand un peer fait 200 Go en une nuit (probablement un téléchargement Linux ISO, ou Plex backup), quand le CPU spike (souvent un OOM kill mal réglé), quand un peer ne handshake plus depuis 1h (client mort ou disparu).

C'est 30 minutes de setup une fois, et 14 mois de paix avec un Contabo VPS S qui tient ses 200 Mbps sans surprise.

Pour démarrer :

Le VPS qu'on utilise : /go/contabo — 4,99 €/mois, 200 Mbps, juridiction Allemagne GDPR. Notre avis complet sur Contabo VPS après 14 mois d'usage continu.

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

Voir l'offre Contabo30 jours satisfait ou remboursé