Skip to main content
Lumos Gate Docs

WireGuard Tunnel

Encrypt all traffic between your shield VPS and origin server with WireGuard. Complete privacy and enhanced origin IP protection guide.

Overview

By default, traffic between your shield VPS and your origin server travels over the public internet. While Lumos Gate hides your origin IP from external attackers by proxying all traffic through the shield, the traffic itself between shield and origin is not encrypted at the network level (unless your origin serves HTTPS and SSL/TLS is configured end-to-end). This means your VPS provider, or anyone with access to the network path, could theoretically inspect the traffic between the shield and origin.

WireGuard solves this by creating an encrypted tunnel between the two servers. All traffic flows through this tunnel, ensuring complete privacy and adding another layer of origin IP protection.

Why Use WireGuard

  • End-to-end encryption. All traffic between shield and origin is encrypted with modern cryptography (ChaCha20, Poly1305). Even if someone has access to the network infrastructure -- including your VPS provider at the hypervisor level -- they cannot read the traffic.

  • Origin IP invisibility. Without WireGuard, your VPS provider can see the destination IP of outgoing connections from the shield VPS, which reveals your origin IP. With WireGuard, traffic goes to a local tunnel interface (10.0.0.x), and the origin's public IP is only known to the WireGuard configuration on the shield VPS.

  • Minimal performance overhead. WireGuard is built into the Linux kernel (since version 5.6) and adds approximately 3% CPU overhead. It is significantly faster than IPsec or OpenVPN, handling multi-gigabit throughput on modern hardware.

  • Simple configuration. WireGuard uses a single configuration file per server with just a handful of settings. No certificates, no complex PKI, no connection negotiation protocols.

  • Jurisdiction isolation. By placing your shield VPS and origin server in different countries and connecting them via WireGuard, you create strong jurisdictional separation. No single provider or authority has access to both the traffic content and the origin server location.

  • Stronger firewall rules. When combined with an origin firewall, you can restrict origin access to WireGuard tunnel IPs (private 10.x.x.x addresses) which cannot be spoofed from the public internet, making the firewall rules more secure than IP-based allow rules.

Prerequisites

Before starting, ensure you have:

  • Linux kernel 5.6+ on both servers (for built-in WireGuard support). Check with: uname -r
  • Root/sudo access on both the shield VPS and origin server
  • UDP port 51820 open on the shield VPS firewall (for incoming WireGuard connections)
  • A working Lumos Gate setup with at least one shield server and one domain configured

Note: All supported distributions (Debian 12+ and Ubuntu 24.04+) include WireGuard support out of the box with built-in kernel modules. See Supported OS for the full compatibility list.

Network Diagram

Before diving into the setup, here is what the network looks like with and without WireGuard:

WITHOUT WireGuard:
Internet -> Shield VPS (HAProxy) --[public internet, unencrypted]--> Origin (public IP visible to VPS provider)

WITH WireGuard:
Internet -> Shield VPS (HAProxy) --[encrypted WireGuard tunnel]--> Origin (only tunnel IP 10.0.0.2 visible)
            10.0.0.1                                                10.0.0.2

The shield VPS acts as the WireGuard "server" (listens on UDP port 51820), and the origin server connects to it as a "client" (initiates the connection with a keepalive).

Step-by-Step Setup

Step 1: Install WireGuard on Both Servers

Install WireGuard on both the shield VPS and the origin server:

Debian / Ubuntu:

sudo apt update && sudo apt install wireguard -y

Verify installation on both servers:

wg --version

Expected output:

wireguard-tools v1.0.20210914 - https://git.zx2c4.com/wireguard-tools/

Step 2: Generate Keys on Both Servers

Generate a private and public key pair on each server. Every WireGuard peer needs its own unique key pair.

On the shield VPS:

# Generate keys
wg genkey | sudo tee /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

# Secure the private key (critical -- must not be world-readable)
sudo chmod 600 /etc/wireguard/private.key

# Display the public key -- copy this, you will need it for the origin server config
sudo cat /etc/wireguard/public.key

Example output:

aB3dEfGhIjKlMnOpQrStUvWxYz0123456789abcde=

