Skip to content

Xrayebator v0.7.0

Choose a tag to compare

@Ap3x0s Ap3x0s released this 22 Oct 13:14
a921a31

Xrayebator v0.7 — multi-protocol, PQ on every transport, DNS-01 and a reworked panel

An update of the server manager and the Xrayebator Desktop GUI. It installs over 0.6.0 (and over any 0.6.5-beta) — migrations finish the rest on their own, servers do not need to be reconfigured. Found a problem, have logs or errors — post them in the comments of this release or a separate issue: logs are the fastest way to a fix.

Changes since 0.6.5-beta.2

That cut shipped unchanged code, but everything accumulated after it (112 commits) was not in beta.2. In short:

  • PQ on every transport: mlkem768x25519plus is no longer hard-wired to xhttp — profile-pq --transport tcp|tcp-utls|tcp-xudp|tcp-mux|grpc|xhttp adds a post-quantum route on any of them, with its own inbound and port (VLESS decryption is inbound-level).
  • Four subscription bodies from one token: Clash/mihomo (YAML) and sing-box (JSON) join HAPP and base64; the body is chosen by ?target= and User-Agent, the default is still HAPP.
  • DNS-01 as a deployment fallback plus repair-dns01 for a subscription that already degraded: the chain is "existing cert → http-01 on the IP → DNS-01 → http_tls".
  • ACME staging contour and dns01-test: a verification-only issuance in staging with its own lineage and no side effects, so debugging no longer burns the production Let's Encrypt quota.
  • Per-profile traffic limits: accounting through the Stats API, automatic disabling on overrun, profile-limit / traffic-check, a chip and a dialog in the GUI.
  • Telegram alerts and monitoring: alerts-setup, monitor-check every 15 minutes (units, backends, expiry, limits, subscription liveness, TLS mode, SNI probe, reboots). The GUI has no alerts surface any more — terminal only.
  • channel-test: channel verification with a real Xray client, no Let's Encrypt needed, PQ routes included.
  • A GUI wave from feedback: the "Existing profiles" page split off from creation, sections in the server settings, a collapsible "Subscription and TLS" card, a shorter deployment form, backend keys next to a profile, the green "Done" button.
  • Fixes found on live servers: profile-pq no longer drops the base route, profile-delete leaves no orphaned inbounds, the SNI probe rejects unreachable hosts, ?target=v2ray does not return the HAPP body, traffic accounting actually counts, AWG comes back after a reboot, and jq 1.6 no longer breaks PQ on Ubuntu 22.04.
  • Documentation is synchronized across three languages and cross-checked against the code; the test set grew to 42 scripts (from 28).

In two words

Until now the server spoke one protocol — Xray Reality over TCP. Censorship strangles TCP, and the whole VPN dies with it: one transport, one point of failure.

v0.7 puts two more transports on the same server, and the panel learns to manage them:

  1. Hysteria 2 — a UDP/QUIC transport: fast on bad links, alive where TCP is cut;
  2. AmneziaWG 3.1 — a system VPN (WireGuard with anti-DPI junk in the headers): a full tunnel, native AmneziaVPN apps;
  3. Per-profile grants — each protocol's key is issued separately and lives in the profile's lifecycle: revoke, expiry and deletion revoke the backend keys together with VLESS.
┌────────────────────────────────────────────────────────┐
│                      one VPS                           │
│                                                        │
│  Xray (Reality, TCP)      ── ports 443 / high 30xxx    │
│  Hysteria 2 (QUIC, UDP)   ── its own port              │
│  AmneziaWG 3.1 (UDP)      ── awg0, its own port        │
│                                                        │
│  subscription: vless:// + hysteria2:// + HAPP routes   │
└────────────────────────────────────────────────────────┘
        ▲                        ▲                    ▲
        │                        │                    │
   HAPP / v2rayNG          HAPP / Hiddify         AmneziaVPN
   ( Reality+Hysteria )    ( Reality+Hysteria )   ( AmneziaWG 3.1 )

