xray panel supporting multi-protocol multi-user expire day & traffic & IP-Limit (Vmess & Vless & Trojan & Shadowsocks & Hysteria)
See the codeAn Advanced Web Panel • Built on Xray Core
Disclaimer: This project is only for personal learning and communication, please do not use it for illegal purposes, please do not use it in a production environment
If you think this project is helpful to you, you may wish to give a🌟 or donate me a coffee:
Official Donation Page: https://donate.alireza0.dev/
| Features | Enable? |
|---|---|
| Multi-Protocol | ✔️ |
| Multi-Language | ✔️ |
| Multi-Client/Inbound | ✔️ |
| Advanced Traffic Routing Interface | ✔️ |
| Client & Traffic & System Status | ✔️ |
| Date & Traffic Cap Based on First Use | ✔️ |
| REST API | ✔️ |
| TG Bot (DB backup + admin + client) | ✔️ |
| Subscription Service (link + info) | ✔️ |
| Search in Deep | ✔️ |
| Dark/Light Theme | ✔️ |
| IP Limit per client (Linux Only) | ✔️* |
bash <(curl -Ls https://raw.githubusercontent.com/alireza0/x-ui/master/install.sh)
On a fresh install, you can skip the questions and set the login info with environment variables. Any variable you leave out gets a random value.
| Variable | Description |
|---|---|
XUI_NONINTERACTIVE | Set to 1 to never ask questions during the install |
XUI_USERNAME | Panel username |
XUI_PASSWORD | Panel password |
XUI_PANEL_PORT | Panel port |
XUI_WEB_BASE_PATH | Panel web base path |
XUI_NONINTERACTIVE=1 XUI_USERNAME=me XUI_PASSWORD=secret XUI_PANEL_PORT=2053 XUI_WEB_BASE_PATH=abc123 \
bash <(curl -Ls https://raw.githubusercontent.com/alireza0/x-ui/master/install.sh)
These values are used only when the panel still has the default admin login. An existing setup is not changed.
Step 1: To install an old version, use following installation command. e.g., version 1.8.0:
VERSION=1.8.0 && bash <(curl -Ls "https://raw.githubusercontent.com/alireza0/x-ui/$VERSION/install.sh") $VERSION
# Debian/Ubuntu
apt-get update && apt-get install -y wget curl tar tzdata cron ca-certificates nftables
# CentOS/Alma/Rocky/Fedora
# yum install -y wget curl tar tzdata cronie ca-certificates nftables
# Arch/Manjaro
# pacman -Syu --noconfirm wget curl tar tzdata cronie ca-certificates nftables
ca-certificatesis needed for HTTPS/TLS connections, andnftablesis required by the per-client IP limit feature.
ARCH=$(uname -m)
case "${ARCH}" in
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
i*86 | x86) XUI_ARCH="386" ;;
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
armv7* | armv7) XUI_ARCH="armv7" ;;
*) XUI_ARCH="amd64" ;;
esac
wget https://github.com/alireza0/x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
ARCH=$(uname -m)
case "${ARCH}" in
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
i*86 | x86) XUI_ARCH="386" ;;
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
armv7* | armv7) XUI_ARCH="armv7" ;;
*) XUI_ARCH="amd64" ;;
esac
cd /root/
rm x-ui/ /usr/local/x-ui/ /usr/bin/x-ui -rf
tar zxvf x-ui-linux-${XUI_ARCH}.tar.gz
chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh
cp x-ui/x-ui.sh /usr/bin/x-ui
cp -f x-ui/x-ui.service /etc/systemd/system/
mv x-ui/ /usr/local/
systemctl daemon-reload
systemctl enable x-ui
systemctl restart x-ui
Step 1: Install Docker
curl -fsSL https://get.docker.com | sh
Step 2: Clone the Project Repository:
git clone https://github.com/alireza0/x-ui.git
cd x-ui
Step 3: Start the Service
docker compose up -d
OR
mkdir x-ui && cd x-ui
docker run -itd \
-p 54321:54321 -p 443:443 -p 80:80 \
-e XRAY_VMESS_AEAD_FORCED=false \
-v $PWD/db/:/etc/x-ui/ \
-v $PWD/cert/:/root/cert/ \
--name x-ui --restart=unless-stopped \
alireza7/x-ui:latest
update to latest version
cd x-ui
docker compose down
docker compose pull x-ui
docker compose up -d
remove x-ui from docker
docker stop x-ui
docker rm x-ui
cd --
rm -r x-ui
Build your own image
docker build -t x-ui .

