VPNSmith
tunneling-obfuscationINFO

sing-box VLESS Reality Setup 2026: The Config Fields Most Guides Still Get Wrong

A current sing-box VLESS + Reality config, checked against the official documentation for 1.13. Includes the inbound fields that were deprecated in 1.11 and are still copied into most tutorials.

By Eric Gerard · Founder · VPNSmith - Self-host VPN & GDPR VPS specialist6 min readPhoto via Pexels

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.

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), containing server and server_port, the external site your server borrows from
  • private_key (string), which the documentation says is generated by sing-box generate reality-keypair
  • short_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. The public key is not recoverable from a config file that only stores the private one, and regenerating the pair invalidates every client you have already handed out.

Blue ethernet cables plugged into the numbered ports of a network switch, with green status LEDs lit along the front panel.
Blue ethernet cables plugged into the numbered ports of a network switch, with green status LEDs lit along the front panel.

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:

  • sniff
  • sniff_timeout
  • domain_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 key
  • short_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.

★ Nuremberg GDPR datacenter · ✓ Dedicated IPv4 included · 200+ Mbps guaranteed

A VPS you fully control for tunneling & obfuscation → ContaboRoot access · open any port · run your own stack

Frequently asked questions

Which sing-box fields do I actually need for a VLESS Reality inbound?
The VLESS inbound itself requires type, tag, a listen address and port, and a users array where each entry carries a uuid. The Reality part lives inside the tls object and requires three things on the server: a handshake object pointing at a real external site with its server and server_port, a private_key generated by sing-box, and a short_id. Everything else in the inbound is optional.
What generates the Reality private key and public key?
The command sing-box generate reality-keypair. It prints a matched pair. The private_key stays in the server config and the public_key goes in the client config. They are not interchangeable, and a client using the wrong public_key will fail the handshake rather than fall back to plain TLS.
Is the short_id allowed to be empty?
The documentation describes short_id as a hexadecimal string with zero to eight digits, so an empty value is within spec. The value on the client must match a value the server accepts, which is the part people miss when they copy a server config and edit only the UUID.
Why do older sing-box tutorials put sniff and domain_strategy inside the inbound?
Because that was correct before version 1.11.0. Those fields, along with sniff_timeout, were deprecated then and moved to route rule actions: action sniff with a timeout parameter, and action resolve with a strategy parameter. Configs written the old way still parse, but you are following a deprecated path, which is worth knowing before you build on it.
Do I need utls on the client?
The sing-box documentation presents utls as its own option in the TLS block with an enabled flag and a fingerprint, and it does not state that Reality requires it. Many client configs set it anyway. If you leave fingerprint empty the documentation says the Chrome fingerprint is used.