The client subscription stays one: hysteria2:// lines go into the same bodies (with a kill switch in the GUI), the AWG config is handed out as a .conf file or a QR, and for the full AmneziaVPN app in its native vpn:// shape. A single token serves four bodies: HAPP, base64 v2ray, Clash/mihomo and sing-box.

What's new

1. A neutral backend registry

The add-on protocol state lives in the neutral root /usr/local/etc/xrayebator/ (the backends.json registry is 644 with no secrets, the runtime state with secrets is 750). /usr/local/etc/xray/ stays Xray-only. A single choke point — _backend_apply_profile_lifecycle — runs every profile lifecycle through all installed backends, so revoke/expiry/deletion never leave orphaned credentials.

2. Hysteria 2 (UDP/QUIC)

  • installed from the official HyNetworks/hysteria releases with a sha256 check, a dedicated hysteria system user and its own hysteria-server.service (CAP_NET_BIND_SERVICE, auto-restart), QUIC buffers in sysctl;
  • TLS is adaptive: if the subscription has a Let's Encrypt certificate it is copied into the backend (with a renewal deploy hook), otherwise a self-signed one is generated — and the client links honestly carry insecure=1;
  • per-profile keys: the password lives in the profile's .backends.hysteria2, and server.yaml is always regenerated from the profiles — revoking or extending a key is a regeneration plus a restart with rollback;
  • hysteria2:// is appended to both bodies (HAPP and v2rayNG) and is controlled by a kill switch without a service restart.

3. AmneziaWG 3.1 (system VPN)

  • the kernel module via DKMS: the primary path is the amnezia/ppa PPA, the fallback is a source build (kernels ≥5.6 need the full linux-source tree); the module is loaded at boot, otherwise the tunnel stayed down after a reboot while the card said "active";
  • junk parameters match the official Amnezia dialect one-for-one (Jc=5, Jmin/Jmax, H1–H4, S1–S4): their native apps apply them predictably;
  • format 3.1 is on by default: HeaderProtectionKey, RandomTrailers, S3/S4; the awg-31 toggle exists with an explicit warning — previously issued client .conf files have to be downloaded again (AmneziaVPN ≥ 5.0.1.5);
  • per-profile peers: a client key pair plus a preshared key, addresses from 10.8.1.0/24; awg0.conf is regenerated from the profiles;
  • the client .conf is a full tunnel (AllowedIPs = 0.0.0.0/0, ::/0), keepalive 25; in the GUI a key can be taken as .conf, QR, or "QR · AmneziaVPN" — the native vpn:// shape that the app imports whole (a raw .conf pasted into the full AmneziaVPN app does not reach its tunnel intact).

4. PQ (VLESS Encryption) on every transport

  • xrayebator profile-pq --name N [--transport tcp|tcp-utls|tcp-xudp|tcp-mux|grpc|xhttp] adds a post-quantum route (mlkem768x25519plus) on any transport;
  • VLESS decryption is inbound-level, so a PQ route gets its own inbound and port with the shared key from .vless_decryption; ordinary routes keep encryption=none and stay usable by every client;
  • PQ routes are hidden from the base64/v2ray body (a client without ML-KEM could not connect anyway) and skipped with a reason in Clash/sing-box; the HAPP body keeps them;
  • profiles carries the additive pq_routes counter — the top-level pq_enabled only describes the first route.

5. Subscription: four bodies from one token

  • HAPP, base64 v2ray, Clash/mihomo (YAML) and sing-box (JSON) are rendered from one link set; the body is chosen by ?target= and User-Agent, HAPP by default so already-issued links keep working;
  • routes a client cannot use (PQ, xhttp in sing-box, xhttp in Clash without ?xhttp=1) are skipped with a reason instead of breaking the whole config;
  • subscription-userinfo is sent for every body; format links are cached in the server card, so the GUI no longer grows them after the SSH answer;
  • in the GUI this is an extra view, not an obligation: by default the Keys page serves the main set — the HAPP/v2ray subscription and the VLESS links, as before — and the Clash/sing-box formats are switched on by the «Clash / sing-box formats» toggle in the page header. Without it the same token was printed three times per profile, which read as a duplicated key.

