Set up comprehensive monitoring for your WireGuard VPN server using Prometheus metrics collection and Grafana visualization. This guide covers installing the WireGuard exporter, configuring alerting rules, and building dashboards to track connection status, bandwidth usage, and peer activity.
Prerequisites
- WireGuard VPN server installed and configured
- Root or sudo access
- Basic understanding of Prometheus and Grafana
- 4GB RAM minimum for monitoring stack
What this solves
WireGuard VPN servers need monitoring to track peer connections, bandwidth usage, and server health. This tutorial sets up Prometheus to collect WireGuard metrics and Grafana to visualize connection status, data transfer rates, and peer activity with automated alerting for connection failures or performance issues.
Step-by-step installation
Update system packages
Start by updating your package manager to ensure you get the latest versions of monitoring tools.
sudo apt update && sudo apt upgrade -y
Install Go programming language
The WireGuard Prometheus exporter is written in Go, so we need to install the Go compiler to build it from source.
sudo apt install -y golang-go git
Download and compile WireGuard Prometheus exporter
Clone the official WireGuard exporter repository and build the binary for monitoring WireGuard interfaces.
cd /opt
sudo git clone https://github.com/MindFlavor/prometheus_wireguard_exporter.git
cd prometheus_wireguard_exporter
sudo go build -o wireguard_exporter
Create WireGuard exporter user and directories
Create a dedicated system user for the exporter service with proper permissions to read WireGuard configuration.
sudo useradd --system --shell /bin/false --home /var/lib/wireguard-exporter wireguard-exporter
sudo mkdir -p /var/lib/wireguard-exporter
sudo cp wireguard_exporter /usr/local/bin/
sudo chmod +x /usr/local/bin/wireguard_exporter
sudo chown wireguard-exporter:wireguard-exporter /var/lib/wireguard-exporter
Configure WireGuard exporter systemd service
Create a systemd service file to run the WireGuard exporter as a daemon with proper security settings.
[Unit]
Description=Prometheus WireGuard Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=wireguard-exporter
Group=wireguard-exporter
Type=simple
ExecStart=/usr/local/bin/wireguard_exporter -n /etc/wireguard/wg0.conf
Restart=on-failure
RestartSec=5
CapabilityBoundingSet=CAP_NET_ADMIN
AmbientCapabilities=CAP_NET_ADMIN
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
[Install]
WantedBy=multi-user.target
Grant WireGuard exporter access to configuration
Add the exporter user to the necessary groups to read WireGuard configuration and interface statistics.
sudo usermod -a -G systemd-network wireguard-exporter
sudo chmod 640 /etc/wireguard/wg0.conf
sudo chgrp systemd-network /etc/wireguard/wg0.conf
Start and enable WireGuard exporter service
Enable the exporter service to start automatically on boot and verify it's collecting metrics properly.
sudo systemctl daemon-reload
sudo systemctl enable --now wireguard-exporter.service
sudo systemctl status wireguard-exporter.service
Install Prometheus server
Install Prometheus to collect and store WireGuard metrics from the exporter endpoint.
sudo apt install -y prometheus
Configure Prometheus to scrape WireGuard metrics
Update the Prometheus configuration to collect metrics from the WireGuard exporter endpoint every 15 seconds.
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "/etc/prometheus/wireguard-rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- localhost:9093
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
- job_name: 'wireguard'
static_configs:
- targets: ['localhost:9586']
scrape_interval: 10s
metrics_path: /metrics
Create WireGuard alerting rules
Define Prometheus alerting rules to notify when WireGuard peers disconnect or bandwidth thresholds are exceeded.
groups:
- name: wireguard
rules:
- alert: WireGuardPeerDown
expr: wireguard_peer_up == 0
for: 2m
labels:
severity: warning
annotations:
summary: "WireGuard peer {{ $labels.peer }} is down"
description: "WireGuard peer {{ $labels.peer }} on interface {{ $labels.interface }} has been down for more than 2 minutes."
- alert: WireGuardHighBandwidth
expr: rate(wireguard_peer_receive_bytes_total[5m]) > 100000000 or rate(wireguard_peer_transmit_bytes_total[5m]) > 100000000
for: 5m
labels:
severity: info
annotations:
summary: "High bandwidth usage on WireGuard peer {{ $labels.peer }}"
description: "WireGuard peer {{ $labels.peer }} is using high bandwidth: {{ $value }} bytes/sec over 5 minutes."
- alert: WireGuardExporterDown
expr: up{job="wireguard"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "WireGuard Prometheus exporter is down"
description: "The WireGuard Prometheus exporter has been down for more than 1 minute."
- alert: WireGuardOldHandshake
expr: time() - wireguard_peer_last_handshake_seconds > 300
for: 0m
labels:
severity: warning
annotations:
summary: "WireGuard peer {{ $labels.peer }} has stale handshake"
description: "WireGuard peer {{ $labels.peer }} last handshake was {{ $value }} seconds ago."
Install Prometheus Alertmanager
Install Alertmanager to handle alert notifications from Prometheus rules and send them to external systems.
sudo apt install -y prometheus-alertmanager
Configure Alertmanager for email notifications
Set up Alertmanager to send email notifications when WireGuard monitoring alerts are triggered.
global:
smtp_smarthost: 'localhost:587'
smtp_from: 'alertmanager@example.com'
smtp_auth_username: 'alertmanager@example.com'
smtp_auth_password: 'your-email-password'
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 1h
receiver: 'wireguard-alerts'
receivers:
- name: 'wireguard-alerts'
email_configs:
- to: 'admin@example.com'
subject: 'WireGuard Alert: {{ .GroupLabels.alertname }}'
body: |
{{ range .Alerts }}
Alert: {{ .Annotations.summary }}
Description: {{ .Annotations.description }}
Labels: {{ .Labels }}
{{ end }}
Install Grafana dashboard
Install Grafana to create visual dashboards for WireGuard metrics and monitoring data.
sudo apt install -y apt-transport-https software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
Configure Grafana data source
Create a Grafana configuration file to automatically provision Prometheus as a data source.
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://localhost:9090
isDefault: true
editable: true
Create WireGuard Grafana dashboard configuration
Set up a comprehensive dashboard to visualize WireGuard peer connections, bandwidth usage, and handshake status.
{
"dashboard": {
"id": null,
"title": "WireGuard VPN Monitor",
"tags": ["wireguard", "vpn"],
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "Connected Peers",
"type": "stat",
"targets": [
{
"expr": "sum(wireguard_peer_up)",
"legendFormat": "Active Peers"
}
],
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 0}
},
{
"id": 2,
"title": "Total Bandwidth (In/Out)",
"type": "graph",
"targets": [
{
"expr": "rate(wireguard_peer_receive_bytes_total[5m]) * 8",
"legendFormat": "Received - {{ peer }}"
},
{
"expr": "rate(wireguard_peer_transmit_bytes_total[5m]) * 8",
"legendFormat": "Transmitted - {{ peer }}"
}
],
"yAxes": [
{
"unit": "bps",
"label": "Bits per second"
}
],
"gridPos": {"h": 8, "w": 12, "x": 6, "y": 0}
},
{
"id": 3,
"title": "Peer Status",
"type": "table",
"targets": [
{
"expr": "wireguard_peer_up",
"legendFormat": "",
"format": "table",
"instant": true
}
],
"gridPos": {"h": 8, "w": 18, "x": 0, "y": 8}
}
],
"time": {
"from": "now-1h",
"to": "now"
},
"refresh": "10s"
}
}
Start monitoring services
Enable and start all monitoring services to begin collecting and visualizing WireGuard metrics.
sudo systemctl enable --now prometheus
sudo systemctl enable --now prometheus-alertmanager
sudo systemctl enable --now grafana-server
Configure firewall for monitoring ports
Open the necessary ports for Prometheus, Alertmanager, and Grafana web interfaces.
sudo ufw allow 9090/tcp comment 'Prometheus'
sudo ufw allow 9093/tcp comment 'Alertmanager'
sudo ufw allow 3000/tcp comment 'Grafana'
sudo ufw allow 9586/tcp comment 'WireGuard Exporter'
Verify your setup
Test that all monitoring components are working correctly and collecting WireGuard metrics.
# Check WireGuard exporter metrics
curl http://localhost:9586/metrics | grep wireguard
Verify Prometheus is scraping targets
curl http://localhost:9090/api/v1/targets
Test Prometheus query for WireGuard peers
curl 'http://localhost:9090/api/v1/query?query=wireguard_peer_up'
Check service status
sudo systemctl status wireguard-exporter prometheus prometheus-alertmanager grafana-server
http://your-server-ip:3000 with default credentials admin/admin. Prometheus is available at http://your-server-ip:9090 and Alertmanager at http://your-server-ip:9093.Common issues
| Symptom | Cause | Fix |
|---|---|---|
| WireGuard exporter returns no metrics | Insufficient permissions to read WireGuard config | Check user groups with groups wireguard-exporter and file permissions |
| Prometheus can't scrape exporter | Firewall blocking port 9586 | Allow port with sudo ufw allow 9586/tcp |
| Grafana shows no data | Prometheus data source not configured | Verify datasource configuration and Prometheus URL |
| Alerts not firing | Alertmanager not connected to Prometheus | Check alertmanager targets in Prometheus at /targets |
| Exporter service fails to start | WireGuard config file not found | Update service file with correct config path |
Next steps
- Setup Grafana alerting with Slack and Microsoft Teams integration
- Configure Prometheus Alertmanager with email notifications for production monitoring
- Set up NGINX monitoring with Prometheus and Grafana for web server observability
- Configure WireGuard VPN high availability clustering with automatic failover
- Implement WireGuard user management automation with web interface
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# WireGuard Monitoring with Prometheus and Grafana Installation Script
# Supports: Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS, RHEL, Fedora
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Configuration
WIREGUARD_INTERFACE=${1:-wg0}
EXPORTER_PORT=9586
PROMETHEUS_PORT=9090
GRAFANA_PORT=3000
usage() {
echo "Usage: $0 [wireguard_interface]"
echo "Example: $0 wg0"
exit 1
}
cleanup() {
echo -e "${RED}Installation failed. Cleaning up...${NC}"
systemctl stop wireguard-exporter.service 2>/dev/null || true
systemctl disable wireguard-exporter.service 2>/dev/null || true
rm -f /etc/systemd/system/wireguard-exporter.service
rm -f /usr/local/bin/wireguard_exporter
userdel wireguard-exporter 2>/dev/null || true
rm -rf /var/lib/wireguard-exporter
rm -rf /opt/prometheus_wireguard_exporter
}
trap cleanup ERR
# Check if running as root or with sudo
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}This script must be run as root or with sudo${NC}"
exit 1
fi
# Detect distribution
echo -e "${YELLOW}[1/12] Detecting distribution...${NC}"
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update && apt upgrade -y"
PKG_INSTALL="apt install -y"
PROMETHEUS_CONFIG="/etc/prometheus/prometheus.yml"
PROMETHEUS_SERVICE="prometheus"
GRAFANA_CONFIG="/etc/grafana/grafana.ini"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
PROMETHEUS_CONFIG="/etc/prometheus/prometheus.yml"
PROMETHEUS_SERVICE="prometheus"
GRAFANA_CONFIG="/etc/grafana/grafana.ini"
if [[ "$ID" == "centos" && "${VERSION_ID%%.*}" -lt 8 ]]; then
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
fi
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
PROMETHEUS_CONFIG="/etc/prometheus/prometheus.yml"
PROMETHEUS_SERVICE="prometheus"
GRAFANA_CONFIG="/etc/grafana/grafana.ini"
;;
*)
echo -e "${RED}Unsupported distribution: $ID${NC}"
exit 1
;;
esac
echo -e "${GREEN}Detected: $PRETTY_NAME${NC}"
else
echo -e "${RED}Cannot detect distribution${NC}"
exit 1
fi
# Check if WireGuard is installed
echo -e "${YELLOW}[2/12] Checking WireGuard installation...${NC}"
if ! command -v wg >/dev/null 2>&1; then
echo -e "${RED}WireGuard is not installed. Please install WireGuard first.${NC}"
exit 1
fi
if [ ! -f "/etc/wireguard/$WIREGUARD_INTERFACE.conf" ]; then
echo -e "${RED}WireGuard configuration /etc/wireguard/$WIREGUARD_INTERFACE.conf not found${NC}"
exit 1
fi
echo -e "${GREEN}WireGuard is installed and configured${NC}"
# Update system packages
echo -e "${YELLOW}[3/12] Updating system packages...${NC}"
$PKG_UPDATE
# Install dependencies
echo -e "${YELLOW}[4/12] Installing dependencies...${NC}"
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL golang-go git curl wget
elif [[ "$PKG_MGR" == "dnf" || "$PKG_MGR" == "yum" ]]; then
$PKG_INSTALL golang git curl wget
if [[ "$ID" == "almalinux" || "$ID" == "rocky" || "$ID" == "centos" ]]; then
$PKG_INSTALL epel-release
fi
fi
# Download and compile WireGuard Prometheus exporter
echo -e "${YELLOW}[5/12] Building WireGuard Prometheus exporter...${NC}"
cd /opt
git clone https://github.com/MindFlavor/prometheus_wireguard_exporter.git
cd prometheus_wireguard_exporter
go build -o wireguard_exporter
# Create WireGuard exporter user and directories
echo -e "${YELLOW}[6/12] Creating system user and directories...${NC}"
useradd --system --shell /bin/false --home /var/lib/wireguard-exporter --create-home wireguard-exporter
mkdir -p /var/lib/wireguard-exporter
cp wireguard_exporter /usr/local/bin/
chmod 755 /usr/local/bin/wireguard_exporter
chown wireguard-exporter:wireguard-exporter /var/lib/wireguard-exporter
# Grant WireGuard exporter access
echo -e "${YELLOW}[7/12] Configuring permissions...${NC}"
usermod -a -G systemd-network wireguard-exporter
chmod 640 "/etc/wireguard/$WIREGUARD_INTERFACE.conf"
chgrp systemd-network "/etc/wireguard/$WIREGUARD_INTERFACE.conf"
# Create systemd service
echo -e "${YELLOW}[8/12] Creating systemd service...${NC}"
cat > /etc/systemd/system/wireguard-exporter.service << EOF
[Unit]
Description=Prometheus WireGuard Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=wireguard-exporter
Group=wireguard-exporter
Type=simple
ExecStart=/usr/local/bin/wireguard_exporter -n /etc/wireguard/$WIREGUARD_INTERFACE.conf
Restart=on-failure
RestartSec=5
CapabilityBoundingSet=CAP_NET_ADMIN
AmbientCapabilities=CAP_NET_ADMIN
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
[Install]
WantedBy=multi-user.target
EOF
# Start WireGuard exporter
echo -e "${YELLOW}[9/12] Starting WireGuard exporter...${NC}"
systemctl daemon-reload
systemctl enable --now wireguard-exporter.service
# Install Prometheus
echo -e "${YELLOW}[10/12] Installing Prometheus...${NC}"
if [[ "$PKG_MGR" == "apt" ]]; then
$PKG_INSTALL prometheus
elif [[ "$PKG_MGR" == "dnf" ]]; then
$PKG_INSTALL prometheus2
PROMETHEUS_SERVICE="prometheus2"
elif [[ "$PKG_MGR" == "yum" ]]; then
$PKG_INSTALL prometheus2 || $PKG_INSTALL prometheus
fi
# Configure Prometheus
echo -e "${YELLOW}[11/12] Configuring Prometheus...${NC}"
mkdir -p /etc/prometheus
cat > $PROMETHEUS_CONFIG << EOF
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:$PROMETHEUS_PORT']
- job_name: 'wireguard'
static_configs:
- targets: ['localhost:$EXPORTER_PORT']
scrape_interval: 10s
metrics_path: /metrics
EOF
chown prometheus:prometheus $PROMETHEUS_CONFIG
chmod 644 $PROMETHEUS_CONFIG
# Install and configure Grafana
echo -e "${YELLOW}[12/12] Installing Grafana...${NC}"
if [[ "$PKG_MGR" == "apt" ]]; then
curl -fsSL https://packages.grafana.com/gpg.key | apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | tee /etc/apt/sources.list.d/grafana.list
apt update
$PKG_INSTALL grafana
elif [[ "$PKG_MGR" == "dnf" || "$PKG_MGR" == "yum" ]]; then
cat > /etc/yum.repos.d/grafana.repo << EOF
[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF
$PKG_INSTALL grafana
fi
# Configure firewall
if command -v ufw >/dev/null 2>&1; then
ufw allow $EXPORTER_PORT/tcp
ufw allow $PROMETHEUS_PORT/tcp
ufw allow $GRAFANA_PORT/tcp
elif command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --permanent --add-port=$EXPORTER_PORT/tcp
firewall-cmd --permanent --add-port=$PROMETHEUS_PORT/tcp
firewall-cmd --permanent --add-port=$GRAFANA_PORT/tcp
firewall-cmd --reload
fi
# Start services
systemctl enable --now $PROMETHEUS_SERVICE
systemctl enable --now grafana-server
# Verification
echo -e "${GREEN}Installation completed! Verifying services...${NC}"
sleep 5
if systemctl is-active --quiet wireguard-exporter.service; then
echo -e "${GREEN}✓ WireGuard exporter is running${NC}"
else
echo -e "${RED}✗ WireGuard exporter failed to start${NC}"
exit 1
fi
if systemctl is-active --quiet $PROMETHEUS_SERVICE; then
echo -e "${GREEN}✓ Prometheus is running${NC}"
else
echo -e "${RED}✗ Prometheus failed to start${NC}"
exit 1
fi
if systemctl is-active --quiet grafana-server; then
echo -e "${GREEN}✓ Grafana is running${NC}"
else
echo -e "${RED}✗ Grafana failed to start${NC}"
exit 1
fi
# Test endpoints
if curl -s localhost:$EXPORTER_PORT/metrics >/dev/null; then
echo -e "${GREEN}✓ WireGuard exporter metrics available${NC}"
else
echo -e "${RED}✗ WireGuard exporter metrics not accessible${NC}"
fi
if curl -s localhost:$PROMETHEUS_PORT >/dev/null; then
echo -e "${GREEN}✓ Prometheus web interface accessible${NC}"
else
echo -e "${RED}✗ Prometheus web interface not accessible${NC}"
fi
echo -e "${GREEN}"
echo "=================================================="
echo "WireGuard Monitoring Setup Complete!"
echo "=================================================="
echo "WireGuard Exporter: http://localhost:$EXPORTER_PORT/metrics"
echo "Prometheus: http://localhost:$PROMETHEUS_PORT"
echo "Grafana: http://localhost:$GRAFANA_PORT (admin/admin)"
echo ""
echo "Next steps:"
echo "1. Access Grafana and change default password"
echo "2. Add Prometheus as data source (http://localhost:$PROMETHEUS_PORT)"
echo "3. Import WireGuard dashboard"
echo -e "${NC}"
Review the script before running. Execute with: bash install.sh