Files
Michael Schiemer 95147ff23e refactor(deployment): Remove WireGuard VPN dependency and restore public service access
Remove WireGuard integration from production deployment to simplify infrastructure:
- Remove docker-compose-direct-access.yml (VPN-bound services)
- Remove VPN-only middlewares from Grafana, Prometheus, Portainer
- Remove WireGuard middleware definitions from Traefik
- Remove WireGuard IPs (10.8.0.0/24) from Traefik forwarded headers

All monitoring services now publicly accessible via subdomains:
- grafana.michaelschiemer.de (with Grafana native auth)
- prometheus.michaelschiemer.de (with Basic Auth)
- portainer.michaelschiemer.de (with Portainer native auth)

All services use Let's Encrypt SSL certificates via Traefik.
2025-11-05 12:48:25 +01:00
..

Minimalistic WireGuard VPN Setup

Purpose: Secure admin access to internal services (Traefik Dashboard, Prometheus, Grafana, etc.)

Architecture: Host-based WireGuard with IP-based service access (no DNS required)

Overview

Public Internet
    ↓
┌─────────────────────────────────────────┐
│ Server (Public IP)                      │
│                                         │
│ Public Ports:                           │
│   80/443  → Traefik (Public Apps)       │
│   22      → SSH                         │
│   51820   → WireGuard                   │
│                                         │
│ VPN Network (10.8.0.0/24):              │
│   10.8.0.1 → Server (VPN Gateway)       │
│                                         │
│ Admin Services (VPN-only):              │
│   https://10.8.0.1:8080  → Traefik      │
│   http://10.8.0.1:9090   → Prometheus   │
│   https://10.8.0.1:3001  → Grafana      │
│   http://10.8.0.1:9000   → Portainer    │
│   http://10.8.0.1:8001   → Redis Insight│
│                                         │
└─────────────────────────────────────────┘

Components

1. WireGuard (Host-based)

  • Interface: wg0
  • Server IP: 10.8.0.1/24
  • Port: 51820/udp
  • Management: systemd + wg-quick

2. nftables Firewall

  • VPN Access: 10.8.0.0/24 → All admin services
  • Public Access: Only ports 80, 443, 22
  • Default Policy: DROP all other traffic

3. Service Access (IP-based)

Service URL Purpose
Traefik Dashboard https://10.8.0.1:8080 Reverse Proxy Management
Prometheus http://10.8.0.1:9090 Metrics Collection
Grafana https://10.8.0.1:3001 Monitoring Dashboards
Portainer http://10.8.0.1:9000 Docker Management
Redis Insight http://10.8.0.1:8001 Redis Debugging

Quick Start

Server Setup (Automated)

# Deploy WireGuard + Firewall
cd deployment/ansible
ansible-playbook playbooks/setup-wireguard-host.yml

Client Setup

# Generate new client config
cd deployment/scripts
./generate-client-config.sh michael-laptop

# Import config (Linux/macOS)
sudo wg-quick up ./configs/michael-laptop.conf

# Import config (Windows)
# 1. Open WireGuard GUI
# 2. Import Tunnel from File
# 3. Select ./configs/michael-laptop.conf

# Import config (iOS/Android)
# Scan QR code generated by script

Verify Connection

# Check VPN connection
ping 10.8.0.1

# Access Traefik Dashboard
curl -k https://10.8.0.1:8080

Manual Server Setup

If you prefer manual installation:

1. Install WireGuard

# Ubuntu/Debian
sudo apt update
sudo apt install wireguard wireguard-tools qrencode

# Check kernel module
sudo modprobe wireguard
lsmod | grep wireguard

2. Generate Server Keys

# Create config directory
sudo mkdir -p /etc/wireguard
cd /etc/wireguard

# Generate keys
umask 077
wg genkey | tee server_private.key | wg pubkey > server_public.key

# Save keys
SERVER_PRIVATE_KEY=$(cat server_private.key)
SERVER_PUBLIC_KEY=$(cat server_public.key)

3. Create Server Config

sudo tee /etc/wireguard/wg0.conf <<EOF
[Interface]
PrivateKey = $SERVER_PRIVATE_KEY
Address = 10.8.0.1/24
ListenPort = 51820

# Firewall: Allow VPN traffic forwarding
PostUp = nft add table inet wireguard
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
PostUp = nft add chain inet wireguard forward { type filter hook forward priority filter\; }
PostUp = nft add rule inet wireguard postrouting oifname "eth0" ip saddr 10.8.0.0/24 masquerade
PostUp = nft add rule inet wireguard forward iifname "wg0" accept
PostUp = nft add rule inet wireguard forward oifname "wg0" ct state established,related accept

