SSTEALTHNETSOFTWARE

Nodes

A node is a server running the Xray engine and our agent. The agent pulls the profile from the panel, writes the clients into it and reports traffic and load.

Attaching

On the Nodes page press “Attach node” — the panel assembles a command with the address and the key. It installs the engine, the agent and a systemd unit:

PANEL_URL=https://panel.your-domain NODE_SECRET=... bash install-node.sh

The secret is shown once: only its hash is stored. If you lose it, issue a new one from the node's menu.

The script takes the agent from a GitHub release, falling back to the panel itself when that is unreachable. Point it elsewhere with AGENT_URL, or pin a release with AGENT_RELEASE.

Certificate

The installer issues no certificates: the install is the same for every node, with no branches. Reality — the default choice — needs none at all, since it hides behind somebody else's site.

A certificate is only needed by what runs over TLS: Trojan, Hysteria2 and the like. There it is tied to the domain of one particular node, so it is issued on the spot.

Point a domain's A record at the node, free up port 80, and issue it:

apt-get install -y certbot
certbot certonly --standalone -d de1.your-domain

mkdir -p /etc/sn-node/tls
cp /etc/letsencrypt/live/de1.your-domain/fullchain.pem /etc/sn-node/tls/de1.your-domain.crt
cp /etc/letsencrypt/live/de1.your-domain/privkey.pem   /etc/sn-node/tls/de1.your-domain.key

Then point the profile at those paths, in streamSettings.tlsSettings.certificates.

The path is to this node's certificate, not the panel's domain. The Hysteria2 preset ships with a placeholder; leave the panel's domain in it and the engine on the node answers no such file or directory and refuses to start — taking the profile's other inbounds with it.
One profile across nodes. The path in the config is a single value, so a TLS inbound cannot live in a profile shared by nodes with different domains. Give those nodes a profile of their own.
After a renewal the engine has to be restarted: it reads the certificate only at start-up and would otherwise keep serving an expired one. There is a "Restart Xray" action in the node menu; in a certbot job it is --deploy-hook "systemctl restart sn-node".

Updating

The engine version is set in the panel: the “Xray version” button on the nodes page. The agent compares its own on every poll, downloads the release, makes sure the binary runs and reports the expected version, and only then replaces the working one. Nodes left behind are listed there too.

The agent itself is updated with “Apply to every node” in the same window. It replaces itself and exits — the service brings it back up.

A node with an old agent does not understand the panel's commands and stays on its previous engine — in the list this shows up as mismatched versions. Such a node has to be updated once, on the server itself:
curl -fsSL https://panel.your-domain/update-node.sh | PANEL_URL=https://panel.your-domain bash

The node secret is not needed: it is already in the systemd unit. The script leaves the engine alone — the panel owns its version and the agent will bring the node to it. To pin a specific version, name it: XRAY_VERSION=v26.7.11.

Geo databases

Rules like geoip:ru and geosite:category-ads-all rely on the geoip.dat and geosite.dat files. The engine's archive installs them once and they go stale from there, so the installer sets up a weekly update.

zapret.dat — the list of resources blocked in Russia — is installed alongside. You only need it if your rules mention zapret:*; without the file, the engine refuses to start with such a rule.

An update replaces a file only when it has genuinely changed: the engine reads the databases at start-up, and a needless restart is a needless drop of every connection.

Node states

LookWhat it means
GreenThe agent is in touch, the engine runs, clients are served.
RedEither the agent is out of touch, or the engine failed to start — the reason is written in the row. The latter happens with a bad config or a missing certificate.
GreySwitched off by an administrator. Not a fault: it is deliberately not serving clients.
The agent being alive is not the same as the engine running. These are different states and the panel tells them apart: a node that answers polls while Xray is down shows as broken, not as fine.

Protection from a broken config

Before replacing a working config, the agent asks the engine whether it would accept the new one. If not, it stays on the old config and reports the reason to the panel. One typo in a new protocol does not take the whole node down along with the locations that worked.

Traffic and who is online

The engine counts per client and per inbound; the agent collects the counters every 15 seconds and sends the delta. “Online” means “passed traffic within the last polling window”: Xray does not expose a list of live connections, and this is an honest approximation.