Xray panel supporting multi-protocol multi-user expire day & traffic & IP limit (Vmess, Vless, Trojan, ShadowSocks, Wireguard, Hysteria, Tunnel, Mixed, HTTP, Tun) https://t.me/XrayUI
Find a file
n0ctal e940f30bb8
feat(clients): cap how many times a client may auto-renew (#6238)
* feat(clients): cap how many times a client may auto-renew

Auto-renew today runs forever: a prepaid or fixed-term client keeps being
handed new periods until an operator remembers to switch it off. There is no
way to say "renew this three times, then let it lapse".

Add a per-client maximum. Zero keeps today's behaviour, so nothing changes for
anyone who does not set one. When the count is reached the client is simply
left to expire, like any client without auto-renew.

Catching up several missed periods spends one allowance per period. A client
that was away for three cycles must not receive three of them free of the cap,
and the catch-up stops at the last period the cap paid for rather than jumping
to the present.

* fix(clients): persist the auto-renew cap and stop the capped churn

resetMax lived only in the inbound settings JSON and client_traffics, so
every path that rebuilds a client from the clients table wrote it back as
zero. The edit dialog showed 0 for a capped client, and saving an
unrelated comment change lifted the cap; an attach or a traffic reset did
the same with no operator action at all.

Adds reset_max to ClientRecord and threads it through ToRecord, ToClient,
applyClientRecordMerge, the record update map and ClientSlim, so the cap
survives the round trip.

When the cap truncates a catch-up the client is still expired, but the
renewal side effects fired anyway: counters were zeroed for periods it
can never use, and it was enabled and pushed to xray only for
disableInvalidClients to undo both in the same transaction. Those are now
skipped when the new expiry has not reached the present.

Also makes any non-positive resetMax mean unlimited instead of silently
meaning "never renew again", rejects a negative one at the service layer,
surfaces renewals used against allowed in the client info modal so the
operator can see what to raise, adds the field to the bulk-add modal,
translates the labels in all 13 locales, and drops the stray
internal/web/dist/.gitkeep build stub.

* fix(clients): let the renewal cap be changed after creation

ClientService.Update writes the record columns directly only for a client
with no inbounds. The normal path goes through SyncInbound and
applyClientRecordMerge, which this change had not extended, so raising a
cap from 3 to 6 — the natural action when a customer buys another block
of periods — updated the inbound settings JSON while clients.reset_max
kept the old value and the renewal query kept enforcing it.

The existing test did not catch it: it asserted the cap survived an
unrelated edit, and it survived precisely because nothing on that path
ever wrote it. TestClientEditChangesTheRenewalCap raises the cap and then
lifts it entirely; removing the record write turns it red.

* chore: drop the accidentally committed dist build stub

internal/web/dist/.gitkeep is what make dist-stub creates locally. Committing
it changes fresh-clone behaviour for everyone: today a bare go build fails
loudly on //go:embed all:dist, which is the documented signal to run the stub
target; with the file present the build succeeds and the panel serves an empty
dist instead.

---------

Co-authored-by: n0ctal <n0ctal@users.noreply.github.com>
2026-08-18 11:53:11 +02:00
.github ci: actually run the PostgreSQL schema and migration tests (#6224) 2026-08-18 11:38:14 +02:00
.vscode chore(vscode): fix Linux paths in the task and launch configs 2026-08-02 12:40:11 +02:00
deploy fix(install): preserve custom bin/ files (e.g. hand-added geoip) across updates (#6152) 2026-08-14 16:41:45 +02:00
docs feat(inbounds): add a narrow endpoint for subscription sort order (#6179) 2026-08-15 21:48:24 +02:00
frontend feat(clients): cap how many times a client may auto-renew (#6238) 2026-08-18 11:53:11 +02:00
internal feat(clients): cap how many times a client may auto-renew (#6238) 2026-08-18 11:53:11 +02:00
media
tools/openapigen feat(xray): browse geosite/geoip categories from routing rules (#6165) 2026-08-15 17:12:59 +02:00
windows_files
.dockerignore refactor: focused service files, leaf subpackages, and an internal/ layout (#5167) 2026-06-10 15:19:22 +02:00
.env.example Env vars example file update (#5678) 2026-07-03 00:28:13 +02:00
.gitattributes chore: add golangci-lint tasks and force LF on Go files 2026-07-08 22:11:28 +02:00
.gitignore feat(xray): update xray-core to v26.7.28 and adapt panel 2026-07-28 13:14:06 +02:00
.golangci.yml style: adopt golangci-lint v2 and resolve all findings 2026-06-27 15:42:22 +02:00
.nvmrc chore: standardize the toolchain on Node 24 LTS 2026-07-14 03:39:03 +02:00
CLAUDE.md feat(xray): browse geosite/geoip categories from routing rules (#6165) 2026-08-15 17:12:59 +02:00
CONTRIBUTING.md fix(ci): resync the bot prompts with the repo and close the gaps an audit found 2026-08-17 02:41:21 +02:00
docker-compose.yml fix(docker): start crond and persist acme.sh state so cert renewal works 2026-07-03 09:32:28 +02:00
DockerEntrypoint.sh fix(docker): start crond and persist acme.sh state so cert renewal works 2026-07-03 09:32:28 +02:00
Dockerfile refactor: focused service files, leaf subpackages, and an internal/ layout (#5167) 2026-06-10 15:19:22 +02:00
DockerInit.sh feat(xray): update xray-core to v26.7.28 and adapt panel 2026-07-28 13:14:06 +02:00
go.mod Bump Go toolchain and x dependencies 2026-08-14 17:02:17 +02:00
go.sum Bump Go toolchain and x dependencies 2026-08-14 17:02:17 +02:00
install.sh fix(install): preserve custom bin/ files (e.g. hand-added geoip) across updates (#6152) 2026-08-14 16:41:45 +02:00
LICENSE
main.go feat(nodes): opt-in encryption at rest for the outbound node API token (#6186) 2026-08-15 16:48:50 +02:00
main_test.go feat(nodes): opt-in encryption at rest for the outbound node API token (#6186) 2026-08-15 16:48:50 +02:00
Makefile feat(frontend): make Storybook a validated, fully covered component workbench 2026-07-14 03:37:21 +02:00
README.ar_EG.md fix(mtproto): stop dropping connections on client/inbound edits; add live updates + ad-tag (#5838) 2026-07-07 01:13:24 +02:00
README.es_ES.md fix(mtproto): stop dropping connections on client/inbound edits; add live updates + ad-tag (#5838) 2026-07-07 01:13:24 +02:00
README.fa_IR.md fix(mtproto): stop dropping connections on client/inbound edits; add live updates + ad-tag (#5838) 2026-07-07 01:13:24 +02:00
README.md fix(mtproto): stop dropping connections on client/inbound edits; add live updates + ad-tag (#5838) 2026-07-07 01:13:24 +02:00
README.ru_RU.md fix(mtproto): stop dropping connections on client/inbound edits; add live updates + ad-tag (#5838) 2026-07-07 01:13:24 +02:00
README.tr_TR.md fix(mtproto): stop dropping connections on client/inbound edits; add live updates + ad-tag (#5838) 2026-07-07 01:13:24 +02:00
README.zh_CN.md fix(mtproto): stop dropping connections on client/inbound edits; add live updates + ad-tag (#5838) 2026-07-07 01:13:24 +02:00
SECURITY.md fix(ci): resync the bot prompts with the repo and close the gaps an audit found 2026-08-17 02:41:21 +02:00
update.sh fix(script): Remove old mtg binary (#5955) 2026-07-14 12:44:22 +02:00
x-ui.rc
x-ui.service.arch Bug-label issue sweep: 16 fixes (#6083) 2026-07-23 15:34:42 +02:00
x-ui.service.debian Bug-label issue sweep: 16 fixes (#6083) 2026-07-23 15:34:42 +02:00
x-ui.service.rhel Bug-label issue sweep: 16 fixes (#6083) 2026-07-23 15:34:42 +02:00
x-ui.sh fix(script): confirm auto-detected public IPv4 before issuing IP certificate 2026-07-11 22:35:31 +02:00

English | فارسی | العربية | 中文 | Español | Русский | Türkçe

3x-ui

Release Build GO Version Downloads License Go Reference

3X-UI is an advanced, open-source web control panel for managing Xray-core servers. It provides a clean, multi-language interface for deploying, configuring, and monitoring a wide range of proxy and VPN protocols — from a single VPS to multi-node deployments.

Built as an enhanced fork of the original X-UI project, 3X-UI adds broader protocol support, improved stability, per-client traffic accounting, and many quality-of-life features.

Important

This project is intended for personal use only. Please do not use it for illegal purposes or in a production environment.

Features

  • Multi-protocol inbounds — VLESS, VMess, Trojan, Shadowsocks, WireGuard, Hysteria2, HTTP, SOCKS (Mixed), Dokodemo-door / Tunnel, and TUN.
  • Modern transports & security — TCP (Raw), mKCP, WebSocket, gRPC, HTTPUpgrade, and XHTTP, secured with TLS, XTLS, and REALITY.
  • Fallbacks — serve multiple protocols on a single port (e.g. VLESS and Trojan on 443) using Xray's fallback support.
  • Per-client management — traffic quotas, expiry dates, IP limits, live online status, and one-click share links, QR codes, and subscriptions.
  • Traffic statistics — per inbound, per client, and per outbound, with reset controls.
  • Multi-node support — manage and scale across multiple servers from a single panel.
  • Outbound & routing — WARP, NordVPN, custom routing rules, load balancers, and outbound proxy chaining.
  • Built-in subscription server with multiple output formats and custom page templates.
  • Telegram bot for remote monitoring and management.
  • RESTful API with in-panel Swagger documentation.
  • Flexible storage — SQLite (default) or PostgreSQL.
  • 13 UI languages with dark and light themes.
  • Fail2ban integration for enforcing per-client IP limits.

Screenshots

Click to expand Overview Inbounds Add client Configs

Quick Start

bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)

To install a specific version, append its tag (e.g. v3.4.0):

bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v3.4.0

To install the rolling dev build (latest per-commit pre-release from main, not a stable release), pass dev-latest:

bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) dev-latest

During installation a random username, password, and access path are generated. After installation, run x-ui to open the management menu, where you can start/stop the service, view or reset your login credentials, manage SSL certificates, and more.

For full documentation, please visit the project Wiki.

Unattended install

The installer also runs non-interactively for cloud-init. Set XUI_NONINTERACTIVE=1 (or pipe with no TTY) and it installs end-to-end with zero prompts, generating random credentials and writing them to /etc/x-ui/install-result.env. See deploy/ for:

Supported Platforms

Operating systems: Ubuntu, Debian, Armbian, Fedora, CentOS, RHEL, AlmaLinux, Rocky Linux, Oracle Linux, Amazon Linux, Virtuozzo, Arch, Manjaro, Parch, openSUSE (Tumbleweed / Leap), Alpine, and Windows.

Architectures: amd64 · 386 · arm64 (aarch64) · armv7 · armv6 · armv5 · s390x.

Database Options

3X-UI supports two backends, chosen during the install:

  • SQLite (default) — a single file at /etc/x-ui/x-ui.db. Zero setup, ideal for small and medium deployments.
  • PostgreSQL — recommended for high client counts or multi-node setups. The installer can install PostgreSQL locally for you, or accept a DSN to an existing server.

At runtime the backend is selected via environment variables (the installer writes these to /etc/default/x-ui for you):

XUI_DB_TYPE=postgres
XUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable

Migrating an existing SQLite install to PostgreSQL

x-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable"
# then set XUI_DB_TYPE and XUI_DB_DSN in /etc/default/x-ui and restart:
systemctl restart x-ui

The source SQLite file is left untouched; remove it manually once you have verified the new backend.

Docker

The default docker compose up -d keeps using SQLite. To run with the bundled PostgreSQL service, uncomment the two XUI_DB_* env lines in docker-compose.yml and start with the profile:

docker compose --profile postgres up -d

The image bundles Fail2ban (enabled by default) to enforce per-client IP limits. Fail2ban bans offenders with iptables, which requires the NET_ADMIN capability. docker-compose.yml already grants it via cap_add; if you start the container with docker run instead, add the capabilities yourself, otherwise bans are logged but never applied:

docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... ghcr.io/mhsanaei/3x-ui

Environment Variables

Variable Description Default
XUI_DB_TYPE Database backend: sqlite or postgres sqlite
XUI_DB_DSN PostgreSQL connection string (when XUI_DB_TYPE=postgres)
XUI_DB_FOLDER Directory for the SQLite database file /etc/x-ui
XUI_DB_MAX_OPEN_CONNS Maximum open connections (PostgreSQL pool)
XUI_DB_MAX_IDLE_CONNS Maximum idle connections (PostgreSQL pool)
XUI_INIT_WEB_BASE_PATH The initial URI path for the web panel /
XUI_ENABLE_FAIL2BAN Enable Fail2ban-based IP-limit enforcement true
XUI_LOG_LEVEL Log verbosity (debug, info, warning, error) info
XUI_DEBUG Enable debug mode false
XUI_TUNNEL_HEALTH_MONITOR Enable the tunnel health monitor (probes a URL and restarts xray after repeated failures; a restart drops all clients) false
XUI_TUNNEL_HEALTH_PROXY Proxy the probe is sent through; point it at a local xray inbound so the probe tests the tunnel (e.g. socks5://127.0.0.1:1080). Empty means the probe only checks host connectivity
XUI_TUNNEL_HEALTH_URL URL probed for tunnel health https://www.cloudflare.com/cdn-cgi/trace
XUI_TUNNEL_HEALTH_INTERVAL Interval between probes 30s
XUI_TUNNEL_HEALTH_TIMEOUT Per-probe timeout 10s
XUI_TUNNEL_HEALTH_FAILURES Consecutive failures before a restart is triggered 3
XUI_TUNNEL_HEALTH_COOLDOWN Minimum delay between consecutive restarts 5m

Supported Languages

The panel UI is available in 13 languages:

English · فارسی · العربية · 中文(简体) · 中文(繁體) · Español · Русский · Українська · Türkçe · Tiếng Việt · 日本語 · Bahasa Indonesia · Português (Brasil)

Contributing

Contributions are welcome. Please read the Contributing Guide before opening an issue or pull request.

A Special Thanks to

Acknowledgment

  • Iran v2ray rules (License: GPL-3.0): Enhanced v2ray/xray and v2ray/xray-clients routing rules with built-in Iranian domains and a focus on security and adblocking.
  • Russia v2ray rules (License: GPL-3.0): This repository contains automatically updated V2Ray routing rules based on data on blocked domains and addresses in Russia.

Community Tools

Tools and integrations built by the community around 3x-ui.

  • terraform-provider-3x-ui (License: MIT): Manage inbounds, clients, panel settings, and Xray configuration as code with Terraform / OpenTofu.

Support project

If this project is helpful to you, you may wish to give it a🌟

Buy Me A Coffee
Crypto donation button by NOWPayments

Stargazers over Time

Stargazers over time