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 un setup de qualité production pour un Contabo Cloud VPS 10. 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.
Pourquoi monitorer un VPN self-host (et ne pas juste regarder wg show)
Faire wg show dans un terminal te donne l'état instantané : les peers connectés, le dernier handshake, le total des bytes échangés depuis le démarrage du tunnel. C'est utile pour un debug ponctuel, mais ça ne te dira jamais combien de bande passante tu consommais hier à 22h, ni quel peer monopolise ton upload depuis trois jours, ni si ta latence Paris ↔ Nuremberg a doublé silencieusement à cause d'un peering BGP cassé chez l'upstream Contabo. Pour ça il faut du time-series : enregistrer la valeur d'une métrique toutes les 15 secondes, garder l'historique 30 jours, et pouvoir interroger « moyenne du throughput entre 18h et 22h, sur les 14 derniers jours ouvrés ». C'est exactement ce que Prometheus fait, et c'est exactement pour ça que Grafana existe par-dessus.
L'autre raison qu'on sous-estime souvent : les alertes proactives. Sans monitoring, tu découvres un tunnel coupé quand un peer t'envoie un message Telegram « ça ne marche plus chez moi ». Avec Alertmanager + un webhook Discord, tu reçois la notification dans la minute qui suit la panne, généralement avant que tes utilisateurs s'en rendent compte. Le genre d'incidents que ça détecte tôt : un OOM du process WireGuard suite à un peer mal configuré qui ouvre des centaines de connexions parallèles, un disque qui se remplit silencieusement à cause d'un log rotation cassé, ou un upstream coupé pendant une maintenance non annoncée. Sans le monitoring, ces cas sont galère à diagnostiquer.
Enfin, c'est la base de la transparence pour les utilisateurs. Si tu héberges un VPN pour ta famille ou ton entreprise, pouvoir leur montrer un dashboard public en lecture seule avec uptime + bande passante consommée donne une crédibilité que personne d'autre n'offre côté grand public (NordVPN ne publie pas son uptime, ExpressVPN non plus).
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 :
- Settings → Data Sources → Add data source → Prometheus
- URL :
http://127.0.0.1:9090 - Save & Test → "Data source is working"
Étape 7 - Importer les dashboards
Dashboards prêts à l'emploi :
- Node Exporter Full : ID
1860sur grafana.com - métriques système complètes - WireGuard : ID
12557ou 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 75 Go NVMe, large marge.
Erreurs courantes à éviter pendant le setup
Voici une liste de pièges fréquents qui font perdre des heures à diagnostiquer si on n'a pas le réflexe de les vérifier d'emblée.
Le premier classique : oublier le flag -n /etc/wireguard/wg0.conf sur wireguard_exporter. Sans ce flag, l'exporter te sort les métriques labellisées par clé publique nue (44 caractères base64), ce qui rend les dashboards Grafana illisibles. Tu vois wireguard_sent_bytes_total{public_key="aB3xR9..."} au lieu de wireguard_sent_bytes_total{peer="laptop-eric"}. Pour que les noms soient repris, il faut que tu commentes chaque peer dans ton wg0.conf avec un # friendly_name = "laptop-eric" juste au-dessus de la section [Peer]. C'est ce que l'exporter parse.
Deuxième erreur fréquente : binder Prometheus sur 0.0.0.0:9090 parce que les tutos copient bêtement la config par défaut. Si ton VPS est exposé sur Internet et que ton firewall iptables n'est pas restrictif, ton instance Prometheus devient accessible publiquement avec toute ton infra interne visible. On a vu trois cas Reddit où des Prometheus exposés ont servi de point d'entrée à des attaquants pour cartographier toute l'infra avant d'attaquer ailleurs. La règle : tout sur 127.0.0.1 sauf si tu as une raison documentée du contraire.
Troisième piège : ne pas configurer --storage.tsdb.retention.time. Par défaut Prometheus 2.x garde 15 jours. Sur un Cloud VPS 10 de Contabo avec 75 Go de NVMe c'est très conservatif - tu peux confortablement monter à 30 ou 60 jours sans saturer le disque. On garde 30 jours, ça permet de comparer le mois courant au mois précédent et de détecter les drifts saisonniers (rentrée scolaire : +40 % de bande passante chez les peers familiaux, par exemple).
Quatrième piège, lié à WireGuard plus qu'au monitoring : l'exporter dépend de la commande wg qui doit être accessible au user root (le service systemd qu'on a écrit utilise root). Si tu lances l'exporter en non-root pour suivre une best practice de sécurité, il faut passer setcap cap_net_admin+ep au binaire wg ou utiliser sudo non interactif, sinon wg show échoue silencieusement et l'exporter retourne une réponse vide sans erreur claire dans les logs.
Cinquième : Grafana 11.x a changé la syntaxe par défaut de certaines query units. Si tu importes un dashboard ID 1860 (Node Exporter Full) sur Grafana 11+, certains panneaux affichent No data simplement parce que les unit names ont migré. Solution : éditer chaque panel concerné et choisir l'unit correcte (souvent bytes(IEC) au lieu de bytes).
Comparaison avec les alternatives (et pourquoi on reste sur Prometheus)
Avant de figer cette stack, on a comparé trois alternatives sérieuses.
Netdata est l'option la plus simple à installer (bash <(curl -fsSL https://my-netdata.io/kickstart.sh) et tu as un dashboard complet en 3 minutes). Mais le modèle de données Netdata Cloud est SaaS par défaut, et la version self-host complète demande quand même un account central. Pour un setup privacy-first où tout doit rester sur ton VPS, c'est un compromis qu'on n'a pas voulu faire. Netdata reste excellent pour du monitoring de poste local ou d'un homelab interne.
InfluxDB + Telegraf est l'alternative time-series à Prometheus. Telegraf collecte, InfluxDB stocke. Modèle push (Telegraf pousse vers Influx) vs pull (Prometheus scrape les exporters). Le push est plus simple côté firewall (pas besoin que Prometheus accède à chaque exporter, il suffit que Telegraf accède à Influx), mais ça impose un agent par host. Sur un VPS unique c'est neutre, sur plusieurs hosts ça devient un avantage. On préfère Prometheus pour la richesse de PromQL (langage de query) et l'écosystème massif de dashboards Grafana déjà existants.
Zabbix reste le standard old-school pour les SysAdmins entreprise. Très puissant, très complet, mais lourd à configurer et la UI est de l'autre côté de l'esthétique 2026. Pour un VPN self-host perso ou petite équipe, c'est over-engineered. Garde Zabbix pour le datacenter avec 500 serveurs.
VictoriaMetrics est un drop-in remplacement de Prometheus écrit en Go, 10× plus efficace en RAM et CPU à charge équivalente. Si tu montes au-delà de 10 VPS surveillés, c'est l'évolution naturelle. Pour 1-3 VPS, Prometheus suffit largement et reste plus standard pour trouver de l'aide en ligne.
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, pour une tranquillité durable avec un Contabo Cloud VPS 10 et sa connexion 200 Mbit/s annoncée. Pour un VPS perso ou familial, la consommation marginale de la stack en RAM et CPU est négligeable face à la visibilité gagnée. Sur un Contabo S avec 8 Go de RAM, tu utilises une petite fraction de tes ressources pour avoir une infrastructure de monitoring qu'aucun fournisseur commercial ne te donne sur leur portail.
L'investissement temps réel est très limité une fois en place. Hors maintenance Prometheus (zéro action courante hors update du binaire deux fois par an), on consulte les dashboards Grafana généralement par curiosité plus que par nécessité. Les alertes Discord arrivent suffisamment vite pour qu'on ne soit pas obligé de surveiller activement. Avec un seuil bien réglé (alerte après 2 checks échoués), le ratio signal/bruit reste excellent après quelques ajustements initiaux.
Si tu débutes le self-host VPN et que tu hésites à investir 30 minutes dans cette stack, retiens ça : tous les sysadmins expérimentés qu'on connaît regrettent de ne PAS avoir monitoré dès le jour 1. À l'inverse, personne ne regrette d'avoir installé Prometheus quand il était encore facile de le faire, avant que la production parte en charge et qu'on n'ait plus le temps de poser proprement la stack. Mieux vaut le poser ce week-end, avec quatre peers connectés et 5 Mbps de trafic, qu'attendre d'en avoir vingt et 150 Mbps pour découvrir qu'on aurait dû le faire avant.
Pour démarrer :
- Setup VPS Contabo + WireGuard en 20 min
- Templates WireGuard prêts à l'emploi
- Kill switch netfilter pour ne jamais fuiter
Le VPS qu'on recommande : Contabo Cloud VPS 10 - 5,50 €/mois, connexion 200 Mbit/s annoncée, juridiction Allemagne GDPR. Voir notre avis complet sur Contabo VPS.
★ Datacenter Nuremberg GDPR · ✓ IPv4 dédiée incluse · 200+ Mbps garantis
Héberge ton VPN sur ton propre VPS → ContaboAccès root complet · IPv4 publique · choisis ta région→