The panel publishes a full OpenAPI 3.0 description of its API at
{basePath}xui/API/openapi.json, behind the same login as the API itself. It
covers every endpoint with its parameters, request bodies and response shapes,
and a test in the repository fails the build if a route is ever added or removed
without updating it — so it cannot drift from the code.
Fetch it once you have a session cookie and open it in any OpenAPI viewer, or point a client generator at it:
curl -c cookies.txt -X POST https://example.com:2053/mypanel/login \
-d 'username=admin&password=secret'
curl -b cookies.txt https://example.com:2053/mypanel/xui/API/openapi.json -o openapi.json
The table below is a quick reference for the same endpoints.
/login with PUSH user data: {username: '', password: ''} for login/xui/API/inbounds base for following actions:| Method | Path | Action |
|---|---|---|
GET | "/" | Get all inbounds |
GET | "/get/:id" | Get inbound with inbound.id |
POST | "/add" | Add inbound |
POST | "/del/:id" | Delete inbound |
POST | "/update/:id" | Update inbound |
POST | "/addClient/" | Add client to inbound |
POST | "/:id/delClient/:clientId" | Delete client by clientId* |
POST | "/updateClient/:clientId" | Update client by clientId* |
GET | "/getClientTraffics/:email" | Get client's traffic |
GET | "/getClientTrafficsById/:id" | Get client's traffic By ID |
POST | "/:id/resetClientTraffic/:email" | Reset client's traffic |
POST | "/resetAllTraffics" | Reset traffics of all inbounds |
POST | "/resetAllClientTraffics/:id" | Reset inbound clients traffics (-1: all) |
POST | "/delDepletedClients/:id" | Delete inbound depleted clients (-1: all) |
POST | "/import" | Import an inbound from exported data |
POST | "/onlines" | Get online users ( list of emails ) |
The field clientId should be filled by:
client.id for VMess and VLESSclient.password for Trojanclient.email for Shadowsocks/xui/API/outbounds base for following actions:
| Method | Path | Action |
|---|---|---|
GET | "/" | Get all outbounds |
POST | "/add" | Add outbound |
POST | "/del/:id" | Delete outbound |
POST | "/update/:id" | Update outbound |
POST | "/setFirst/:id" | Move outbound to the top of the list |
POST | "/:id/resetTraffic" | Reset outbound's traffic |
POST | "/resetAllTraffics" | Reset traffics of all outbounds |
POST | "/onlines" | Get online outbound tags |
POST | "/test" | Test outbound connectivity |
POST | "/reverseTags" | Get client reverse tags (usable as dialer) |
/xui/API/routing base for following actions:| Method | Path | Action |
|---|---|---|
GET | "/" | Get all routing rules |
GET | "/refs" | Get routing references (tags & metadata) |
POST | "/save" | Save routing rules |
POST | "/replaceBalancerTag" | Replace a balancer tag in routing rules |
/xui/API/server base for following actions:| Method | Path | Action |
|---|---|---|
GET | "/status" | Get server status |
GET | "/getDb" | Get database backup |
GET | "/createbackup" | Telegram bot sends backup to admins |
GET | "/getConfigJson" | Get config.json |
GET | "/getXrayVersion" | Get last xray versions |
GET | "/getNewVlessEnc" | Get new vless enc |
GET | "/getNewX25519Cert" | Get new x25519 cert |
GET | "/getNewmldsa65" | Get new mldsa65 |
POST | "/getNewEchCert" | Get new ech cert |
POST | "/getCertHash" | Get hash for provided cert |
POST | "/getTlsPing" | Get hash by TLS ping |
POST | "/importDB" | Import database to x-ui |
POST | "/stopXrayService" | Stop xray service |
POST | "/restartXrayService" | Restart xray service |
POST | "/installXray/:version" | Install specific version of xray |
POST | "/logs/:count" | Get panel/xray logs |
| Variable | Type | Default |
|---|---|---|
| XUI_LOG_LEVEL | "debug" | "info" | "warn" | "error" | "info" |
| XUI_DEBUG | boolean | false |
| XUI_BIN_FOLDER | string | "bin" |
| XUI_DB_FOLDER | string | "/etc/x-ui" |
The admin management script has a built-in SSL certificate application for Cloudflare. To use this script to apply for a certificate, you need the following:
Step 1: Run thex-uicommand on the server's terminal and then choose 17. Then enter the information as requested.
snap install core; snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
certbot certonly --standalone --register-unsafely-without-email --non-interactive --agree-tos -d <Your Domain Name>
The web panel supports daily traffic, panel login, database backup, system status, client info, and other notification and functions through the Telegram Bot. To use the bot, you need to set the bot-related parameters in the panel, including:
Crontab Time Format
Reference syntax:
*/30 * * * * - Notify every 30 minutes, every hour30 * * * * * - Notify at the 30th second of each minute0 */10 * * * * - Notify at the start of every 10 minutes@hourly - Hourly notification@daily - Daily notification (00:00 AM)@every 8h - Notify every 8 hoursFor more info about Crontab
If you are upgrading from an older version or other forks and find that data traffic usage for clients may not work by default, follow the steps below to enable it:
Step 1: Locate the Configuration Section
Find the following section in the config file:
"policy": {
"system": {
// Other policy configurations
}
},
Step 2: Add the Required Configuration
Add the following section just after "policy": {:
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
Step 3: Final Configuration
Your final config should look like this:
"policy": {
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
"system": {
"statsInboundDownlink": true,
"statsInboundUplink": true
}
},
"routing": {
// Other routing configurations
},
Step 4: Save and Restart
Save your changes and restart the Xray Service
86 followers · starred May 2026
185 followers · starred Oct 2023
29 followers · starred Jan 2024
3 followers · starred Apr 2023
xray panel supporting multi-protocol multi-user expire day & traffic & IP-Limit (Vmess & Vless & Trojan & Shadowsocks & Hysteria)
See the codeAn Advanced Web Panel • Built on Xray Core
Disclaimer: This project is only for personal learning and communication, please do not use it for illegal purposes, please do not use it in a production environment
If you think this project is helpful to you, you may wish to give a🌟 or donate me a coffee:
Official Donation Page: https://donate.alireza0.dev/
| Features | Enable? |
|---|---|
| Multi-Protocol | ✔️ |
| Multi-Language | ✔️ |
| Multi-Client/Inbound | ✔️ |
| Advanced Traffic Routing Interface | ✔️ |
| Client & Traffic & System Status | ✔️ |
| Date & Traffic Cap Based on First Use | ✔️ |
| REST API | ✔️ |
| TG Bot (DB backup + admin + client) | ✔️ |
| Subscription Service (link + info) | ✔️ |
| Search in Deep | ✔️ |
| Dark/Light Theme | ✔️ |
| IP Limit per client (Linux Only) | ✔️* |
bash <(curl -Ls https://raw.githubusercontent.com/alireza0/x-ui/master/install.sh)
On a fresh install, you can skip the questions and set the login info with environment variables. Any variable you leave out gets a random value.
| Variable | Description |
|---|---|
XUI_NONINTERACTIVE | Set to 1 to never ask questions during the install |
XUI_USERNAME | Panel username |
XUI_PASSWORD | Panel password |
XUI_PANEL_PORT | Panel port |
XUI_WEB_BASE_PATH | Panel web base path |
XUI_NONINTERACTIVE=1 XUI_USERNAME=me XUI_PASSWORD=secret XUI_PANEL_PORT=2053 XUI_WEB_BASE_PATH=abc123 \
bash <(curl -Ls https://raw.githubusercontent.com/alireza0/x-ui/master/install.sh)
These values are used only when the panel still has the default admin login. An existing setup is not changed.
Step 1: To install an old version, use following installation command. e.g., version 1.8.0:
VERSION=1.8.0 && bash <(curl -Ls "https://raw.githubusercontent.com/alireza0/x-ui/$VERSION/install.sh") $VERSION
# Debian/Ubuntu
apt-get update && apt-get install -y wget curl tar tzdata cron ca-certificates nftables
# CentOS/Alma/Rocky/Fedora
# yum install -y wget curl tar tzdata cronie ca-certificates nftables
# Arch/Manjaro
# pacman -Syu --noconfirm wget curl tar tzdata cronie ca-certificates nftables
ca-certificatesis needed for HTTPS/TLS connections, andnftablesis required by the per-client IP limit feature.
ARCH=$(uname -m)
case "${ARCH}" in
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
i*86 | x86) XUI_ARCH="386" ;;
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
armv7* | armv7) XUI_ARCH="armv7" ;;
*) XUI_ARCH="amd64" ;;
esac
wget https://github.com/alireza0/x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
ARCH=$(uname -m)
case "${ARCH}" in
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
i*86 | x86) XUI_ARCH="386" ;;
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
armv7* | armv7) XUI_ARCH="armv7" ;;
*) XUI_ARCH="amd64" ;;
esac
cd /root/
rm x-ui/ /usr/local/x-ui/ /usr/bin/x-ui -rf
tar zxvf x-ui-linux-${XUI_ARCH}.tar.gz
chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh
cp x-ui/x-ui.sh /usr/bin/x-ui
cp -f x-ui/x-ui.service /etc/systemd/system/
mv x-ui/ /usr/local/
systemctl daemon-reload
systemctl enable x-ui
systemctl restart x-ui
Step 1: Install Docker
curl -fsSL https://get.docker.com | sh
Step 2: Clone the Project Repository:
git clone https://github.com/alireza0/x-ui.git
cd x-ui
Step 3: Start the Service
docker compose up -d
OR
mkdir x-ui && cd x-ui
docker run -itd \
-p 54321:54321 -p 443:443 -p 80:80 \
-e XRAY_VMESS_AEAD_FORCED=false \
-v $PWD/db/:/etc/x-ui/ \
-v $PWD/cert/:/root/cert/ \
--name x-ui --restart=unless-stopped \
alireza7/x-ui:latest
update to latest version
cd x-ui
docker compose down
docker compose pull x-ui
docker compose up -d
remove x-ui from docker
docker stop x-ui
docker rm x-ui
cd --
rm -r x-ui
Build your own image
docker build -t x-ui .

