Files
3x-ui-pro/CLAUDE.md
T
Ivan RazinandClaude Fable 5 ba6d9ca1d2 Add h2/http1.1 ALPN to tls hosts; make raw diag link self-authorize
Host ALPN: ws/xhttp/trojan hosts now advertise ["h2","http/1.1"];
reality host gets [] (its ALPN comes from the reality stream).

Diagnostics access: opening the diag path directly without the
diag_key cookie previously 404'd, so a bookmarked link only worked
after manually visiting /<panel_path>/diag. Now the diag page
302-bounces unauthenticated hits through the SSO bridge, which
validates the 3x-ui panel session and mints the cookie, then redirects
back - so the link works once you're logged into the panel. API and
asset sub-locations still 404 without the cookie (only the HTML page
redirects, never XHR/asset requests).

Verified end to end with nginx + the auth semantics of the installed
3x-ui v3.4.2: logged-in raw hit resolves to the page with no loop,
anonymous hit lands on the panel login.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 15:54:56 +03:00

4.7 KiB

x-ui-pro-refactor

Refactored single-file installer for 3x-ui VPN panel (based on x-ui-pro).

Repository structure

x-ui-latest.sh          — main installer script (single file, run remotely)
x-ui-patch.sh           — apply current features to an existing install (no DB changes)
assets/
  backup/x-ui-backup.sh — backup / restore / list script
  clash/clash.yaml      — Clash/Mihomo subscription template (served by UA sniffing)
  diagnostics/
    index.html          — network diagnostics page (speed test, MTR, test files)
    mtr-backend.py      — localhost-only backend: MTR, LibreSpeed endpoints, clash.yaml generator
    librespeed/         — vendored LibreSpeed engine (speedtest.js, speedtest_worker.js, LGPL)
  fake-sites/
    site-01 … site-50/  — static HTML cover pages (index.html per site)

Scripts download assets at install time from this repo's raw GitHub URL (https://raw.githubusercontent.com/mozaroc/3x-ui-pro/main/...) — changes take effect on servers only after push to main.

What x-ui-latest.sh does

  1. Checks OS (Ubuntu 24.04/26.04, Debian 12/13) and rejects QEMU-emulated CPUs
  2. Parses CLI arguments (-install y, -subdomain, -reality_domain, -auto_domain y, -uninstall y)
  3. Validates domains (panel ≠ REALITY), then stops/cleans any previous install
  4. Installs packages (install_packages) — nginx-full, certbot, sqlite3, ufw, mtr, python3 …
  5. Obtains Let's Encrypt certs via certbot standalone (get_ssl_certs) — panel + reality domains
  6. Installs 3x-ui panel from MHSanaei/3x-ui latest release (install_panel)
  7. Configures nginx (configure_nginx) — SNI stream (443 → reality:8443 / panel:7443), per-domain vhosts, shared includes snippet, rate-limit zones
  8. Pushes all settings and inbounds into x-ui.db (configure_xui_db). Share-link endpoints use the hosts table (supersedes legacy externalProxy arrays in stream_settings): one host per inbound — REALITY gets security=same, the rest front through nginx :443 with security=tls, fingerprint firefox
  9. Installs Clash subscription template (install_clash_sub) → /var/www/subpage/clash.yaml.tpl; Clash/Mihomo user agents get generated clash.yaml, ?provider=1 bypasses it
  10. Downloads a random fake cover site (install_fake_site) → /var/www/html/
  11. Installs network diagnostics (install_diagnostics) → /var/www/diagnostics/ + mtr-backend systemd service (hardened, dedicated user, localhost-only). Access is gated by the 3x-ui panel session via an nginx SSO bridge at /<panel_path>/diag: auth_request validates the session against GET <basePath>/panel/ (with X-Requested-With → 401 instead of a login redirect), then issues a path-scoped diag_key cookie and redirects to the diag page. Hitting the diag path directly without the cookie 302-bounces through that bridge, so a bookmarked diag link "just works" once logged into the panel (API/asset sub-locations stay 404 without the cookie). The 3x-ui session cookie is Path-scoped to the panel base path, which is why the bridge must live under the panel path
  12. Tunes kernel/BBR (tune_system)
  13. Sets up cron (setup_cron) — daily x-ui restart + nginx reload; monthly certbot renew with pre/post hooks stopping/starting nginx (certs are standalone-issued)
  14. Configures UFW (setup_firewall) — 22/80/443 tcp, 443 udp
  15. Prints panel URL + credentials (show_results)

Speed test (LibreSpeed)

Upload over HTTP/2 is throttled per-stream by the h2 flow-control window, so a single big POST measures ~4x low. The diagnostics page uses the vendored LibreSpeed engine: parallel streams, XHR-progress measurement, no telemetry, no database. h2 must stay enabled on the vhosts — trojan-gRPC needs it. Endpoints: download = static testfiles/test-100m.bin; upload = api/st/up (Python sink, proxy_request_buffering off); ping = api/st/ping (nginx return 200); IP = api/st/getip. Speedtest locations use limit_conn, not limit_req (the engine fires many requests).

Inbounds created

Protocol Port Transport
vless 8443 REALITY / TCP
vless $ws_port WebSocket
vless UDS socket XHTTP (gRPC)
trojan $trojan_port gRPC

Running

bash <(curl -fsSL https://raw.githubusercontent.com/mozaroc/3x-ui-pro/main/x-ui-latest.sh) \
  -install y -subdomain panel.example.com -reality_domain r.example.com

Patch an existing install (re-reads ports/paths from x-ui.db and nginx):

bash <(curl -fsSL https://raw.githubusercontent.com/mozaroc/3x-ui-pro/main/x-ui-patch.sh)