WireGuard
Overview¶
WireGuard is a modern, high-performance VPN protocol built into the Linux kernel. The solti-ensemble WireGuard role automates client configuration for secure remote connectivity.
Purpose: - Secure remote access to monitoring infrastructure - Encrypted data transport for metrics and logs - NAT traversal for hosts behind firewalls - Low-overhead VPN connectivity
Note: This role configures WireGuard clients that connect to existing WireGuard servers.
Key Features¶
Security¶
- Secure key generation (private/public key pairs)
- Pre-shared key support for additional security
- Automatic key backup
- Secure file permissions (600 for private keys)
Configuration¶
- Simple client setup
- Persistent connection mode
- Automatic route management
- DNS configuration support
Lifecycle Management¶
- Clean installation (
state: present) - Complete removal (
state: absent) - Configuration backup and restoration
- Idempotent operations
Installation¶
Basic Client Configuration¶
- hosts: remote_hosts
become: true
roles:
- role: jackaltx.solti_ensemble.wireguard
vars:
wireguard_state: present
wireguard_endpoint: "hub.example.com:51820"
wireguard_server_public_key: "{{ vault_wg_server_pubkey }}"
wireguard_client_address: "10.10.0.20/24"
wireguard_allowed_ips: "10.10.0.0/24"
Client with Pre-Shared Key¶
- hosts: remote_hosts
become: true
roles:
- role: jackaltx.solti_ensemble.wireguard
vars:
wireguard_endpoint: "hub.example.com:51820"
wireguard_server_public_key: "{{ vault_wg_server_pubkey }}"
wireguard_preshared_key: "{{ vault_wg_psk }}"
wireguard_client_address: "10.10.0.20/24"
wireguard_allowed_ips: "10.10.0.0/24"
Configuration Options¶
Required Variables¶
# WireGuard server endpoint
wireguard_endpoint: "hub.example.com:51820"
# Server's public key
wireguard_server_public_key: ""
# Client's VPN IP address
wireguard_client_address: "10.10.0.20/24"
Optional Variables¶
# State management
wireguard_state: present # 'present' to install, 'absent' to remove
# Network configuration
wireguard_allowed_ips: "10.10.0.0/24" # Routes through VPN
wireguard_dns: "10.10.0.1" # DNS server via VPN
wireguard_persistent_keepalive: 25 # Keep connection alive (NAT traversal)
# Security
wireguard_preshared_key: "" # Additional encryption layer
# Interface
wireguard_interface: "wg0" # Interface name
# Backup
wireguard_backup_enabled: true
wireguard_backup_dir: "/root/wireguard-backup"
Use Case: Remote Monitoring¶
Architecture¶
Remote Host (ispconfig3-server.example.com)
├─ WireGuard Client (10.10.0.20)
├─ Telegraf → sends to 10.10.0.11:8086
└─ Alloy → sends to 10.10.0.11:3100
↓ [WireGuard Tunnel]
Monitoring Hub (monitor11.example.com)
├─ WireGuard Server (10.10.0.11)
├─ InfluxDB (listens on 10.10.0.11:8086)
└─ Loki (listens on 10.10.0.11:3100)
Deployment¶
Step 1: Configure WireGuard on monitoring hub
(Server setup not covered by this role - use manual configuration or separate role)
# On hub: Generate server keys
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
# On hub: Create server config
cat > /etc/wireguard/wg0.conf << EOF
[Interface]
PrivateKey = $(cat /etc/wireguard/server_private.key)
Address = 10.10.0.11/24
ListenPort = 51820
[Peer]
# Client: ispconfig3-server.example.com
PublicKey = CLIENT_PUBLIC_KEY_HERE
AllowedIPs = 10.10.0.20/32
EOF
# Start server
systemctl enable --now wg-quick@wg0
Step 2: Deploy WireGuard client on remote host
- hosts: ispconfig3-server.example.com
become: true
roles:
- role: jackaltx.solti_ensemble.wireguard
vars:
wireguard_endpoint: "monitor11.example.com:51820"
wireguard_server_public_key: "{{ vault_wg_server_pubkey }}"
wireguard_client_address: "10.10.0.20/24"
wireguard_allowed_ips: "10.10.0.0/24"
wireguard_persistent_keepalive: 25
Step 3: Configure monitoring collectors
- hosts: ispconfig3-server.example.com
roles:
- role: jackaltx.solti_monitoring.telegraf
vars:
telegraf_outputs_influxdb_url: "http://10.10.0.11:8086"
- role: jackaltx.solti_monitoring.alloy
vars:
alloy_loki_endpoint: "http://10.10.0.11:3100"
Service Management¶
Check Status¶
Start/Stop/Restart¶
View Connection Status¶
Output:
interface: wg0
public key: CLIENT_PUBLIC_KEY
private key: (hidden)
listening port: 51820
peer: SERVER_PUBLIC_KEY
endpoint: 1.2.3.4:51820
allowed ips: 10.10.0.0/24
latest handshake: 45 seconds ago
transfer: 1.25 MiB received, 856.32 KiB sent
persistent keepalive: every 25 seconds
Check Connectivity¶
# Ping VPN gateway
ping -c 3 10.10.0.11
# Test monitoring endpoint
curl -I http://10.10.0.11:8086/health # InfluxDB
curl -s http://10.10.0.11:3100/ready # Loki
Key Management¶
Client Keys¶
The role automatically generates client keys if they don't exist:
# Private key (600 permissions)
/etc/wireguard/privatekey
# Public key (644 permissions)
/etc/wireguard/publickey
Backup Keys¶
Keys are backed up to configurable location:
Retrieve Client Public Key¶
After role execution, retrieve the public key:
# Method 1: From file
cat /etc/wireguard/publickey
# Method 2: From running interface
wg show wg0 public-key
Add this key to server's [Peer] section.
Network Configuration¶
AllowedIPs Patterns¶
Route only VPN network:
Route all traffic through VPN:
Route multiple networks:
Persistent Keepalive¶
Why needed: Maintains connection through NAT/firewall
When to use: - Client behind NAT/firewall - Monitoring with continuous data flow - Prevent connection timeouts
Configuration:
Disable if not needed (server-side connections):
Firewall Configuration¶
Client Firewall (if using ufw)¶
# Allow WireGuard UDP traffic
ufw allow 51820/udp
# Allow outbound to VPN network
ufw allow out to 10.10.0.0/24
Server Firewall (hub side)¶
# Rocky Linux
firewall-cmd --add-port=51820/udp --permanent
firewall-cmd --reload
# Debian/Ubuntu
ufw allow 51820/udp
Troubleshooting¶
Connection Not Establishing¶
Check service status:
Check configuration:
Verify keys:
# Client public key
cat /etc/wireguard/publickey
# Server public key (must match config)
grep PublicKey /etc/wireguard/wg0.conf
Test endpoint reachability:
No Handshake¶
Symptom: wg show displays no handshake or very old timestamp
Causes: - Firewall blocking UDP port 51820 - Incorrect endpoint address - Key mismatch - Server not running
Debug:
# Enable WireGuard debug logging
echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control
journalctl -kf | grep wireguard
Can Ping VPN but Not Services¶
Check routing:
Should see route via wg0:
Check services listening on VPN interface:
High CPU Usage¶
Possible causes: - Frequent keepalives (increase interval) - Large data transfers - Encryption overhead
Monitor:
Platform-Specific Notes¶
Debian 12¶
Package: wireguard
Module: Kernel module (mainline kernel ≥5.6)
Config: /etc/wireguard/wg0.conf
Rocky Linux 9¶
Package: wireguard-tools
Module: Kernel module (included in kernel)
Config: /etc/wireguard/wg0.conf
SELinux: No special configuration needed
Ubuntu 24.04¶
Package: wireguard
Module: Kernel module (included)
Config: /etc/wireguard/wg0.conf
Removal¶
Remove WireGuard (Keep Config)¶
- hosts: remote_hosts
become: true
roles:
- role: jackaltx.solti_ensemble.wireguard
vars:
wireguard_state: absent
wireguard_remove_config: false
Actions:
- Stop wg-quick@wg0 service
- Disable from boot
- Remove packages
- Keep /etc/wireguard/ directory
Complete Removal¶
- hosts: remote_hosts
become: true
roles:
- role: jackaltx.solti_ensemble.wireguard
vars:
wireguard_state: absent
wireguard_remove_config: true
Actions:
- Stop and disable service
- Remove packages
- Delete /etc/wireguard/ directory
- Delete backup directory
Security Best Practices¶
- Store Keys in Ansible Vault
# vars/vault.yml (encrypted)
vault_wg_server_pubkey: "SERVER_PUBLIC_KEY"
vault_wg_psk: "PRE_SHARED_KEY"
- Use Pre-Shared Keys
Adds quantum-resistant layer:
- Limit AllowedIPs
Route only necessary networks:
- Backup Keys Securely
- Monitor Connection Status
# Alert if no recent handshake
wg show wg0 latest-handshake | awk '{if (systime() - $2 > 300) print "WireGuard connection stale"}'
- Rotate Keys Periodically
Plan for key rotation (manual or automated):
# Generate new keys
wg genkey | tee /etc/wireguard/privatekey.new | wg pubkey > /etc/wireguard/publickey.new
Integration with solti-monitoring¶
Monitoring Architecture¶
# Deploy WireGuard + Monitoring stack
- hosts: remote_hosts
roles:
# 1. Establish VPN
- role: jackaltx.solti_ensemble.wireguard
vars:
wireguard_endpoint: "hub.example.com:51820"
wireguard_server_public_key: "{{ vault_wg_server_pubkey }}"
wireguard_client_address: "10.10.0.20/24"
wireguard_allowed_ips: "10.10.0.0/24"
# 2. Configure collectors
- role: jackaltx.solti_monitoring.telegraf
vars:
telegraf_outputs_influxdb_url: "http://10.10.0.11:8086"
- role: jackaltx.solti_monitoring.alloy
vars:
alloy_loki_endpoint: "http://10.10.0.11:3100"
Reference Deployment¶
ispconfig3-server.example.com (Linode VPS): - WireGuard client connected to monitor11 - VPN address: 10.10.0.20 - Routes monitoring traffic through VPN - Persistent keepalive: 25 seconds (NAT traversal) - Encrypted metrics and logs to hub
Resource Requirements¶
Client Resources¶
- CPU: Negligible (<1% for typical monitoring traffic)
- RAM: <100MB
- Disk: <10MB
- Network: Low overhead (~60 bytes per packet)
Performance¶
Throughput: Up to 1+ Gbps (depending on hardware)
Latency: +1-2ms vs unencrypted
CPU Usage: Minimal (kernel-space encryption)
Next Steps¶
- Monitoring Integration - Configure Telegraf and Alloy
- Security Hardening - Add fail2ban rules for WireGuard
- Multi-Site Deployment - Connect multiple remote hosts
- Server Configuration - Set up WireGuard hub (manual or separate role)