6. DNS-01 and ACME

  • dns01-setup --domain --provider cloudflare|route53 issues a certificate through a TXT record — inbound port 80 is not needed at all;
  • repair-dns01 converts a subscription that already degraded to http_tls onto a domain, idempotently;
  • the staging contour (--staging) and dns01-test — a verification-only issuance with its own lineage, no deploy hook and no side effects: debugging no longer burns the production quota (5 certificates per exact identifier set per 168 hours);
  • dns01-status decides the contour from the certificate itself and accepts both spellings of the hook record (deploy-hook / renew_hook).

7. Per-profile traffic limits

  • accounting through the Xray Stats API (a loopback dokodemo-door), deltas against a watermark — an Xray restart does not lose already-counted bytes;
  • profile-limit --name N --limit 500MB|2TB|none [--reset], traffic-check every 5 minutes; on overrun the client is removed from the inbound and restored when the limit is raised;
  • expiry and limits are cross-guarded: a profile does not come back while the other restriction still applies;
  • the GUI shows a chip in the profile card and a limit dialog.

8. Telegram alerts and monitoring

  • alerts-setup validates the token with getMe and delivers a test message before writing the config — an undeliverable chat never leaves a half-configuration;
  • monitor-check every 15 minutes: units, installed backends, approaching and expired profiles, profiles disabled by a limit, subscription liveness, TLS-mode degradation, a daily SNI probe, reboots;
  • deduplication, "no more often than once per N", and a retry after a failed send live in monitor-state.json;
  • the desktop app has no alerts surface — the bot token has exactly one entry point, the terminal.

9. Lifecycle: keys do not live on their own

  • Profile creation — a key is NOT issued automatically: the operator picks a protocol in the GUI (or runs an explicit hysteria2-grant / awg-grant), otherwise every new profile would receive keys from all installed backends at once;
  • Revoke — rotates the Hysteria password and the AWG peer key pair plus PSK (old configs stop connecting, the address is kept);
  • Expiry/extension — for backends this is a regeneration from the profiles filtered by the disabled flag: an expired profile stops receiving its key, an extended one comes back;
  • Profile deletion — the peer is removed from awg0.conf and the password leaves server.yaml in the same command; no orphaned credentials.

10. GUI: sections, a profiles page and compact cards

  • "Server settings" is split into sections instead of one long scroll; panels are hidden by an attribute, so typed input is not lost on switching;
  • an "Existing profiles" page separate from creation: search by name/SNI/subscription domain, an "All/Active/Disabled" filter, a card counter; both screens live in one component, so switching does not open a second SSH session;
  • the "Subscription and TLS" card is collapsible: a certificate icon, the mode as a badge, three values in monospace boxes;
  • the deployment form is a quarter shorter: the IP shares a row with the SSH port, PQ and DNS-01 sit in one "Additional options" block, and the host-key note is the progress card's footer;
  • the backend panel in "Server settings": official logos, state (version, port, TLS mode / interface, junk summary), install/uninstall, and a "Start" button for an installed but idle backend;
  • backend keys next to a profile, on par with VLESS: QR (including "QR · AmneziaVPN"), expiry with presets, Revoke, delete; confirmations use the soft danger style.

11. HAPP routing: split routing from bypass groups

The managed HAPP profile can be assembled from bypass sets (bypass list/add/remove/reset/bundle): domains of the selected groups go direct, everything else goes through the tunnel. The client downloads geo bases through the subscription itself ({{GEOIP_URL}} / {{GEOSITE_URL}} / {{LAST_UPDATED}} placeholders are rendered per subscriber — the base URL is bound to their token).

12. quickstart degrades to http_tls instead of dying

