This guide explains how to deploy V2Ray with WebSocket, TLS, Cloudflare CDN, and Warp. It is intended for users in China who want stable, encrypted international internet access while keeping their VPS IP hidden.

1. Preparation

1.1 VPS

This guide uses a RackNerd VPS in Los Angeles, though any offshore VPS will work.

Recommended system environment:

  • OS: Debian 11+ or Ubuntu 20.04+
  • CPU: 1 core or higher
  • RAM: at least 1 GB
  • Open TCP ports 80 and 443

Connect to your VPS and update the system:

ssh root@your_vps_ip
sudo apt update && sudo apt upgrade -y

Install required dependencies for all modules:

sudo apt install -y curl socat uuid-runtime unzip

Tip:

  • Different VPS providers may have minor variations; always check OS version and resource availability.
  • Ensure SSH port is accessible and firewall rules allow TCP ports 80 and 443.
  • Confirm your VPS IP and region before proceeding.
  • Keep your root login secure and consider setting up a non-root user for future operations.

1.2 Domain

  1. Purchase your domain from NameSilo
  2. Set Cloudflare nameservers in NameSilo’s DNS settings (provided by Cloudflare).
  3. In Cloudflare DNS:
    • A Record
      • Name: @
      • IPv4: Your VPS IP
      • Proxy Status: Proxied (orange cloud)
    • CNAME Record (optional)
      • Name: www
      • Target: yourdomain.com
      • Proxy Status: Proxied

Tip: Keep your VPS IP hidden behind Cloudflare proxy to avoid scanners and attacks.

1.3 Cloudflare

  1. SSL/TLSFull (Strict)
  2. Enable Always Use HTTPS
  3. Enable HTTP/2 and HTTP/3
  4. (Optional) Security → Enable Bot Fight Mode
  5. Create an API Token:
    • Go to: ProfileAPI TokensCreate Token
    • Template: Edit zone DNS
    • Scope: Your domain only
    • Save your token for later use (in acme.sh step).

2. Nginx Setup

2.1 Nginx Installation

sudo apt install -y nginx

2.2 TLS Certificate Issuance

curl https://get.acme.sh | sh -s email=youremail@example.com
source ~/.bashrc
export CF_Token="your_cloudflare_api_token"
acme.sh --issue --dns dns_cf -d yourdomain.com --keylength ec-256
sudo mkdir -p /etc/nginx/ssl
acme.sh --install-cert -d yourdomain.com \
  --key-file /etc/nginx/ssl/yourdomain.key \
  --fullchain-file /etc/nginx/ssl/yourdomain.crt \
  --reloadcmd "sudo systemctl reload nginx"

2.3 Nginx Configuration

server {
    listen 443 ssl http2;
    server_name yourdomain;

    ssl_certificate /etc/nginx/ssl/yourdomain.crt;
    ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location your_websocket_path {
        proxy_pass http://127.0.0.1:your_port;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        limit_req zone=req_limit burst=10 nodelay;
    }

    location / {
        root /var/www/html;
        index index.html;
    }
}

server {
    listen 80;
    server_name yourdomain;
    return 301 https://$host$request_uri;
}

Tip: Add rate limiting in the http {} block:

limit_req_zone $binary_remote_addr zone=req_limit:10m rate=1r/s;

3. V2Ray Setup

3.1 V2Ray Installation

bash <(curl -Ls https://github.com/v2fly/fhs-install-v2ray/raw/master/install-release.sh)

3.2 UUID Generation

uuidgen

3.3 V2Ray Configuration

  • Edit /usr/local/etc/v2ray/config.json
{
  "log": { "loglevel": "warning" },
  "dns": { "servers": ["1.1.1.1","8.8.8.8","8.8.4.4"] },
  "inbounds": [{
    "port": your_port,
    "listen": "127.0.0.1",
    "protocol": "vless",
    "settings": {
      "clients": [{"id": "your_uuid","flow": ""}],
      "decryption": "none"
    },
    "streamSettings": {
      "network": "ws",
      "security": "none",
      "wsSettings": {
        "path": "your_websocket_path",
        "headers": { "Host": "your_domain" }
      }
    }
  }],
  "outbounds": [
    { "tag": "warp-out", "protocol": "freedom", "settings": {}, "streamSettings": { "sockopt": { "interface": "wgcf" } } },
    { "tag": "direct", "protocol": "freedom", "settings": {} }
  ],
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      { "type":"field","ip":["geoip:cn","geoip:private"],"outboundTag":"direct" },
      { "type":"field","domain":["geosite:cn"],"outboundTag":"direct" },
      { "type":"field","network":"tcp,udp","outboundTag":"warp-out" }
    ]
  }
}
  • Set a random WebSocket path, e.g., /ws/8f3a7b2c9d
  • Make sure the UUID matches the client configuration

Warning: Do not expose your_port directly to the internet.

4. Warp Setup

4.1 WireGuard Installation (Required)

sudo apt install -y wireguard-tools

bash <(curl -fsSL git.io/warp.sh) wg4

4.2 Warp Configuration

  • Edit /etc/wireguard/wgcf.conf.
  • Set PrivateKey, PublicKey, AllowedIPs, Endpoint, and the remaining values.
