Search for a sing-box Reality guide and you will find a lot of configuration files that were correct in 2024. They still parse, which is the problem: nothing warns you that you have just built on fields the project deprecated. This walks through a VLESS Reality setup checked field by field against the current documentation, and flags the parts that have quietly moved.
For reference, the version this was checked against is sing-box 1.13.15, released on 29 July 2026.
No server yet? The setup below needs a VPS with a public IPv4, root access and port 443 free, outside the network that filters you: a Contabo Cloud VPS 4 (affiliate link) does it from €5.50 a month on a 24-month term.
Bank card declined? Ultahost also takes Bitcoin and other cryptocurrencies, Alipay, WeChat Pay and Qiwi (its payments page, read on 25 October 2026). This is an affiliate link; check its terms for your country before ordering.
Prefer not to assemble the JSON by hand? Our free VLESS REALITY config generator creates the X25519 key pair, UUID and short ID in your browser and writes the matching server and client configs for sing-box and Xray-core, ready to paste into the steps below.
Runs entirely in your browser: keys, UUID and configs are generated locally and never sent anywhere.
Your VPS public IP (or a domain pointing to it). Used in the client config and the share link.
443 is the norm: REALITY imitates HTTPS.
A third-party site with TLS 1.3 and HTTP/2, reachable from your clients. See the checklist below the tool.
The TLS fingerprint the client imitates. chrome is the usual choice.
The private key goes on the server only. The public key goes to every client.
Hex, even length, up to 16 characters.
- The keys are missing or invalid (32 bytes, base64url, 43 characters). Generate a pair or paste yours.
vless:// share link
vless://@203.0.113.10:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=www.example.com&fp=chrome&pbk=&sid=&type=tcp&headerType=none#my-reality
Import it in v2rayN, v2rayNG, Hiddify, Streisand or Shadowrocket, or scan the QR code.
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "",
"flow": "xtls-rprx-vision",
"email": "my-reality"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"show": false,
"target": "www.example.com:443",
"xver": 0,
"serverNames": [
"www.example.com"
],
"privateKey": "",
"shortIds": [
""
]
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
],
"routeOnly": true
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
]
}{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"udp": true
}
},
{
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http"
}
],
"outbounds": [
{
"protocol": "vless",
"tag": "proxy",
"settings": {
"vnext": [
{
"address": "203.0.113.10",
"port": 443,
"users": [
{
"id": "",
"flow": "xtls-rprx-vision",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "www.example.com",
"fingerprint": "chrome",
"publicKey": "",
"shortId": "",
"spiderX": "/"
}
}
},
{
"protocol": "freedom",
"tag": "direct"
}
]
}# Install Xray-core with the official script (systemd service included)
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
# Optional: confirm the public key matches the private key
xray x25519 -i ""
# Check that the target answers in TLS 1.3 and HTTP/2
xray tls ping www.example.com
# Open the port
sudo ufw allow 443/tcp
# Paste the server config, test it, then start the service
sudo nano /usr/local/etc/xray/config.json
xray run -test -c /usr/local/etc/xray/config.json
sudo systemctl restart xray && sudo systemctl enable xray
# Follow the log while the first client connects
sudo journalctl -u xray -f
REALITY needs a server you control
A REALITY server is a VPS with a public IP and port 443 free, nothing more. Contabo's entry VPS includes a public IPv4, root access and a large traffic allowance, and you can pick the datacenter closest to your users.
Second option, a US host with a 30-day money-back guarantee: Ultahost VPS Basic, 5.52 $/mo on a 24-month term, 1 CPU, 1 GB DDR5 and a dedicated IPv4 (read on 21 October 2026), enough for one Xray server. It also takes Bitcoin and other cryptocurrencies, Alipay, WeChat Pay and Qiwi (its payments page, read on 25 October 2026), which helps if your bank card is declined; check its terms for your country before ordering. See Ultahost VPS
Affiliate link: we may earn a commission, at no extra cost to you. The generator stays free and does not depend on it.
Still choosing the server? Our guide Best VPS for V2Ray and Xray compares providers on what decides whether a censorship-bypass server lasts: datacenter location, IP reputation, included traffic and how fast you can replace a blocked IP.
What Reality actually changes
Conventional TLS-based proxies have a structural weakness: the certificate belongs to you. A censor who inspects the handshake sees a domain and a certificate that do not correspond to a real, popular website, and that mismatch is itself the signal.
Reality's approach is to borrow the handshake of a genuine third-party site. Your server is configured to point at a real external host, and traffic that fails authentication is passed through to it. To an observer, the connection resembles a connection to that site, because in part it is.
This is why the configuration has a handshake block. It is not decoration and its choice matters more than any other value you will set.
The three required Reality fields on the server
Inside the tls object, the reality block requires exactly three things according to the documentation:
handshake(object), containingserverandserver_port, the external site your server borrows fromprivate_key(string), which the documentation says is generated bysing-box generate reality-keypairshort_id(string), described as a hexadecimal string with zero to eight digits
There is also an enabled boolean, and an optional max_time_difference, which sets the tolerated clock difference between the two ends. The documentation notes that the check is disabled when this is left empty. If you do set it, keep in mind that you are now dependent on both machines keeping accurate time.
Generating the keys
Two values need generating before you write anything:
sing-box generate reality-keypair
sing-box generate uuid
The keypair prints a private key and a public key. The private key stays on the server. The public key goes to every client. The UUID is the VLESS user identity.
Keep the pair together somewhere safe when you generate it. If only the private key survived, in a server config for instance, the public key is not lost: it is derived from the private one, with xray x25519 -i "<private key>" or by pasting it into our VLESS REALITY config generator, which works locally. Regenerating the pair, on the other hand, invalidates every client you have already handed out.
Keeping the values straight is where most REALITY setups break. Our free VLESS REALITY Cheat Sheet (3-page PDF, direct download, no sign-up) puts the Xray, sing-box and vless:// names of each field side by side, with the server checks and the usual failure causes. Download the cheat sheet.

The server part below runs on any VPS with a public IPv4 address, root access and port 443 free for the inbound. If you do not have one yet:
★ Nuremberg GDPR datacenter · ✓ Dedicated IPv4 included · 200 Mbit/s port
See Contabo Cloud VPS →Cloud VPS 4 at €5.50/month with a public IPv4 and full root access, enough for a personal REALITY server. Pick a region close to your users.→The server inbound
A VLESS inbound requires type, tag, the listen fields, and a users array. Each user entry takes a uuid, optionally a name, and optionally a flow. The documentation lists exactly one available flow value: xtls-rprx-vision.
{
"type": "vless",
"tag": "vless-in",
"listen": "::",
"listen_port": 443,
"users": [
{
"name": "me",
"uuid": "PASTE-YOUR-GENERATED-UUID",
"flow": "xtls-rprx-vision"
}
],
"tls": {
"enabled": true,
"server_name": "your-handshake-host.example",
"reality": {
"enabled": true,
"handshake": {
"server": "your-handshake-host.example",
"server_port": 443
},
"private_key": "PASTE-YOUR-PRIVATE-KEY",
"short_id": "0123abcd"
}
}
}
Note server_name and the handshake server. These are separate fields that will normally hold the same host, and a mismatch between them is a common cause of a setup that builds fine and then fails at connection time.
The part most guides get wrong
Here is the difference between a 2024 config and a current one. These three inbound fields were deprecated in version 1.11.0:
sniffsniff_timeoutdomain_strategy
They moved out of the inbound and became route rule actions. The migration guide gives the direct equivalents:
{
"route": {
"rules": [
{ "inbound": "vless-in", "action": "sniff", "timeout": "1s" },
{ "inbound": "vless-in", "action": "resolve", "strategy": "prefer_ipv4" }
]
}
}
So "sniff": true becomes an action of sniff, sniff_timeout becomes that action's timeout, and domain_strategy becomes an action of resolve with a strategy.
To be accurate about the stakes: the documentation marks these as deprecated and does not announce a removal date. Nothing breaks today. But a config that still carries them is written against an interface the project has moved away from, and that is worth knowing when you are choosing which tutorial to follow.
Two related fields, sniff_override_destination and udp_disable_domain_unmapping, are also marked deprecated in the current listen field documentation.
The client side
The client needs less than the server. Reality on the client requires:
public_key, the counterpart to the server's private keyshort_id, which must match a value the server accepts
The utls object sits alongside it, with enabled and fingerprint. Accepted fingerprint values documented are chrome, firefox, edge, safari, 360, qq, ios, android, random and randomized. The documentation states that the Chrome fingerprint is used when the field is empty.
One point of honesty here, because guides tend to assert the opposite: the sing-box documentation presents utls as an independent TLS option and does not state that Reality requires it. Most client configs enable it regardless.
Choosing the handshake host
No config value affects your outcome more, and no guide can pick it for you, because the right answer depends on where your server is and where your clients are.
The properties that matter:
- It should be a host that genuinely supports TLS 1.3 on the port you point at
- It should be plausible traffic from your server's network location
- It should not be a site that is itself blocked in the country you are connecting from, which would defeat the purpose entirely
- It should not be a site you control, since the point is that it is somebody else's real traffic
A frequently repeated piece of advice is to pick something large and generic. Be careful with that reasoning: a host that every tutorial recommends is, by definition, a host that appears in every config, and popularity within the proxy community is not the same thing as blending in.
Before you conclude it works
Two checks worth doing that go beyond "the client connected".
Confirm the fallback behaves. Point a plain browser at your server's address and port. What you should see is the handshake site, not an error and not a timeout. If you get something else, the passthrough is not doing its job and the setup is more conspicuous than an ordinary proxy.
Check both clocks. If you set max_time_difference, drift on either machine will produce failures that look like authentication problems and send you editing keys that were never wrong.
If you are still deciding between engines rather than configuring one, the trade-offs are laid out in our sing-box vs Xray comparison.
The short version
Three required Reality fields on the server: handshake, private_key, short_id. Two on the client: public_key, short_id. Keys come from sing-box generate reality-keypair. And if the guide you are reading puts sniff or domain_strategy inside the inbound, it predates version 1.11 and the current equivalent is a route rule action.
Field names, requirements and deprecations in this article were taken from the official sing-box documentation and migration guide, checked against release 1.13.15 on 30 July 2026. Configuration interfaces change between versions, so verify against the documentation for the release you are running. Bypassing censorship is restricted or unlawful in some jurisdictions; check what applies where you are.
REALITY needs a server with a clean IP and an untouched TLS path. Our cheapest-VPS comparison sets out which providers fit that requirement and at what price.
★ Nuremberg GDPR datacenter · ✓ Dedicated IPv4 included · 200 Mbit/s port
A VPS you fully control for tunneling & obfuscation → ContaboRoot access · open any port · run your own stack→