Some hosters filter inbound port 80 for foreign sources — Let's Encrypt cannot validate http-01 for a bare IP (Connection reset by peer from validation hosts). That used to be a dead end; now:

  • the deploy finishes with degraded:true, tls_mode:"http_tls" and the certbot reason;
  • the subscription stays loopback-only — there is no public URL at all: the GUI fetches keys over SSH from http://127.0.0.1:8080/sub/<token> on the server itself (nothing can leak);
  • a self-signed certificate is prepared in advance for future Hysteria installs;
  • if a domain and a DNS provider token are supplied, the fallback goes through DNS-01 and the subscription stays on HTTPS;
  • the ACME location on :80 is kept: once the hoster unblocks the port, a repeated quickstart (idempotent) issues the LE certificate and restores HTTPS.

The GUI stores such a server as "Partially configured" with a degradation note.

13. SNI and country

  • probe-test and the default SNI choice follow a strict criterion: a completed TLS 1.3 handshake with a verified certificate and an HTTP answer, two measurements, a 3 s budget per attempt. An unreachable dest is no longer handed to fresh profiles;
  • subscription keys are labelled with the server country: fragments look like 🇫🇮 Finland · happ-* — handy when there are several servers.

Also in this branch

  • profile-pq no longer discards the base route of the profile it was asked to extend (the single-route shape is expanded into routes[] first);
  • profile-delete leaves no orphaned inbounds: the port set is the union of the top-level .port and every routes[].port;
  • ?target=v2ray no longer returns the HAPP body; the rule that dropped an xhttp route from HAPP is gone — it silently removed a working xhttp-pq;
  • jq 1.6 no longer breaks PQ (label is a keyword): the route is created on Ubuntu 22.04 / Debian 12 too;
  • quickstart --pq is no longer dead code — the block moved out of the failure branch it used to sit in;
  • traffic accounting is enabled where the Xray policy actually reports it (statsUserUplink/Downlink), plus a repair migration for servers with an early marker;
  • AWG: S1 != S2, the card's label and colour come from one field, revoke rotates the PSK too;
  • inspect --json no longer reports installed backends as missing; xrayebator-uninstall tears backends down before removing state;
  • revoke --full works on single-route profiles; profile-delete prints JSON only;
  • GUI polish from feedback: the profile row is one line, "valid until" no longer shifts the card, the update-branch menu is a HeroUI Dropdown again, and the green "Done" button has no blur.

Stability and security

  • TLS and ACME. The staging contour and dns01-test verify a domain and a token without burning the production Let's Encrypt quota; dns01-status decides the contour from the certificate itself and accepts both spellings of the hook record; the short-lived IP certificate no longer fights the distribution certbot.timer; repair-dns01 no longer shifts the subscription port.
  • Access. The SSH host key is pinned on the first successful login, root/sudo is an explicit choice, passwords and keys live in the system keychain; DNS-01 credentials are stored on the server in a 0600 root file and are never kept by the GUI; the Telegram bot token is not printed by any command and is configured from the terminal only.
  • Subscription. PQ routes are kept out of bodies a client without ML-KEM could not use anyway, and unsupported routes are skipped with a reason instead of shipping a broken config; deleting a profile no longer leaves orphaned inbounds still serving the removed profile.
  • Limits. Hitting a traffic limit removes the client from the inbound and restores it when the limit is raised; expiry and limits are cross-guarded, so one restriction cannot be bypassed through the other.
  • Network. The default SNI is chosen only by a strict criterion — a completed TLS 1.3 handshake with a verified certificate and an HTTP answer — so fresh profiles no longer receive dead routes.
  • Reliability. Migrations are idempotent and registered on every entry path; safe_restart_xray validates the config and rolls back on failure; UFW rules and nginx vhosts are tracked by a manifest so removal leaves no leftovers.

How well this is tested

