# WireGuard Hub-and-Spoke VPN Setup Guide
A step-by-step guide to creating a secure VPN with a central hub and multiple spokes.

---
## Prerequisites
Before you start, gather the public IP addresses of all three virtual machines:
- **VM A Public IP:** `VM_A_PUBLIC_IP`
- **VM B Public IP:** `VM_B_PUBLIC_IP`
- **VM C Public IP:** `VM_C_PUBLIC_IP`
---
## Step 1: Install WireGuard on All Three VMs
**On Ubuntu / Debian:**
```bash
sudo apt update
sudo apt install wireguard -y
```
**On AlmaLinux / Rocky Linux / RHEL:**
```bash
# Enable the EPEL repository
sudo dnf install epel-release -y
# Install WireGuard tools
sudo dnf install wireguard-tools -y
```
---
## Step 2: Generate Keys on All Three VMs
Each VM needs its own unique pair of cryptographic keys. **Perform these commands on VM A, VM B, and VM C.**
```bash
# Create a directory for the keys
mkdir -p ~/.wireguard
cd ~/.wireguard
# Generate the keys
wg genkey | tee privatekey | wg pubkey > publickey
# Secure the private key file
chmod 600 privatekey
# View the keys so you can copy them
echo "--- PUBLIC KEY (Share this) ---"
cat publickey
echo "--- PRIVATE KEY (Keep this secret) ---"
cat privatekey
```
> **Important:** Copy and paste each VM's public and private key into a text editor. Label them clearly (e.g., "VM A Public Key," "VM B Private Key") so you don't mix them up.
---
## Step 3: Configure the Hub (VM B)
This is the central server. It will listen for connections from VM A and VM C and forward their traffic.
**1. Enable IP Forwarding**
```bash
# Enable forwarding now
sudo sysctl -w net.ipv4.ip_forward=1
# Make it permanent across reboots
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
```
**2. Create `/etc/wireguard/wg0.conf` on VM B**
> Replace `eth0` in the `PostUp`/`PostDown` lines with your VM's actual public network interface (find it with `ip a`).
```ini
# /etc/wireguard/wg0.conf on VM B (The Hub)
[Interface]
# VM B's private key and tunnel IP
PrivateKey = <PASTE_VM_B_PRIVATE_KEY_HERE>
Address = 10.10.0.1/24
ListenPort = 51820
# Firewall rules to NAT traffic from peers to the internet
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# --- Peer 1: VM A ---
[Peer]
# VM A's public key and assigned tunnel IP
PublicKey = <PASTE_VM_A_PUBLIC_KEY_HERE>
AllowedIPs = 10.10.0.2/32
# --- Peer 2: VM C ---
[Peer]
# VM C's public key and assigned tunnel IP
PublicKey = <PASTE_VM_C_PUBLIC_KEY_HERE>
AllowedIPs = 10.10.0.3/32
```
---
## Step 4: Configure the Spokes (VM A & VM C)
**On VM A** — create `/etc/wireguard/wg0.conf`:
```ini
# /etc/wireguard/wg0.conf on VM A (Spoke 1)
[Interface]
PrivateKey = <PASTE_VM_A_PRIVATE_KEY_HERE>
Address = 10.10.0.2/24
[Peer]
PublicKey = <PASTE_VM_B_PUBLIC_KEY_HERE>
Endpoint = <VM_B_PUBLIC_IP>:51820
AllowedIPs = 10.10.0.0/24, 93.184.216.34/32
PersistentKeepalive = 25
```
**On VM C** — create `/etc/wireguard/wg0.conf`:
```ini
# /etc/wireguard/wg0.conf on VM C (Spoke 2)
[Interface]
PrivateKey = <PASTE_VM_C_PRIVATE_KEY_HERE>
Address = 10.10.0.3/24
[Peer]
PublicKey = <PASTE_VM_B_PUBLIC_KEY_HERE>
Endpoint = <VM_B_PUBLIC_IP>:51820
AllowedIPs = 10.10.0.0/24, 93.184.216.34/32
PersistentKeepalive = 25
```
---
## Step 5: Start the Tunnels
Bring the `wg0` interface up on all three machines:
```bash
sudo wg-quick up wg0
```
To make WireGuard start automatically on boot:
```bash
sudo systemctl enable wg-quick@wg0
```
---
## Step 6: Verification
**1. Check Tunnel Status**
On any VM, run `sudo wg`. You should see your interface details and the latest handshake information for your peers.
**2. Ping Across the Tunnel**
- From VM A, ping the hub: `ping 10.10.0.1`
- From VM A, ping VM C: `ping 10.10.0.3`
- From VM C, ping VM A: `ping 10.10.0.2`
**3. Test the Specific Route**
On VM A or VM C, use `traceroute` to see the path your traffic takes:
```bash
# Install if needed: sudo apt install traceroute
traceroute example.com
```
The **first hop** should be the hub's tunnel IP (`10.10.0.1`). This confirms traffic is correctly going through the VPN.
