11 KiB
🔌 VPN Stack - Your Encrypted Tunnel to Freedom
"The internet, but make it private!" - WireGuard
What's This All About?
WG-Easy is your self-hosted VPN server powered by WireGuard! It's like having your own private tunnel through the internet - encrypt all your traffic, bypass geo-restrictions, access your home network from anywhere, and surf safely on sketchy public WiFi. Plus, it has a beautiful web UI for managing clients! 🚇
The Privacy Protector
🛡️ WG-Easy
Container: vpn_app
Image: ghcr.io/wg-easy/wg-easy:15
Ports: 51820 (VPN), 51821 (Web UI)
Home: https://vpn.pivoine.art
WG-Easy makes WireGuard actually easy:
- 🎨 Beautiful Web UI: Manage VPN from browser
- 📱 QR Codes: Instant mobile setup
- 👥 Multi-Client: Unlimited devices
- ⚡ WireGuard: Modern, fast, secure protocol
- 📊 Traffic Stats: See bandwidth usage
- 🔒 Encrypted: Industry-standard crypto
- 🌍 Route All Traffic: Or split-tunnel
- 🚀 Performance: Faster than OpenVPN
WireGuard: The Modern VPN Protocol
Why WireGuard is Awesome
- ⚡ Fast: 4000+ lines of code vs OpenVPN's 600,000+
- 🔒 Secure: State-of-the-art cryptography
- 📱 Battery Friendly: Less power consumption
- 🔄 Roaming: Seamless connection switching
- 🐧 Linux Kernel: Built into Linux 5.6+
- 🎯 Simple: Easier to audit and configure
Configuration Breakdown
Network Configuration
The stack creates TWO networks:
wg Network (Internal WireGuard):
subnet: 10.42.42.0/24 # IPv4
subnet: fdcc:ad94:bacf:61a3::/64 # IPv6
Your VPN clients get IPs from this range.
kompose Network (External):
external: true
Connects to other services via Traefik.
Environment Variables
WireGuard Settings:
WG_HOST=vpn.pivoine.art # Your public domain/IP
WG_PORT=51820 # WireGuard port (UDP)
WG_DEFAULT_ADDRESS=10.42.0.x # Client IP range
WG_DEFAULT_DNS=1.1.1.1 # DNS for clients
WG_ALLOWED_IPS=0.0.0.0/0 # Route all traffic through VPN
Web UI Settings:
PORT=51821 # Web interface port
UI_TRAFFIC_STATS=true # Show bandwidth graphs
UI_CHART_TYPE=0 # Chart style
Security & Capabilities
Required Linux capabilities:
cap_add:
- NET_ADMIN # Network configuration
- SYS_MODULE # Load kernel modules
System controls:
sysctls:
- net.ipv4.ip_forward=1 # Enable IP forwarding
- net.ipv4.conf.all.src_valid_mark=1 # Packet routing
First Time Setup 🚀
1. Ensure Ports are Open
Firewall:
# Allow WireGuard port
sudo ufw allow 51820/udp
# Allow Web UI (temporary for setup)
sudo ufw allow 51821/tcp
Router:
- Forward UDP port 51820 to your server
- Check your router's port forwarding settings
2. Set Your Public Address
In .env:
# Use your domain
WG_HOST=vpn.yourdomain.com
# Or your public IP
WG_HOST=123.45.67.89
3. Start the Stack
docker compose up -d
4. Access Web UI
URL: https://vpn.pivoine.art
Password: (set via PASSWORD_HASH in .env)
5. Generate Password Hash
If you haven't set password yet:
# Generate bcrypt hash
echo -n 'your-password' | npx bcrypt-cli
# Or use Docker
docker run --rm -it node:alpine sh -c "npm install -g bcrypt-cli && echo -n 'your-password' | bcrypt"
# Copy hash to .env
PASSWORD_HASH=$2a$10$...your_hash...
Restart container:
docker compose restart
Creating VPN Clients 📱
Add a Client
- Login to Web UI: https://vpn.pivoine.art
- Click "New Client"
- Give it a name: "My iPhone", "Work Laptop", etc.
- Click "Create"
Mobile Setup (QR Code)
For iPhone/Android:
-
Install WireGuard app:
-
Open app → "Add tunnel" → "Scan QR code"
-
Scan the QR code from web UI
-
Give tunnel a name
-
Toggle on!
Desktop Setup (Config File)
For Windows/Mac/Linux:
-
Download WireGuard:
-
In web UI, click "Download" next to client
-
Import config file into WireGuard app
-
Activate tunnel!
Manual Configuration
Download the .conf file and inspect it:
[Interface]
PrivateKey = your_private_key
Address = 10.42.0.2/32
DNS = 1.1.1.1
[Peer]
PublicKey = server_public_key
PresharedKey = shared_key
Endpoint = vpn.pivoine.art:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Using Your VPN 🌐
Full Tunnel (All Traffic)
Default behavior - all internet traffic goes through VPN:
- ✅ Complete privacy
- ✅ Bypass geo-blocks
- ✅ Secure public WiFi
- ⚠️ Slightly slower (routing through your server)
Split Tunnel (Selective Routing)
Only route specific traffic through VPN.
Edit client config to only route home network:
AllowedIPs = 10.0.0.0/24 # Only home network
# Instead of: 0.0.0.0/0
Benefits:
- 🏠 Access home services
- 🌐 Normal internet speed
- 📊 Less VPN bandwidth
Traffic Statistics 📊
Web UI shows for each client:
- 📥 Download: Data received
- 📤 Upload: Data sent
- 🕐 Last Seen: When last connected
- 📈 Charts: Bandwidth over time
Common Use Cases
1. Secure Public WiFi ☕
Coffee Shop WiFi → WireGuard → Your Server → Internet
Encrypt traffic on untrusted networks.
2. Access Home Network 🏠
You (anywhere) → VPN → Home Network → NAS, Printer, etc.
Access devices as if you're home.
3. Bypass Geo-Restrictions 🌍
Your Location → VPN (Server Country) → Streaming Service
Appear to be in server's location.
4. Privacy from ISP 🕵️
Your Device → Encrypted Tunnel → Your Server → Internet
ISP only sees encrypted traffic to your server.
5. Multiple Locations 🗺️
Deploy VPN servers in different countries:
- USA server for US content
- EU server for European services
- Home server for local access
Security Features 🔒
Encryption
- Protocol: Noise Protocol Framework
- Key Exchange: Curve25519
- Cipher: ChaCha20-Poly1305
- Hash: BLAKE2s
Translation: Military-grade encryption! 💪
Authentication
- Public/Private Keys: Per-client keypairs
- Preshared Keys: Extra security layer
- Endpoint Verification: Prevents spoofing
Privacy
- No Logs: WireGuard doesn't log by default
- Perfect Forward Secrecy: Past sessions stay secure
- IP Masquerading: Hides your real IP
DNS Configuration 🌐
Default DNS (Cloudflare)
WG_DEFAULT_DNS=1.1.1.1
Other Options
Google:
WG_DEFAULT_DNS=8.8.8.8
Quad9 (Security):
WG_DEFAULT_DNS=9.9.9.9
AdGuard (Ad-blocking):
WG_DEFAULT_DNS=94.140.14.14
Custom (Your Pi-hole):
WG_DEFAULT_DNS=192.168.1.2
Performance Optimization ⚡
Enable BBR (Better Congestion Control)
# On host
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p
Increase MTU
# In client config
[Interface]
MTU = 1420 # Default, try 1500 if stable
Persistent Keepalive
# Keep connection alive through NAT
PersistentKeepalive = 25
Troubleshooting 🔧
Q: Can't connect to VPN?
# Check server is running
docker logs vpn_app
# Verify port is open
nc -zvu vpn.pivoine.art 51820
# Check firewall
sudo ufw status
Q: Connected but no internet?
# Verify IP forwarding
sysctl net.ipv4.ip_forward
# Should return: 1
# Check NAT rules
sudo iptables -t nat -L
Q: Slow speeds?
- Check server bandwidth
- Try different MTU values
- Enable BBR congestion control
- Use split-tunnel for non-sensitive traffic
Q: Client won't auto-reconnect?
- Add
PersistentKeepalive = 25to config - Check client has network connectivity
Q: DNS not working?
# Test DNS from client
nslookup google.com
# Change DNS in config
DNS = 8.8.8.8
Mobile Tips 📱
iOS
- On-Demand: Auto-connect on untrusted WiFi
- Shortcuts: Create Siri shortcuts
- Widget: Quick toggle from home screen
Android
- Always-On: VPN reconnects automatically
- Kill Switch: Block internet if VPN drops
- Split Tunneling: Exclude specific apps
Advanced Configuration
IPv6 Support
Already configured!
enable_ipv6: true
subnet: fdcc:ad94:bacf:61a3::/64
Custom Routing
Route only specific subnets:
AllowedIPs = 192.168.1.0/24, 10.0.0.0/24
Block specific IPs:
# On server
iptables -A FORWARD -d 192.168.1.100 -j DROP
Port Forwarding
Forward ports through VPN:
# Forward port 8080 to client
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to 10.42.0.2:8080
Monitoring & Logs
Check Connection Status
# Via web UI
https://vpn.pivoine.art
# Or check container
docker exec vpn_app wg show
View Logs
docker logs vpn_app -f
Bandwidth Stats
Web UI shows real-time graphs for each client!
Backup & Restore 🔄
Backup Configuration
# Backup WireGuard configs
docker exec vpn_app tar -czf /tmp/wg-backup.tar.gz /etc/wireguard
docker cp vpn_app:/tmp/wg-backup.tar.gz ./backups/
Restore
# Copy backup to container
docker cp ./backups/wg-backup.tar.gz vpn_app:/tmp/
# Extract
docker exec vpn_app tar -xzf /tmp/wg-backup.tar.gz -C /
# Restart
docker compose restart
Security Best Practices 🛡️
- Strong Password: Use bcrypt hash for web UI
- Regular Updates: Keep WG-Easy updated
- Firewall: Only expose necessary ports
- Client Management: Remove inactive clients
- Monitoring: Watch for unusual traffic
- Backups: Regular config backups
- Access Control: Limit who can create clients
Why Self-Host a VPN?
- 🔒 Full Control: Your server, your rules
- 💰 Cost Effective: No monthly fees
- 🚀 Performance: Direct to your server
- 🕵️ Privacy: No third-party logging
- 🌍 Flexibility: Use any server location
- 📊 Transparency: You know what's happening
- 🛠️ Customization: Configure exactly as needed
Resources
"Privacy is not about having something to hide. It's about protecting what you value." - VPN Philosophy 🔒✨