[Interface]
PrivateKey = your_private_key (use default)
Address = 172.16.0.2/32
DNS = 1.1.1.1,8.8.8.8,8.8.4.4
MTU = 1420
PostUp = ip -4 rule add from your_vps_ip lookup main prio 18
PostDown = ip -4 rule delete from your_vps_ip lookup main prio 18

[Peer]
PublicKey = your_warp_public_key (use default)
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = engage.cloudflareclient.com:2408

4.3 Warp Startup

sudo wg-quick up wgcf
sudo systemctl enable wg-quick@wgcf
sudo wg

Tip: Ensure traffic still routes correctly after enabling Warp.

5. Fail2Ban Setup

5.1 Fail2Ban Installation

sudo apt install -y fail2ban

5.2 Fail2Ban Activation

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Tip: Combine with Nginx rate limiting for extra security.

6. v2rayN and v2rayNG Setup

FieldValueRemark
AddressyourdomainYour VPS domain
Port443Nginx TLS
UUIDyour_uuidGenerated in the setup
Encryptionnone (VLESS)TLS handled by Nginx
TransportWebSocketWebSocket over TLS
Pathyour_websocket_pathRandomized path
TLSEnabledMust match server
Host (SNI)yourdomainServer Name Indication

Example VLESS link:

vless://your_uuid@yourdomain.com:443?encryption=none&security=tls&type=ws&host=yourdomain.com&path=%2Fws%2F8f3a7b2c9d#VLESS-CDN

Tip: %2F is URL-encoded / for WebSocket path.

7. Security

  1. Use a random WebSocket path for stealth.
  2. Keep the Nginx default site for cover traffic.
  3. Set the Cloudflare SSL mode to Full (Strict).
  4. Enable Fail2Ban and rate limiting to block scanners.
  5. Regularly update the VPS and its packages:
sudo apt update && sudo apt upgrade -y
  1. Set the V2Ray loglevel to warning to reduce I/O load.
  2. Never expose port 10000 directly to the internet.
  3. Review Warp routing to ensure it does not interfere with VPS traffic.

8. Backup and Restore

Before making major configuration changes, back up the existing files so you can restore the setup if something goes wrong.

8.1 Configuration Backup

sudo mkdir -p /root/backup/v2ray
sudo mkdir -p /root/backup/nginx
sudo mkdir -p /root/backup/wireguard
sudo cp /usr/local/etc/v2ray/config.json /root/backup/v2ray/config.json.bak
sudo cp /etc/nginx/sites-available/default /root/backup/nginx/default.bak
sudo cp /etc/wireguard/wgcf.conf /root/backup/wireguard/wgcf.conf.bak

Tip: You can also back up certificates and keys:

sudo cp -r /etc/nginx/ssl /root/backup/nginx-ssl/

8.2 Configuration Restore

If a configuration change causes errors, restore the backup:

sudo cp /root/backup/v2ray/config.json.bak /usr/local/etc/v2ray/config.json
sudo cp /root/backup/nginx/default.bak /etc/nginx/sites-available/default
sudo cp /root/backup/wireguard/wgcf.conf.bak /etc/wireguard/wgcf.conf
sudo systemctl restart nginx
sudo systemctl restart v2ray
sudo systemctl restart wg-quick@wgcf

Tip: Always restart related services after restoring configuration files.

9. Troubleshooting

If the setup does not work as expected, use the following checks to find the problem.

9.1 V2Ray Startup Errors

Check the V2Ray service status:

sudo systemctl status v2ray

If errors appear, check logs:

sudo journalctl -u v2ray --no-pager -n 50

Common causes:

  • Invalid JSON format in config.json
  • Incorrect UUID or mismatched WebSocket path
  • Nginx proxy port does not match the V2Ray inbound port

9.2 Nginx Reload Errors

sudo nginx -t

If syntax errors exist, fix them before restarting:

sudo systemctl reload nginx

9.3 TLS Certificate Errors

Check certificate paths in Nginx:

  • /etc/nginx/ssl/yourdomain.crt
  • /etc/nginx/ssl/yourdomain.key

If expired or missing, reissue with acme.sh:

acme.sh --renew -d yourdomain.com --force
sudo systemctl reload nginx

9.4 Warp Connectivity Issues

Check WireGuard status:

sudo wg
sudo systemctl status wg-quick@wgcf

If traffic does not route properly:

  • Verify AllowedIPs include 0.0.0.0/0, ::/0
  • Ensure correct endpoint: engage.cloudflareclient.com:2408
  • Restart Warp:
sudo wg-quick down wgcf
sudo wg-quick up wgcf

9.5 Cloudflare Configuration Errors

If HTTPS or CDN is not working:

  • Confirm DNS proxy (orange cloud) is enabled.
  • SSL/TLS mode must be Full (Strict).
  • Ensure Nginx is serving port 443 correctly.
  • Use curl -Iv https://yourdomain.com to check SSL response.

9.6 Client Connection Errors

  • Verify your WebSocket path /ws/xxxxxx matches the server config.
  • Ensure VLESS link matches UUID and domain.
  • Test using direct IP to rule out DNS issues.
  • Disable CDN temporarily to debug connectivity.

Tip: Check both V2Ray and Nginx logs for real-time clues.