The panel publishes a full OpenAPI 3.0 description of its API at
{basePath}xui/API/openapi.json, behind the same login as the API itself. It
covers every endpoint with its parameters, request bodies and response shapes,
and a test in the repository fails the build if a route is ever added or removed
without updating it — so it cannot drift from the code.
Fetch it once you have a session cookie and open it in any OpenAPI viewer, or point a client generator at it:
curl -c cookies.txt -X POST https://example.com:2053/mypanel/login \
-d 'username=admin&password=secret'
curl -b cookies.txt https://example.com:2053/mypanel/xui/API/openapi.json -o openapi.json
The table below is a quick reference for the same endpoints.
/login with PUSH user data: {username: '', password: ''} for login/xui/API/inbounds base for following actions:| Method | Path | Action |
|---|---|---|
GET | "/" | Get all inbounds |
GET | "/get/:id" | Get inbound with inbound.id |
POST | "/add" | Add inbound |
POST | "/del/:id" | Delete inbound |
POST | "/update/:id" | Update inbound |
POST | "/addClient/" | Add client to inbound |
POST | "/:id/delClient/:clientId" | Delete client by clientId* |
POST | "/updateClient/:clientId" | Update client by clientId* |
GET | "/getClientTraffics/:email" | Get client's traffic |
GET | "/getClientTrafficsById/:id" | Get client's traffic By ID |
POST | "/:id/resetClientTraffic/:email" | Reset client's traffic |
POST | "/resetAllTraffics" | Reset traffics of all inbounds |
POST | "/resetAllClientTraffics/:id" | Reset inbound clients traffics (-1: all) |
POST | "/delDepletedClients/:id" | Delete inbound depleted clients (-1: all) |
POST | "/import" | Import an inbound from exported data |
POST | "/onlines" | Get online users ( list of emails ) |
The field clientId should be filled by:
client.id for VMess and VLESSclient.password for Trojanclient.email for Shadowsocks/xui/API/outbounds base for following actions:
| Method | Path | Action |
|---|---|---|
GET | "/" | Get all outbounds |
POST | "/add" | Add outbound |
POST | "/del/:id" | Delete outbound |
POST | "/update/:id" | Update outbound |
POST | "/setFirst/:id" | Move outbound to the top of the list |
POST | "/:id/resetTraffic" | Reset outbound's traffic |
POST | "/resetAllTraffics" | Reset traffics of all outbounds |
POST | "/onlines" | Get online outbound tags |
POST | "/test" | Test outbound connectivity |
POST | "/reverseTags" | Get client reverse tags (usable as dialer) |
/xui/API/routing base for following actions:| Method | Path | Action |
|---|---|---|
GET | "/" | Get all routing rules |
GET | "/refs" | Get routing references (tags & metadata) |
POST | "/save" | Save routing rules |
POST | "/replaceBalancerTag" | Replace a balancer tag in routing rules |
/xui/API/server base for following actions:| Method | Path | Action |
|---|---|---|
GET | "/status" | Get server status |
GET | "/getDb" | Get database backup |
GET | "/createbackup" | Telegram bot sends backup to admins |
GET | "/getConfigJson" | Get config.json |
GET | "/getXrayVersion" | Get last xray versions |
GET | "/getNewVlessEnc" | Get new vless enc |
GET | "/getNewX25519Cert" | Get new x25519 cert |
GET | "/getNewmldsa65" | Get new mldsa65 |
POST | "/getNewEchCert" | Get new ech cert |
POST | "/getCertHash" | Get hash for provided cert |
POST | "/getTlsPing" | Get hash by TLS ping |
POST | "/importDB" | Import database to x-ui |
POST | "/stopXrayService" | Stop xray service |
POST | "/restartXrayService" | Restart xray service |
POST | "/installXray/:version" | Install specific version of xray |
POST | "/logs/:count" | Get panel/xray logs |
| Variable | Type | Default |
|---|---|---|
| XUI_LOG_LEVEL | "debug" | "info" | "warn" | "error" | "info" |
| XUI_DEBUG | boolean | false |
| XUI_BIN_FOLDER | string | "bin" |
| XUI_DB_FOLDER | string | "/etc/x-ui" |
The admin management script has a built-in SSL certificate application for Cloudflare. To use this script to apply for a certificate, you need the following:
Step 1: Run thex-uicommand on the server's terminal and then choose 17. Then enter the information as requested.
snap install core; snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
certbot certonly --standalone --register-unsafely-without-email --non-interactive --agree-tos -d <Your Domain Name>
The web panel supports daily traffic, panel login, database backup, system status, client info, and other notification and functions through the Telegram Bot. To use the bot, you need to set the bot-related parameters in the panel, including:
Crontab Time Format
Reference syntax:
*/30 * * * * - Notify every 30 minutes, every hour30 * * * * * - Notify at the 30th second of each minute0 */10 * * * * - Notify at the start of every 10 minutes@hourly - Hourly notification@daily - Daily notification (00:00 AM)@every 8h - Notify every 8 hoursFor more info about Crontab
If you are upgrading from an older version or other forks and find that data traffic usage for clients may not work by default, follow the steps below to enable it:
Step 1: Locate the Configuration Section
Find the following section in the config file:
"policy": {
"system": {
// Other policy configurations
}
},
Step 2: Add the Required Configuration
Add the following section just after "policy": {:
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
Step 3: Final Configuration
Your final config should look like this:
"policy": {
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
"system": {
"statsInboundDownlink": true,
"statsInboundUplink": true
}
},
"routing": {
// Other routing configurations
},
Step 4: Save and Restart
Save your changes and restart the Xray Service
86 followers · starred May 2026
185 followers · starred Oct 2023
29 followers · starred Jan 2024
3 followers · starred Apr 2023