Skip to content

Xray stats configuration

Xray counts nothing by default. Until a node’s config.json asks for statistics and exposes the gRPC API, Orrery connects and reads zero counters.

Three top-level blocks are needed: stats turns counting on, api exposes the StatsService endpoint, and policy selects which counters exist.

{
"stats": {},
"api": {
"tag": "api",
"listen": "127.0.0.1:10085",
"services": ["StatsService"]
},
"policy": {
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true,
"statsUserOnline": true
}
},
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true,
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
}
}

Restart Xray afterwards.

Notes:

  • api.listen (Xray >= v1.8.11, 2024-05, XTLS/Xray-core#3317) binds the gRPC listener directly. No dokodemo-door inbound and no routing rule are involved; do not use the legacy inbound+routing wiring.
  • Clients are implicitly level 0 unless configured otherwise, so the "0" policy covers everyone.
  • On exits, drop statsUserOnline. Per-user counters there track per-hub pseudo-identities (hub01-exit01@ns) rather than people, and the default collect: traffic for exits ignores user detail anyway.
  • The port must match the fleet’s xray_api_port in orrery.yaml. Both default to 10085.
  • Counters live in memory, so an Xray restart resets them. Orrery detects the reset and keeps its history.

Fleets whose configs are generated by HexRift can have these blocks emitted by its observability feature instead of editing generated files.

The listen address pairs with the fleet’s dial mode.

dial: ssh (the default) wants listen on 127.0.0.1. Orrery tunnels gRPC over its existing SSH access to the node, so nothing is exposed and no firewall rule changes.

dial: direct needs a routable bind, and the node’s firewall must allow the collector’s addresses to that port. The Xray commander listener is plain TCP with no authentication, so source-IP filtering is the only protection and per-user emails and IPs would cross the network unencrypted. Reasonable for exits collected at tag level, a bad idea for hubs.

Terminal window
orrery -config /etc/orrery/orrery.yaml probe main/hub01

A successful connection reporting 0 counters means this page’s configuration has not taken effect on that node.