On the origin server:

# Generate keys
wg genkey | sudo tee /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

# Secure the private key
sudo chmod 600 /etc/wireguard/private.key

# Display the public key -- copy this, you will need it for the shield VPS config
sudo cat /etc/wireguard/public.key

Example output:

xY9zAbCdEfGhIjKlMnOpQrStUvWxYz0123456789ab=

Save both public keys. You will need each server's public key for the other server's configuration:

ServerPublic Key (example)Used In
Shield VPSaB3dEfGh...abcde=Origin server's [Peer] section
Origin ServerxY9zAbCd...9ab=Shield VPS's [Peer] section

Warning: Never share or expose private keys. The private key must stay on the server that generated it. Only the public key is shared between peers.

Step 3: Configure the Shield VPS (WireGuard Server)

Create the WireGuard configuration on your shield VPS. The shield VPS acts as the "server" -- it listens on a fixed UDP port for incoming connections.

sudo nano /etc/wireguard/wg0.conf

Paste the following configuration:

[Interface]
# Shield VPS tunnel IP -- this becomes the "source IP" for traffic to the origin
Address = 10.0.0.1/24
# Shield VPS private key (from Step 2)
PrivateKey = SHIELD_PRIVATE_KEY_HERE
# WireGuard listen port (UDP)
ListenPort = 51820

[Peer]
# Origin server public key (from Step 2)
PublicKey = ORIGIN_PUBLIC_KEY_HERE
# Only allow traffic from the origin's tunnel IP
AllowedIPs = 10.0.0.2/32

Replace the placeholder values:

  • SHIELD_PRIVATE_KEY_HERE -- Contents of /etc/wireguard/private.key on the shield VPS
  • ORIGIN_PUBLIC_KEY_HERE -- The public key you copied from the origin server in Step 2

Secure the configuration file:

sudo chmod 600 /etc/wireguard/wg0.conf

Open UDP port 51820 on the shield VPS firewall:

# UFW
sudo ufw allow 51820/udp

# Or iptables
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT

Note: The Lumos agent install script includes edge-setup.sh which tunes the VPS kernel for high performance. This does not conflict with WireGuard. However, if you have custom firewall rules, ensure UDP port 51820 is not blocked.

Step 4: Configure the Origin Server (WireGuard Client)

Create the WireGuard configuration on your origin server. The origin acts as the "client" -- it initiates the connection to the shield VPS.

sudo nano /etc/wireguard/wg0.conf

Paste the following configuration:

[Interface]
# Origin server tunnel IP
Address = 10.0.0.2/24
# Origin server private key (from Step 2)
PrivateKey = ORIGIN_PRIVATE_KEY_HERE

[Peer]
# Shield VPS public key (from Step 2)
PublicKey = SHIELD_PUBLIC_KEY_HERE
# Shield VPS public IP and WireGuard port -- replace with your actual shield VPS IP
Endpoint = 203.0.113.10:51820
# Only allow traffic from the shield's tunnel IP
AllowedIPs = 10.0.0.1/32
# Keep the connection alive (essential when origin is behind NAT or stateful firewall)
PersistentKeepalive = 25

Replace the placeholder values:

  • ORIGIN_PRIVATE_KEY_HERE -- Contents of /etc/wireguard/private.key on the origin server
  • SHIELD_PUBLIC_KEY_HERE -- The public key you copied from the shield VPS in Step 2
  • 203.0.113.10 -- Your shield VPS's actual public IP address

Secure the configuration file:

sudo chmod 600 /etc/wireguard/wg0.conf

Important: The PersistentKeepalive = 25 setting sends a keepalive packet every 25 seconds. This is essential when the origin server is behind NAT or a stateful firewall, as it keeps the UDP connection state alive. Without this, the NAT mapping may expire after a period of inactivity, causing the tunnel to stop working. Even if your origin is not behind NAT, this setting is harmless and recommended.

Step 5: Start WireGuard on Both Servers

Start WireGuard and enable it to start automatically on boot. Start the shield VPS first (since it is the "server" that listens for connections), then start the origin server.

On the shield VPS:

# Start WireGuard and enable on boot
sudo systemctl enable --now wg-quick@wg0

