VPN Deployment Guide

    Deploying WG-Easy

    WG-Easy is a lightweight, Docker-based solution that bundles a WireGuard VPN server with an intuitive web-based admin interface. Eliminate the complexity of managing keys and configurations manually with a clean dashboard on RamNode's reliable VPS hosting.

    WireGuard VPN
    Web Admin UI
    Docker Compose
    QR Code Clients
    1

    What You Will Need

    RequirementDetails
    RamNode VPSKVM VPS with 1+ GB RAM, Ubuntu 22.04 or 24.04 LTS
    Domain name (optional)For HTTPS access to the web UI (e.g., vpn.yourdomain.com)
    SSH accessRoot or sudo-enabled user on your VPS
    Firewall portsUDP 51820 (WireGuard), TCP 443 (HTTPS) or TCP 51821 (HTTP)

    Why WG-Easy on RamNode?

    • WireGuard kernel-level performance on RamNode KVM instances with full root access
    • Web UI for effortless client management, QR codes, and real-time connection stats
    • Minimal resource footprint — runs comfortably on RamNode's $5/month plan (1 vCPU, 1 GB RAM)
    • Docker Compose deployment for reproducible, portable infrastructure
    • IPv4 and IPv6 dual-stack support with v15's complete rewrite
    2

    Prepare Your RamNode VPS

    Update system packages
    sudo apt update && sudo apt upgrade -y

    Verify Kernel WireGuard Support

    All modern Linux kernels (5.6+) include WireGuard natively. Verify your kernel version:

    Check kernel version
    uname -r

    Install Docker and Docker Compose

    Install Docker
    curl -fsSL https://get.docker.com | sh
    sudo usermod -aG docker $(whoami)
    newgrp docker
    
    # Verify installation
    docker --version
    docker compose version
    3

    Configure the Firewall

    Open required ports
    sudo ufw allow 22/tcp        # SSH
    sudo ufw allow 51820/udp     # WireGuard VPN tunnel
    sudo ufw allow 443/tcp       # HTTPS for web UI (if using Caddy)
    sudo ufw allow 51821/tcp     # HTTP web UI (if not using reverse proxy)
    sudo ufw enable
    sudo ufw status

    Tip: If you plan to use Caddy as a reverse proxy (recommended), you only need ports 22, 51820/udp, and 443/tcp. You can skip opening port 51821 since Caddy will handle HTTPS termination.

    4

    Generate a Password Hash

    WG-Easy v15+ requires a bcrypt-hashed password for the admin UI. Generate one using the built-in utility:

    Generate bcrypt hash
    docker run --rm -it ghcr.io/wg-easy/wg-easy wgpw 'YourSecurePassword'

    Copy the bcrypt hash for use in the next step. When placing the hash in your Docker Compose file, you must escape every dollar sign ($) by doubling it ($). Example: $2a$12$abc... becomes $2a$12$abc...

    5

    Deploy WG-Easy with Docker Compose

    Create project directory
    mkdir -p ~/wg-easy && cd ~/wg-easy
    ~/wg-easy/docker-compose.yml
    volumes:
      etc_wireguard:
    
    services:
      wg-easy:
        image: ghcr.io/wg-easy/wg-easy
        container_name: wg-easy
        environment:
          - LANG=en
          - WG_HOST=YOUR_SERVER_IP_OR_DOMAIN
          - PASSWORD_HASH=YOUR_BCRYPT_HASH_HERE
          - PORT=51821
          - WG_PORT=51820
        volumes:
          - etc_wireguard:/etc/wireguard
        ports:
          - "51820:51820/udp"
          - "51821:51821/tcp"
        restart: unless-stopped
        cap_add:
          - NET_ADMIN
          - SYS_MODULE
        sysctls:
          - net.ipv4.ip_forward=1
          - net.ipv4.conf.all.src_valid_mark=1

    Key Configuration Values

    VariableDescription
    WG_HOSTYour VPS public IP or domain name (e.g., vpn.example.com)
    PASSWORD_HASHBcrypt hash from Step 4 (remember to escape $ as $)
    PORTWeb UI listening port inside the container (default: 51821)
    WG_PORTWireGuard UDP port for VPN traffic (default: 51820)
    LANGWeb UI language (en, de, fr, es, zh, and many more)
    Launch the stack
    cd ~/wg-easy
    docker compose up -d
    
    # Verify the container is running
    docker compose ps
    docker compose logs -f wg-easy
    6

    Secure with Caddy Reverse Proxy (Recommended)

    Running the WG-Easy web UI over plain HTTP is insecure. Caddy provides automatic HTTPS with Let's Encrypt certificates. This step requires a domain name pointed at your VPS.

    Updated ~/wg-easy/docker-compose.yml with Caddy
    volumes:
      etc_wireguard:
      caddy_data:
    
    services:
      wg-easy:
        image: ghcr.io/wg-easy/wg-easy
        container_name: wg-easy
        environment:
          - LANG=en
          - WG_HOST=vpn.yourdomain.com
          - PASSWORD_HASH=YOUR_BCRYPT_HASH_HERE
          - PORT=51821
          - WG_PORT=51820
        volumes:
          - etc_wireguard:/etc/wireguard
        ports:
          - "51820:51820/udp"
        restart: unless-stopped
        cap_add:
          - NET_ADMIN
          - SYS_MODULE
        sysctls:
          - net.ipv4.ip_forward=1
          - net.ipv4.conf.all.src_valid_mark=1
    
      caddy:
        image: caddy:2
        container_name: caddy
        ports:
          - "443:443"
          - "80:80"
        volumes:
          - ./Caddyfile:/etc/caddy/Caddyfile
          - caddy_data:/data
        restart: unless-stopped
    Caddyfile
    vpn.yourdomain.com {
        reverse_proxy wg-easy:51821
    }

    Note: Replace vpn.yourdomain.com with your actual domain. Ensure your DNS A record points to your RamNode VPS IP address before starting the stack. Caddy will automatically obtain and renew TLS certificates.

    Redeploy the stack
    docker compose down
    docker compose up -d

    Your WG-Easy admin panel is now accessible at https://vpn.yourdomain.com with a valid TLS certificate.

    7

    Connect Your First VPN Client

    Create a Client in the Web UI

    1. Open the WG-Easy admin panel in your browser
    2. Log in with the admin password you set in Step 4
    3. Click "New Client" and enter a descriptive name (e.g., "Laptop", "Phone")
    4. Click "Create" to generate the client configuration

    Install WireGuard on Your Device

    PlatformInstallation
    WindowsDownload from wireguard.com/install → Import tunnel → Select .conf file
    macOSInstall from App Store → Import tunnel from file
    Linuxsudo apt install wireguard → wg-quick up ./client.conf
    iOS / AndroidInstall WireGuard from App Store / Play Store → Scan QR code

    Verify the Connection

    Check your public IP
    curl ifconfig.me

    The returned IP should match your RamNode VPS public IP address.

    8

    Advanced Configuration

    Optional Environment Variables

    VariableDescriptionDefault
    WG_DEFAULT_DNSDNS server for clients1.1.1.1
    WG_DEFAULT_ADDRESSClient IP range10.8.0.x
    WG_ALLOWED_IPSAllowed IPs for clients0.0.0.0/0, ::/0
    WG_PERSISTENT_KEEPALIVEKeepalive interval (seconds)0 (disabled)
    WG_MTUMTU for WireGuard interfacenull (auto)
    UI_TRAFFIC_STATSEnable traffic charts in UIfalse

    9

    Backup & Maintenance

    10

    Troubleshooting

    IssueSolution
    Web UI not loadingVerify firewall allows TCP 51821 (or 443 if using Caddy). Check container logs for errors.
    VPN connects but no internetEnsure net.ipv4.ip_forward=1 is set. Check that the host firewall isn't blocking forwarded traffic.
    Password hash not acceptedRegenerate with the wgpw command. Ensure all $ are escaped as $ in docker-compose.yml.
    QR code won't scanEnsure WG_HOST is set to your public IP or domain, not a private/internal address.
    Caddy certificate failsVerify DNS A record resolves to your VPS IP. Ports 80 and 443 must be open for the ACME challenge.
    Container keeps restartingCheck logs with docker compose logs. Common cause: invalid PASSWORD_HASH format or missing capabilities.

    WG-Easy Deployed Successfully!

    Your self-hosted WireGuard VPN server with web admin UI is now running. Create clients, share QR codes, and enjoy kernel-level VPN performance on your RamNode VPS.