PostDown = nft delete table inet wireguard

# Peers will be added here
EOF

# Secure permissions
sudo chmod 600 /etc/wireguard/wg0.conf

4. Enable WireGuard

# Enable IP forwarding
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# Start WireGuard
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

# Check status
sudo wg show
sudo systemctl status wg-quick@wg0

5. Apply Firewall Rules

See deployment/ansible/templates/wireguard-firewall.nft.j2 for complete firewall configuration.

# Allow WireGuard port
sudo nft add rule inet filter input udp dport 51820 accept

# Allow VPN network to access admin services
sudo nft add rule inet filter input ip saddr 10.8.0.0/24 tcp dport { 8080, 9090, 3001, 9000, 8001 } accept

# Block public access to admin services
sudo nft add rule inet filter input tcp dport { 8080, 9090, 3001, 9000, 8001 } drop

Client Configuration

Generate Client

# Generate client keys
umask 077
wg genkey | tee client_private.key | wg pubkey > client_public.key
wg genpsk > client_preshared.key

CLIENT_PRIVATE_KEY=$(cat client_private.key)
CLIENT_PUBLIC_KEY=$(cat client_public.key)
CLIENT_PSK=$(cat client_preshared.key)

Add Client to Server

# Add peer to server config
sudo tee -a /etc/wireguard/wg0.conf <<EOF

[Peer]
# michael-laptop
PublicKey = $CLIENT_PUBLIC_KEY
PresharedKey = $CLIENT_PSK
AllowedIPs = 10.8.0.2/32
EOF

# Reload WireGuard
sudo systemctl reload wg-quick@wg0

Create Client Config File

# Create client config
cat > michael-laptop.conf <<EOF
[Interface]
PrivateKey = $CLIENT_PRIVATE_KEY
Address = 10.8.0.2/32
DNS = 1.1.1.1, 9.9.9.9

[Peer]
PublicKey = $SERVER_PUBLIC_KEY
PresharedKey = $CLIENT_PSK
Endpoint = YOUR_SERVER_IP:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25
EOF

Troubleshooting

VPN Not Connecting

# Check WireGuard status
sudo wg show

# Check firewall
sudo nft list ruleset | grep 51820

# Check logs
sudo journalctl -u wg-quick@wg0 -f

# Test connectivity
ping 10.8.0.1  # From client

Cannot Access Services

# Verify firewall allows VPN network
sudo nft list ruleset | grep "10.8.0.0"

# Check service is listening
sudo ss -tlnp | grep 8080  # Traefik Dashboard

# Test from VPN
curl -k https://10.8.0.1:8080  # From client

Key Rotation

Recommended: Rotate keys annually

# Generate new server keys
cd /etc/wireguard
wg genkey | tee server_private_new.key | wg pubkey > server_public_new.key

# Update server config
# ... update PrivateKey in wg0.conf

# Regenerate all client configs with new server PublicKey
# ... update clients

# Restart WireGuard
sudo systemctl restart wg-quick@wg0

Security Best Practices

1. Strong Cryptography

  • WireGuard uses modern crypto (ChaCha20, Poly1305, Curve25519)
  • Preshared keys for quantum resistance
  • Perfect forward secrecy

2. Firewall Isolation

  • Admin services only accessible via VPN
  • Explicit ALLOW rules, default DROP
  • Rate limiting on VPN port (optional)

3. Key Management

  • Private keys never leave server/client
  • Preshared keys for each peer
  • Annual key rotation recommended

4. Monitoring

  • Log all VPN connections
  • Alert on unusual traffic patterns
  • Regular security audits

Performance

  • Latency Overhead: <1ms (kernel-native)
  • Throughput: Near-native (minimal encryption overhead)
  • Concurrent Peers: 10-20 recommended
  • Keepalive: 25 seconds (NAT traversal)

Maintenance

Add New Client

./deployment/scripts/generate-client-config.sh new-device-name

Remove Client

# Edit server config
sudo nano /etc/wireguard/wg0.conf
# Remove [Peer] section

# Reload
sudo systemctl reload wg-quick@wg0

Backup Configuration

# Backup keys and configs
sudo tar -czf wireguard-backup-$(date +%Y%m%d).tar.gz /etc/wireguard/

Next Steps

  • Deploy WireGuard on server
  • Generate client configs for all devices
  • Test VPN connectivity
  • Verify admin service access
  • Optional: Add minimal CoreDNS for .internal domains (Phase 2)

Support