Automated:

  • Bash validation: 42 scripts (up from 28) — new ones cover PQ on every transport, subscription formats, DNS-01/certbot, the quickstart TLS fallback, traffic limits, alerts/monitoring, the Hysteria 2 and AmneziaWG lifecycles, the backend registry, channel-test, HAPP client routing, SNI reachability, legacy profile port sync, and jq 1.6 compatibility;
  • GUI: 25 Vitest files (172 tests) — AWG export (vpn://, range timers, qCompress), backend-manager, the inspector, render tests for the settings and profiles pages, and ru/en/zh i18n parity; typecheck and build are clean;
  • CI on ubuntu-24.04 runs all 42 scripts; bundles are built on three OSes.

Live runs: three deployments with live measurements — two control deploys from scratch on Ubuntu 22.04 (the GUI default mode and one with the PQ route enabled) and a production server deployed earlier, where the profiles, subscription bodies and both backends were verified; plus control deploys on four distributions (Ubuntu 22.04/24.04, Debian 12/13), including the http_tls fallback on a hoster filtering :80. All three were checked with a real Xray client on every route, post-quantum ones included (HTTP 200, ≈170–330 ms); all four subscription bodies from outside; Hysteria 2 and AmneziaWG installs and grants; a vpn:// import into AmneziaVPN ≥ 5.0.1.5; and the CLI self-update main → dev.

And manual device testing: every route of all three deployments connects and works from a phone and from a PC through HAPP and Hiddify — link acceptance out of the subscription is verified not only server-side but by real clients.

Before you upgrade

Server requirements

  • Debian 12/13 or Ubuntu 22.04/24.04, systemd, bash, root/sudo;
  • for AmneziaWG — kernel ≥ 5.6 and a working DKMS build (PPA or sources);
  • migrations catch the state up automatically on the first menu launch or quickstart.

Breaking changes

There are none for existing VLESS installations: everything is additive, profiles and the subscription stay compatible. Worth knowing:

  • one AWG key = one device — two devices on the same .conf will fight over the endpoint;
  • Hysteria under a self-signed certificate runs with insecure=1 — a deliberate mode until an LE certificate is issued;
  • an http_tls server has no public subscription — keys are taken over SSH from the GUI (or with curl over SSH on the server);
  • a PQ route is not part of the base64/v2ray body — HAPP gets it, other clients need ML-KEM;
  • Telegram alerts are configured from the CLI only — the GUI no longer has that surface.

Honest limitations

  • the routes of all three deployments were also verified on devices — from a phone and from a PC through HAPP and Hiddify they connect and work; per-app latency was not measured separately, the numbers in this release come from channel-test on the server;
  • a real AmneziaWG client connection and the network parts of backend installs were verified in a live spike, not in CI — DKMS builds and tunnels are not reproducible there;
  • restarting awg0 on a grant/revoke briefly drops the tunnel for every peer;
  • HAPP geo bases are unavailable to a client without preloaded bases under an http_tls fallback ("no data" — not a broken key).

How to upgrade

Server

sudo xrayebator update main

Backends are not installed automatically: after the update open "Server settings" → "Extra protocols" and install Hysteria 2 and/or AmneziaWG with the button. Keys are issued per profile — creation goes through the protocol choice.

Xrayebator Desktop GUI

  1. Download the package for your OS from the GitHub Release.
  2. Install it over the previous version — server cards are preserved.
  3. New: the "Existing profiles" page, settings sections, the compact "Subscription and TLS" card, backend cards next to a profile, Hysteria/AWG keys on the "Keys" page.
  4. The "Update Xrayebator" button is now a branch menu: "Auto — as pinned on the server", "main — the latest stable", "dev — all the new stuff at once" (may be unstable — that is how this beta reaches a server before the release).

Build

The release is built natively for three systems:

  • Windows — Xrayebator-0.7.0-win.exe;
  • macOS Apple Silicon — Xrayebator-0.7.0-mac-arm64.dmg and .zip (the ZIP is needed by the built-in auto-updater);
  • Linux — Xrayebator-0.7.0-linux.AppImage.

Before building on Ubuntu the pipeline runs typecheck, unit tests and the full Bash validation set (42 scripts).

Links