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 :
- 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 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 :
- Setup VPS Contabo + WireGuard en 20 min
- Templates WireGuard prêts à l'emploi
- Kill switch netfilter pour ne jamais fuiter
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é→