WireGuard is the right answer most of the time: it's fast, simple, and genuinely secure. This isn't a "WireGuard is bad" article — it's the honest next step for the one situation where WireGuard stops working. In some networks, deep packet inspection (DPI) recognizes the WireGuard protocol by its signature and blocks it outright. When that happens, no amount of config-tweaking helps, because the problem isn't your setup — it's that the traffic looks like a VPN. That's the problem VLESS+Reality solves.
The honest fork: WireGuard or Xray?
Decide this first, because the simpler tool is usually the right one:
- Use WireGuard if it works where you are. It's easier to run, easier to reason about, and fast. There's no reason to reach for anything more complex until you have to.
- Use VLESS+Reality (Xray) when WireGuard is blocked. Reality disguises your connection as an ordinary TLS handshake to a real website — so to DPI it looks like someone browsing a normal HTTPS site, with no VPN signature to detect. More moving parts, but it survives where WireGuard doesn't.
If you're not being blocked, stop here and use WireGuard. The rest of this is for when you are.
Why this needs a dedicated IP
An Xray server accepts inbound connections — your client dials into it on port 443. That requires a public IP that's addressable and yours. A NAT plan shares one egress IP among customers and gives you no inbound endpoint, so it won't work here. You need a dedicated-IP plan — and since this is a traffic workload rather than a CPU one, the smallest one does the job: Nano-IP at $8/mo (1 vCPU / 1 GB) is plenty. Bigger plans buy you more throughput headroom, not a better tunnel.
Install Xray
Use the official installer — don't hunt for random builds:
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
Generate the two things a Reality config needs — a key pair and a UUID:
xray x25519 # prints a Private key and a Public key
xray uuid # prints a UUID for the client
Keep the private key for the server config and the public key for the client link. Save both.
The server config, explained
Drop this into /usr/local/etc/xray/config.json, filling in your generated values:
{
"inbounds": [{
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [{ "id": "YOUR-UUID", "flow": "xtls-rprx-vision" }],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"dest": "www.microsoft.com:443",
"serverNames": ["www.microsoft.com"],
"privateKey": "YOUR-PRIVATE-KEY",
"shortIds": [""]
}
}
}],
"outbounds": [{ "protocol": "freedom" }]
}
What the key fields actually do:
dest— the real website your traffic will impersonate. It must be a site that supports TLS 1.3 and HTTP/2; a big, always-up domain is the usual pick. This is the site DPI thinks you're visiting.serverNames— the SNI(s) your handshake presents. It has to matchdest(same domain), because that's the disguise.privateKey— the private half of yourxray x25519pair. The public half goes to the client.shortIds— an array;[""](empty) is valid and fine for a personal setup. You can add hex IDs to distinguish clients.flow: xtls-rprx-vision— the flow control mode Reality uses; it must match on both ends.
Then enable it:
sudo systemctl enable --now xray
sudo systemctl status xray
The client link
Point an open-source client at the server — v2rayN, Hiddify, or any Xray-compatible app. The connection string encodes everything:
vless://YOUR-UUID@YOUR-SERVER-IP:443?type=tcp&security=reality&sni=www.microsoft.com&pbk=YOUR-PUBLIC-KEY&sid=&fp=chrome&flow=xtls-rprx-vision#my-server
The pieces: pbk is the public key, sni matches your serverNames, sid is the short ID (empty here), fp=chrome fakes a browser TLS fingerprint. Paste the link into the client and you're connected.
Honest limits
- Speed depends on the route to you. Reality doesn't make packets faster — throughput is bounded by the network path between you and the server. A closer server is a faster one; there's no magic here.
- It's for one to a few users. This is your private endpoint, not a public VPN. One small VPS can't be a service for strangers, and turning it into one invites abuse.
- The AUP still applies. A personal circumvention tunnel is fine; running an open public proxy or using it for attacks is not, and gets the service terminated.
- Your provider sees traffic exists. The disguise is aimed at DPI on the path to you, not at the host — the provider sees volume and timing, not contents. It's pseudonymity, the same honest caveat as any anonymous VPS.
The bottom line
WireGuard first; Reality when WireGuard is blocked. VLESS+Reality on Xray hides your tunnel inside ordinary-looking TLS to a real site, which is exactly what defeats DPI — and it runs fine on the cheapest $8/mo dedicated-IP plan because it's traffic, not compute. Install via the official script, generate your keys, match dest/serverNames, and point an open-source client at it. Lock the box down first with the security checklist, and keep expectations honest: it beats DPI, it doesn't make you invisible.