# Verify the interface is up
sudo wg show

Expected output:

interface: wg0
  public key: aB3dEfGhIjKlMnOpQrStUvWxYz0123456789abcde=
  private key: (hidden)
  listening port: 51820

On the origin server:

# Start WireGuard and enable on boot
sudo systemctl enable --now wg-quick@wg0

# Verify the interface is up and connected
sudo wg show

Expected output (after connection is established):

interface: wg0
  public key: xY9zAbCdEfGhIjKlMnOpQrStUvWxYz0123456789ab=
  private key: (hidden)
  listening port: 43210

peer: aB3dEfGhIjKlMnOpQrStUvWxYz0123456789abcde=
  endpoint: 203.0.113.10:51820
  allowed ips: 10.0.0.1/32
  latest handshake: 5 seconds ago
  transfer: 1.24 KiB received, 1.08 KiB sent
  persistent keepalive: every 25 seconds

The key indicator of a working connection is latest handshake: X seconds ago. If this field is missing, the peers have not successfully connected yet.

Step 6: Test the Tunnel

Verify connectivity through the tunnel from both sides:

From the shield VPS, ping the origin:

ping -c 4 10.0.0.2

Expected output:

PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=12.3 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=11.8 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=12.1 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=11.9 ms

From the origin, ping the shield:

ping -c 4 10.0.0.1

Test HTTP connectivity (if your origin serves web traffic):

# From the shield VPS, test HTTP through the tunnel
curl -v http://10.0.0.2

If pings succeed but HTTP fails, your origin server may have a firewall rule that only allows HTTP on specific interfaces. See the troubleshooting section below.

Step 7: Update Lumos Dashboard

Now that the WireGuard tunnel is active, update your domain configuration in Lumos to use the tunnel IP instead of the origin's public IP:

  1. Go to Dashboard -> Domains.
  2. Select your domain.
  3. Edit the origin server address.
  4. Change the origin IP from the public IP (e.g., 198.51.100.50) to the WireGuard tunnel IP: 10.0.0.2.
  5. Save the changes.

HAProxy will now forward traffic to 10.0.0.2, which routes through the encrypted WireGuard tunnel to your origin server.

Note: Lumos Gate explicitly allows private/tunnel IPs as valid origin addresses. WireGuard addresses (10.x.x.x), Docker networks (172.x.x.x), and localhost (127.x.x.x) are all accepted. Only non-routable addresses like 0.0.0.0 and link-local (169.254.x.x, fe80::) are rejected.

Step 8: Lock Down the Origin Firewall

This is a critical step that is often overlooked. Now that traffic flows through the WireGuard tunnel, configure your origin server's firewall to only accept web traffic from the tunnel IP, not from the public internet:

# On the origin server:

# Allow SSH (do this FIRST to avoid lockout)
sudo ufw allow 22/tcp

# Allow HTTP/HTTPS only from WireGuard tunnel
sudo ufw allow from 10.0.0.1 to any port 80 proto tcp
sudo ufw allow from 10.0.0.1 to any port 443 proto tcp

# Allow WireGuard traffic (so the tunnel itself works)
sudo ufw allow 51820/udp

# Block all other HTTP/HTTPS traffic
sudo ufw deny 80/tcp
sudo ufw deny 443/tcp

# Enable the firewall
sudo ufw enable

This is more secure than allowing the shield VPS's public IP because:

  • The tunnel IP 10.0.0.1 is a private address that cannot be spoofed from the public internet.
  • Even if someone discovers both the shield VPS's public IP and your origin's IP, they cannot send traffic that appears to come from 10.0.0.1.

See Origin Firewall for detailed firewall configuration including iptables alternatives, verification steps, and other ports to consider.

Multiple Origin Servers

If you have multiple origin servers behind the same shield VPS, assign each one a unique tunnel IP:

ServerTunnel IPRole
Shield VPS10.0.0.1Proxy / WAF
Origin Server 110.0.0.2Web application
Origin Server 210.0.0.3API server
Origin Server 310.0.0.4Database frontend

Add a [Peer] block for each origin server in the shield VPS configuration:

