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.
- At a Glance
- 30-Second Quick Start
- 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# 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 first install, use the persisted helper:
sudo /usr/local/sbin/xray-reality-bootstrap statusTip
If the wizard asks about SSH hardening, keep a second SSH session open until you confirm new settings work.
- Fresh VPS or host where system-level firewall/SSH changes are acceptable
- Root access (
sudoworks) - Supported OS: Debian 12, Ubuntu 22.04, or Ubuntu 24.04
- 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 12, Ubuntu 22.04, Ubuntu 24.04 |
| 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 |
| 2 | Primary + optional fallback port | 443, fallback off |
Controls reachability and surface area | Start with primary 443, skip fallback initially |
| 3 | Firewall style | nftables |
Host policy enforcement | Keep nftables unless your team standard is ufw |
| 4 | SSH hardening | keep 22, key-based checks |
Prevent lockout and improve admin security | Keep defaults unless you already validated key login |
| 5 | OS/Xray update policy | OS upgrades on, Xray weekly |
Patch cadence and operational effort | Keep OS upgrades on + weekly Xray |
| 6 | Logging profile | minimal |
Troubleshooting detail vs exposure/noise | Use minimal; switch to verbose only during debug |
| 7 | Client profile + shortIds + private egress block | shortIds 3, block private egress on |
Affects client artifacts and exposure controls | Keep 3 shortIds and block private egress |
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. Current script checks only Debian 12, Ubuntu 22.04, and Ubuntu 24.04.
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.