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
- Purchase your domain from NameSilo
- Set Cloudflare nameservers in NameSilo’s DNS settings (provided by Cloudflare).
- In Cloudflare DNS:
- A Record
- Name:
@ - IPv4: Your VPS IP
- Proxy Status: Proxied (orange cloud)
- Name:
- CNAME Record (optional)
- Name:
www - Target:
yourdomain.com - Proxy Status: Proxied
- Name:
- A Record
Tip: Keep your VPS IP hidden behind Cloudflare proxy to avoid scanners and attacks.
1.3 Cloudflare
- SSL/TLS → Full (Strict)
- Enable Always Use HTTPS
- Enable HTTP/2 and HTTP/3
- (Optional) Security → Enable Bot Fight Mode
- Create an API Token:
- Go to: Profile → API Tokens → Create Token
- Template: Edit zone DNS
- Scope: Your domain only
- Save your token for later use (in
acme.shstep).
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_portdirectly 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
| Field | Value | Remark |
|---|---|---|
| Address | yourdomain | Your VPS domain |
| Port | 443 | Nginx TLS |
| UUID | your_uuid | Generated in the setup |
| Encryption | none (VLESS) | TLS handled by Nginx |
| Transport | WebSocket | WebSocket over TLS |
| Path | your_websocket_path | Randomized path |
| TLS | Enabled | Must match server |
| Host (SNI) | yourdomain | Server 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:
%2Fis URL-encoded/for WebSocket path.
7. Security
- Use a random WebSocket path for stealth.
- Keep the Nginx default site for cover traffic.
- Set the Cloudflare SSL mode to Full (Strict).
- Enable Fail2Ban and rate limiting to block scanners.
- Regularly update the VPS and its packages:
sudo apt update && sudo apt upgrade -y
- Set the V2Ray
logleveltowarningto reduce I/O load. - Never expose port
10000directly to the internet. - 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
AllowedIPsinclude0.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.comto check SSL response.
9.6 Client Connection Errors
- Verify your WebSocket path
/ws/xxxxxxmatches 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.