resist-vpn-infra/docs/TWO_TIER_DEPLOYMENT.md
2026-01-26 21:22:41 -05:00

9.7 KiB

# Two-Tier VPN Architecture Deployment Guide ## Architecture Overview This Ansible collection is designed for a two-tier VPN architecture: ### Tier 1: Admin Control Plane (ValleyForge) - WireGuard admin VPN (10.100.0.0/24) - Ansible control node - GitHub Actions runner (future) - 2-5 admin users ### Tier 2: User Data Plane (VPN1/VPN2/VPN3) - User-facing VPN endpoints (Algo/Outline) - 50-70 users per endpoint (200 total) - Separate VPN networks: - VPN1: 10.200.0.0/24 - VPN2: 10.201.0.0/24 - VPN3: 10.202.0.0/24

Prerequisites

Before You Start

  1. ValleyForge deployed with WireGuard admin VPN
  2. Ansible installed on ValleyForge
  3. SSH access from ValleyForge to VPN1/VPN2/VPN3
  4. ValleyForge public IP known

Step 1: Configure Inventory

Edit hosts.yml

On ValleyForge:

cd /root/ansible/secure_vpn_server
nano inventory/hosts.yml

Set your VPN endpoint IPs:

vpn_servers:
  hosts:
    vpn1:
      ansible_host: 203.0.113.10  # Your VPN1 public IP
    vpn2:
      ansible_host: 203.0.113.11  # Your VPN2 public IP
    vpn3:
      ansible_host: 203.0.113.12  # Your VPN3 public IP
  
  vars:
    valleyforge_public_ip: "185.112.147.205"  # Your ValleyForge public IP

Step 2: Configure Variables

Edit group_vars/vpn_servers.yml

nano inventory/group_vars/vpn_servers.yml

CRITICAL: Set management_allowed_sources:

# Allow management from ValleyForge
management_allowed_sources:
  - "185.112.147.205"  # Your ValleyForge public IP

# Or if you have VPN routing configured:
# management_allowed_sources:
#   - "10.100.0.0/24"  # ValleyForge admin VPN network

Configure users:

wg_peers:
  - name: user1
  - name: user2
  - name: user3
  # Add up to 70 users per endpoint

Verify host_vars

Check that each VPN endpoint has unique networks:

cat inventory/host_vars/vpn1.yml
# wg_network: "10.200.0.0/24"

cat inventory/host_vars/vpn2.yml
# wg_network: "10.201.0.0/24"

cat inventory/host_vars/vpn3.yml
# wg_network: "10.202.0.0/24"

Step 3: Validate Configuration

Run validation playbook:

ansible-playbook -i inventory/hosts.yml playbooks/validate.yml

Expected output:

TASK [Validate management_allowed_sources is defined]
ok: [vpn1] => {
    "msg": "✓ management_allowed_sources is configured"
}

TASK [Validate ValleyForge IP is set]
ok: [vpn1] => {
    "msg": "✓ ValleyForge IP is configured: 185.112.147.205"
}

TASK [Display configuration summary]
ok: [vpn1] => {
    "msg": [
        "Host: vpn1",
        "VPN Network: 10.200.0.0/24",
        "Management allowed from: 185.112.147.205",
        "Users configured: 3"
    ]
}

If validation fails:

  • Check that management_allowed_sources is set in group_vars/vpn_servers.yml
  • Check that valleyforge_public_ip is set in inventory/hosts.yml
  • Check that each host has unique wg_network in host_vars/

Step 4: Test SSH Access

From ValleyForge, test SSH to each endpoint:

ssh root@203.0.113.10  # VPN1
ssh root@203.0.113.11  # VPN2
ssh root@203.0.113.12  # VPN3

If SSH fails:

# Generate SSH key on ValleyForge
ssh-keygen -t ed25519

# Copy to VPN endpoints
ssh-copy-id root@203.0.113.10
ssh-copy-id root@203.0.113.11
ssh-copy-id root@203.0.113.12

Step 5: Deploy (Dry Run)

Test deployment without making changes:

ansible-playbook -i inventory/hosts.yml playbooks/site.yml --check --diff

Review output for errors:

  • Syntax errors
  • Missing variables
  • Connection issues

Step 6: Deploy to Single Endpoint (Test)

Deploy to VPN1 only:

ansible-playbook -i inventory/hosts.yml playbooks/site.yml --limit vpn1

Monitor deployment (~10-15 minutes):

  • System hardening
  • WireGuard installation
  • Firewall configuration

Expected final output:

TASK [Display deployment summary]
ok: [vpn1] => {
    "msg": [
        "=========================================",
        "Deployment Complete!",
        "=========================================",
        "Server: vpn1",
        "Public IP: 203.0.113.10",
        "VPN Network: 10.200.0.0/24",
        "Client configs: /root/wireguard-client-configs/",
        "Firewall config: /root/firewall-config.txt"
    ]
}

Step 7: Verify VPN1 Deployment

Check Services

# SSH to VPN1 (should still work from ValleyForge)
ssh root@203.0.113.10

# Check WireGuard
sudo wg show
# Should show wg0 interface

# Check firewall
sudo ufw status verbose
# Should show:
# - Port 51820/udp ALLOW from Anywhere (user VPN)
# - Port 22/tcp ALLOW from 185.112.147.205 (ValleyForge)
# - Port 22/tcp DENY from Anywhere (default deny)

# Check services
systemctl status wg-quick@wg0
systemctl status fail2ban
systemctl status sshd

