inbounds · profiles · subscription · bypass · cascade
Read this in other languages
🇺🇸 English ·
🇷🇺 Русский ·
🇨🇳 简体中文
One bash script turns a clean VPS into a personal VLESS Reality server.
Xrayebator installs Xray-core, brings up Reality inbounds on random ports, builds a profile of seven
routes and hands them to the client as a single HTTPS subscription link. Current line — 3.0.
curl -fsSLo ./xrayebator-install.sh \
https://raw.githubusercontent.com/howdeploy/Xrayebator/main/install.sh
less ./xrayebator-install.sh # review the script before running it
sudo bash ./xrayebator-install.sh
Debian 12/13 · Ubuntu 22.04/24.04 · 512 MB RAM or more · root or sudo
Then run sudo xrayebator, pick item 9, and the subscription is ready.
Details: Quick start
Purpose · Capabilities · How it works · Quick start · Documentation · Limitations · Updating
A personal VLESS Reality setup is a dozen manual steps: assemble the inbound, generate keys, pick an
SNI, avoid breaking the config, deliver the link to a phone. One typo in config.json and Xray does
not start.
A single route is also not enough. DPI blocks transports unevenly: TCP Vision survives in one network, only gRPC in another, and nothing but XHTTP in a third. Maintaining separate configs for each case by hand is impractical.
Xrayebator solves both problems:
- a profile is not one route but a set of
routessharing a singlesub_token; - the client receives the whole set as one short subscription link instead of seven
vless://links; - every config change goes through a backup, an
xray run -testvalidation and an automatic rollback, so a failed edit never leaves the server without VPN; - changing SNI, port or fingerprint does not require recreating the profile.
The project is developed and tested by one person. The consequences are listed plainly in Known limitations — read that section before installing on a VPS you care about.
| Capability | What it does | Where it lives |
|---|---|---|
| Xray-core installation | Downloads the release from GitHub, always verifies SHA-256 against .dgst, installs the binary via install -m 755, runs a self-test |
install.sh |
| Reality inbounds | Brings up inbounds on free ports in 30000-60000, checking both config.json and actually listening sockets |
xrayebator |
| Multi-route profile | One profile = a set of routes with a shared sub_token; several profiles may share one port |
profiles/<name>.json |
| HAPP subscription | A local HTTP server serves the vless:// list and HAPP metadata; nginx publishes it over HTTPS |
subhttp.sh, xrayebator-sub.service |
| Post-quantum XHTTP | The xhttp-pq route runs VLESS encryption mlkem768x25519plus |
.vless_encryption, .vless_decryption |
| v2ray compatibility | v2rayNG and v2rayN receive a classic base64 body without HAPP metadata |
subhttp.sh |
| Subscription revoke | Generates a new 32-character hex token; the old URL stops working | openssl rand -hex 16 |
| Bypass routing | Seven domain groups can be sent straight through freedom, skipping the VPN |
menu 7 |
| Cascade | Switches the tcp,udp catch-all to a foreign VLESS Reality upstream of type tcp or xhttp |
upstreams/cascade.json |
| Self-steal stub | Puts nginx with a valid certificate on 127.0.0.1:9444 and points a Reality fallback at it |
menu 9 |
| Safe JSON writes | Writes a temporary file inside the destination directory, validates it, renames atomically | safe_jq_write |
| Safe restart | Runs xray run -test -config before restarting; rolls the config back from a backup on failure |
safe_restart_xray |
| Migrations | One-shot migrations driven by marker files: backup → edit → restart → marker | run_migration |
| geo databases | Places extended geoip.dat and geosite.dat from Loyalsoldier releases into /usr/local/share/xray |
install.sh |
Not supported and not claimed: H2, WebSocket, SplitHTTP, Clash/mihomo subscriptions.
Control flow. Every config change follows the same path:
sudo xrayebator
│
▼
xrayebator (bash)
create profile · change SNI/port/fingerprint · migrations · routing
│
├─ backup_config ───────► /usr/local/etc/xray/backups/<timestamp>
│
├─ safe_jq_write ───────► config.json + profiles/<name>.json
│
└─ safe_restart_xray
│
├─ xray run -test -config → ok ──► systemctl restart xray
│
└─ invalid config ─────────────────► rollback from backup,
Xray keeps running
on the previous config
Client flow. From the subscription link to the open internet:
client (HAPP)
│ https://<domain-or-ip>/sub/<32-hex-token>
▼
nginx :443 (or :8443 when 443 is taken)
│ proxy_pass
▼
xrayebator-sub.service 127.0.0.1:8080
│ reads profiles/*.json and checks routes against the live config.json
▼
vless:// list — HAPP receives 6 of the profile's 7 routes
│
▼
Reality inbound on a port in 30000-60000 (User=xray, CAP_NET_BIND_SERVICE)
│
├─ domain in an enabled bypass group ──► freedom (direct, no VPN)
│
└─ all other tcp/udp ─────────────────► direct
OR cascade-upstream ──► foreign VPS
The HAPP flow creates or reuses a profile of seven routes:
| Route | Transport | Purpose |
|---|---|---|
xhttp-legacy |
xhttp | HAPP-compatible XHTTP fallback, decryption=none, no PQ |
xhttp-pq |
xhttp | XHTTP with post-quantum encryption mlkem768x25519plus |
tcp-mux |
tcp | TCP Reality without Vision flow, a separate compatible fallback |
grpc |
grpc | gRPC Reality; sensitive to HTTP/2 and SNI |
tcp-vision |
tcp | TCP Reality with xtls-rprx-vision |
tcp-utls-firefox |
tcp | TCP Vision with a Firefox fingerprint |
tcp-xudp |
tcp | TCP Vision + XUDP, a narrow fallback for harsh mobile networks |
Six of the seven routes reach the HAPP subscription: when xhttp-legacy is present, PQ-XHTTP is not
offered as the XHTTP candidate. All seven remain in the profile JSON itself.
The default client fingerprint for new and updated profiles is firefox. Explicitly chosen
fingerprints other than the deprecated chrome are preserved across updates.
Route order in the subscription is stable but it is not a best-to-worst ranking. Whether a transport works depends on the client, its bundled Xray-core version and the specific network.
| Mode | Result | When to use |
|---|---|---|
| Public TLS by VPS IP | https://<ip>/sub/<token> |
Quick start without a domain. Let's Encrypt IP certificates are short-lived, renewal is mandatory |
| Public TLS by domain | https://sub.example.com/sub/<token> |
Recommended for permanent use |
| Local-only debug | http://127.0.0.1:8080/sub/<token> |
Only for checks from the VPS itself or through an SSH tunnel. Does not work from a phone directly |
- A VPS with Debian 12/13 or Ubuntu 22.04/24.04 LTS and
rootorsudoaccess - 512 MB RAM minimum, 1 GB or more recommended
- 1 CPU core, 2 or more recommended
- 1 GB of free disk space
The installer pulls ca-certificates curl wget jq qrencode uuid-runtime ufw unzip openssl socat.
The installer does not check the OS version — the matrix above is declared, not enforced. Field testing happens mostly on Debian. Take a snapshot before installing on a VPS that matters.
Download the script, review it, and only then run the local file as root:
curl -fsSLo ./xrayebator-install.sh \
https://raw.githubusercontent.com/howdeploy/Xrayebator/main/install.sh
less ./xrayebator-install.sh
sudo bash ./xrayebator-install.shThe installer does not change host TCP or sysctl settings, but manages UFW on its own. Read Environment variables and Firewall and host networking BEFORE running it, especially if SSH listens on a non-standard port.
-
Open the menu:
sudo xrayebator
-
Choose
6) Подписка HAPP— the HAPP subscription entry. -
Choose the publishing mode: by VPS IP for a quick start without a domain, by domain for permanent use.
-
Xrayebator creates the
happprofile, brings up the inbounds, issues the certificate and prints the URL and a QR code. -
Import the subscription URL or QR into HAPP — not an individual
vless://link.
HAPP 3.3.6 or newer is required. If Xrayebator routes have a green ping but connections do not work, fully quit every old HAPP process, start exactly one current instance and refresh the subscription. A green route ping uses a separate temporary Xray-core and does not prove that the main TUN is healthy. On Linux,
ss -lntp | grep ':10808'must show the main HAPP core listening.
Also check the active Routing profile in HAPP. Routing profiles left over from another paid VPN
can override Xrayebator and send Telegram directly instead of through the VPS, even while route
pings stay green. Disable third-party routing and use Global Proxy, or select
xrayebator-default if that profile is present. In particular, avoid profiles with
globalProxy: false and no explicit Telegram proxy rule.
Use 1) Создать новый профиль for manual control over SNI, transport or a single route.
The terminal interface is in Russian. This README and the documentation describe every menu item, so the interface language is not a blocker.
| Document | Contents |
|---|---|
| Configuration | Environment variables, firewall and host networking, main menu, commands, bypass, cascade, self-steal, domain and DNS |
| Architecture | Repository and on-server state trees, inbound versus profile, subscription internals |
| Security | Service account and permissions, subscription protection, SSH access to the VPS |
| Troubleshooting | Subscription not refreshing, XHTTP not working, client not connecting and other cases |
| Testing | Local checks, what validation/ covers, manual checks on a live server |
Russian and Chinese versions live in docs/ru/ and docs/zh-CN/.
- The installer enables UFW via
ufw --force enableand opens a fixed list of eleven ports. SSH on a non-standard port is not in that list. xrayebator-updateautomatically removes a detected/opt/AdGuardHomeas deprecated: it first moves Xray DNS back to DoH, then stops the service and deletes the files. Do not update without a snapshot if AdGuard Home is in use on that VPS./usr/local/etc/xray/is owned byxray:xrayin full andconfig.jsonhas mode0644: the service account can write to its own config and profiles.- The installer does not check the OS version. The support matrix is declared, not enforced.
- The Xray core is verified by SHA-256 unconditionally, while Loyalsoldier geo databases are downloaded without a checksum check.
xrayebator-uninstalldoes not remove everything. It stops and disablesxray, deletes/usr/local/etc/xray,/usr/local/bin/xrayebatorand thexray.serviceandxray@.serviceunits. It does NOT remove the/usr/local/bin/xraybinary,subhttp,xrayebator-update,xrayebator-uninstall, thexrayebator-sub.serviceunit, nginx configs, geo databases, UFW rules or thexraysystem user. Clean up the remains manually.- The
tcp-muxroute is kept for compatibility; it is not a mux preset. - H2, WebSocket, SplitHTTP and Clash/mihomo subscriptions are not supported.
- The interface imposes no hard limit on users, but real capacity is bound by CPU, RAM, VPS bandwidth, route count and provider limits.
sudo xrayebator update # Xray-core only
sudo xrayebator-update # Xrayebator itself, branch from .current_branch
sudo xrayebator-update main # Xrayebator itself, forced from main
sudo xrayebator-uninstall # remove the service and configurationThe names look alike, the meaning does not:
sudo xrayebator update |
sudo xrayebator-update main |
|
|---|---|---|
| What it updates | The Xray-core binary | The Xrayebator scripts |
| Source | GitHub Releases of the XTLS project | The main branch of this repository |
| Argument | Takes none | Takes a branch name: main, dev, experimental or any other |
| Affects | Core version, transports, protocols | Menu, migrations, subscription generation |
| Side effect | Xray restart after config validation | Migrations run on the next menu launch |
The chosen branch is stored in /usr/local/etc/xray/.current_branch and shown in the menu header.
After updating Xrayebator itself, the first sudo xrayebator run executes migrations: wait for them
to finish before refreshing the subscription in the client.
What stays on the system after xrayebator-uninstall is listed in
Known limitations.
Import the subscription URL into the client, not an individual vless:// link. Raw routes from
3) Подключиться по профилю are for diagnostics.
| Client | Status | Comment |
|---|---|---|
| HAPP | Recommended | The target client. Supports subscriptions by URL and QR plus VLESS links |
| v2rayNG | Partial | Receives the base64 subscription, ignores HAPP metadata |
| v2rayN | Partial | VLESS subscriptions work, HAPP specifics are unused |
| Shadowrocket | Manual | Fine for raw VLESS, not the primary subscription client |
| sing-box · Hiddify · NekoBox · mihomo | Not targeted | Do not expect PQ-XHTTP or HAPP routing |
- Android: HAPP · v2rayNG · NekoBox
- iOS: HAPP · Shadowrocket · V2Box
- Windows: Throne · v2rayN · NekoRay
- macOS: Throne · V2RayXS · Qv2ray
- Linux: Throne · v2rayA · Qv2ray
Client documentation: HAPP subscription · v2rayN subscription format
MIT. See the LICENSE file.
- XTLS/Xray-core — for the protocol.
- HAPP — for the target client and the subscription format.
- 2dust/v2rayNG and 2dust/v2rayN — for the clients and subscription formats.
- Loyalsoldier/v2ray-rules-dat — for the extended geo databases.
- Umalanif/xray-server-setup — for the uTLS reference and automation.
- ServerTechnologies/simple-xray-core — for fast deployment.
- The community — for support and testing.
A star on GitHub is the simplest way to support the project.
Donations:
EVM 0x7acE4442b92f2769c24484c78A13024B139E1A5b
Solana FS9RBrG5yXJty3WNWgkBkfai6BfNoYxGMFeH1LQEpRZr
TON UQA56zsOv3zvU5x-p7iNNDL8jHh9dt7Q7WlY_gfbaj4ZhcyT
BTC 34EznmkBGpBu4dUnzoHL5GBnpg2Rq86v4H