Production-oriented, single-file Bash bootstrap for Xray-core with VLESS + REALITY + XTLS Vision, focused on:
- fast first deployment,
- repeatable operations,
- built-in hardening choices,
- and reliable behavior in restrictive network conditions.
Important
This README is beginner-first. If this is your first Xray deployment, follow sections in order from Quick Start through Post-Install Validation.
Warning
Use only where you are authorized. Network transport tooling may be regulated in your country or organization. You are responsible for lawful and ethical use.
Supported OS: any Debian or Ubuntu (apt + systemd). Tested on Debian 12 and Ubuntu 22.04 / 24.04; newer releases (including Ubuntu 26.04) and Debian 11/13 work too. Run as root on the VPS.
# 1) Clone on your VPS
cd /root
git clone https://github.com/braydos-h/vless-xtls-vision-installer.git
cd vless-xtls-vision-installer
# 2) Run interactive install
sudo bash xray_reality_bootstrap.sh installAfter the first install, use the persisted helper for day-2 operations:
sudo /usr/local/sbin/xray-reality-bootstrap status # health check
sudo /usr/local/sbin/xray-reality-bootstrap diagnose # triage
sudo /usr/local/sbin/xray-reality-bootstrap update # upgrade Xray binaryTip
If the wizard asks about SSH hardening, keep a second SSH session open until you confirm the new settings work.
Note
The script must be saved with LF line endings (this repo enforces that via .gitattributes). CRLF line endings break bash on the VPS. If you edited files on Windows, re-clone or run dos2unix xray_reality_bootstrap.sh before running it.
- At a Glance
- Before You Run
- Why This Works Well Against DPI (Technical)
- How Installation Works
- Install Modes
- Wizard Prompt Reference
- Post-Install Validation
- Command Reference
- Generated Client Artifacts
- Day-2 Operations Cookbook
- Troubleshooting Matrix
- Backup and Rollback
- Security Model and Hardening Notes
- Glossary
- FAQ
- License
| If you want to... | Start here |
|---|---|
| Get online quickly | 30-Second Quick Start |
| Understand DPI resilience mechanics | Why This Works Well Against DPI (Technical) |
| Run fully automated install | Install Modes |
| Verify if everything is healthy | Post-Install Validation |
| Fix failed connections | Troubleshooting Matrix |
Supported script modes:
install | update | repair | status | diagnose | reprint | rotate-shortid | uninstall- Fresh VPS or host where system-level firewall/SSH changes are acceptable
- Root access (
sudoworks) - Supported OS: Debian or Ubuntu (any recent version; Debian 11+ / Ubuntu 20.04+ recommended)
- Domain you control with DNS
A/AAAArecord pointing to this server - Outbound internet from VPS (for package install, Xray download, TLS probe)
- Port plan decided (
443recommended primary)
| Item | Value |
|---|---|
| Supported OS | Debian or Ubuntu (apt + systemd); any recent version |
| Service manager | systemd |
| Script file | xray_reality_bootstrap.sh |
| Persisted helper path | /usr/local/sbin/xray-reality-bootstrap |
| Xray config path | /etc/xray/config.json |
| State path | /etc/xray/bootstrap-state.env |
| Options profile path | /etc/xray/bootstrap-options.json |
| Client export directory | /root/xray-client-configs |
| Default primary port | 443 |
| Default update policy | weekly |
| Default logging profile | minimal |
This section is intentionally technical, but still operationally practical.
The server is configured with a serverName and dest target. During connection establishment, traffic characteristics are shaped to align with legitimate TLS destinations, reducing obvious protocol signatures.
Generated client configs use fingerprint: chrome, which helps present common browser-like TLS behavior rather than uncommon custom stacks.
flow=xtls-rprx-vision reduces unnecessary overhead and helps maintain stable performance under constrained paths where noisy or inefficient tunnels degrade quickly.
The server can accept multiple REALITY shortIds; the script can rotate them (rotate-shortid) without replacing UUID/keypair. This supports ongoing hygiene when a profile needs to be cycled.
A local Nginx camouflage service is bound on loopback (default 127.0.0.1:18080) and used as fallback destination handling. This helps avoid obvious dead-end behavior on non-matching flows.
flowchart LR
C[Client: VLESS + REALITY + XTLS Vision] --> X[Xray Inbound :443/:fallback]
X -->|REALITY settings| T[TLS-looking handshake behavior]
X -->|Validated route| O[Normal outbound]
X -->|Fallback path| N[Nginx camouflage on 127.0.0.1:18080]
- It does not guarantee universal bypass on every network.
- It does not prevent endpoint/device compromise.
- It does not remove the need for good OPSEC and credential handling.
- It does not make illegal use acceptable.
flowchart TD
A[Run install mode] --> B[OS and root checks]
B --> C[Wizard or auto-profile load]
C --> D[REALITY destination TLS reachability probe]
D --> E[Install dependencies]
E --> F[Install/Update Xray binary]
F --> G[Generate or reuse UUID + REALITY keys + shortIds]
G --> H[Write config + systemd unit]
H --> I[Configure SSH hardening + firewall + fail2ban + updates]
I --> J[Start services and persist state]
J --> K[Generate client URI/JSON/QR artifacts]
sudo bash xray_reality_bootstrap.sh installsudo bash xray_reality_bootstrap.sh install --auto --non-interactivesudo bash xray_reality_bootstrap.sh install --auto --non-interactive --profile-json /path/to/profile.jsoninstall --non-interactiverequires--auto.- If default profile is missing, the script can materialize an embedded template.
- Existing deployment detection menu is interactive by design unless running with explicit mode flags.
Example auto-profile JSON template
{
"profile_format": "1",
"SERVER_NAME": "www.cloudflare.com",
"DEST_ENDPOINT": "www.cloudflare.com:443",
"LISTEN_PORT": "443",
"FALLBACK_PORT": "",
"FIREWALL_STYLE": "nftables",
"SSH_PORT": "22",
"CHANGE_SSH_PORT": "no",
"HAS_SSH_KEYS": "yes",
"DISABLE_PASSWORD_AUTH": "yes",
"FAIL2BAN_ENABLED": "yes",
"UNATTENDED_UPGRADES_ENABLED": "yes",
"XRAY_UPDATE_POLICY": "weekly",
"LOG_PROFILE": "minimal",
"PROFILE_NAME": "reality-main",
"SHORT_ID_LABEL": "main",
"SHORT_ID_COUNT": "3",
"BLOCK_PRIVATE_OUTBOUND": "yes",
"CAMOUFLAGE_WEB_PORT": "18080"
}| Step | What you choose | Default | Why it matters | Beginner-safe choice |
|---|---|---|---|---|
| 1 | serverName + DEST_ENDPOINT |
www.cloudflare.com + :443 |
Defines REALITY impersonation target and TLS probe behavior | Use a stable high-traffic TLS site and keep port 443 |
Built-in serverName presets (Step 1)
The wizard probes reachability of whichever target you pick before continuing.
| # | Preset | Notes |
|---|---|---|
| 1 | www.cloudflare.com |
Recommended — globally common TLS profile |
| 2 | www.apple.com |
High legitimate mobile/desktop traffic |
| 3 | www.amazon.com |
High-volume commerce traffic |
| 4 | www.google.com |
Ubiquitous; TLS 1.3 + X25519 |
| 5 | www.yahoo.com |
Broad global traffic |
| 6 | addons.mozilla.org |
Stable Mozilla CDN endpoint |
| 7 | store.steampowered.com |
Gaming platform traffic |
| 8 | www.icloud.com |
Apple iCloud infrastructure |
| 9 | custom | Enter any domain you control that serves TLS 1.3 |
Pick a target not hosted behind the same CDN as your VPS, and prefer one whose TLS 1.3 + X25519 handshake is common in your region.
Run this in order right after install:
sudo /usr/local/sbin/xray-reality-bootstrap status
sudo /usr/local/sbin/xray-reality-bootstrap diagnose
sudo /usr/local/bin/xray -test -config /etc/xray/config.json
sudo systemctl is-active xray
sudo curl -fsS http://127.0.0.1:18080/healthzExpected signals:
| Check | Healthy signal |
|---|---|
systemctl is-active xray |
active |
xray -test -config ... |
no fatal parse/runtime errors |
curl .../healthz |
returns ok |
status mode |
Xray + Nginx active, expected listen ports visible |
diagnose mode |
no persistent config/firewall/service errors |
If any check fails, jump to Troubleshooting Matrix.
Use either:
- repo-local command:
sudo bash xray_reality_bootstrap.sh <mode> - persisted helper:
sudo /usr/local/sbin/xray-reality-bootstrap <mode>
| Mode | What it does | Typical use |
|---|---|---|
install |
Full wizard install/reconfigure | First deployment or planned reconfiguration |
update |
Updates Xray binary, keeps config/keys | Routine upgrade |
repair |
Reapplies saved state and hardening | Drift correction |
status |
Service + ports + firewall summary | Fast health check |
diagnose |
Unified diagnostics dump | Incident triage |
reprint |
Regenerates client exports from saved state | Re-share configs safely |
rotate-shortid |
Rotates shortIds only | Credential hygiene |
uninstall |
Removes deployment components | Decommission |
All client outputs are written under:
/root/xray-client-configsFile naming pattern (where <profile> is sanitized profile name):
| File | Purpose |
|---|---|
<profile>-primary.uri.txt |
Primary vless:// URI |
<profile>-fallback.uri.txt |
Fallback URI (if configured) |
<profile>-v2rayn-primary.json |
v2rayN JSON |
<profile>-v2rayng-primary.json |
v2rayNG JSON |
<profile>-sing-box-primary.json |
sing-box JSON |
<profile>-shadowrocket-streisand-singbox-primary.json |
Apple client compatible copy |
<profile>-shortids.txt |
All accepted shortIds |
<profile>-summary.txt |
Deployment summary |
<profile>-primary.uri.qr.txt / .png |
Primary QR (if qrencode available) |
<profile>-fallback.uri.qr.txt / .png |
Fallback QR (if fallback configured) |
Warning
These files contain credentials and metadata. Keep them private and avoid posting screenshots publicly.
sudo /usr/local/sbin/xray-reality-bootstrap status
sudo /usr/local/sbin/xray-reality-bootstrap diagnosesudo /usr/local/sbin/xray-reality-bootstrap updatesudo /usr/local/sbin/xray-reality-bootstrap repairsudo /usr/local/sbin/xray-reality-bootstrap reprintsudo /usr/local/sbin/xray-reality-bootstrap rotate-shortid| Symptom | Most likely cause | Run this first | Typical fix |
|---|---|---|---|
| Client timeout on connect | DNS mismatch, blocked port, wrong dest | sudo /usr/local/sbin/xray-reality-bootstrap diagnose |
Verify domain points to VPS IP; ensure port open in firewall; rerun install with correct DEST_ENDPOINT |
| Wizard fails on REALITY destination probe | Target endpoint unreachable or TLS mismatch | getent hosts <dest-domain> and probe section output |
Use a reachable TLS 1.3-capable target and matching serverName/dest |
xray service inactive |
Config error or failed restart | sudo journalctl -u xray -xe --no-pager |
Validate config with xray -test, then run repair |
| No QR files generated | qrencode missing/unavailable |
command -v qrencode |
Run reprint; script attempts to install qrencode |
| SSH lockout risk after hardening | Port/auth change without validated key login | Existing SSH session + sshd status |
Keep second SSH session open; only disable password auth after key login verified |
| Update timer not running | Policy set to manual or timer disabled | systemctl status xray-update.timer |
Re-run install/repair and choose weekly or daily policy |
| Clients fail after shortId rotation | Old client shortId still in use | sudo /usr/local/sbin/xray-reality-bootstrap reprint |
Distribute newly exported configs to clients |
status shows unexpected open ports |
Legacy rules or manual drift | sudo /usr/local/sbin/xray-reality-bootstrap status |
Normalize via repair, then verify firewall manager (nftables or ufw) |
Deep-dive diagnostic command bundle
sudo /usr/local/sbin/xray-reality-bootstrap diagnose
sudo journalctl -u xray -p err -n 120 --no-pager
sudo /usr/local/bin/xray -test -config /etc/xray/config.json
sudo ss -lntpBefore major changes (install reconfigure, repair, update), back up:
sudo tar czf /root/xray-backup-$(date +%F-%H%M).tgz /etc/xray /root/xray-client-configs /usr/local/sbin/xray-reality-bootstrapBasic rollback approach:
- Restore files from backup archive.
- Re-run
repairto reapply services/firewall/hardening from restored state. - Validate with the Post-Install Validation checklist.
- Firewall is enforced via
nftablesorufw. - SSH hardening choices are applied during install flow.
- Optional
fail2banandunattended-upgradesare integrated. - Logging profile can be tuned between
minimalandverbose. rotate-shortidhelps refresh client identifiers without replacing full identity material.- Uninstall intentionally leaves generic security packages in place.
Recommended operator habits:
- Keep SSH keys tested in a second session before auth changes.
- Restrict access to
/etc/xrayand/root/xray-client-configs. - Rotate shared client credentials periodically.
- Run
diagnosebefore manual edits.
| Term | Meaning in this project |
|---|---|
VLESS |
Lightweight proxy protocol used for client-server transport |
REALITY |
TLS-camouflage transport mode used by Xray |
XTLS Vision |
Flow mode (xtls-rprx-vision) used in generated configs |
serverName |
Domain value presented in REALITY/TLS behavior |
dest (DEST_ENDPOINT) |
Upstream destination target used for REALITY behavior |
shortId |
REALITY identifier; server can accept multiple values |
reprint |
Regenerates client outputs without rotating core secrets |
repair |
Reapplies saved state and hardening to correct drift |
Is this a panel?
No. It is a single Bash bootstrap focused on transparent single-node operations, not a multi-user management panel.
Can I run this on CentOS/RHEL/Alpine?
No — the installer assumes apt + systemd, so it targets Debian and Ubuntu (and close apt-based derivatives like Linux Mint / Pop!_OS / Kali). Any Debian or Ubuntu version is accepted (tested on Debian 12 and Ubuntu 22.04/24.04; Ubuntu 26.04 and Debian 11/13 work too); only genuinely old releases (Debian < 11, Ubuntu < 20.04) get a warning.
Can I install non-interactively?
Yes. Use install --auto --non-interactive and provide a valid options profile JSON.
Does this guarantee bypass on every network?
No. It improves resilience characteristics, but results vary by network controls, endpoint hygiene, and operational choices.
How do I safely share client configs?
Use reprint, share only necessary artifacts per user/device, and treat all exported files as secrets.
MIT. See LICENSE.