[Interface]
Address = 10.0.0.1/24
PrivateKey = SHIELD_PRIVATE_KEY_HERE
ListenPort = 51820

[Peer]
# Origin Server 1 (web app)
PublicKey = ORIGIN1_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32

[Peer]
# Origin Server 2 (API)
PublicKey = ORIGIN2_PUBLIC_KEY
AllowedIPs = 10.0.0.3/32

[Peer]
# Origin Server 3 (DB frontend)
PublicKey = ORIGIN3_PUBLIC_KEY
AllowedIPs = 10.0.0.4/32

Each origin server gets its own standard config pointing to the shield VPS, with its own unique Address (10.0.0.2, 10.0.0.3, etc.).

In the Lumos dashboard, set each domain's origin to the appropriate tunnel IP (e.g., app.example.com -> 10.0.0.2, api.example.com -> 10.0.0.3).

Multiple Shield Servers

If a domain is assigned to multiple shield VPS servers for failover, set up a WireGuard tunnel from each shield server to the origin. Use separate tunnel IPs for each shield:

# On the origin server -- multiple peers
[Interface]
Address = 10.0.0.2/24
PrivateKey = ORIGIN_PRIVATE_KEY

[Peer]
# Shield VPS 1 (primary)
PublicKey = SHIELD1_PUBLIC_KEY
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.0.0.1/32
PersistentKeepalive = 25

[Peer]
# Shield VPS 2 (secondary)
PublicKey = SHIELD2_PUBLIC_KEY
Endpoint = 203.0.113.20:51820
AllowedIPs = 10.0.1.1/32
PersistentKeepalive = 25

In this setup:

  • Shield VPS 1 has tunnel IP 10.0.0.1
  • Shield VPS 2 has tunnel IP 10.0.1.1 (different subnet to avoid routing conflicts)
  • The origin server connects to both shields and accepts traffic from both tunnel IPs

Update the origin firewall to allow both tunnel IPs:

sudo ufw allow from 10.0.0.1 to any port 80,443 proto tcp
sudo ufw allow from 10.0.1.1 to any port 80,443 proto tcp

Note: Using separate subnets (10.0.0.x and 10.0.1.x) is recommended for multi-shield setups to avoid routing ambiguity. If both shields are in the same /24 subnet, the origin might not know which shield to route return traffic through.

Adding or Removing a WireGuard Peer

Adding a New Origin Server

  1. Generate keys on the new origin server (Step 2 above).
  2. Add a new [Peer] block to the shield VPS config.
  3. Create the config on the new origin server.
  4. Restart WireGuard on the shield: sudo systemctl restart wg-quick@wg0
  5. Start WireGuard on the new origin: sudo systemctl enable --now wg-quick@wg0
  6. Update the domain origin address in the Lumos dashboard.

Removing an Origin Server

  1. Remove the [Peer] block from the shield VPS config.
  2. Restart WireGuard on the shield: sudo systemctl restart wg-quick@wg0
  3. Stop and disable WireGuard on the origin: sudo systemctl disable --now wg-quick@wg0
  4. Optionally, remove the keys: sudo rm /etc/wireguard/private.key /etc/wireguard/public.key /etc/wireguard/wg0.conf

Security Considerations

Jurisdiction Isolation

For maximum privacy, place your shield VPS and origin server in different countries and with different providers. With WireGuard:

  • The shield VPS provider sees encrypted traffic going to the origin but cannot read it.
  • The origin provider does not know the shield VPS is a proxy (it only sees WireGuard tunnel traffic from a single IP).
  • No single provider or jurisdiction has access to both the decrypted traffic and the origin server.

This is useful for protecting whistleblower sites, privacy-sensitive services, or applications that require strong jurisdictional separation. See VPS Providers for recommendations on providers in different jurisdictions.

Key Rotation

WireGuard keys do not expire, but it is good practice to rotate them periodically (e.g., every 6-12 months) or immediately if you suspect a key compromise:

  1. Generate new keys on both servers (Step 2).
  2. Update the configurations with new keys (Steps 3-4).
  3. Restart WireGuard on both servers:
# On both servers
sudo systemctl restart wg-quick@wg0
  1. Verify the tunnel is working (Step 6).

Tip: When rotating keys, update the shield VPS config first (with the new origin public key), then update the origin config (with the new shield public key). Restart both simultaneously. The tunnel will be briefly down during the restart (typically under 2 seconds).

Private Key Security

  • The private key file (/etc/wireguard/private.key) must have permissions 600 (owner-only read/write).
  • The WireGuard config file (/etc/wireguard/wg0.conf) also contains the private key and should have permissions 600.
  • Never commit private keys to version control, share them in chat, or include them in scripts.
  • If you suspect a private key has been compromised, rotate keys immediately on both servers.

Troubleshooting

Tunnel is up but no traffic flowing:

  • Check AllowedIPs on both sides. The shield must allow the origin's tunnel IP (10.0.0.2/32) and the origin must allow the shield's tunnel IP (10.0.0.1/32).
  • Verify HAProxy is configured to send traffic to the tunnel IP (10.0.0.2), not the origin's public IP. Check the domain settings in Dashboard -> Domains.
  • Run sudo wg show to check handshake status. If "latest handshake" is missing, the peers have not connected.
  • Check if the origin server's firewall is blocking traffic on the wg0 interface. Some firewall configurations block all traffic not explicitly allowed per interface.

Handshake not completing:

  • Ensure UDP port 51820 is open on the shield VPS:
# Check if the port is listening
sudo ss -ulnp | grep 51820

# Test from the origin server
nc -vzu SHIELD_PUBLIC_IP 51820
  • Verify the Endpoint in the origin's config points to the correct shield VPS public IP and port.
  • Check that public keys are correct on both sides. A common mistake is using the private key instead of the public key in the [Peer] section, or swapping the keys between servers.
  • Verify the config file syntax is correct: sudo wg-quick strip wg0 should print the config without errors.

High latency through the tunnel:

  • WireGuard itself adds less than 1ms of latency. High latency is due to geographic distance between servers or network congestion.
  • Diagnose the path: mtr 10.0.0.2 from the shield VPS.
  • Consider choosing a shield VPS provider geographically closer to your origin. See VPS Providers for options.

WireGuard not starting on boot:

  • Verify the service is enabled: sudo systemctl is-enabled wg-quick@wg0
  • Check for configuration errors by starting manually: sudo wg-quick up wg0 (shows errors in real time).
  • Verify the config file has correct permissions: ls -la /etc/wireguard/wg0.conf (should be -rw-------).
  • Check the system journal for errors: sudo journalctl -u wg-quick@wg0 --no-pager -n 50

Connection drops intermittently:

  • If the origin is behind NAT, ensure PersistentKeepalive = 25 is set in the origin's [Peer] section.
  • Check for MTU issues. WireGuard's default MTU is 1420 (to fit inside standard 1500-byte Ethernet frames with WireGuard overhead). Some networks with additional encapsulation (e.g., PPPoE) may need a lower MTU:
# Add to the [Interface] section of wg0.conf on both servers
MTU = 1380
  • Check system logs for WireGuard-related errors: dmesg | grep wireguard

After agent config push, traffic stops flowing:

  • A Lumos config push triggers a HAProxy reload. This should not affect the WireGuard tunnel, as WireGuard operates at the network level independently of HAProxy.
  • Verify the domain's origin address in the Lumos dashboard is still set to the tunnel IP (10.0.0.2), not the public IP.
  • Check HAProxy is routing to the correct backend: sudo haproxy -c -f /etc/haproxy/haproxy.cfg

Next Steps

  • Origin Firewall -- Lock down your origin to only accept traffic from the WireGuard tunnel
  • Multiple Servers -- Set up WireGuard with multiple shield servers for redundancy
  • Failover -- Configure DNS failover between multiple shield servers
  • Domains -- Update origin addresses to use WireGuard tunnel IPs
  • SSL/TLS -- Configure SSL certificates on your shield servers
  • VPS Providers -- Choose providers in different jurisdictions for maximum privacy
  • Architecture -- Understand how WireGuard fits into the overall Lumos Gate architecture
  • Troubleshooting -- General troubleshooting guide