How to Install 3X-UI Panel on a VPS
A complete, production-oriented guide to installing the 3X-UI Xray panel on Ubuntu, locking down the web interface, issuing TLS, creating a VLESS Reality inbound, managing users, and connecting clients on desktop and mobile.

3X-UI is a web panel for Xray-core. It lets you manage inbounds (VLESS, VMess, Trojan, Shadowsocks and others), issue subscription links, set traffic limits and expiry dates, and watch live connections without editing JSON by hand. For people who already run a VPS, it is one of the fastest ways to get a maintainable proxy stack instead of a one-off config that nobody can update six months later.
This guide is written for a fresh Ubuntu 22.04 or 24.04 VPS, which is what most Hiddence Linux images look like after first boot. We will install the widely used MHSanaei 3X-UI build, change every default secret on first login, put the panel behind HTTPS, open only the ports you actually need, create a VLESS + Reality inbound, and then walk through client apps. If you already followed our Marzban article, the idea is similar — a panel on top of Xray — but the install path, file layout and daily workflow are different, so do not mix the two on the same server unless you really know how to split ports.
Why 3X-UI instead of a raw Xray config
A raw Xray config is fine for a single user and a single inbound. The moment you add friends, rotate Reality keys, or need a subscription URL that phones can import in one tap, a panel saves hours. 3X-UI stores users in a local database, can restart Xray cleanly after changes, and exposes a compact dashboard for traffic and online status. It is not a magic anonymity layer by itself: the VPS location, TLS fingerprint, inbound type and your own operational hygiene still decide how the setup behaves on the network.
- Web UI for inbounds, clients, traffic and expiry instead of hand-edited JSON
- Built-in subscription links for v2rayN, v2rayNG, Streisand, Happ and similar clients
- One-command install plus a documented update path
- Works well on a small VPS (1 vCPU / 1 GB RAM is enough for personal use)
- You keep root on your own server — the panel does not send configs to a third-party cloud
What you need before you start
Do not skip the domain and firewall parts. A panel left on HTTP at port 2053 with the default password is scanned by bots within hours. Prepare these items, then connect as root (or a sudo user) over SSH.
- A Linux VPS with a public IPv4 address (Ubuntu 22.04/24.04 recommended)
- At least 1 GB RAM and 10 GB disk; 2 GB RAM is more comfortable if you also run other services
- Root or sudo access over SSH
- A domain or subdomain pointing an A record at the VPS IP (needed for a proper panel certificate)
- About 20–30 minutes, plus DNS waiting time if you just created the A record
Step 1: Update the system and set the timezone
A brand-new VPS often has pending security updates and UTC as the clock. Update packages first so the installer is not fighting an outdated OpenSSL or curl. Setting the timezone is optional for Xray itself, but it makes panel logs and certificate expiry dates much easier to read.
ssh root@YOUR_VPS_IP
apt update && apt -y upgrade
apt -y install curl wget ca-certificates gnupg socat tar unzip
timedatectl set-timezone UTC
hostnamectl set-hostname panel
# Confirm DNS for your subdomain (should print your VPS IP):
dig +short panel.example.comStep 2: Install 3X-UI
The official install script for the MHSanaei 3X-UI build downloads the latest release, installs Xray-core, creates a systemd service and prints the first-login URL. Read the output carefully: it contains a random path and a generated username/password. Copy them to a password manager immediately. If the script asks about the panel port, either keep 2053 or pick an unused high port; just remember it for the firewall step.
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
# After install, useful commands:
x-ui # interactive menu (start/stop/restart, reset, update)
systemctl status x-ui # confirm the service is active
ss -tulpn | grep x-ui # see which port the panel listens onStep 3: First login and immediate hardening
Open the URL printed by the installer, usually http://YOUR_IP:2053/<random-path>. Log in with the generated credentials, then go to Panel Settings (or Configuration). Change the username and password to unique values. If the panel lets you change the web base path, do it — a long random path cuts a huge amount of drive-by scans. Set the listen port if you want something other than 2053. Save and restart the panel from the UI or with systemctl restart x-ui, then log in again on the new URL.
Next, turn on two-factor authentication if your build offers it, and disable unused inbound templates you will never use. Under Xray settings, leave the core version that shipped with the panel unless you have a specific reason to pin another build. Do not expose the panel on port 80/443 yet if those ports will later be used by Reality or a reverse proxy — pick one strategy and stick to it.
- Replace the generated admin login immediately
- Keep the secret web path; do not move the panel to /
- Prefer a non-default panel port and record it
- Never reuse this password on other services
Step 4: TLS certificate for the panel
Browsers will warn on HTTP, and sending the admin password in clear text on a public network is a bad idea. 3X-UI can request a Let's Encrypt certificate if port 80 is free and the domain points to this VPS. In the panel, open the certificate / SSL section, enter panel.example.com, and request the cert. If port 80 is already taken, use a DNS-01 flow or put Caddy/Nginx in front and reverse-proxy to 127.0.0.1:2053.
# Quick check that port 80 is free before the panel ACME challenge:
ss -tulpn | grep ':80'
# If you terminate TLS on Caddy instead of inside 3X-UI:
# Caddyfile example (panel stays on 127.0.0.1:2053):
# panel.example.com {
# reverse_proxy 127.0.0.1:2053
# }Step 5: Create a VLESS Reality inbound
In Inbounds, create a new inbound. A solid default for many networks is VLESS with Reality and TCP. Pick a port that is not the panel port — 443 is common if nothing else is bound there; otherwise use a high TCP port and be consistent in the firewall. Generate a UUID for the first client, generate Reality key pairs in the UI, and set dest / serverNames to a legitimate target that you are allowed to mimic (a well-known site that supports TLS 1.3). Save the inbound and confirm Xray reloads without errors in the panel logs.
Then add extra clients on that inbound if you need them: each user gets a UUID, optional email tag, and optional traffic or time limit. Copy the connection link or the subscription URL from the user row. Do not post those links in public chats; they are equivalent to a password.
# On the server, confirm Xray is listening on the inbound port (example: 443):
ss -tulpn | grep -E ':443|:2053'
# Follow Xray logs if a client cannot connect:
journalctl -u x-ui -fStep 6: Firewall — only the ports you need
UFW on Ubuntu is enough. Allow SSH first so you cannot lock yourself out, then the panel port and the inbound port. If you requested a Let's Encrypt cert from the panel, also allow 80/tcp during issuance. Reality inbound on 443 needs 443/tcp (and not the panel on the same port).
ufw allow OpenSSH
ufw allow 2053/tcp comment '3x-ui panel (change if you picked another port)'
ufw allow 443/tcp comment 'VLESS Reality inbound'
# ufw allow 80/tcp comment 'only if panel ACME needs it'
ufw enable
ufw status verboseConnect clients
On Windows, v2rayN can import a VLESS link from the clipboard. On Android, v2rayNG or similar Xray clients do the same from a QR code. On iOS, use a client that supports VLESS Reality (for example Streisand or Happ, depending on what is currently available in your region). After import, enable the profile and check the panel's online list. If the client stays offline, the usual causes are a wrong port, UDP left on for a TCP-only inbound, a Reality serverName that does not match dest, or a local firewall on the laptop.
- Windows: v2rayN — import VLESS link, set routing as you need (global vs rule-based)
- Android: v2rayNG — scan QR from the panel user page
- macOS / iOS: a client with VLESS + Reality support; paste the same link
- Subscription URL: add it in the client so UUID rotations do not require a manual re-import
Updates, backup and reinstall safety
Before every panel update, download a backup from the UI (database + config). Store it off the VPS. Updates are typically x-ui then the update option in the menu, or the same install script which detects an existing install. After an update, confirm the systemd service is active and that inbounds still listen. If you reinstall the OS, restore the backup in the panel instead of recreating every UUID by hand.
x-ui # choose update when prompted, or:
# bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
# Backup files commonly live under /etc/x-ui/ — copy them off-box:
ls -la /etc/x-ui/
# Example offsite copy:
# scp -r /etc/x-ui/ you@backup-host:~/x-ui-backup-$(date +%F)/Troubleshooting
Most first-day failures are DNS, ports or Reality fields. Work through this list before reinstalling the panel. Reinstalling without a backup is how people lose every client UUID.
- Cannot open the web UI: check systemctl status x-ui, ss -tulpn, and UFW. Confirm you included the secret path in the URL.
- Forgot admin password: run x-ui on the server and use the reset option.
- Client connects then stalls: inbound port blocked, or you enabled UDP on a TCP Reality inbound.
- TLS errors on the panel: domain A record not pointing here yet, or port 80 busy during ACME.
- Reality handshake fails: dest/serverNames mismatch, or another service already bound to 443.
- High CPU: too many inbounds on a 1 vCPU plan, or a scan/flood on an open port — check ss and panel online count.
Security notes that actually matter
Treat the panel like production admin software. It can mint new users and read every UUID. Limit who can reach the web port: if you have a stable office IP, allow only that IP in UFW for 2053/tcp. Keep SSH on keys, not passwords. Do not run unrelated public websites on the same IP if you are using Reality on 443 — competing TLS stacks on one port are a classic source of outages. Rotate the admin password if a screenshot of the panel ever leaked into a chat.
- SSH keys only; disable password login after keys work
- Restrict the panel port in the firewall when you can
- Back up /etc/x-ui off the server on a schedule
- Do not share subscription URLs in public Telegram groups
- Watch disk: logs and traffic stats grow on a busy inbound
Practical tips
- One inbound with many clients is easier to operate than ten nearly identical inbounds
- Name clients by device (laptop-anna, phone-ben) so traffic charts mean something
- If you also need a reverse proxy for a website, put the site on another IP or another port — do not fight Reality for 443
- After any x-ui restart, test one client before you leave the SSH session
- Read the changelog before updating; skip 'latest' jumps on a Friday night
You now have 3X-UI installed as a systemd service, a locked-down admin URL, TLS on the panel, a VLESS Reality inbound, firewall rules that match those ports, and a backup habit. Add clients from the inbound page, import the link on each device, and update the panel only after a backup. If something breaks, the x-ui menu on the VPS is the recovery path — not a full reinstall.