# Exit
exit

Test Management Access

From ValleyForge:

# SSH should work (you're from allowed source)
ssh root@203.0.113.10
# Connected!

From your local machine (NOT ValleyForge):

# SSH should be BLOCKED
ssh root@203.0.113.10
# Connection refused or timeout

This is correct! Management is restricted to ValleyForge.


Step 8: Retrieve User Configs

From ValleyForge:

# Download VPN1 user configs
scp -r root@203.0.113.10:/root/wireguard-client-configs/ /root/vpn1-configs/

# Check configs
ls /root/vpn1-configs/
# user1.conf  user1_qr.txt
# user2.conf  user2_qr.txt
# user3.conf  user3_qr.txt

Step 9: Deploy to All Endpoints

If VPN1 test was successful:

# Deploy to VPN2 and VPN3
ansible-playbook -i inventory/hosts.yml playbooks/site.yml --limit vpn2,vpn3

# Or deploy to all at once
ansible-playbook -i inventory/hosts.yml playbooks/site.yml

Step 10: Retrieve All User Configs

# Download from all endpoints
scp -r root@203.0.113.10:/root/wireguard-client-configs/ /root/vpn1-configs/
scp -r root@203.0.113.11:/root/wireguard-client-configs/ /root/vpn2-configs/
scp -r root@203.0.113.12:/root/wireguard-client-configs/ /root/vpn3-configs/

Firewall Rules Explained

What Gets Configured

On each VPN endpoint (VPN1/VPN2/VPN3):

# Public ports (user VPN)
Port 51820/udp → ALLOW from Anywhere

# Management ports (restricted to ValleyForge)
Port 22/tcp → ALLOW from 185.112.147.205
Port 22/tcp → DENY from Anywhere

# Default policy
Incoming → DENY
Outgoing → ALLOW

Why This Works

  1. User VPN access: Port 51820 is open to internet for end users
  2. Management access: SSH only from ValleyForge public IP
  3. Security: All other management blocked from internet

Access Matrix

Source Destination Port Result
Internet VPN1/2/3 51820 (user VPN) ALLOWED
ValleyForge VPN1/2/3 22 (SSH) ALLOWED
Internet VPN1/2/3 22 (SSH) BLOCKED
Internet VPN1/2/3 80/443 BLOCKED

Troubleshooting

Can't SSH from ValleyForge After Deployment

Problem: SSH connection refused from ValleyForge

Solution:

# Use VPS console/VNC to access VPN endpoint
# Check firewall rules
sudo ufw status verbose

# Check if ValleyForge IP is allowed
sudo ufw status | grep 185.112.147.205

# If not, add it
sudo ufw allow from 185.112.147.205 to any port 22

# Or temporarily disable firewall
sudo ufw disable

Wrong ValleyForge IP in Firewall

Problem: Set wrong IP in management_allowed_sources

Solution:

# On ValleyForge, update group_vars
nano inventory/group_vars/vpn_servers.yml

# Fix the IP
management_allowed_sources:
  - "CORRECT.IP.ADDRESS.HERE"

# Re-deploy firewall only
ansible-playbook -i inventory/hosts.yml playbooks/firewall.yml

Users Can't Connect to VPN

Problem: User VPN port not accessible

Solution:

# Check firewall on VPN endpoint
ssh root@vpn-ip  # From ValleyForge
sudo ufw status | grep 51820

# Should show:
# 51820/udp ALLOW Anywhere

# If not, add it
sudo ufw allow 51820/udp

# Or re-deploy
ansible-playbook -i inventory/hosts.yml playbooks/firewall.yml

Validation Playbook Fails

Problem: management_allowed_sources not defined

Solution:

# Edit group_vars
nano inventory/group_vars/vpn_servers.yml

# Add this section
management_allowed_sources:
  - "YOUR_VALLEYFORGE_IP"

# Re-run validation
ansible-playbook -i inventory/hosts.yml playbooks/validate.yml

Adding Users

Add Users to Existing Endpoint

# On ValleyForge
cd /root/ansible/secure_vpn_server

# Edit group_vars or host_vars
nano inventory/group_vars/vpn_servers.yml

# Add user
wg_peers:
  - name: user1
  - name: user2
  - name: new_user4  # Add this

# Re-deploy WireGuard only
ansible-playbook -i inventory/hosts.yml playbooks/wireguard.yml --limit vpn1

# Retrieve new config
scp root@203.0.113.10:/root/wireguard-client-configs/new_user4.conf /root/

Monitoring

Check All Endpoints Status

# From ValleyForge
ansible vpn_servers -i inventory/hosts.yml -m shell -a "wg show"
ansible vpn_servers -i inventory/hosts.yml -m shell -a "ufw status"
ansible vpn_servers -i inventory/hosts.yml -m shell -a "systemctl status wg-quick@wg0"

Summary

Deployment complete when:

  1. All VPN endpoints deployed (VPN1/VPN2/VPN3)
  2. Firewall restricts management to ValleyForge
  3. User VPN ports open to internet
  4. User configs retrieved
  5. Services running (WireGuard, fail2ban, SSH)

Your infrastructure:

  • Secure: Management only from ValleyForge
  • Scalable: 200 users across 3 endpoints
  • Manageable: Centralized Ansible control
  • Resilient: Multiple endpoints for redundancy

Next steps:

  • Distribute user configs
  • Deploy collaboration server
  • Set up monitoring
  • Configure GitHub Actions (future)