10 Commits
Author SHA1 Message Date
Muse 1d340b5abd release: panel V2.7.1 (panel-only, agent line A2.6.0)
CI / go-test (push) Waiting to run
CI / postgres-durable-first (push) Waiting to run
CI / codegen (push) Waiting to run
CI / govulncheck (push) Waiting to run
CI / race (push) Waiting to run
CI / fuzz-smoke (push) Waiting to run
CI / golangci (push) Waiting to run
CI / frontend (push) Waiting to run
Docs CI / build (push) Waiting to run
Docs Deploy (GitHub Pages) / build (push) Waiting to run
Docs Deploy (GitHub Pages) / deploy (push) Blocked by required conditions
Release 3X-UI / build (386) (push) Waiting to run
Release 3X-UI / build (amd64) (push) Waiting to run
Release 3X-UI / build (arm64) (push) Waiting to run
Release 3X-UI / build (armv5) (push) Waiting to run
Release 3X-UI / build (armv6) (push) Waiting to run
Release 3X-UI / build (armv7) (push) Waiting to run
Release 3X-UI / build (s390x) (push) Waiting to run
Release 3X-UI / Build for Windows (amd64) (push) Waiting to run
Release 3X-UI / Publish rolling dev release (push) Blocked by required conditions
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
2026-10-24 16:26:10 +00:00
Muse 71e9ee1767 Restore locale test fixtures deleted in error
The internal/web/locale/translation/ files (en-US, fa-IR, zh-CN) are
not production data — the panel embeds internal/web/translation —
but they ARE test fixtures: locale_lazy_test.go embeds this package's
own translation/ directory (//go:embed translation) and asserts lazy
parsing against hello/greet keys in exactly these three languages.
Deleting them broke the locale package's test setup
('pattern translation: no matching files found'), which the full Go
run caught. The 'zero references' check missed the test's relative
embed pattern because it grepped for the full locale/translation path.

Restored byte-identical to 5a9c983; locale package tests pass again.
2026-10-24 16:01:13 +00:00
Muse 1acf4643b6 Close out panel API token removal (V2.7.1 follow-up)
1. Drop the dormant api_tokens table on startup: initModels now runs
dropApiTokensTable (GORM Migrator, string table name since the model is
gone). No-ops on fresh databases, where AutoMigrate never creates it;
covers databases carried over from V2.7.0 whose install row was already
deleted by hand. Covered by TestDropApiTokensTable_DropsLegacyTable.

2. Delete provably dead Nord/PIA integration: service/integration/nord.go
and pia.go (+ pia_test.go), the whole internal/pia package (only pia.go
imported it), the nord/pia setting keys and getters, the HasNordSecret
view field, and the frontend model/schema fields; openapigen regenerated
(generated diff is exactly the hasNordSecret removal). Evidence: zero
production callers for NordService/PiaService, no controller routes, no
jobs, no frontend UI, no openapi exposure; panel egress is a separate
netproxy mechanism and does not consume them. maxResponseSize moves to
warp.go, which is its remaining user (it was declared in nord.go).

3. Delete unreferenced internal/web/locale/translation/ (3 files):
the runtime loads internal/web/translation (web.go embed + locale.go
disk fallback); zero references to the locale/translation path.

4. gofmt-align the AllSetting SubPort block (pre-existing drift).

5. Docs: architecture.md token table row, API-tokens troubleshooting
row, api_token.go tree entry, setting/api gateway token comments, the
mtls 'API token optional' phrase, and the integration provider list
(now warp.go only); the 4 api-tokens.mdx pages plus their meta.json
entries; the per-node apiToken prose in nodes.mdx (4 languages, title
and anchor slugs updated in pairs; frontmatter re-parsed clean).

Deliberately NOT changed: install-agent.sh RELEASE_BASE stays V2.7.0
(agent installs keep pulling from V2.7.0); install-master.sh LUI_URL
V2.7.0 -> V2.7.1 is left to the release commit; no forced first-login
password change.

Kept as live, with evidence: WARP (hourly WarpIpJob in web.go),
mtproto (live inbound protocol + sidecar manager + traffic job),
xray_version (NodeList UI fallback when singboxVersion is absent),
session.apiAuthUserKey (spa_test login simulation + GetLoginUser
production fast path).
2026-10-24 15:47:49 +00:00
Muse 5a9c9837e1 Remove panel API token system (panel-only, V2.7.1)
Delete the whole ApiToken stack from the panel: the api_tokens table
model and seed/migrate/normalize paths, the Bearer auth and
admin/monitor scope chain in the panel API (session login is now the
only panel API credential), the settings token-management endpoints,
the CLI -getApiToken bootstrap command, and the SecurityTab token
management UI plus its models/schemas/i18n keys. Regenerate the
frontend OpenAPI files (31 -> 26 schemas).

Agent side untouched: agent runtime, agent version (A2.6.0),
install-agent.sh, subscription/probe paths and node behavior are
unchanged. The /panel/api/agent group never went through checkAPIAuth
and is unaffected.

Also drop provably dead weight found in the same pass: the unimported
internal/xray/geodata package and its generated schemas, the retired
SPA shell routes (/groups, /xray, /outbound, /routing, /api-docs;
unregistered paths still reach the shell via the NoRoute fallback),
the never-set SettingController.xrayService field, and the CSRF
api_authed exemption whose only setter was the deleted Bearer branch.

Deliberately NOT dropped: the api_tokens table itself (left dormant
and empty in existing databases; a DROP migration needs a separate
decision) and the session apiAuthUserKey helper (test-only use remains).
2026-10-24 15:04:06 +00:00
Muse 739c18ce48 release: panel V2.7.0 / agent line A2.6.0
CI / go-test (push) Waiting to run
CI / postgres-durable-first (push) Waiting to run
CI / codegen (push) Waiting to run
CI / govulncheck (push) Waiting to run
CI / race (push) Waiting to run
CI / fuzz-smoke (push) Waiting to run
CI / golangci (push) Waiting to run
CI / frontend (push) Waiting to run
Docs CI / build (push) Waiting to run
Release 3X-UI / build (386) (push) Waiting to run
Release 3X-UI / build (amd64) (push) Waiting to run
Release 3X-UI / build (arm64) (push) Waiting to run
Release 3X-UI / build (armv5) (push) Waiting to run
Release 3X-UI / build (armv6) (push) Waiting to run
Release 3X-UI / build (armv7) (push) Waiting to run
Release 3X-UI / build (s390x) (push) Waiting to run
Release 3X-UI / Build for Windows (amd64) (push) Waiting to run
Release 3X-UI / Publish rolling dev release (push) Blocked by required conditions
Deploy Smoke Tests / noninteractive-install (ubuntu-24.04-arm) (push) Waiting to run
Deploy Smoke Tests / noninteractive-install (ubuntu-latest) (push) Waiting to run
Deploy Smoke Tests / release-tag-install (ubuntu-24.04-arm) (push) Waiting to run
Deploy Smoke Tests / release-tag-install (ubuntu-latest) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Docs Deploy (GitHub Pages) / build (push) Canceled after 0s
Docs Deploy (GitHub Pages) / deploy (push) Canceled after 0s
Agent code changed in the rename batch (lui-agent binary, LUI_ env prefix, /etc/l-ui paths and services), so the agent line moves 2.5.0 -> 2.6.0 and its default-expectation tests move with it; panel version is injected at build time (V2.7.0). install-agent.sh RELEASE_BASE and install-master.sh LUI_URL move V2.6.0 -> V2.7.0. Repo name settled as rogue/l-ui (user decision 2026-10-24); the rename-batch placeholder warnings in docs/release.md, selfupdate.go and install-master.sh are closed by the Gitea rename that precedes publishing this release.
2026-10-24 20:53:51 +08:00
Muse f2695ddb22 test: track LUI_ skip gates in bot-context checks
The rename changed the env prefix XUI_ -> LUI_, so the gate regexes only matched XRAY_E2E_BINARY (1 < 5) and TestBotContextSkipGatesExist failed on the rename branch while passing on base. LUI_ joins the alternation; XUI_ stays so a stray old gate is still checked, not silently ignored. REVIEW.md's LUI_SCALE_TEST is now covered by the review check too.
2026-10-24 20:53:13 +08:00
Muse e0ed2b0352 fix: gofmt NodeView AgentOS field alignment 2026-10-24 12:15:41 +00:00
Muse 2b914d374f docs: RENAMING.md + l-ui migration runbook
RENAMING.md: exact mapping, LUI_ inventory, sing-box orphan-scan
re-verification, Tianyi badge mechanism, intentionally-kept items
(module path, upstream mentions, frozen Windows, ps1, log
filenames, Postgres creds, generated schemas, stale test
binaries), and pending items (repo spelling BLOCKER, version
bump, ps1 URL after repo rename, schema regeneration).
docs/migration-l-ui.md: operator-only mv table, DB file rename,
unit-env translation, backup-then-delete, old-core stop rule,
rollback before acceptance only, per-machine acceptance
checklist, pilot order (probe node, master, rest one by one,
TYYUN untouched). docs/release.md: placeholder-repo warning.
2026-10-24 12:03:26 +00:00
Muse 269c37653c ui: suppress agent-update badge on Windows rows, refuse Windows update intents
NodeView gains agentOs from AgentNode.ProbeOS (overlaid ahead of
the telemetry early-exit, like ProbeOnly). NodeList gates both
badge sites (list column + detail) on !isWindowsAgentOS(agentOs).
Backend requestAgentUpdate refuses Windows rows up front instead
of recording an intent that would only age out.

ProbeOS is reliable here: the frozen A2.2.1 Windows agent reports
probeFacts.os 'Windows 10' on register and heartbeat (see the
legacy-Windows contract test) and the panel persists it to
probe_os. Empty ProbeOS fails open on both sides. No fake
version, no per-node freeze switch, no Windows agent change, no
new win asset. The one-click action button itself is unchanged;
clicking it on a Windows row now errors clearly instead of
recording a dangling intent.
2026-10-24 12:02:05 +00:00
Muse 6a5ee8f77b rename: 3x-ui/x-ui -> L-UI/l-ui/lui-agent (paths, services, env, assets)
Display L-UI; panel binary/process l-ui, agent lui-agent.
Dirs /usr/local/l-ui, /etc/l-ui, /var/log/l-ui; DB /etc/l-ui/l-ui.db
(name file drives it via GetName), probe.db beside it, cert
/etc/l-ui/cert, bin /usr/local/l-ui/bin. Services l-ui.service /
lui-agent.service, OpenRC lui-agent, l-ui.sh, cmd/lui-agent.
Env prefix XUI_ -> LUI_ (code reads new prefix only). Release
assets l-ui-linux-* / lui-agent-linux-*; Gitea repo rogue/l-ui is
a placeholder pending user confirmation (see selfupdate.go note).
Go module path github.com/mhsanaei/3x-ui/v3 intentionally kept.
Versions unchanged: panel V2.6.0 / agent A2.5.0.
2026-10-24 12:00:55 +00:00
473 changed files with 3267 additions and 9364 deletions
+1 -1
View File
@@ -5,6 +5,6 @@ build
db db
cert cert
pgdata pgdata
x-ui/ l-ui/
*.db *.db
*.dump *.dump
+46 -46
View File
@@ -2,25 +2,25 @@
# 1. Developer Bootstrap: The active (uncommented) variables directly below # 1. Developer Bootstrap: The active (uncommented) variables directly below
# configure a safe, unprivileged local environment for 'go run .'. # configure a safe, unprivileged local environment for 'go run .'.
# This allows 'cp .env.example .env' to work out-of-the-box without root. # This allows 'cp .env.example .env' to work out-of-the-box without root.
# 2. Production Reference: All available XUI_* configuration options are # 2. Production Reference: All available LUI_* configuration options are
# documented and commented out in the reference section further below. # documented and commented out in the reference section further below.
# #
# 3x-ui reads its runtime configuration from XUI_* environment variables. # L-UI reads its runtime configuration from LUI_* environment variables.
# On a script install, the installer writes them to the service environment file # On a script install, the installer writes them to the service environment file
# (/etc/default/x-ui, /etc/conf.d/x-ui, or /etc/sysconfig/x-ui depending on the distro). # (/etc/default/l-ui, /etc/conf.d/l-ui, or /etc/sysconfig/l-ui depending on the distro).
# For Docker, you set them in docker-compose.yml or via 'docker run -e'. # For Docker, you set them in docker-compose.yml or via 'docker run -e'.
# #
# Defaults are sensible — set only what you need to change, then restart: # Defaults are sensible — set only what you need to change, then restart:
# systemctl restart x-ui # systemctl restart l-ui
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# LOCAL DEVELOPMENT OVERRIDES (ACTIVE BY DEFAULT) # LOCAL DEVELOPMENT OVERRIDES (ACTIVE BY DEFAULT)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
XUI_DEBUG=true LUI_DEBUG=true
XUI_DB_FOLDER=x-ui LUI_DB_FOLDER=l-ui
XUI_LOG_FOLDER=x-ui LUI_LOG_FOLDER=l-ui
XUI_BIN_FOLDER=x-ui LUI_BIN_FOLDER=l-ui
XUI_INIT_WEB_BASE_PATH=/ LUI_INIT_WEB_BASE_PATH=/
# ============================================================================== # ==============================================================================
# REFERENCE CONFIGURATION (ALL OPTIONS) # REFERENCE CONFIGURATION (ALL OPTIONS)
@@ -31,21 +31,21 @@ XUI_INIT_WEB_BASE_PATH=/
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Backend database type: sqlite, or postgres (also accepts postgresql / pg) # Backend database type: sqlite, or postgres (also accepts postgresql / pg)
# Default: sqlite # Default: sqlite
#XUI_DB_TYPE=sqlite #LUI_DB_TYPE=sqlite
# Folder for the SQLite database file (x-ui.db) # Folder for the SQLite database file (l-ui.db)
# Default: /etc/x-ui (Overridden to 'x-ui' in the development block above) # Default: /etc/l-ui (Overridden to 'l-ui' in the development block above)
#XUI_DB_FOLDER=/etc/x-ui #LUI_DB_FOLDER=/etc/l-ui
# PostgreSQL connection string (used when XUI_DB_TYPE=postgres) # PostgreSQL connection string (used when LUI_DB_TYPE=postgres)
# Example: postgres://user:password@localhost:5432/dbname?sslmode=disable # Example: postgres://user:password@localhost:5432/dbname?sslmode=disable
#XUI_DB_DSN= #LUI_DB_DSN=
# Max open connections in the PostgreSQL pool # Max open connections in the PostgreSQL pool
#XUI_DB_MAX_OPEN_CONNS= #LUI_DB_MAX_OPEN_CONNS=
# Max idle connections in the PostgreSQL pool # Max idle connections in the PostgreSQL pool
#XUI_DB_MAX_IDLE_CONNS= #LUI_DB_MAX_IDLE_CONNS=
# PostgreSQL Docker Container Settings # PostgreSQL Docker Container Settings
# Default credentials used if you are running PostgreSQL via docker-compose # Default credentials used if you are running PostgreSQL via docker-compose
@@ -58,19 +58,19 @@ XUI_INIT_WEB_BASE_PATH=/
# Panel # Panel
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Override the panel port (1–65535). Takes precedence over the stored setting. # Override the panel port (1–65535). Takes precedence over the stored setting.
#XUI_PORT= #LUI_PORT=
# Initial web base path on FIRST launch (e.g., /panel) # Initial web base path on FIRST launch (e.g., /panel)
# Default: / # Default: /
#XUI_INIT_WEB_BASE_PATH=/ #LUI_INIT_WEB_BASE_PATH=/
# Enable Fail2ban-based IP-limit enforcement # Enable Fail2ban-based IP-limit enforcement
# Default: true # Default: true
#XUI_ENABLE_FAIL2BAN=true #LUI_ENABLE_FAIL2BAN=true
# Skip the HSTS header — set true when TLS is terminated by a reverse proxy # Skip the HSTS header — set true when TLS is terminated by a reverse proxy
# Default: false # Default: false
#XUI_SKIP_HSTS=false #LUI_SKIP_HSTS=false
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -78,26 +78,26 @@ XUI_INIT_WEB_BASE_PATH=/
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Logging level: debug, info, notice, warning, or error # Logging level: debug, info, notice, warning, or error
# Default: info # Default: info
#XUI_LOG_LEVEL=info #LUI_LOG_LEVEL=info
# Debug mode. Forces log level to debug, enables Gin debug mode, # Debug mode. Forces log level to debug, enables Gin debug mode,
# and ensures frontend assets are served directly from disk (see CLAUDE.md). # and ensures frontend assets are served directly from disk (see CLAUDE.md).
# Default: false (Overridden to 'true' in the development block at the top) # Default: false (Overridden to 'true' in the development block at the top)
#XUI_DEBUG=false #LUI_DEBUG=false
# Log output directory # Log output directory
# Default: /var/log/x-ui (Overridden to 'x-ui' in the development block above) # Default: /var/log/l-ui (Overridden to 'l-ui' in the development block above)
#XUI_LOG_FOLDER=/var/log/x-ui #LUI_LOG_FOLDER=/var/log/l-ui
# Folder for the Xray-core binary and geosite/geoip files # Folder for the Xray-core binary and geosite/geoip files
# Default: bin (Overridden to 'x-ui' in the development block above) # Default: bin (Overridden to 'l-ui' in the development block above)
#XUI_BIN_FOLDER=bin #LUI_BIN_FOLDER=bin
# Legacy Path Settings # Legacy Path Settings
# Main installation folder (Default: /usr/local/x-ui for Linux, /app for Docker) # Main installation folder (Default: /usr/local/l-ui for Linux, /app for Docker)
#XUI_MAIN_FOLDER=/usr/local/x-ui #LUI_MAIN_FOLDER=/usr/local/l-ui
# Path to the systemd service file (Default: /etc/systemd/system) # Path to the systemd service file (Default: /etc/systemd/system)
#XUI_SERVICE=/etc/systemd/system #LUI_SERVICE=/etc/systemd/system
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -105,27 +105,27 @@ XUI_INIT_WEB_BASE_PATH=/
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Go GC target percentage; lower = less RAM, slightly more CPU. # Go GC target percentage; lower = less RAM, slightly more CPU.
# Default: 75 # Default: 75
#XUI_GOGC= #LUI_GOGC=
# Minutes between FreeOSMemory calls; 0 disables. # Minutes between FreeOSMemory calls; 0 disables.
# Default: 10 # Default: 10
#XUI_MEMORY_RELEASE_INTERVAL= #LUI_MEMORY_RELEASE_INTERVAL=
# Go soft memory limit in MiB # Go soft memory limit in MiB
#XUI_MEMORY_LIMIT= #LUI_MEMORY_LIMIT=
# Go-syntax soft limit (e.g., 400MiB); takes precedence over XUI_MEMORY_LIMIT # Go-syntax soft limit (e.g., 400MiB); takes precedence over LUI_MEMORY_LIMIT
#GOMEMLIMIT= #GOMEMLIMIT=
# Expose pprof profiling on 127.0.0.1:6060 # Expose pprof profiling on 127.0.0.1:6060
# Default: false # Default: false
#XUI_PPROF=false #LUI_PPROF=false
# Automatically set to 'true' inside the official Docker image. # Automatically set to 'true' inside the official Docker image.
# Consumed by internal scripts (x-ui.sh) to detect the environment. # Consumed by internal scripts (l-ui.sh) to detect the environment.
# There is normally no need to set or toggle this variable manually. # There is normally no need to set or toggle this variable manually.
# Default: false (automatically 'true' in Docker environments) # Default: false (automatically 'true' in Docker environments)
#XUI_IN_DOCKER=false #LUI_IN_DOCKER=false
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -142,36 +142,36 @@ XUI_INIT_WEB_BASE_PATH=/
# Optional watchdog: probes a URL (optionally through a local Xray inbound) # Optional watchdog: probes a URL (optionally through a local Xray inbound)
# and restarts Xray after repeated failures. A restart drops all connected clients. # and restarts Xray after repeated failures. A restart drops all connected clients.
# Default: false # Default: false
#XUI_TUNNEL_HEALTH_MONITOR=false #LUI_TUNNEL_HEALTH_MONITOR=false
# Proxy to send the probe through, e.g., socks5://127.0.0.1:1080 # Proxy to send the probe through, e.g., socks5://127.0.0.1:1080
# Empty = only checks host connectivity # Empty = only checks host connectivity
#XUI_TUNNEL_HEALTH_PROXY= #LUI_TUNNEL_HEALTH_PROXY=
# URL to probe # URL to probe
# Default: https://www.cloudflare.com/cdn-cgi/trace # Default: https://www.cloudflare.com/cdn-cgi/trace
#XUI_TUNNEL_HEALTH_URL=https://www.cloudflare.com/cdn-cgi/trace #LUI_TUNNEL_HEALTH_URL=https://www.cloudflare.com/cdn-cgi/trace
# Interval between probes # Interval between probes
# Default: 30s # Default: 30s
#XUI_TUNNEL_HEALTH_INTERVAL=30s #LUI_TUNNEL_HEALTH_INTERVAL=30s
# Per-probe timeout # Per-probe timeout
# Default: 10s # Default: 10s
#XUI_TUNNEL_HEALTH_TIMEOUT=10s #LUI_TUNNEL_HEALTH_TIMEOUT=10s
# Consecutive failures before a restart # Consecutive failures before a restart
# Default: 3 # Default: 3
#XUI_TUNNEL_HEALTH_FAILURES=3 #LUI_TUNNEL_HEALTH_FAILURES=3
# Minimum delay between restarts # Minimum delay between restarts
# Default: 5m # Default: 5m
#XUI_TUNNEL_HEALTH_COOLDOWN=5m #LUI_TUNNEL_HEALTH_COOLDOWN=5m
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Unattended install # Unattended install
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Set to 1 (or run with no TTY) to install with zero prompts. # Set to 1 (or run with no TTY) to install with zero prompts.
# Generated credentials will be written to /etc/x-ui/install-result.env # Generated credentials will be written to /etc/l-ui/install-result.env
#XUI_NONINTERACTIVE=1 #LUI_NONINTERACTIVE=1
+4 -4
View File
@@ -54,7 +54,7 @@ body:
attributes: attributes:
label: Relevant logs label: Relevant logs
description: | description: |
Panel logs (`journalctl -u x-ui -n 200`) and/or the browser DevTools Panel logs (`journalctl -u l-ui -n 200`) and/or the browser DevTools
console output. **Redact** tokens, real domains, IPs, and client UUIDs. console output. **Redact** tokens, real domains, IPs, and client UUIDs.
render: shell render: shell
validations: validations:
@@ -74,7 +74,7 @@ body:
- type: input - type: input
id: xui-version id: xui-version
attributes: attributes:
label: 3x-ui version label: L-UI version
description: Shown at the top of the panel sidebar. description: Shown at the top of the panel sidebar.
placeholder: 3.1.0 placeholder: 3.1.0
validations: validations:
@@ -92,7 +92,7 @@ body:
- type: dropdown - type: dropdown
id: install-method id: install-method
attributes: attributes:
label: How did you install 3x-ui? label: How did you install L-UI?
options: options:
- install.sh script - install.sh script
- Docker / Docker Compose - Docker / Docker Compose
@@ -159,7 +159,7 @@ body:
options: options:
- label: I searched [existing issues](../issues?q=is%3Aissue) and this bug has not been reported. - label: I searched [existing issues](../issues?q=is%3Aissue) and this bug has not been reported.
required: true required: true
- label: I am running the latest released version of 3x-ui (or have verified the bug still exists on it). - label: I am running the latest released version of L-UI (or have verified the bug still exists on it).
required: true required: true
- label: This bug report is written in English. - label: This bug report is written in English.
required: true required: true
+3 -3
View File
@@ -1,11 +1,11 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: 📖 Project home (Gitea) - name: 📖 Project home (Gitea)
url: https://git.881218.xyz/rogue/3x-ui-agent url: https://git.881218.xyz/rogue/l-ui
about: Setup, install, configuration, and "how do I…" guides live here. Please check before opening a question. about: Setup, install, configuration, and "how do I…" guides live here. Please check before opening a question.
- name: 🔍 Search existing issues - name: 🔍 Search existing issues
url: https://git.881218.xyz/rogue/3x-ui-agent/issues url: https://git.881218.xyz/rogue/l-ui/issues
about: Your bug, feature, or question may already be tracked. Comment on the existing one rather than opening a duplicate. about: Your bug, feature, or question may already be tracked. Comment on the existing one rather than opening a duplicate.
- name: 🚀 Latest release - name: 🚀 Latest release
url: https://git.881218.xyz/rogue/3x-ui-agent/releases url: https://git.881218.xyz/rogue/l-ui/releases
about: Reproduce on the latest version before reporting — many bugs are already fixed in the most recent release. about: Reproduce on the latest version before reporting — many bugs are already fixed in the most recent release.
+1 -1
View File
@@ -1,5 +1,5 @@
name: Feature request name: Feature request
description: Suggest an idea or improvement for 3x-ui description: Suggest an idea or improvement for L-UI
title: "[Feature]: " title: "[Feature]: "
labels: ["enhancement"] labels: ["enhancement"]
+5 -5
View File
@@ -1,5 +1,5 @@
name: Question name: Question
description: Ask how to do something with 3x-ui description: Ask how to do something with L-UI
title: "[Question]: " title: "[Question]: "
labels: ["question"] labels: ["question"]
@@ -9,7 +9,7 @@ body:
value: | value: |
Before opening a question, please: Before opening a question, please:
- Read the [project home](https://git.881218.xyz/rogue/3x-ui-agent) — - Read the [project home](https://git.881218.xyz/rogue/l-ui) —
most setup, install, and "how do I …" answers live there. most setup, install, and "how do I …" answers live there.
- Search [existing issues](../issues?q=is%3Aissue) — the question - Search [existing issues](../issues?q=is%3Aissue) — the question
may already have been asked. may already have been asked.
@@ -43,7 +43,7 @@ body:
- type: input - type: input
id: xui-version id: xui-version
attributes: attributes:
label: 3x-ui version label: L-UI version
description: Shown at the top of the panel sidebar. description: Shown at the top of the panel sidebar.
placeholder: 3.1.0 placeholder: 3.1.0
validations: validations:
@@ -52,7 +52,7 @@ body:
- type: dropdown - type: dropdown
id: install-method id: install-method
attributes: attributes:
label: How did you install 3x-ui? label: How did you install L-UI?
options: options:
- install.sh script - install.sh script
- Docker / Docker Compose - Docker / Docker Compose
@@ -85,7 +85,7 @@ body:
attributes: attributes:
label: Before submitting label: Before submitting
options: options:
- label: I read the [project home](https://git.881218.xyz/rogue/3x-ui-agent) and searched [existing issues](../issues?q=is%3Aissue). - label: I read the [project home](https://git.881218.xyz/rogue/l-ui) and searched [existing issues](../issues?q=is%3Aissue).
required: true required: true
- label: This is a usage question, not a bug report. - label: This is a usage question, not a bug report.
required: true required: true
+17 -17
View File
@@ -13,7 +13,7 @@ question it already answers.
## Stack ## Stack
3x-ui is an open-source web control panel for managing Xray-core servers. L-UI is an open-source web control panel for managing Xray-core servers.
- Backend: Go 1.27, module `github.com/mhsanaei/3x-ui/v3`, Gin and GORM. - Backend: Go 1.27, module `github.com/mhsanaei/3x-ui/v3`, Gin and GORM.
- It runs Xray-core as a managed child process (`internal/xray/process.go`) and - It runs Xray-core as a managed child process (`internal/xray/process.go`) and
@@ -26,8 +26,8 @@ question it already answers.
per inbound. Client, ad-tag and quota/expiry edits are hot-applied through the per inbound. Client, ad-tag and quota/expiry edits are hot-applied through the
fork's management API (`PUT /secrets`) so connections survive, with a process fork's management API (`PUT /secrets`) so connections survive, with a process
restart as the fallback on older binaries. restart as the fallback on older binaries.
- Storage: SQLite by default (`/etc/x-ui/x-ui.db` on Linux, the executable - Storage: SQLite by default (`/etc/l-ui/l-ui.db` on Linux, the executable
directory on Windows) or PostgreSQL (`XUI_DB_TYPE` / `XUI_DB_DSN`). The SQLite directory on Windows) or PostgreSQL (`LUI_DB_TYPE` / `LUI_DB_DSN`). The SQLite
driver is CGo, so `CGO_ENABLED=0` builds fail. driver is CGo, so `CGO_ENABLED=0` builds fail.
- Frontend: React 19 + Ant Design 6 + Vite 8 + TypeScript in `frontend/`, built - Frontend: React 19 + Ant Design 6 + Vite 8 + TypeScript in `frontend/`, built
into `internal/web/dist/` (gitignored) and embedded with `embed.FS`. into `internal/web/dist/` (gitignored) and embedded with `embed.FS`.
@@ -36,7 +36,7 @@ question it already answers.
| area | path | | area | path |
| --- | --- | | --- | --- |
| entry point + `x-ui` CLI | `main.go` | | entry point + `l-ui` CLI | `main.go` |
| env parsing | `internal/config/` | | env parsing | `internal/config/` |
| schema, migrations | `internal/database/`, `internal/database/model/` | | schema, migrations | `internal/database/`, `internal/database/model/` |
| Xray child process + config | `internal/xray/` | | Xray child process + config | `internal/xray/` |
@@ -48,7 +48,7 @@ question it already answers.
| master/sub-node over mTLS | `internal/web/runtime/` | | master/sub-node over mTLS | `internal/web/runtime/` |
| i18n | `internal/web/locale/`, `internal/web/translation/` | | i18n | `internal/web/locale/`, `internal/web/translation/` |
| UI source | `frontend/src/` | | UI source | `frontend/src/` |
| install / upgrade | `install.sh`, `x-ui.sh`, `DockerInit.sh` | | install / upgrade | `install.sh`, `l-ui.sh`, `DockerInit.sh` |
## Hard rules a change must respect ## Hard rules a change must respect
@@ -93,7 +93,7 @@ question it already answers.
subtests and `t.Helper()` on helpers. An assertion must pin the exact value, subtests and `t.Helper()` on helpers. An assertion must pin the exact value,
typed error or emitted string — `err != nil` and `len(x) > 0` are findings, typed error or emitted string — `err != nil` and `len(x) > 0` are findings,
not nits. Prefer real dependencies: a throwaway DB via not nits. Prefer real dependencies: a throwaway DB via
`database.InitDB(filepath.Join(t.TempDir(), "x-ui.db"))` with `t.Cleanup`, and `database.InitDB(filepath.Join(t.TempDir(), "l-ui.db"))` with `t.Cleanup`, and
`httptest` for HTTP. `internal/sub`'s `initSubDB(t)` is the template. `httptest` for HTTP. `internal/sub`'s `initSubDB(t)` is the template.
A test must FAIL without its fix; one that passes either way certifies A test must FAIL without its fix; one that passes either way certifies
nothing and then gets cited as proof the fix works. nothing and then gets cited as proof the fix works.
@@ -143,36 +143,36 @@ variable is set, and CI sets only the PostgreSQL ones above:
| gate | covers | | gate | covers |
| --- | --- | | --- | --- |
| `XUI_TEST_PG_DSN` | PostgreSQL-specific paths | | `LUI_TEST_PG_DSN` | PostgreSQL-specific paths |
| `XUI_DB_TYPE` + `XUI_DB_DSN` | dialect-dependent behaviour | | `LUI_DB_TYPE` + `LUI_DB_DSN` | dialect-dependent behaviour |
| `XRAY_E2E_BINARY` | the Xray gRPC end-to-end tests in `internal/xray/` | | `XRAY_E2E_BINARY` | the Xray gRPC end-to-end tests in `internal/xray/` |
| `XUI_SCALE_TEST` | scale tests in `internal/sub/`, `internal/web/job/`, `internal/web/service/` | | `LUI_SCALE_TEST` | scale tests in `internal/sub/`, `internal/web/job/`, `internal/web/service/` |
Mutation testing (`mutation.yml`) runs nightly and never on a pull request, so a Mutation testing (`mutation.yml`) runs nightly and never on a pull request, so a
test that cannot fail is invisible to CI. `make verify` is the local gate. test that cannot fail is invisible to CI. `make verify` is the local gate.
## Support facts reporters get wrong ## Support facts reporters get wrong
- Linux install: `bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-master.sh)` - Linux install: `bash <(curl -Ls https://git.881218.xyz/rogue/l-ui/raw/branch/main/install-master.sh)`
- Install generates a RANDOM username, password and web base path — never - Install generates a RANDOM username, password and web base path — never
admin/admin. The `x-ui` menu on the server shows or resets them. admin/admin. The `l-ui` menu on the server shows or resets them.
- The installer service environment file is DISTRO-DEPENDENT: - The installer service environment file is DISTRO-DEPENDENT:
`/etc/default/x-ui` (Debian/Ubuntu), `/etc/conf.d/x-ui` (Arch), `/etc/default/l-ui` (Debian/Ubuntu), `/etc/conf.d/l-ui` (Arch),
`/etc/sysconfig/x-ui` (RHEL/Fedora). Naming the wrong one means the reporter's `/etc/sysconfig/l-ui` (RHEL/Fedora). Naming the wrong one means the reporter's
edit is silently never read by systemd — a common cause of "I set the variable edit is silently never read by systemd — a common cause of "I set the variable
and nothing happened". and nothing happened".
- Windows is supported. There the database sits next to the executable, not in - Windows is supported. There the database sits next to the executable, not in
`/etc` — never quote the Linux path to a Windows user. `/etc` — never quote the Linux path to a Windows user.
- SQLite to PostgreSQL: `x-ui migrate-db --dsn "postgres://..."`, then set - SQLite to PostgreSQL: `l-ui migrate-db --dsn "postgres://..."`, then set
`XUI_DB_TYPE`/`XUI_DB_DSN` in that file and `systemctl restart x-ui`. The `LUI_DB_TYPE`/`LUI_DB_DSN` in that file and `systemctl restart l-ui`. The
source SQLite file is left in place. source SQLite file is left in place.
- Docker image `ghcr.io/mhsanaei/3x-ui`; PostgreSQL profile - Docker image `ghcr.io/mhsanaei/3x-ui`; PostgreSQL profile
`docker compose --profile postgres up -d`. Fail2ban IP-limit enforcement needs `docker compose --profile postgres up -d`. Fail2ban IP-limit enforcement needs
`NET_ADMIN` + `NET_RAW` (compose grants them; a bare `docker run` must add `NET_ADMIN` + `NET_RAW` (compose grants them; a bare `docker run` must add
`--cap-add=NET_ADMIN --cap-add=NET_RAW`). `--cap-add=NET_ADMIN --cap-add=NET_RAW`).
- Never state that a `XUI_*` variable does not exist without grepping - Never state that a `LUI_*` variable does not exist without grepping
`internal/config/` and `internal/tunnelmonitor/` first. The `internal/config/` and `internal/tunnelmonitor/` first. The
`XUI_TUNNEL_HEALTH_*` family is the usual answer to "the panel restarts Xray `LUI_TUNNEL_HEALTH_*` family is the usual answer to "the panel restarts Xray
every few minutes". every few minutes".
- Security per inbound is none / tls / reality. XTLS is a VLESS *flow* - Security per inbound is none / tls / reality. XTLS is a VLESS *flow*
(`xtls-rprx-vision`), not a security setting — never tell anyone to pick XTLS (`xtls-rprx-vision`), not a security setting — never tell anyone to pick XTLS
+2 -2
View File
@@ -58,8 +58,8 @@ jobs:
--health-timeout 5s --health-timeout 5s
--health-retries 5 --health-retries 5
env: env:
XUI_DB_TYPE: postgres LUI_DB_TYPE: postgres
XUI_DB_DSN: "host=127.0.0.1 port=5432 user=postgres password=postgres dbname=xui_durable sslmode=disable" LUI_DB_DSN: "host=127.0.0.1 port=5432 user=postgres password=postgres dbname=xui_durable sslmode=disable"
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
- uses: actions/setup-go@v7 - uses: actions/setup-go@v7
+10 -10
View File
@@ -53,7 +53,7 @@ jobs:
--allowedTools "Bash(gh label list:*),Bash(gh issue view:*),Bash(gh issue list:*),Bash(gh issue comment ${{ github.event.issue.number }}:*),Bash(gh issue edit ${{ github.event.issue.number }} --add-label:*),Bash(gh issue edit ${{ github.event.issue.number }} --remove-label:*),Bash(gh issue edit ${{ github.event.issue.number }} --title:*),Bash(gh issue close ${{ github.event.issue.number }}:*),Bash(gh search issues:*),Bash(gh search commits:*),Bash(gh search prs:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr list:*),Bash(gh release list:*),Bash(gh release view:*),Bash(git log:*),Bash(git show:*),Bash(git blame:*),Bash(git ls-tree:*),Bash(git tag:*),Read,Glob,Grep,Write(//tmp/**),Edit(//tmp/**)" --allowedTools "Bash(gh label list:*),Bash(gh issue view:*),Bash(gh issue list:*),Bash(gh issue comment ${{ github.event.issue.number }}:*),Bash(gh issue edit ${{ github.event.issue.number }} --add-label:*),Bash(gh issue edit ${{ github.event.issue.number }} --remove-label:*),Bash(gh issue edit ${{ github.event.issue.number }} --title:*),Bash(gh issue close ${{ github.event.issue.number }}:*),Bash(gh search issues:*),Bash(gh search commits:*),Bash(gh search prs:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr list:*),Bash(gh release list:*),Bash(gh release view:*),Bash(git log:*),Bash(git show:*),Bash(git blame:*),Bash(git ls-tree:*),Bash(git tag:*),Read,Glob,Grep,Write(//tmp/**),Edit(//tmp/**)"
--disallowedTools "Read(//**/.git/**),Edit(//**/.git/**)" --disallowedTools "Read(//**/.git/**),Edit(//**/.git/**)"
prompt: | prompt: |
You are the SENIOR GITHUB ISSUE ANALYST for the MHSanaei/3x-ui You are the SENIOR GITHUB ISSUE ANALYST for the MHSanaei/L-UI
repository, an open-source web control panel for managing Xray-core repository, an open-source web control panel for managing Xray-core
servers. You are the only automated reply an issue ever gets. Your servers. You are the only automated reply an issue ever gets. Your
question is: IS THE REPORTED PROBLEM REAL, AND IF SO, WHY? question is: IS THE REPORTED PROBLEM REAL, AND IF SO, WHY?
@@ -106,7 +106,7 @@ jobs:
reports, "enhancement" for feature requests, "question" for reports, "enhancement" for feature requests, "question" for
questions - so a pre-applied type label is a template default to questions - so a pre-applied type label is a template default to
verify, not the reporter's considered classification. The bug form verify, not the reporter's considered classification. The bug form
already REQUIRES the 3x-ui version, install method and OS, and also already REQUIRES the L-UI version, install method and OS, and also
collects logs, the Xray version, affected areas and reverse-proxy collects logs, the Xray version, affected areas and reverse-proxy
setup; the question form requires the version and install method. It setup; the question form requires the version and install method. It
all arrives under "### <heading>" sections of the body. Read those all arrives under "### <heading>" sections of the body. Read those
@@ -251,7 +251,7 @@ jobs:
question you could have answered by reading more code. question you could have answered by reading more code.
SECURITY EXCEPTION, which overrides everything else: if the report SECURITY EXCEPTION, which overrides everything else: if the report
describes what looks like an exploitable vulnerability in 3x-ui - an describes what looks like an exploitable vulnerability in L-UI - an
authentication bypass, remote code execution, injection, secret or authentication bypass, remote code execution, injection, secret or
credential exposure, privilege escalation - do NOT investigate or credential exposure, privilege escalation - do NOT investigate or
analyse it publicly. Post one short comment asking the reporter to analyse it publicly. Post one short comment asking the reporter to
@@ -285,7 +285,7 @@ jobs:
- CLOSE AS INVALID when the body, judged exactly as written, is - CLOSE AS INVALID when the body, judged exactly as written, is
empty or only whitespace, punctuation or emoji; pure gibberish; empty or only whitespace, punctuation or emoji; pure gibberish;
advertising or unrelated links; a throwaway test ("test", "asdf"); advertising or unrelated links; a throwaway test ("test", "asdf");
or unrelated to 3x-ui and Xray. Then: post the comment, add the or unrelated to L-UI and Xray. Then: post the comment, add the
`invalid` label, and `invalid` label, and
`gh issue close ${{ github.event.issue.number }} --reason "not planned"`. `gh issue close ${{ github.event.issue.number }} --reason "not planned"`.
A short, vague, badly formatted, machine-translated or low-quality A short, vague, badly formatted, machine-translated or low-quality
@@ -628,11 +628,11 @@ jobs:
--allowedTools "Bash(gh issue view:*),Bash(gh issue list:*),Bash(gh issue comment ${{ github.event.issue.number }}:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr list:*),Bash(gh pr comment ${{ github.event.issue.number }}:*),Bash(gh search issues:*),Bash(gh search commits:*),Bash(gh release list:*),Bash(gh label list:*),Read,Glob,Grep,Write(//tmp/**),Edit(//tmp/**)" --allowedTools "Bash(gh issue view:*),Bash(gh issue list:*),Bash(gh issue comment ${{ github.event.issue.number }}:*),Bash(gh pr view:*),Bash(gh pr diff:*),Bash(gh pr list:*),Bash(gh pr comment ${{ github.event.issue.number }}:*),Bash(gh search issues:*),Bash(gh search commits:*),Bash(gh release list:*),Bash(gh label list:*),Read,Glob,Grep,Write(//tmp/**),Edit(//tmp/**)"
--disallowedTools "Read(//**/.git/**),Edit(//**/.git/**)" --disallowedTools "Read(//**/.git/**),Edit(//**/.git/**)"
prompt: | prompt: |
You are replying to an @claude mention from a maintainer of the MHSanaei/3x-ui repository - its owner, or somebody invited to it with write access, an open-source web panel for managing Xray-core servers. This run investigates and explains; it never changes anything. You have no tool that can edit a file in the checkout, no git command that can write, and a token that cannot push, so no file is edited, no branch is created, no commit is made and no pull request is opened or merged - on an issue and on a pull request alike. The one exception in this repository lives in a separate workflow job that only the repository owner can start, so do not mention it or offer it. The full repo source is checked out in the working directory; use Read, Glob and Grep to open and verify the relevant files before stating any default, path, flag, option name, or behavior. Your file-writing tool is limited to /tmp: a long reply goes to /tmp/comment.md and is posted with gh issue comment <number> --body-file /tmp/comment.md (or gh pr comment for a pull request). If that write is refused for any reason, pass the body inline with --body instead - never leave the thread unanswered. You are replying to an @claude mention from a maintainer of the MHSanaei/L-UI repository - its owner, or somebody invited to it with write access, an open-source web panel for managing Xray-core servers. This run investigates and explains; it never changes anything. You have no tool that can edit a file in the checkout, no git command that can write, and a token that cannot push, so no file is edited, no branch is created, no commit is made and no pull request is opened or merged - on an issue and on a pull request alike. The one exception in this repository lives in a separate workflow job that only the repository owner can start, so do not mention it or offer it. The full repo source is checked out in the working directory; use Read, Glob and Grep to open and verify the relevant files before stating any default, path, flag, option name, or behavior. Your file-writing tool is limited to /tmp: a long reply goes to /tmp/comment.md and is posted with gh issue comment <number> --body-file /tmp/comment.md (or gh pr comment for a pull request). If that write is refused for any reason, pass the body inline with --body instead - never leave the thread unanswered.
Key layout: Key layout:
- main.go holds the entry point and the x-ui management CLI (run, migrate, migrate-db, encrypt-tokens, setting, cert). - main.go holds the entry point and the l-ui management CLI (run, migrate, migrate-db, encrypt-tokens, setting, cert).
- internal/config/ parses env vars (XUI_DEBUG, XUI_LOG_LEVEL, XUI_LOG_FOLDER, XUI_BIN_FOLDER, XUI_SKIP_HSTS, XUI_PORT, XUI_DB_FOLDER, XUI_DB_TYPE, XUI_DB_DSN). - internal/config/ parses env vars (LUI_DEBUG, LUI_LOG_LEVEL, LUI_LOG_FOLDER, LUI_BIN_FOLDER, LUI_SKIP_HSTS, LUI_PORT, LUI_DB_FOLDER, LUI_DB_TYPE, LUI_DB_DSN).
- internal/database/ and internal/database/model/ hold the GORM schema (Inbound, Client, Setting, User) and the inbound protocol enum (vmess, vless, tunnel, http, trojan, shadowsocks, mixed, wireguard, hysteria, mtproto). - internal/database/ and internal/database/model/ hold the GORM schema (Inbound, Client, Setting, User) and the inbound protocol enum (vmess, vless, tunnel, http, trojan, shadowsocks, mixed, wireguard, hysteria, mtproto).
- internal/mtproto/ runs MTProto (Telegram) proxy inbounds via the bundled mtg binary. - internal/mtproto/ runs MTProto (Telegram) proxy inbounds via the bundled mtg binary.
- internal/web/controller/ has panel and REST API handlers with the OpenAPI spec served at /panel/api/openapi.json. - internal/web/controller/ has panel and REST API handlers with the OpenAPI spec served at /panel/api/openapi.json.
@@ -643,13 +643,13 @@ jobs:
- internal/sub/ is the subscription server. - internal/sub/ is the subscription server.
- internal/eventbus/ is an in-process pub/sub event bus (outbound and node health, xray.crash, cpu.high, memory.high, login.attempt). - internal/eventbus/ is an in-process pub/sub event bus (outbound and node health, xray.crash, cpu.high, memory.high, login.attempt).
- internal/xray/ runs Xray-core as a managed child process and generates its config; internal/xray/geodata/ streams the geosite/geoip .dat files. - internal/xray/ runs Xray-core as a managed child process and generates its config; internal/xray/geodata/ streams the geosite/geoip .dat files.
- internal/crypto/ (node-token encryption), internal/logger/, internal/util/ (link, ldap, sys, wireguard - leaf-only helpers) and internal/tunnelmonitor/ (the XUI_TUNNEL_HEALTH_* tunnel watchdog) are shared infrastructure. - internal/crypto/ (node-token encryption), internal/logger/, internal/util/ (link, ldap, sys, wireguard - leaf-only helpers) and internal/tunnelmonitor/ (the LUI_TUNNEL_HEALTH_* tunnel watchdog) are shared infrastructure.
- frontend/ is the React 19 plus Ant Design 6 plus Vite 8 plus TypeScript source built into the embedded internal/web/dist/. - frontend/ is the React 19 plus Ant Design 6 plus Vite 8 plus TypeScript source built into the embedded internal/web/dist/.
- tools/openapigen emits the frontend API types and Zod/JSON schemas; the OpenAPI document itself is assembled by frontend/scripts/build-openapi.mjs. - tools/openapigen emits the frontend API types and Zod/JSON schemas; the OpenAPI document itself is assembled by frontend/scripts/build-openapi.mjs.
- docs/ is a separate Next.js docs site; docs/lib/xray/ holds a third independent implementation of link/subscription generation. - docs/ is a separate Next.js docs site; docs/lib/xray/ holds a third independent implementation of link/subscription generation.
CLAUDE.md and docs/architecture.md in the checkout are the maintained maps; when they and this layout disagree, they win. CLAUDE.md and docs/architecture.md in the checkout are the maintained maps; when they and this layout disagree, they win.
Stack and runtime facts: Backend is Go (module github.com/mhsanaei/3x-ui/v3) with Gin and GORM; storage is SQLite by default at /etc/x-ui/x-ui.db or PostgreSQL via XUI_DB_TYPE and XUI_DB_DSN; further env vars include XUI_DB_MAX_OPEN_CONNS, XUI_DB_MAX_IDLE_CONNS, XUI_INIT_WEB_BASE_PATH, XUI_ENABLE_FAIL2BAN, and the XUI_TUNNEL_HEALTH_* family in internal/tunnelmonitor/ - never say a XUI_* variable does not exist without grepping internal/config/ and internal/tunnelmonitor/ first; the installer's service env file is distro-dependent - /etc/default/x-ui (Debian/Ubuntu/Armbian), /etc/conf.d/x-ui (Arch/Alpine), /etc/sysconfig/x-ui (RHEL/Fedora and others); SQLite to PostgreSQL migration is x-ui migrate-db --dsn followed by a service restart; install uses install.sh and the x-ui menu, generating random initial credentials; Docker image is ghcr.io/mhsanaei/3x-ui and Fail2ban IP-limit enforcement needs NET_ADMIN and NET_RAW; Windows is a supported platform (the DB sits next to the executable there, not in /etc). Do not hardcode a version: for version or is-this-fixed questions, check the latest release and recent commits or closed PRs with gh. The same discipline applies to every fact in this prompt - the repo moves, so re-verify names, paths, flags, and enum values in the source before quoting them. Stack and runtime facts: Backend is Go (module github.com/mhsanaei/3x-ui/v3) with Gin and GORM; storage is SQLite by default at /etc/l-ui/l-ui.db or PostgreSQL via LUI_DB_TYPE and LUI_DB_DSN; further env vars include LUI_DB_MAX_OPEN_CONNS, LUI_DB_MAX_IDLE_CONNS, LUI_INIT_WEB_BASE_PATH, LUI_ENABLE_FAIL2BAN, and the LUI_TUNNEL_HEALTH_* family in internal/tunnelmonitor/ - never say a LUI_* variable does not exist without grepping internal/config/ and internal/tunnelmonitor/ first; the installer's service env file is distro-dependent - /etc/default/l-ui (Debian/Ubuntu/Armbian), /etc/conf.d/l-ui (Arch/Alpine), /etc/sysconfig/l-ui (RHEL/Fedora and others); SQLite to PostgreSQL migration is l-ui migrate-db --dsn followed by a service restart; install uses install.sh and the l-ui menu, generating random initial credentials; Docker image is ghcr.io/mhsanaei/3x-ui and Fail2ban IP-limit enforcement needs NET_ADMIN and NET_RAW; Windows is a supported platform (the DB sits next to the executable there, not in /etc). Do not hardcode a version: for version or is-this-fixed questions, check the latest release and recent commits or closed PRs with gh. The same discipline applies to every fact in this prompt - the repo moves, so re-verify names, paths, flags, and enum values in the source before quoting them.
Style: lead with the answer in the first sentence; use fenced code blocks for commands and backtick formatting for paths and setting names; distinguish what you confirmed in the source (name the file) from what you infer; never promise fixes, timelines, or releases. Ground every claim in the code or the README and wiki; do not invent features, paths, flags, or commands, and do not stop at the first plausible match. Token cost is not a concern, so investigate as deeply as the question needs. Style: lead with the answer in the first sentence; use fenced code blocks for commands and backtick formatting for paths and setting names; distinguish what you confirmed in the source (name the file) from what you infer; never promise fixes, timelines, or releases. Ground every claim in the code or the README and wiki; do not invent features, paths, flags, or commands, and do not stop at the first plausible match. Token cost is not a concern, so investigate as deeply as the question needs.
@@ -836,7 +836,7 @@ jobs:
--disallowedTools "Bash,WebFetch,WebSearch,Task,Edit(//**/.git/**),Read(//**/.git/**)" --disallowedTools "Bash,WebFetch,WebSearch,Task,Edit(//**/.git/**),Read(//**/.git/**)"
prompt: | prompt: |
The repository owner asked for the merge conflicts on pull request The repository owner asked for the merge conflicts on pull request
#${{ github.event.issue.number }} of MHSanaei/3x-ui, an open-source #${{ github.event.issue.number }} of MHSanaei/L-UI, an open-source
web panel for managing Xray-core servers, to be resolved. The merge web panel for managing Xray-core servers, to be resolved. The merge
of `${{ steps.merge.outputs.base }}` into the pull request's branch of `${{ steps.merge.outputs.base }}` into the pull request's branch
`${{ steps.merge.outputs.head }}` is already in progress in the `${{ steps.merge.outputs.head }}` is already in progress in the
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
uses: docker/metadata-action@v6 uses: docker/metadata-action@v6
with: with:
images: | images: |
hsanaeii/3x-ui hsanaeii/L-UI
ghcr.io/mhsanaei/3x-ui ghcr.io/mhsanaei/3x-ui
tags: | tags: |
type=ref,event=branch type=ref,event=branch
+29 -29
View File
@@ -13,9 +13,9 @@ on:
- "go.sum" - "go.sum"
- "**.sh" - "**.sh"
- "frontend/**" - "frontend/**"
- "x-ui.service.debian" - "l-ui.service.debian"
- "x-ui.service.arch" - "l-ui.service.arch"
- "x-ui.service.rhel" - "l-ui.service.rhel"
- ".github/workflows/release.yml" - ".github/workflows/release.yml"
pull_request: pull_request:
paths: paths:
@@ -24,9 +24,9 @@ on:
- "go.sum" - "go.sum"
- "**.sh" - "**.sh"
- "frontend/**" - "frontend/**"
- "x-ui.service.debian" - "l-ui.service.debian"
- "x-ui.service.arch" - "l-ui.service.arch"
- "x-ui.service.rhel" - "l-ui.service.rhel"
- ".github/workflows/release.yml" - ".github/workflows/release.yml"
jobs: jobs:
@@ -113,15 +113,15 @@ jobs:
file xui-release file xui-release
ldd xui-release || echo "Static binary confirmed" ldd xui-release || echo "Static binary confirmed"
mkdir x-ui mkdir l-ui
cp xui-release x-ui/ cp xui-release l-ui/
cp x-ui.service.debian x-ui/ cp l-ui.service.debian l-ui/
cp x-ui.service.arch x-ui/ cp l-ui.service.arch l-ui/
cp x-ui.service.rhel x-ui/ cp l-ui.service.rhel l-ui/
cp x-ui.sh x-ui/ cp l-ui.sh l-ui/
mv x-ui/xui-release x-ui/x-ui mv l-ui/xui-release l-ui/l-ui
mkdir x-ui/bin mkdir l-ui/bin
cd x-ui/bin cd l-ui/bin
# Download dependencies # Download dependencies
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v26.7.28/" Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v26.7.28/"
@@ -183,13 +183,13 @@ jobs:
cd ../.. cd ../..
- name: Package - name: Package
run: tar -zcvf x-ui-linux-${{ matrix.platform }}.tar.gz x-ui run: tar -zcvf l-ui-linux-${{ matrix.platform }}.tar.gz l-ui
- name: Upload files to Artifacts - name: Upload files to Artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: x-ui-linux-${{ matrix.platform }} name: l-ui-linux-${{ matrix.platform }}
path: ./x-ui-linux-${{ matrix.platform }}.tar.gz path: ./l-ui-linux-${{ matrix.platform }}.tar.gz
- name: Upload files to GH release - name: Upload files to GH release
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
@@ -197,8 +197,8 @@ jobs:
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.ref_name }} tag: ${{ github.ref_name }}
file: x-ui-linux-${{ matrix.platform }}.tar.gz file: l-ui-linux-${{ matrix.platform }}.tar.gz
asset_name: x-ui-linux-${{ matrix.platform }}.tar.gz asset_name: l-ui-linux-${{ matrix.platform }}.tar.gz
overwrite: true overwrite: true
prerelease: true prerelease: true
@@ -277,10 +277,10 @@ jobs:
shell: pwsh shell: pwsh
run: | run: |
$retry = @{ MaximumRetryCount = 5; RetryIntervalSec = 10 } $retry = @{ MaximumRetryCount = 5; RetryIntervalSec = 10 }
mkdir x-ui mkdir l-ui
Copy-Item xui-release.exe x-ui\x-ui.exe Copy-Item xui-release.exe l-ui\l-ui.exe
mkdir x-ui\bin mkdir l-ui\bin
cd x-ui\bin cd l-ui\bin
# Download Xray for Windows # Download Xray for Windows
$Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v26.7.28/" $Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v26.7.28/"
@@ -315,13 +315,13 @@ jobs:
- name: Package to Zip - name: Package to Zip
shell: pwsh shell: pwsh
run: | run: |
Compress-Archive -Path .\x-ui -DestinationPath "x-ui-windows-amd64.zip" Compress-Archive -Path .\l-ui -DestinationPath "l-ui-windows-amd64.zip"
- name: Upload files to Artifacts - name: Upload files to Artifacts
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: x-ui-windows-amd64 name: l-ui-windows-amd64
path: ./x-ui-windows-amd64.zip path: ./l-ui-windows-amd64.zip
- name: Upload files to GH release - name: Upload files to GH release
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2
@@ -329,8 +329,8 @@ jobs:
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.ref_name }} tag: ${{ github.ref_name }}
file: x-ui-windows-amd64.zip file: l-ui-windows-amd64.zip
asset_name: x-ui-windows-amd64.zip asset_name: l-ui-windows-amd64.zip
overwrite: true overwrite: true
prerelease: true prerelease: true
+2 -2
View File
@@ -65,5 +65,5 @@ jobs:
- uses: actions/checkout@v7 - uses: actions/checkout@v7
- name: Pinned release install smoke test - name: Pinned release install smoke test
env: env:
XUI_SMOKE_VERSION: ${{ github.event.workflow_run.head_branch }} LUI_SMOKE_VERSION: ${{ github.event.workflow_run.head_branch }}
run: bash deploy/test/smoke-noninteractive.sh "$XUI_SMOKE_VERSION" run: bash deploy/test/smoke-noninteractive.sh "$LUI_SMOKE_VERSION"
+4 -4
View File
@@ -17,7 +17,7 @@ tmp/
# Ignore build and distribution directories # Ignore build and distribution directories
backup/ backup/
bin/ bin/
x-ui/ l-ui/
dist/ dist/
# Exception: the vendored embedded fallback theme ships its dist/ as # Exception: the vendored embedded fallback theme ships its dist/ as
# source (go:embed) — it is not a build output. # source (go:embed) — it is not a build output.
@@ -34,9 +34,9 @@ Thumbs.db
# Ignore Go build files # Ignore Go build files
*.exe *.exe
x-ui.db l-ui.db
x-ui.db-shm l-ui.db-shm
x-ui.db-wal l-ui.db-wal
system_metrics.gob system_metrics.gob
*.dump *.dump
+16 -16
View File
@@ -3,41 +3,41 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "Run 3x-ui (Debug)", "name": "Run L-UI (Debug)",
"type": "go", "type": "go",
"request": "launch", "request": "launch",
"mode": "auto", "mode": "auto",
"program": "${workspaceFolder}", "program": "${workspaceFolder}",
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"env": { "env": {
"XUI_DEBUG": "true", "LUI_DEBUG": "true",
"XUI_DB_FOLDER": "x-ui", "LUI_DB_FOLDER": "l-ui",
"XUI_LOG_FOLDER": "x-ui", "LUI_LOG_FOLDER": "l-ui",
"XUI_BIN_FOLDER": "x-ui" "LUI_BIN_FOLDER": "l-ui"
}, },
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
"name": "Run 3x-ui (Postgres)", "name": "Run L-UI (Postgres)",
"type": "go", "type": "go",
"request": "launch", "request": "launch",
"mode": "auto", "mode": "auto",
"program": "${workspaceFolder}", "program": "${workspaceFolder}",
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"env": { "env": {
"XUI_DEBUG": "true", "LUI_DEBUG": "true",
"XUI_LOG_FOLDER": "x-ui", "LUI_LOG_FOLDER": "l-ui",
"XUI_BIN_FOLDER": "x-ui", "LUI_BIN_FOLDER": "l-ui",
"XUI_DB_TYPE": "postgres", "LUI_DB_TYPE": "postgres",
"XUI_DB_DSN": "postgres://xui:xuipass@127.0.0.1:5432/xui?sslmode=disable" "LUI_DB_DSN": "postgres://xui:xuipass@127.0.0.1:5432/xui?sslmode=disable"
}, },
"windows": { "windows": {
"env": { "env": {
"XUI_DEBUG": "true", "LUI_DEBUG": "true",
"XUI_LOG_FOLDER": "x-ui", "LUI_LOG_FOLDER": "l-ui",
"XUI_BIN_FOLDER": "x-ui", "LUI_BIN_FOLDER": "l-ui",
"XUI_DB_TYPE": "postgres", "LUI_DB_TYPE": "postgres",
"XUI_DB_DSN": "postgres://xui:xuipass@127.0.0.1:5432/xui?sslmode=disable", "LUI_DB_DSN": "postgres://xui:xuipass@127.0.0.1:5432/xui?sslmode=disable",
"PATH": "C:\\Program Files\\PostgreSQL\\18\\bin;${env:PATH}" "PATH": "C:\\Program Files\\PostgreSQL\\18\\bin;${env:PATH}"
} }
}, },
+3 -3
View File
@@ -8,14 +8,14 @@
"args": [ "args": [
"build", "build",
"-o", "-o",
"bin/3x-ui", "bin/L-UI",
"./main.go" "./main.go"
], ],
"windows": { "windows": {
"args": [ "args": [
"build", "build",
"-o", "-o",
"bin/3x-ui.exe", "bin/L-UI.exe",
"./main.go" "./main.go"
] ]
}, },
@@ -41,7 +41,7 @@
"options": { "options": {
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"env": { "env": {
"XUI_DEBUG": "true" "LUI_DEBUG": "true"
} }
}, },
"problemMatcher": [ "problemMatcher": [
+9 -9
View File
@@ -24,16 +24,16 @@ file locations when it can answer in one hop.
falls back to a process restart on older binaries. A client's panel-side falls back to a process restart on older binaries. A client's panel-side
traffic reset also calls `POST /secrets/{name}/reset-quota` so a renewed client traffic reset also calls `POST /secrets/{name}/reset-quota` so a renewed client
is not re-blocked by the sidecar's quota counter. is not re-blocked by the sidecar's quota counter.
- Storage: SQLite by default (`/etc/x-ui/x-ui.db` on Linux; the executable dir on - Storage: SQLite by default (`/etc/l-ui/l-ui.db` on Linux; the executable dir on
Windows), PostgreSQL optional (`XUI_DB_TYPE` / `XUI_DB_DSN`). The CGo SQLite Windows), PostgreSQL optional (`LUI_DB_TYPE` / `LUI_DB_DSN`). The CGo SQLite
driver (`mattn/go-sqlite3`) needs a C compiler — `CGO_ENABLED=0` builds fail. driver (`mattn/go-sqlite3`) needs a C compiler — `CGO_ENABLED=0` builds fail.
- Frontend: React 19 + Ant Design 6 + Vite 8 + TypeScript in `frontend/`, - Frontend: React 19 + Ant Design 6 + Vite 8 + TypeScript in `frontend/`,
built into `internal/web/dist/` (gitignored) and embedded via `embed.FS`. built into `internal/web/dist/` (gitignored) and embedded via `embed.FS`.
## Repo map ## Repo map
- `main.go` — entry point + `x-ui` CLI (run, migrate, migrate-db, setting, cert). - `main.go` — entry point + `l-ui` CLI (run, migrate, migrate-db, setting, cert).
- `internal/config/` — env parsing (XUI_DEBUG, XUI_LOG_LEVEL, XUI_LOG_FOLDER, - `internal/config/` — env parsing (LUI_DEBUG, LUI_LOG_LEVEL, LUI_LOG_FOLDER,
XUI_BIN_FOLDER, XUI_SKIP_HSTS, XUI_PORT, XUI_DB_*). LUI_BIN_FOLDER, LUI_SKIP_HSTS, LUI_PORT, LUI_DB_*).
- `internal/database/` + `internal/database/model/` — GORM schema (~24 models; - `internal/database/` + `internal/database/model/` — GORM schema (~24 models;
Inbound, Client, Setting, User are the core), inbound Protocol enum, Inbound, Client, Setting, User are the core), inbound Protocol enum,
AutoMigrate + hand-written migrations in `db.go`. AutoMigrate + hand-written migrations in `db.go`.
@@ -116,7 +116,7 @@ file locations when it can answer in one hop.
- Stdlib `testing` only (no testify). Table-driven, `t.Run` subtests, - Stdlib `testing` only (no testify). Table-driven, `t.Run` subtests,
`t.Helper()` on helpers. Assert the exact value / typed error / emitted `t.Helper()` on helpers. Assert the exact value / typed error / emitted
string, never just `err != nil`. Prefer real deps over mocks: throwaway DB via string, never just `err != nil`. Prefer real deps over mocks: throwaway DB via
`database.InitDB(filepath.Join(t.TempDir(), "x-ui.db"))` + `database.InitDB(filepath.Join(t.TempDir(), "l-ui.db"))` +
`t.Cleanup(func() { _ = database.CloseDB() })`; `httptest` for HTTP. `t.Cleanup(func() { _ = database.CloseDB() })`; `httptest` for HTTP.
`internal/sub`'s `initSubDB(t)` is the template. `internal/sub`'s `initSubDB(t)` is the template.
- A test must fail without its fix. Write it, revert the fix, watch it go red, - A test must fail without its fix. Write it, revert the fix, watch it go red,
@@ -126,8 +126,8 @@ file locations when it can answer in one hop.
pure map lookup, or inputs the function can never receive. One real test that pure map lookup, or inputs the function can never receive. One real test that
drives the bug through the actual code path beats five that restate the code. drives the bug through the actual code path beats five that restate the code.
- Code must pass `golangci-lint run` (gofumpt + goimports formatting): `make lint`. - Code must pass `golangci-lint run` (gofumpt + goimports formatting): `make lint`.
- Postgres, xray-gRPC-e2e and scale tests `t.Skip` unless `XUI_TEST_PG_DSN`, - Postgres, xray-gRPC-e2e and scale tests `t.Skip` unless `LUI_TEST_PG_DSN`,
`XUI_DB_TYPE`+`XUI_DB_DSN`, `XRAY_E2E_BINARY` or `XUI_SCALE_TEST` is set — a `LUI_DB_TYPE`+`LUI_DB_DSN`, `XRAY_E2E_BINARY` or `LUI_SCALE_TEST` is set — a
green `go test ./...` does not mean those paths ran. green `go test ./...` does not mean those paths ran.
## Frontend conventions (summary; full version in frontend/CLAUDE.md) ## Frontend conventions (summary; full version in frontend/CLAUDE.md)
@@ -140,7 +140,7 @@ file locations when it can answer in one hop.
a headless-Chromium Storybook project, so run a headless-Chromium Storybook project, so run
`npx playwright install --with-deps chromium` once or `make verify` fails. `npx playwright install --with-deps chromium` once or `make verify` fails.
- Editing `frontend/src` does NOT change what users see until the Vite build is - Editing `frontend/src` does NOT change what users see until the Vite build is
regenerated into `internal/web/dist/`. In `XUI_DEBUG=true`, HTML is served from regenerated into `internal/web/dist/`. In `LUI_DEBUG=true`, HTML is served from
the frozen embedded FS but JS/CSS off disk — after `npm run build` you MUST the frozen embedded FS but JS/CSS off disk — after `npm run build` you MUST
restart `go run .` or you get a blank page with 404s. restart `go run .` or you get a blank page with 404s.
- After touching share-link logic (`src/lib/xray/`), run `npm run test` (golden - After touching share-link logic (`src/lib/xray/`), run `npm run test` (golden
+40 -40
View File
@@ -1,6 +1,6 @@
# Contributing # Contributing
Thanks for taking the time to contribute to 3x-ui. This guide gets a development panel running locally and explains the conventions the project follows so changes land cleanly. Thanks for taking the time to contribute to L-UI. This guide gets a development panel running locally and explains the conventions the project follows so changes land cleanly.
## Prerequisites ## Prerequisites
@@ -50,12 +50,12 @@ Cross-building the Linux SQLite target from Windows (or vice versa) requires a s
## First-time setup ## First-time setup
```bash ```bash
git clone https://git.881218.xyz/rogue/3x-ui-agent.git git clone https://git.881218.xyz/rogue/l-ui.git
cd 3x-ui-agent cd L-UI
cp .env.example .env cp .env.example .env
mkdir x-ui mkdir l-ui
go mod download go mod download
@@ -65,18 +65,18 @@ npm run build
cd .. cd ..
``` ```
`.env.example` ships with defaults that keep the database, logs, and xray binary inside the local `x-ui/` folder so nothing escapes the project directory: `.env.example` ships with defaults that keep the database, logs, and xray binary inside the local `l-ui/` folder so nothing escapes the project directory:
``` ```
XUI_DEBUG=true LUI_DEBUG=true
XUI_DB_FOLDER=x-ui LUI_DB_FOLDER=l-ui
XUI_LOG_FOLDER=x-ui LUI_LOG_FOLDER=l-ui
XUI_BIN_FOLDER=x-ui LUI_BIN_FOLDER=l-ui
XUI_INIT_WEB_BASE_PATH=/ LUI_INIT_WEB_BASE_PATH=/
# XUI_PORT=8080 # LUI_PORT=8080
``` ```
Drop the xray binary (`xray-windows-amd64.exe` on Windows, `xray-linux-amd64` on Linux, etc.) plus the matching `geoip.dat` and `geosite.dat` files into `x-ui/`. The easiest source is a [released Xray-core build](https://github.com/XTLS/Xray-core/releases). On Windows, `wintun.dll` is also required for testing TUN inbounds. Drop the xray binary (`xray-windows-amd64.exe` on Windows, `xray-linux-amd64` on Linux, etc.) plus the matching `geoip.dat` and `geosite.dat` files into `l-ui/`. The easiest source is a [released Xray-core build](https://github.com/XTLS/Xray-core/releases). On Windows, `wintun.dll` is also required for testing TUN inbounds.
## Running ## Running
@@ -88,7 +88,7 @@ Open [http://localhost:2053](http://localhost:2053) and log in with `admin` / `a
### Inside VS Code ### Inside VS Code
The repo checks in two VS Code launch profiles in `.vscode/launch.json`: **Run 3x-ui (Debug)** for the default SQLite setup, and **Run 3x-ui (Postgres)** which points `XUI_DB_TYPE`/`XUI_DB_DSN` at a local PostgreSQL. The Postgres profile also prepends the PostgreSQL `bin` to `PATH` so the panel can find `pg_dump`/`pg_restore` (the `postgresql-client` tools used for DB backup/restore) — adjust the DSN and that path to your machine: The repo checks in two VS Code launch profiles in `.vscode/launch.json`: **Run L-UI (Debug)** for the default SQLite setup, and **Run L-UI (Postgres)** which points `LUI_DB_TYPE`/`LUI_DB_DSN` at a local PostgreSQL. The Postgres profile also prepends the PostgreSQL `bin` to `PATH` so the panel can find `pg_dump`/`pg_restore` (the `postgresql-client` tools used for DB backup/restore) — adjust the DSN and that path to your machine:
```jsonc ```jsonc
{ {
@@ -96,33 +96,33 @@ The repo checks in two VS Code launch profiles in `.vscode/launch.json`: **Run 3
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "Run 3x-ui (Debug)", "name": "Run L-UI (Debug)",
"type": "go", "type": "go",
"request": "launch", "request": "launch",
"mode": "auto", "mode": "auto",
"program": "${workspaceFolder}", "program": "${workspaceFolder}",
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"env": { "env": {
"XUI_DEBUG": "true", "LUI_DEBUG": "true",
"XUI_DB_FOLDER": "x-ui", "LUI_DB_FOLDER": "l-ui",
"XUI_LOG_FOLDER": "x-ui", "LUI_LOG_FOLDER": "l-ui",
"XUI_BIN_FOLDER": "x-ui" "LUI_BIN_FOLDER": "l-ui"
}, },
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
{ {
"name": "Run 3x-ui (Postgres)", "name": "Run L-UI (Postgres)",
"type": "go", "type": "go",
"request": "launch", "request": "launch",
"mode": "auto", "mode": "auto",
"program": "${workspaceFolder}", "program": "${workspaceFolder}",
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"env": { "env": {
"XUI_DEBUG": "true", "LUI_DEBUG": "true",
"XUI_LOG_FOLDER": "x-ui", "LUI_LOG_FOLDER": "l-ui",
"XUI_BIN_FOLDER": "x-ui", "LUI_BIN_FOLDER": "l-ui",
"XUI_DB_TYPE": "postgres", "LUI_DB_TYPE": "postgres",
"XUI_DB_DSN": "postgres://xui:xuipass@127.0.0.1:5432/xui?sslmode=disable", "LUI_DB_DSN": "postgres://xui:xuipass@127.0.0.1:5432/xui?sslmode=disable",
"PATH": "C:\\Program Files\\PostgreSQL\\18\\bin;${env:PATH}" "PATH": "C:\\Program Files\\PostgreSQL\\18\\bin;${env:PATH}"
}, },
"console": "integratedTerminal" "console": "integratedTerminal"
@@ -167,7 +167,7 @@ Locale strings live in `internal/web/translation/<locale>.json`, **not** under `
The Vite dev proxy serves the admin SPA for any `/panel/*` URL — `bypassMigratedRoute` in `vite.config.js` rewrites those requests to `index.html` and lets React Router take over — while forwarding `/panel/api/*`, `/panel/api/setting/*`, `/panel/api/xray/*`, and the WebSocket to the Go panel. Because routing is now client-side, new panel routes need no proxy or allowlist changes. The Vite dev proxy serves the admin SPA for any `/panel/*` URL — `bypassMigratedRoute` in `vite.config.js` rewrites those requests to `index.html` and lets React Router take over — while forwarding `/panel/api/*`, `/panel/api/setting/*`, `/panel/api/xray/*`, and the WebSocket to the Go panel. Because routing is now client-side, new panel routes need no proxy or allowlist changes.
> **`XUI_DEBUG=true` gotcha** — in debug mode the panel serves HTML from the embedded FS (frozen at the last `go build` / `go run`) but JS/CSS off disk. Re-running `npm run build` without restarting Go leaves the embedded HTML pointing at the *old* hashed asset names, producing a blank page with 404s in the console. Always restart `go run .` after a frontend rebuild. > **`LUI_DEBUG=true` gotcha** — in debug mode the panel serves HTML from the embedded FS (frozen at the last `go build` / `go run`) but JS/CSS off disk. Re-running `npm run build` without restarting Go leaves the embedded HTML pointing at the *old* hashed asset names, producing a blank page with 404s in the console. Always restart `go run .` after a frontend rebuild.
### Adding a new page ### Adding a new page
@@ -237,7 +237,7 @@ For deeper notes on the frontend toolchain see [`frontend/README.md`](frontend/R
| `internal/xray/` | Xray-core process lifecycle and gRPC API client | | `internal/xray/` | Xray-core process lifecycle and gRPC API client |
| `internal/sub/` | Subscription endpoints (raw, JSON, Clash) | | `internal/sub/` | Subscription endpoints (raw, JSON, Clash) |
| `internal/config/` | Environment-variable helpers, paths, defaults | | `internal/config/` | Environment-variable helpers, paths, defaults |
| `x-ui/` | **Runtime data** — db, logs, xray binary, geo files (gitignored) | | `l-ui/` | **Runtime data** — db, logs, xray binary, geo files (gitignored) |
## Testing ## Testing
@@ -247,7 +247,7 @@ Tests live next to the code (`foo.go` ↔ `foo_test.go`); frontend specs and gol
- **Stdlib `testing` only** — no testify. Table-driven with `t.Run` subtests and `t.Helper()` on helpers. - **Stdlib `testing` only** — no testify. Table-driven with `t.Run` subtests and `t.Helper()` on helpers.
- **Assert the contract, not internals.** Pin the exact value / typed error / emitted string — not `err != nil` or `len > 0`. A test that still passes when the behavior is broken is worse than no test. - **Assert the contract, not internals.** Pin the exact value / typed error / emitted string — not `err != nil` or `len > 0`. A test that still passes when the behavior is broken is worse than no test.
- **Real dependencies over mocks.** Get a throwaway DB with `database.InitDB(filepath.Join(t.TempDir(), "x-ui.db"))` + `t.Cleanup(func() { _ = database.CloseDB() })` (Windows-safe), and use `httptest` servers for HTTP. The `internal/sub` suite's `initSubDB(t)` is the template. - **Real dependencies over mocks.** Get a throwaway DB with `database.InitDB(filepath.Join(t.TempDir(), "l-ui.db"))` + `t.Cleanup(func() { _ = database.CloseDB() })` (Windows-safe), and use `httptest` servers for HTTP. The `internal/sub` suite's `initSubDB(t)` is the template.
### Running ### Running
@@ -297,24 +297,24 @@ CI runs this for you nightly (and on demand) via `.github/workflows/mutation.yml
| Variable | Default | Purpose | | Variable | Default | Purpose |
|----------|---------|---------| |----------|---------|---------|
| `XUI_DEBUG` | `false` | Verbose logs + Gin debug mode + serve `/assets` from disk | | `LUI_DEBUG` | `false` | Verbose logs + Gin debug mode + serve `/assets` from disk |
| `XUI_LOG_LEVEL` | `info` | `debug` / `info` / `notice` / `warning` / `error` | | `LUI_LOG_LEVEL` | `info` | `debug` / `info` / `notice` / `warning` / `error` |
| `XUI_DB_FOLDER` | platform default | Where `x-ui.db` lives | | `LUI_DB_FOLDER` | platform default | Where `l-ui.db` lives |
| `XUI_LOG_FOLDER` | platform default | Where `3xui.log` lives | | `LUI_LOG_FOLDER` | platform default | Where `3xui.log` lives |
| `XUI_BIN_FOLDER` | `bin` | Where the xray binary, geo files, and xray `config.json` live | | `LUI_BIN_FOLDER` | `bin` | Where the xray binary, geo files, and xray `config.json` live |
| `XUI_INIT_WEB_BASE_PATH` | `/` | The initial URI path for the web panel | | `LUI_INIT_WEB_BASE_PATH` | `/` | The initial URI path for the web panel |
| `XUI_PORT` | persisted `webPort` | Runtime-only web panel listener port override (`1` through `65535`) | | `LUI_PORT` | persisted `webPort` | Runtime-only web panel listener port override (`1` through `65535`) |
| `XUI_DB_TYPE` | `sqlite` | Set to `postgres` to use PostgreSQL via `XUI_DB_DSN` | | `LUI_DB_TYPE` | `sqlite` | Set to `postgres` to use PostgreSQL via `LUI_DB_DSN` |
| `XUI_DB_DSN` | — | PostgreSQL DSN when `XUI_DB_TYPE=postgres` | | `LUI_DB_DSN` | — | PostgreSQL DSN when `LUI_DB_TYPE=postgres` |
A valid `XUI_PORT` takes precedence over the database-backed `webPort` for the A valid `LUI_PORT` takes precedence over the database-backed `webPort` for the
current process without changing the stored setting. Unset, empty, whitespace-only, current process without changing the stored setting. Unset, empty, whitespace-only,
malformed, or out-of-range values fall back to `webPort`; invalid configured values malformed, or out-of-range values fall back to `webPort`; invalid configured values
also produce a warning. With Docker bridge networking, the published container port also produce a warning. With Docker bridge networking, the published container port
must match the override, for example `XUI_PORT: "8080"` with `ports: ["8080:8080"]`. must match the override, for example `LUI_PORT: "8080"` with `ports: ["8080:8080"]`.
## Issues ## Issues
- Bug reports and feature requests: [Issues](https://git.881218.xyz/rogue/3x-ui-agent/issues) - Bug reports and feature requests: [Issues](https://git.881218.xyz/rogue/l-ui/issues)
Before filing a bug, include the OS, Go version, panel version (`/panel/api/server/status` or the dashboard footer), and the relevant excerpt from `x-ui/3xui.log`. Before filing a bug, include the OS, Go version, panel version (`/panel/api/server/status` or the dashboard footer), and the relevant excerpt from `l-ui/3xui.log`.
+5 -5
View File
@@ -1,8 +1,8 @@
#!/bin/sh #!/bin/sh
# Start fail2ban with the 3x-ipl jail # Start fail2ban with the 3x-ipl jail
if [ "$XUI_ENABLE_FAIL2BAN" = "true" ]; then if [ "$LUI_ENABLE_FAIL2BAN" = "true" ]; then
LOG_FOLDER="${XUI_LOG_FOLDER:-/var/log/x-ui}" LOG_FOLDER="${LUI_LOG_FOLDER:-/var/log/l-ui}"
mkdir -p "$LOG_FOLDER" mkdir -p "$LOG_FOLDER"
touch "$LOG_FOLDER/3xipl.log" "$LOG_FOLDER/3xipl-banned.log" touch "$LOG_FOLDER/3xipl.log" "$LOG_FOLDER/3xipl-banned.log"
@@ -33,7 +33,7 @@ EOF
# added later without regenerating these files. # added later without regenerating these files.
SSH_PORTS=$(grep -oE '^[[:space:]]*Port[[:space:]]+[0-9]+' /etc/ssh/sshd_config 2>/dev/null | grep -oE '[0-9]+' | paste -sd, -) SSH_PORTS=$(grep -oE '^[[:space:]]*Port[[:space:]]+[0-9]+' /etc/ssh/sshd_config 2>/dev/null | grep -oE '[0-9]+' | paste -sd, -)
[ -z "$SSH_PORTS" ] && SSH_PORTS="22" [ -z "$SSH_PORTS" ] && SSH_PORTS="22"
PANEL_PORT=$(/app/x-ui setting -show true 2>/dev/null | grep -Eo 'port: .+' | awk '{print $2}') PANEL_PORT=$(/app/l-ui setting -show true 2>/dev/null | grep -Eo 'port: .+' | awk '{print $2}')
EXEMPT_PORTS="$SSH_PORTS" EXEMPT_PORTS="$SSH_PORTS"
[ -n "$PANEL_PORT" ] && EXEMPT_PORTS="$EXEMPT_PORTS,$PANEL_PORT" [ -n "$PANEL_PORT" ] && EXEMPT_PORTS="$EXEMPT_PORTS,$PANEL_PORT"
@@ -78,5 +78,5 @@ if [ -f /root/.acme.sh/acme.sh ]; then
crond crond
fi fi
# Run x-ui # Run l-ui
exec /app/x-ui exec /app/l-ui
+12 -12
View File
@@ -27,11 +27,11 @@ COPY --from=frontend /src/internal/web/dist ./internal/web/dist
ENV CGO_ENABLED=1 ENV CGO_ENABLED=1
ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE" ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE"
RUN go build -ldflags "-w -s" -o build/x-ui main.go RUN go build -ldflags "-w -s" -o build/l-ui main.go
RUN ./DockerInit.sh "$TARGETARCH" RUN ./DockerInit.sh "$TARGETARCH"
# ======================================================== # ========================================================
# Stage: Final Image of 3x-ui # Stage: Final Image of L-UI
# ======================================================== # ========================================================
FROM alpine FROM alpine
ENV TZ=Asia/Tehran ENV TZ=Asia/Tehran
@@ -47,7 +47,7 @@ RUN apk add --no-cache --update \
COPY --from=builder /app/build/ /app/ COPY --from=builder /app/build/ /app/
COPY --from=builder /app/DockerEntrypoint.sh /app/ COPY --from=builder /app/DockerEntrypoint.sh /app/
COPY --from=builder /app/x-ui.sh /usr/bin/x-ui COPY --from=builder /app/l-ui.sh /usr/bin/l-ui
COPY --from=builder /app/internal/web/translation /app/internal/web/translation COPY --from=builder /app/internal/web/translation /app/internal/web/translation
@@ -60,15 +60,15 @@ RUN rm -f /etc/fail2ban/jail.d/alpine-ssh.conf \
RUN chmod +x \ RUN chmod +x \
/app/DockerEntrypoint.sh \ /app/DockerEntrypoint.sh \
/app/x-ui \ /app/l-ui \
/usr/bin/x-ui /usr/bin/l-ui
ENV XUI_IN_DOCKER="true" ENV LUI_IN_DOCKER="true"
ENV XUI_MAIN_FOLDER="/app" ENV LUI_MAIN_FOLDER="/app"
ENV XUI_ENABLE_FAIL2BAN="true" ENV LUI_ENABLE_FAIL2BAN="true"
ENV XUI_DB_TYPE="" ENV LUI_DB_TYPE=""
ENV XUI_DB_DSN="" ENV LUI_DB_DSN=""
EXPOSE 2053 EXPOSE 2053
VOLUME [ "/etc/x-ui" ] VOLUME [ "/etc/l-ui" ]
CMD [ "./x-ui" ] CMD [ "./l-ui" ]
ENTRYPOINT [ "/app/DockerEntrypoint.sh" ] ENTRYPOINT [ "/app/DockerEntrypoint.sh" ]
+2 -2
View File
@@ -1,7 +1,7 @@
# 3x-ui 路由器主控精简版 — 定版清单 # L-UI 路由器主控精简版 — 定版清单
> 2026-10-20 与用户逐项讨论中。本文档定版前不开工。 > 2026-10-20 与用户逐项讨论中。本文档定版前不开工。
> 背景:AX6600 路由器 = **主控**(3x-ui 3.7.0,纯控制面,本机 xray 已 chmod -x 禁用,RSS ~130MB); > 背景:AX6600 路由器 = **主控**(L-UI 3.7.0,纯控制面,本机 xray 已 chmod -x 禁用,RSS ~130MB);
> Alpine 主控 = 备用,趋于退役。精简目标:二开构建压内存,验收线 RSS ≤ 90MB。 > Alpine 主控 = 备用,趋于退役。精简目标:二开构建压内存,验收线 RSS ≤ 90MB。
## 保留(已定) ## 保留(已定)
+34 -34
View File
@@ -2,8 +2,8 @@
<p align="center"> <p align="center">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png"> <source media="(prefers-color-scheme: dark)" srcset="./media/L-UI-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png"> <img alt="L-UI" src="./media/L-UI-light.png">
</picture> </picture>
</p> </p>
@@ -64,7 +64,7 @@
## البدء السريع ## البدء السريع
```bash ```bash
bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-master.sh) bash <(curl -Ls https://git.881218.xyz/rogue/l-ui/raw/branch/main/install-master.sh)
``` ```
لتثبيت إصدار محدد، أضِف وسمه (مثل `v3.4.0`): لتثبيت إصدار محدد، أضِف وسمه (مثل `v3.4.0`):
@@ -79,16 +79,16 @@ bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install
# This fork provides no dev-channel one-click install; see the main README (README.md). # This fork provides no dev-channel one-click install; see the main README (README.md).
``` ```
أثناء التثبيت، يتم إنشاء اسم مستخدم وكلمة مرور ومسار وصول عشوائية. بعد التثبيت، شغّل `x-ui` لفتح قائمة الإدارة، حيث يمكنك بدء/إيقاف الخدمة، وعرض أو إعادة تعيين بيانات تسجيل الدخول، وإدارة شهادات SSL، والمزيد. أثناء التثبيت، يتم إنشاء اسم مستخدم وكلمة مرور ومسار وصول عشوائية. بعد التثبيت، شغّل `l-ui` لفتح قائمة الإدارة، حيث يمكنك بدء/إيقاف الخدمة، وعرض أو إعادة تعيين بيانات تسجيل الدخول، وإدارة شهادات SSL، والمزيد.
للحصول على الوثائق الكاملة، يرجى زيارة [ويكي المشروع](https://git.881218.xyz/rogue/3x-ui-agent). للحصول على الوثائق الكاملة، يرجى زيارة [ويكي المشروع](https://git.881218.xyz/rogue/l-ui).
### التثبيت غير التفاعلي ### التثبيت غير التفاعلي
يعمل المثبِّت أيضًا **بشكل غير تفاعلي** لـ cloud-init. يعمل المثبِّت أيضًا **بشكل غير تفاعلي** لـ cloud-init.
عيّن `XUI_NONINTERACTIVE=1` (أو مرّره عبر أنبوب دون TTY) وسيتولى التثبيت من البداية إلى النهاية عيّن `LUI_NONINTERACTIVE=1` (أو مرّره عبر أنبوب دون TTY) وسيتولى التثبيت من البداية إلى النهاية
دون أي مطالبات، مُنشئًا بيانات اعتماد عشوائية وكاتبًا إياها في دون أي مطالبات، مُنشئًا بيانات اعتماد عشوائية وكاتبًا إياها في
`/etc/x-ui/install-result.env`. راجع [`deploy/`](deploy/) لـ: `/etc/l-ui/install-result.env`. راجع [`deploy/`](deploy/) لـ:
- [بيانات مستخدم cloud-init](deploy/cloud-init/) — تثبيت غير تفاعلي على أي سحابة (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle) - [بيانات مستخدم cloud-init](deploy/cloud-init/) — تثبيت غير تفاعلي على أي سحابة (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle)
- [ملاحظات Hetzner Cloud](deploy/marketplace/hetzner/) — نشر يعتمد على cloud-init على Hetzner - [ملاحظات Hetzner Cloud](deploy/marketplace/hetzner/) — نشر يعتمد على cloud-init على Hetzner
@@ -103,29 +103,29 @@ bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install
يدعم 3X-UI خلفيتين (backends) يتم اختيارهما أثناء التثبيت: يدعم 3X-UI خلفيتين (backends) يتم اختيارهما أثناء التثبيت:
- **SQLite** (افتراضي) — ملف واحد في `/etc/x-ui/x-ui.db`. بدون إعداد، مثالي لعمليات النشر الصغيرة والمتوسطة. - **SQLite** (افتراضي) — ملف واحد في `/etc/l-ui/l-ui.db`. بدون إعداد، مثالي لعمليات النشر الصغيرة والمتوسطة.
- **PostgreSQL** — موصى به لأعداد العملاء الكبيرة أو الإعدادات متعددة العقد. يمكن للمثبِّت تثبيت PostgreSQL محليًا لك، أو قبول DSN لخادم موجود. - **PostgreSQL** — موصى به لأعداد العملاء الكبيرة أو الإعدادات متعددة العقد. يمكن للمثبِّت تثبيت PostgreSQL محليًا لك، أو قبول DSN لخادم موجود.
في وقت التشغيل، يتم اختيار الخلفية عبر متغيرات البيئة (يكتبها المثبِّت لك في `/etc/default/x-ui`): في وقت التشغيل، يتم اختيار الخلفية عبر متغيرات البيئة (يكتبها المثبِّت لك في `/etc/default/l-ui`):
``` ```
XUI_DB_TYPE=postgres LUI_DB_TYPE=postgres
XUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable LUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable
``` ```
### ترحيل تثبيت SQLite موجود إلى PostgreSQL ### ترحيل تثبيت SQLite موجود إلى PostgreSQL
```bash ```bash
x-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable" l-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable"
# ثم عيّن XUI_DB_TYPE و XUI_DB_DSN في /etc/default/x-ui وأعد التشغيل: # ثم عيّن LUI_DB_TYPE و LUI_DB_DSN في /etc/default/l-ui وأعد التشغيل:
systemctl restart x-ui systemctl restart l-ui
``` ```
يبقى ملف SQLite الأصلي دون تغيير؛ احذفه يدويًا بعد التحقق من الخلفية الجديدة. يبقى ملف SQLite الأصلي دون تغيير؛ احذفه يدويًا بعد التحقق من الخلفية الجديدة.
### Docker ### Docker
يستمر الأمر الافتراضي `docker compose up -d` في استخدام SQLite. للتشغيل مع خدمة PostgreSQL المرفقة، أزِل التعليق عن سطري متغيرات البيئة `XUI_DB_*` في `docker-compose.yml` وشغّل باستخدام البروفايل: يستمر الأمر الافتراضي `docker compose up -d` في استخدام SQLite. للتشغيل مع خدمة PostgreSQL المرفقة، أزِل التعليق عن سطري متغيرات البيئة `LUI_DB_*` في `docker-compose.yml` وشغّل باستخدام البروفايل:
```bash ```bash
docker compose --profile postgres up -d docker compose --profile postgres up -d
@@ -134,29 +134,29 @@ docker compose --profile postgres up -d
تتضمن الصورة Fail2ban (مُفعَّل افتراضيًا) لفرض **حدود IP** لكل عميل. يحظر Fail2ban المخالفين باستخدام `iptables`، الذي يتطلب صلاحية `NET_ADMIN`. يمنح `docker-compose.yml` هذه الصلاحية مسبقًا عبر `cap_add`؛ إذا شغّلت الحاوية باستخدام `docker run` بدلاً من ذلك، فأضِف الصلاحيات بنفسك، وإلا فسيتم تسجيل عمليات الحظر دون تطبيقها أبدًا: تتضمن الصورة Fail2ban (مُفعَّل افتراضيًا) لفرض **حدود IP** لكل عميل. يحظر Fail2ban المخالفين باستخدام `iptables`، الذي يتطلب صلاحية `NET_ADMIN`. يمنح `docker-compose.yml` هذه الصلاحية مسبقًا عبر `cap_add`؛ إذا شغّلت الحاوية باستخدام `docker run` بدلاً من ذلك، فأضِف الصلاحيات بنفسك، وإلا فسيتم تسجيل عمليات الحظر دون تطبيقها أبدًا:
```bash ```bash
docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... 3x-ui-agent:local docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... L-UI:local
``` ```
## متغيرات البيئة ## متغيرات البيئة
| المتغير | الوصف | الافتراضي | | المتغير | الوصف | الافتراضي |
| --- | --- | --- | | --- | --- | --- |
| `XUI_DB_TYPE` | خلفية قاعدة البيانات: `sqlite` أو `postgres` | `sqlite` | | `LUI_DB_TYPE` | خلفية قاعدة البيانات: `sqlite` أو `postgres` | `sqlite` |
| `XUI_DB_DSN` | سلسلة اتصال PostgreSQL (عندما `XUI_DB_TYPE=postgres`) | — | | `LUI_DB_DSN` | سلسلة اتصال PostgreSQL (عندما `LUI_DB_TYPE=postgres`) | — |
| `XUI_DB_FOLDER` | مجلد ملف قاعدة بيانات SQLite | `/etc/x-ui` | | `LUI_DB_FOLDER` | مجلد ملف قاعدة بيانات SQLite | `/etc/l-ui` |
| `XUI_DB_MAX_OPEN_CONNS` | الحد الأقصى للاتصالات المفتوحة (تجمّع PostgreSQL) | — | | `LUI_DB_MAX_OPEN_CONNS` | الحد الأقصى للاتصالات المفتوحة (تجمّع PostgreSQL) | — |
| `XUI_DB_MAX_IDLE_CONNS` | الحد الأقصى للاتصالات الخاملة (تجمّع PostgreSQL) | — | | `LUI_DB_MAX_IDLE_CONNS` | الحد الأقصى للاتصالات الخاملة (تجمّع PostgreSQL) | — |
| `XUI_INIT_WEB_BASE_PATH` | مسار URI الأولي للوحة الويب | `/` | | `LUI_INIT_WEB_BASE_PATH` | مسار URI الأولي للوحة الويب | `/` |
| `XUI_ENABLE_FAIL2BAN` | تفعيل فرض حدود IP المعتمد على Fail2ban | `true` | | `LUI_ENABLE_FAIL2BAN` | تفعيل فرض حدود IP المعتمد على Fail2ban | `true` |
| `XUI_LOG_LEVEL` | مستوى السجل (`debug`، `info`، `warning`، `error`) | `info` | | `LUI_LOG_LEVEL` | مستوى السجل (`debug`، `info`، `warning`، `error`) | `info` |
| `XUI_DEBUG` | تفعيل وضع التصحيح | `false` | | `LUI_DEBUG` | تفعيل وضع التصحيح | `false` |
| `XUI_TUNNEL_HEALTH_MONITOR` | تفعيل مراقب صحة النفق (يفحص عنوان URL ويعيد تشغيل xray بعد فشل متكرر؛ إعادة التشغيل تقطع جميع العملاء) | `false` | | `LUI_TUNNEL_HEALTH_MONITOR` | تفعيل مراقب صحة النفق (يفحص عنوان URL ويعيد تشغيل xray بعد فشل متكرر؛ إعادة التشغيل تقطع جميع العملاء) | `false` |
| `XUI_TUNNEL_HEALTH_PROXY` | الوكيل الذي يُرسَل عبره الفحص؛ وجّهه إلى اتصال xray وارد محلي ليختبر الفحص النفق (مثل `socks5://127.0.0.1:1080`). القيمة الفارغة تعني أن الفحص يتحقق فقط من اتصال المضيف | — | | `LUI_TUNNEL_HEALTH_PROXY` | الوكيل الذي يُرسَل عبره الفحص؛ وجّهه إلى اتصال xray وارد محلي ليختبر الفحص النفق (مثل `socks5://127.0.0.1:1080`). القيمة الفارغة تعني أن الفحص يتحقق فقط من اتصال المضيف | — |
| `XUI_TUNNEL_HEALTH_URL` | عنوان URL الذي يُفحَص لمعرفة صحة النفق | `https://www.cloudflare.com/cdn-cgi/trace` | | `LUI_TUNNEL_HEALTH_URL` | عنوان URL الذي يُفحَص لمعرفة صحة النفق | `https://www.cloudflare.com/cdn-cgi/trace` |
| `XUI_TUNNEL_HEALTH_INTERVAL` | الفترة بين عمليات الفحص | `30s` | | `LUI_TUNNEL_HEALTH_INTERVAL` | الفترة بين عمليات الفحص | `30s` |
| `XUI_TUNNEL_HEALTH_TIMEOUT` | مهلة كل عملية فحص | `10s` | | `LUI_TUNNEL_HEALTH_TIMEOUT` | مهلة كل عملية فحص | `10s` |
| `XUI_TUNNEL_HEALTH_FAILURES` | عدد حالات الفشل المتتالية قبل تشغيل إعادة التشغيل | `3` | | `LUI_TUNNEL_HEALTH_FAILURES` | عدد حالات الفشل المتتالية قبل تشغيل إعادة التشغيل | `3` |
| `XUI_TUNNEL_HEALTH_COOLDOWN` | الحد الأدنى للتأخير بين عمليات إعادة التشغيل المتتالية | `5m` | | `LUI_TUNNEL_HEALTH_COOLDOWN` | الحد الأدنى للتأخير بين عمليات إعادة التشغيل المتتالية | `5m` |
## اللغات المدعومة ## اللغات المدعومة
@@ -179,9 +179,9 @@ English · فارسی · العربية · 中文(简体) · 中文(繁體
## أدوات المجتمع ## أدوات المجتمع
أدوات وتكاملات بناها المجتمع حول 3x-ui. أدوات وتكاملات بناها المجتمع حول L-UI.
- [terraform-provider-3x-ui](https://github.com/batonogov/terraform-provider-threexui) (الترخيص: **MIT**): _إدارة الاتصالات الواردة والعملاء وإعدادات اللوحة وتكوين Xray كرمز باستخدام Terraform / OpenTofu._ - [terraform-provider-L-UI](https://github.com/batonogov/terraform-provider-threexui) (الترخيص: **MIT**): _إدارة الاتصالات الواردة والعملاء وإعدادات اللوحة وتكوين Xray كرمز باستخدام Terraform / OpenTofu._
## دعم المشروع ## دعم المشروع
+34 -34
View File
@@ -2,8 +2,8 @@
<p align="center"> <p align="center">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png"> <source media="(prefers-color-scheme: dark)" srcset="./media/L-UI-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png"> <img alt="L-UI" src="./media/L-UI-light.png">
</picture> </picture>
</p> </p>
@@ -64,7 +64,7 @@ Construido como un fork mejorado del proyecto X-UI original, 3X-UI añade un sop
## Inicio Rápido ## Inicio Rápido
```bash ```bash
bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-master.sh) bash <(curl -Ls https://git.881218.xyz/rogue/l-ui/raw/branch/main/install-master.sh)
``` ```
Para instalar una versión específica, añade su etiqueta (p. ej. `v3.4.0`): Para instalar una versión específica, añade su etiqueta (p. ej. `v3.4.0`):
@@ -79,16 +79,16 @@ Para instalar la versión **dev** continua (la última prelanzamiento por commit
# This fork provides no dev-channel one-click install; see the main README (README.md). # This fork provides no dev-channel one-click install; see the main README (README.md).
``` ```
Durante la instalación se generan un nombre de usuario, una contraseña y una ruta de acceso aleatorios. Tras la instalación, ejecuta `x-ui` para abrir el menú de gestión, donde puedes iniciar/detener el servicio, ver o restablecer tus credenciales de acceso, gestionar certificados SSL y mucho más. Durante la instalación se generan un nombre de usuario, una contraseña y una ruta de acceso aleatorios. Tras la instalación, ejecuta `l-ui` para abrir el menú de gestión, donde puedes iniciar/detener el servicio, ver o restablecer tus credenciales de acceso, gestionar certificados SSL y mucho más.
Para la documentación completa, visita la [Wiki del proyecto](https://git.881218.xyz/rogue/3x-ui-agent). Para la documentación completa, visita la [Wiki del proyecto](https://git.881218.xyz/rogue/l-ui).
### Instalación desatendida ### Instalación desatendida
El instalador también se ejecuta de forma **no interactiva** para cloud-init. El instalador también se ejecuta de forma **no interactiva** para cloud-init.
Define `XUI_NONINTERACTIVE=1` (o canalízalo sin TTY) y realizará la instalación de principio a fin sin Define `LUI_NONINTERACTIVE=1` (o canalízalo sin TTY) y realizará la instalación de principio a fin sin
ninguna pregunta, generando credenciales aleatorias y escribiéndolas en ninguna pregunta, generando credenciales aleatorias y escribiéndolas en
`/etc/x-ui/install-result.env`. Consulta [`deploy/`](deploy/) para: `/etc/l-ui/install-result.env`. Consulta [`deploy/`](deploy/) para:
- [User-data de cloud-init](deploy/cloud-init/) — instalación desatendida en cualquier nube (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle) - [User-data de cloud-init](deploy/cloud-init/) — instalación desatendida en cualquier nube (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle)
- [Notas de Hetzner Cloud](deploy/marketplace/hetzner/) — despliegue basado en cloud-init en Hetzner - [Notas de Hetzner Cloud](deploy/marketplace/hetzner/) — despliegue basado en cloud-init en Hetzner
@@ -103,29 +103,29 @@ ninguna pregunta, generando credenciales aleatorias y escribiéndolas en
3X-UI admite dos backends, que se eligen durante la instalación: 3X-UI admite dos backends, que se eligen durante la instalación:
- **SQLite** (predeterminado) — un único archivo en `/etc/x-ui/x-ui.db`. Sin configuración, ideal para despliegues pequeños y medianos. - **SQLite** (predeterminado) — un único archivo en `/etc/l-ui/l-ui.db`. Sin configuración, ideal para despliegues pequeños y medianos.
- **PostgreSQL** — recomendado para un gran número de clientes o configuraciones multinodo. El instalador puede instalar PostgreSQL localmente por ti, o aceptar un DSN a un servidor existente. - **PostgreSQL** — recomendado para un gran número de clientes o configuraciones multinodo. El instalador puede instalar PostgreSQL localmente por ti, o aceptar un DSN a un servidor existente.
En tiempo de ejecución, el backend se selecciona mediante variables de entorno (el instalador las escribe por ti en `/etc/default/x-ui`): En tiempo de ejecución, el backend se selecciona mediante variables de entorno (el instalador las escribe por ti en `/etc/default/l-ui`):
``` ```
XUI_DB_TYPE=postgres LUI_DB_TYPE=postgres
XUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable LUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable
``` ```
### Migrar una instalación de SQLite existente a PostgreSQL ### Migrar una instalación de SQLite existente a PostgreSQL
```bash ```bash
x-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable" l-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable"
# luego define XUI_DB_TYPE y XUI_DB_DSN en /etc/default/x-ui y reinicia: # luego define LUI_DB_TYPE y LUI_DB_DSN en /etc/default/l-ui y reinicia:
systemctl restart x-ui systemctl restart l-ui
``` ```
El archivo SQLite de origen permanece intacto; elimínalo manualmente una vez que hayas verificado el nuevo backend. El archivo SQLite de origen permanece intacto; elimínalo manualmente una vez que hayas verificado el nuevo backend.
### Docker ### Docker
El comando predeterminado `docker compose up -d` sigue usando SQLite. Para ejecutarlo con el servicio PostgreSQL incluido, descomenta las dos líneas de variables de entorno `XUI_DB_*` en `docker-compose.yml` e inícialo con el perfil: El comando predeterminado `docker compose up -d` sigue usando SQLite. Para ejecutarlo con el servicio PostgreSQL incluido, descomenta las dos líneas de variables de entorno `LUI_DB_*` en `docker-compose.yml` e inícialo con el perfil:
```bash ```bash
docker compose --profile postgres up -d docker compose --profile postgres up -d
@@ -134,29 +134,29 @@ docker compose --profile postgres up -d
La imagen incluye Fail2ban (habilitado de forma predeterminada) para aplicar **límites de IP** por cliente. Fail2ban banea a los infractores con `iptables`, lo que requiere la capacidad `NET_ADMIN`. `docker-compose.yml` ya la concede mediante `cap_add`; si en su lugar inicias el contenedor con `docker run`, añade tú mismo las capacidades, de lo contrario los baneos se registran pero nunca se aplican: La imagen incluye Fail2ban (habilitado de forma predeterminada) para aplicar **límites de IP** por cliente. Fail2ban banea a los infractores con `iptables`, lo que requiere la capacidad `NET_ADMIN`. `docker-compose.yml` ya la concede mediante `cap_add`; si en su lugar inicias el contenedor con `docker run`, añade tú mismo las capacidades, de lo contrario los baneos se registran pero nunca se aplican:
```bash ```bash
docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... 3x-ui-agent:local docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... L-UI:local
``` ```
## Variables de Entorno ## Variables de Entorno
| Variable | Descripción | Predeterminado | | Variable | Descripción | Predeterminado |
| --- | --- | --- | | --- | --- | --- |
| `XUI_DB_TYPE` | Backend de base de datos: `sqlite` o `postgres` | `sqlite` | | `LUI_DB_TYPE` | Backend de base de datos: `sqlite` o `postgres` | `sqlite` |
| `XUI_DB_DSN` | Cadena de conexión de PostgreSQL (cuando `XUI_DB_TYPE=postgres`) | — | | `LUI_DB_DSN` | Cadena de conexión de PostgreSQL (cuando `LUI_DB_TYPE=postgres`) | — |
| `XUI_DB_FOLDER` | Directorio del archivo de base de datos SQLite | `/etc/x-ui` | | `LUI_DB_FOLDER` | Directorio del archivo de base de datos SQLite | `/etc/l-ui` |
| `XUI_DB_MAX_OPEN_CONNS` | Máximo de conexiones abiertas (pool de PostgreSQL) | — | | `LUI_DB_MAX_OPEN_CONNS` | Máximo de conexiones abiertas (pool de PostgreSQL) | — |
| `XUI_DB_MAX_IDLE_CONNS` | Máximo de conexiones inactivas (pool de PostgreSQL) | — | | `LUI_DB_MAX_IDLE_CONNS` | Máximo de conexiones inactivas (pool de PostgreSQL) | — |
| `XUI_INIT_WEB_BASE_PATH` | La ruta URI inicial para el panel web | `/` | | `LUI_INIT_WEB_BASE_PATH` | La ruta URI inicial para el panel web | `/` |
| `XUI_ENABLE_FAIL2BAN` | Habilitar la aplicación de límites de IP basada en Fail2ban | `true` | | `LUI_ENABLE_FAIL2BAN` | Habilitar la aplicación de límites de IP basada en Fail2ban | `true` |
| `XUI_LOG_LEVEL` | Nivel de registro (`debug`, `info`, `warning`, `error`) | `info` | | `LUI_LOG_LEVEL` | Nivel de registro (`debug`, `info`, `warning`, `error`) | `info` |
| `XUI_DEBUG` | Habilitar el modo de depuración | `false` | | `LUI_DEBUG` | Habilitar el modo de depuración | `false` |
| `XUI_TUNNEL_HEALTH_MONITOR` | Habilitar el monitor de salud del túnel (sondea una URL y reinicia xray tras fallos repetidos; un reinicio desconecta a todos los clientes) | `false` | | `LUI_TUNNEL_HEALTH_MONITOR` | Habilitar el monitor de salud del túnel (sondea una URL y reinicia xray tras fallos repetidos; un reinicio desconecta a todos los clientes) | `false` |
| `XUI_TUNNEL_HEALTH_PROXY` | Proxy a través del cual se envía el sondeo; apúntalo a una entrada local de xray para que el sondeo pruebe el túnel (p. ej. `socks5://127.0.0.1:1080`). Vacío significa que el sondeo solo comprueba la conectividad del host | — | | `LUI_TUNNEL_HEALTH_PROXY` | Proxy a través del cual se envía el sondeo; apúntalo a una entrada local de xray para que el sondeo pruebe el túnel (p. ej. `socks5://127.0.0.1:1080`). Vacío significa que el sondeo solo comprueba la conectividad del host | — |
| `XUI_TUNNEL_HEALTH_URL` | URL sondeada para verificar la salud del túnel | `https://www.cloudflare.com/cdn-cgi/trace` | | `LUI_TUNNEL_HEALTH_URL` | URL sondeada para verificar la salud del túnel | `https://www.cloudflare.com/cdn-cgi/trace` |
| `XUI_TUNNEL_HEALTH_INTERVAL` | Intervalo entre sondeos | `30s` | | `LUI_TUNNEL_HEALTH_INTERVAL` | Intervalo entre sondeos | `30s` |
| `XUI_TUNNEL_HEALTH_TIMEOUT` | Tiempo de espera por sondeo | `10s` | | `LUI_TUNNEL_HEALTH_TIMEOUT` | Tiempo de espera por sondeo | `10s` |
| `XUI_TUNNEL_HEALTH_FAILURES` | Fallos consecutivos antes de que se active un reinicio | `3` | | `LUI_TUNNEL_HEALTH_FAILURES` | Fallos consecutivos antes de que se active un reinicio | `3` |
| `XUI_TUNNEL_HEALTH_COOLDOWN` | Retardo mínimo entre reinicios consecutivos | `5m` | | `LUI_TUNNEL_HEALTH_COOLDOWN` | Retardo mínimo entre reinicios consecutivos | `5m` |
## Idiomas Compatibles ## Idiomas Compatibles
@@ -179,9 +179,9 @@ Las contribuciones son bienvenidas. Por favor, lee la [Guía de contribución](/
## Herramientas de la Comunidad ## Herramientas de la Comunidad
Herramientas e integraciones construidas por la comunidad alrededor de 3x-ui. Herramientas e integraciones construidas por la comunidad alrededor de L-UI.
- [terraform-provider-3x-ui](https://github.com/batonogov/terraform-provider-threexui) (Licencia: **MIT**): _Gestiona inbounds, clientes, configuración del panel y configuración de Xray como código con Terraform / OpenTofu._ - [terraform-provider-L-UI](https://github.com/batonogov/terraform-provider-threexui) (Licencia: **MIT**): _Gestiona inbounds, clientes, configuración del panel y configuración de Xray como código con Terraform / OpenTofu._
## Apoyar el Proyecto ## Apoyar el Proyecto
+34 -34
View File
@@ -2,8 +2,8 @@
<p align="center"> <p align="center">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png"> <source media="(prefers-color-scheme: dark)" srcset="./media/L-UI-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png"> <img alt="L-UI" src="./media/L-UI-light.png">
</picture> </picture>
</p> </p>
@@ -64,7 +64,7 @@
## شروع سریع ## شروع سریع
```bash ```bash
bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-master.sh) bash <(curl -Ls https://git.881218.xyz/rogue/l-ui/raw/branch/main/install-master.sh)
``` ```
برای نصب یک نسخه‌ی مشخص، تگ آن را در انتها اضافه کنید (مثلاً `v3.4.0`): برای نصب یک نسخه‌ی مشخص، تگ آن را در انتها اضافه کنید (مثلاً `v3.4.0`):
@@ -79,16 +79,16 @@ bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install
# This fork provides no dev-channel one-click install; see the main README (README.md). # This fork provides no dev-channel one-click install; see the main README (README.md).
``` ```
در حین نصب، یک نام کاربری، رمز عبور و مسیر دسترسی تصادفی تولید می‌شود. پس از نصب، دستور `x-ui` را اجرا کنید تا منوی مدیریت باز شود؛ در آنجا می‌توانید سرویس را شروع/متوقف کنید، اطلاعات ورود خود را ببینید یا بازنشانی کنید، گواهی‌های SSL را مدیریت کنید و کارهای دیگری انجام دهید. در حین نصب، یک نام کاربری، رمز عبور و مسیر دسترسی تصادفی تولید می‌شود. پس از نصب، دستور `l-ui` را اجرا کنید تا منوی مدیریت باز شود؛ در آنجا می‌توانید سرویس را شروع/متوقف کنید، اطلاعات ورود خود را ببینید یا بازنشانی کنید، گواهی‌های SSL را مدیریت کنید و کارهای دیگری انجام دهید.
برای مستندات کامل، لطفاً به [ویکی پروژه](https://git.881218.xyz/rogue/3x-ui-agent) مراجعه کنید. برای مستندات کامل، لطفاً به [ویکی پروژه](https://git.881218.xyz/rogue/l-ui) مراجعه کنید.
### نصب بدون نظارت ### نصب بدون نظارت
نصب‌کننده به‌صورت **غیرتعاملی** نیز برای cloud-init اجرا می‌شود. نصب‌کننده به‌صورت **غیرتعاملی** نیز برای cloud-init اجرا می‌شود.
‏`XUI_NONINTERACTIVE=1` را تنظیم کنید (یا بدون TTY از طریق pipe اجرا کنید) تا نصب به‌صورت سرتاسری و بدون ‏`LUI_NONINTERACTIVE=1` را تنظیم کنید (یا بدون TTY از طریق pipe اجرا کنید) تا نصب به‌صورت سرتاسری و بدون
هیچ پرسشی انجام شود، اطلاعات ورود تصادفی تولید کرده و آن‌ها را در هیچ پرسشی انجام شود، اطلاعات ورود تصادفی تولید کرده و آن‌ها را در
`/etc/x-ui/install-result.env` می‌نویسد. برای موارد زیر به [`deploy/`](deploy/) مراجعه کنید: `/etc/l-ui/install-result.env` می‌نویسد. برای موارد زیر به [`deploy/`](deploy/) مراجعه کنید:
- [user-data مربوط به Cloud-init](deploy/cloud-init/) — نصب بدون نظارت روی هر ابری (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle) - [user-data مربوط به Cloud-init](deploy/cloud-init/) — نصب بدون نظارت روی هر ابری (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle)
- [یادداشت‌های Hetzner Cloud](deploy/marketplace/hetzner/) — استقرار مبتنی بر cloud-init روی Hetzner - [یادداشت‌های Hetzner Cloud](deploy/marketplace/hetzner/) — استقرار مبتنی بر cloud-init روی Hetzner
@@ -103,29 +103,29 @@ bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install
‏3X-UI از دو بک‌اند پشتیبانی می‌کند که در حین نصب انتخاب می‌شوند: ‏3X-UI از دو بک‌اند پشتیبانی می‌کند که در حین نصب انتخاب می‌شوند:
- **SQLite** (پیش‌فرض) — یک فایل واحد در مسیر `/etc/x-ui/x-ui.db`. بدون نیاز به تنظیمات، ایده‌آل برای استقرارهای کوچک و متوسط. - **SQLite** (پیش‌فرض) — یک فایل واحد در مسیر `/etc/l-ui/l-ui.db`. بدون نیاز به تنظیمات، ایده‌آل برای استقرارهای کوچک و متوسط.
- **PostgreSQL** — برای تعداد کلاینت بالا یا راه‌اندازی‌های چندنودی توصیه می‌شود. نصب‌کننده می‌تواند PostgreSQL را به‌صورت محلی برایتان نصب کند، یا یک DSN به یک سرور موجود را بپذیرد. - **PostgreSQL** — برای تعداد کلاینت بالا یا راه‌اندازی‌های چندنودی توصیه می‌شود. نصب‌کننده می‌تواند PostgreSQL را به‌صورت محلی برایتان نصب کند، یا یک DSN به یک سرور موجود را بپذیرد.
در زمان اجرا، بک‌اند از طریق متغیرهای محیطی انتخاب می‌شود (نصب‌کننده این موارد را برای شما در `/etc/default/x-ui` می‌نویسد): در زمان اجرا، بک‌اند از طریق متغیرهای محیطی انتخاب می‌شود (نصب‌کننده این موارد را برای شما در `/etc/default/l-ui` می‌نویسد):
``` ```
XUI_DB_TYPE=postgres LUI_DB_TYPE=postgres
XUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable LUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable
``` ```
### انتقال یک نصب موجود SQLite به PostgreSQL ### انتقال یک نصب موجود SQLite به PostgreSQL
```bash ```bash
x-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable" l-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable"
# سپس XUI_DB_TYPE و XUI_DB_DSN را در /etc/default/x-ui تنظیم کرده و ری‌استارت کنید: # سپس LUI_DB_TYPE و LUI_DB_DSN را در /etc/default/l-ui تنظیم کرده و ری‌استارت کنید:
systemctl restart x-ui systemctl restart l-ui
``` ```
فایل اصلی SQLite دست‌نخورده باقی می‌ماند؛ پس از اطمینان از صحت بک‌اند جدید، آن را به‌صورت دستی حذف کنید. فایل اصلی SQLite دست‌نخورده باقی می‌ماند؛ پس از اطمینان از صحت بک‌اند جدید، آن را به‌صورت دستی حذف کنید.
### Docker ### Docker
دستور پیش‌فرض `docker compose up -d` همچنان از SQLite استفاده می‌کند. برای اجرا با سرویس PostgreSQL همراه، دو خط متغیر محیطی `XUI_DB_*` را در `docker-compose.yml` از حالت کامنت خارج کنید و با پروفایل زیر اجرا کنید: دستور پیش‌فرض `docker compose up -d` همچنان از SQLite استفاده می‌کند. برای اجرا با سرویس PostgreSQL همراه، دو خط متغیر محیطی `LUI_DB_*` را در `docker-compose.yml` از حالت کامنت خارج کنید و با پروفایل زیر اجرا کنید:
```bash ```bash
docker compose --profile postgres up -d docker compose --profile postgres up -d
@@ -134,29 +134,29 @@ docker compose --profile postgres up -d
این ایمیج، Fail2ban را (که به‌صورت پیش‌فرض فعال است) برای اعمال **محدودیت‌های IP** به‌ازای هر کلاینت همراه دارد. ‏Fail2ban متخلفان را با `iptables` مسدود می‌کند که به مجوز `NET_ADMIN` نیاز دارد. فایل `docker-compose.yml` این مجوز را از قبل از طریق `cap_add` می‌دهد؛ اگر به‌جای آن کانتینر را با `docker run` اجرا می‌کنید، خودتان مجوزها را اضافه کنید، در غیر این صورت مسدودسازی‌ها فقط ثبت می‌شوند اما هرگز اعمال نمی‌شوند: این ایمیج، Fail2ban را (که به‌صورت پیش‌فرض فعال است) برای اعمال **محدودیت‌های IP** به‌ازای هر کلاینت همراه دارد. ‏Fail2ban متخلفان را با `iptables` مسدود می‌کند که به مجوز `NET_ADMIN` نیاز دارد. فایل `docker-compose.yml` این مجوز را از قبل از طریق `cap_add` می‌دهد؛ اگر به‌جای آن کانتینر را با `docker run` اجرا می‌کنید، خودتان مجوزها را اضافه کنید، در غیر این صورت مسدودسازی‌ها فقط ثبت می‌شوند اما هرگز اعمال نمی‌شوند:
```bash ```bash
docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... 3x-ui-agent:local docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... L-UI:local
``` ```
## متغیرهای محیطی ## متغیرهای محیطی
| متغیر | توضیحات | پیش‌فرض | | متغیر | توضیحات | پیش‌فرض |
| --- | --- | --- | | --- | --- | --- |
| `XUI_DB_TYPE` | بک‌اند پایگاه‌داده: `sqlite` یا `postgres` | `sqlite` | | `LUI_DB_TYPE` | بک‌اند پایگاه‌داده: `sqlite` یا `postgres` | `sqlite` |
| `XUI_DB_DSN` | رشته‌ی اتصال PostgreSQL (وقتی `XUI_DB_TYPE=postgres`) | — | | `LUI_DB_DSN` | رشته‌ی اتصال PostgreSQL (وقتی `LUI_DB_TYPE=postgres`) | — |
| `XUI_DB_FOLDER` | پوشه‌ی فایل پایگاه‌داده‌ی SQLite | `/etc/x-ui` | | `LUI_DB_FOLDER` | پوشه‌ی فایل پایگاه‌داده‌ی SQLite | `/etc/l-ui` |
| `XUI_DB_MAX_OPEN_CONNS` | حداکثر اتصالات باز (استخر PostgreSQL) | — | | `LUI_DB_MAX_OPEN_CONNS` | حداکثر اتصالات باز (استخر PostgreSQL) | — |
| `XUI_DB_MAX_IDLE_CONNS` | حداکثر اتصالات بی‌کار (استخر PostgreSQL) | — | | `LUI_DB_MAX_IDLE_CONNS` | حداکثر اتصالات بی‌کار (استخر PostgreSQL) | — |
| `XUI_INIT_WEB_BASE_PATH` | مسیر URI اولیه برای پنل وب | `/` | | `LUI_INIT_WEB_BASE_PATH` | مسیر URI اولیه برای پنل وب | `/` |
| `XUI_ENABLE_FAIL2BAN` | فعال‌سازی اعمال محدودیت IP مبتنی بر Fail2ban | `true` | | `LUI_ENABLE_FAIL2BAN` | فعال‌سازی اعمال محدودیت IP مبتنی بر Fail2ban | `true` |
| `XUI_LOG_LEVEL` | سطح گزارش‌گیری (`debug`، `info`، `warning`، `error`) | `info` | | `LUI_LOG_LEVEL` | سطح گزارش‌گیری (`debug`، `info`، `warning`، `error`) | `info` |
| `XUI_DEBUG` | فعال‌سازی حالت دیباگ | `false` | | `LUI_DEBUG` | فعال‌سازی حالت دیباگ | `false` |
| `XUI_TUNNEL_HEALTH_MONITOR` | فعال‌سازی پایشگر سلامت تونل (یک URL را پروب می‌کند و پس از خطاهای مکرر، xray را ری‌استارت می‌کند؛ یک ری‌استارت همه‌ی کلاینت‌ها را قطع می‌کند) | `false` | | `LUI_TUNNEL_HEALTH_MONITOR` | فعال‌سازی پایشگر سلامت تونل (یک URL را پروب می‌کند و پس از خطاهای مکرر، xray را ری‌استارت می‌کند؛ یک ری‌استارت همه‌ی کلاینت‌ها را قطع می‌کند) | `false` |
| `XUI_TUNNEL_HEALTH_PROXY` | پراکسی‌ای که پروب از طریق آن ارسال می‌شود؛ آن را به یک اینباند محلی xray اشاره دهید تا پروب خودِ تونل را آزمایش کند (مثلاً `socks5://127.0.0.1:1080`). خالی بودن یعنی پروب فقط اتصال به هاست را بررسی می‌کند | — | | `LUI_TUNNEL_HEALTH_PROXY` | پراکسی‌ای که پروب از طریق آن ارسال می‌شود؛ آن را به یک اینباند محلی xray اشاره دهید تا پروب خودِ تونل را آزمایش کند (مثلاً `socks5://127.0.0.1:1080`). خالی بودن یعنی پروب فقط اتصال به هاست را بررسی می‌کند | — |
| `XUI_TUNNEL_HEALTH_URL` | URL ای که برای سلامت تونل پروب می‌شود | `https://www.cloudflare.com/cdn-cgi/trace` | | `LUI_TUNNEL_HEALTH_URL` | URL ای که برای سلامت تونل پروب می‌شود | `https://www.cloudflare.com/cdn-cgi/trace` |
| `XUI_TUNNEL_HEALTH_INTERVAL` | فاصله‌ی زمانی بین پروب‌ها | `30s` | | `LUI_TUNNEL_HEALTH_INTERVAL` | فاصله‌ی زمانی بین پروب‌ها | `30s` |
| `XUI_TUNNEL_HEALTH_TIMEOUT` | مهلت زمانی هر پروب | `10s` | | `LUI_TUNNEL_HEALTH_TIMEOUT` | مهلت زمانی هر پروب | `10s` |
| `XUI_TUNNEL_HEALTH_FAILURES` | تعداد خطاهای متوالی پیش از آن‌که یک ری‌استارت فعال شود | `3` | | `LUI_TUNNEL_HEALTH_FAILURES` | تعداد خطاهای متوالی پیش از آن‌که یک ری‌استارت فعال شود | `3` |
| `XUI_TUNNEL_HEALTH_COOLDOWN` | حداقل تأخیر بین ری‌استارت‌های متوالی | `5m` | | `LUI_TUNNEL_HEALTH_COOLDOWN` | حداقل تأخیر بین ری‌استارت‌های متوالی | `5m` |
## زبان‌های پشتیبانی‌شده ## زبان‌های پشتیبانی‌شده
@@ -179,9 +179,9 @@ English · فارسی · العربية · 中文(简体) · 中文(繁體
## ابزارهای جامعه ## ابزارهای جامعه
ابزارها و یکپارچه‌سازی‌هایی که توسط جامعه پیرامون 3x-ui ساخته شده‌اند. ابزارها و یکپارچه‌سازی‌هایی که توسط جامعه پیرامون L-UI ساخته شده‌اند.
- [terraform-provider-3x-ui](https://github.com/batonogov/terraform-provider-threexui) (مجوز: **MIT**): _مدیریت اینباندها، کلاینت‌ها، تنظیمات پنل و پیکربندی Xray به‌صورت کد با Terraform / OpenTofu._ - [terraform-provider-L-UI](https://github.com/batonogov/terraform-provider-threexui) (مجوز: **MIT**): _مدیریت اینباندها، کلاینت‌ها، تنظیمات پنل و پیکربندی Xray به‌صورت کد با Terraform / OpenTofu._
## پشتیبانی از پروژه ## پشتیبانی از پروژه
+29 -29
View File
@@ -1,71 +1,71 @@
# 3x-ui-agent # L-UI
基于上游 3x-ui v3.7.0 的二次开发 fork:节点 agent 化。节点鸡不再跑完整面板,只跑一个轻量 agent(约 60MB 内存),由主控统一管理、下发 xray 配置。 基于上游 3x-ui v3.7.0 的二次开发 fork:节点 agent 化。节点鸡不再跑完整面板,只跑一个轻量 agent(约 60MB 内存),由主控统一管理、下发 xray 配置。
本仓库托管在自建 Gitea:<https://git.881218.xyz/rogue/3x-ui-agent>,二进制从本仓库的 Releases 下载。**不要**使用上游的一键安装脚本/命令(`install.sh`、`update.sh` 等仍指向原版,会装成上游原版,与本 fork 不兼容)。 本仓库托管在自建 Gitea:<https://git.881218.xyz/rogue/l-ui>,二进制从本仓库的 Releases 下载。**不要**使用上游的一键安装脚本/命令(`install.sh`、`update.sh` 等仍指向原版,会装成上游原版,与本 fork 不兼容)。
## 架构 ## 架构
- **主控**:完整 3x-ui 面板,唯一的配置可信源。管理节点、入站、客户端,下发完整 xray 配置(含出站、路由)到各 agent。 - **主控**:完整 L-UI 面板,唯一的配置可信源。管理节点、入站、客户端,下发完整 xray 配置(含出站、路由)到各 agent。
- **Agent**:跑在节点鸡上,通过注册 token 向主控注册。定时拉取主控下发的 xray 配置并应用,上报心跳和流量。节点下发仅支持 VLESS / SS2022 两类入站(本 fork 的取向)。 - **Agent**:跑在节点鸡上,通过注册 token 向主控注册。定时拉取主控下发的 xray 配置并应用,上报心跳和流量。节点下发仅支持 VLESS / SS2022 两类入站(本 fork 的取向)。
同一个二进制、两种角色:不带参数运行是主控面板,`x-ui agent --config /etc/x-ui/agent.json` 运行是 agent。 同一个二进制、两种角色:不带参数运行是主控面板,`l-ui agent --config /etc/l-ui/agent.json` 运行是 agent。
## 安装 ## 安装
二进制下载:本仓库 [Releases](https://git.881218.xyz/rogue/3x-ui-agent/releases),按架构选 `x-ui-linux-amd64` 或 `x-ui-linux-arm64`。 二进制下载:本仓库 [Releases](https://git.881218.xyz/rogue/l-ui/releases),按架构选 `l-ui-linux-amd64` 或 `l-ui-linux-arm64`。
> 仓库根目录的 `install-master.sh` / `install-agent.sh` 是一键脚本,下载源已迁至本仓 Gitea Releases(tag `v3.7.0-agent.1`),可直接使用;也可按下面步骤手动部署。 > 仓库根目录的 `install-master.sh` / `install-agent.sh` 是一键脚本,下载源已迁至本仓 Gitea Releases(tag `v3.7.0-agent.1`),可直接使用;也可按下面步骤手动部署。
### 主控 ### 主控
```bash ```bash
mkdir -p /usr/local/x-ui/bin /etc/x-ui mkdir -p /usr/local/l-ui/bin /etc/l-ui
# 1. 放主控二进制(Releases 下载的 x-ui-linux-<架构>) # 1. 放主控二进制(Releases 下载的 l-ui-linux-<架构>)
cp x-ui-linux-amd64 /usr/local/x-ui/x-ui && chmod +x /usr/local/x-ui/x-ui cp l-ui-linux-amd64 /usr/local/l-ui/l-ui && chmod +x /usr/local/l-ui/l-ui
# 2. 放 xray 二进制与 geo 文件到 bin/ 子目录 # 2. 放 xray 二进制与 geo 文件到 bin/ 子目录
# 纯控制面部署(节点全走 agent)可禁用本机 xray:不放,或放了之后 chmod -x # 纯控制面部署(节点全走 agent)可禁用本机 xray:不放,或放了之后 chmod -x
cp xray-linux-amd64 /usr/local/x-ui/bin/ cp xray-linux-amd64 /usr/local/l-ui/bin/
cp geoip.dat geosite.dat /usr/local/x-ui/bin/ cp geoip.dat geosite.dat /usr/local/l-ui/bin/
``` ```
启动(二选一): 启动(二选一):
- Debian/Ubuntu(systemd):把仓库的 `x-ui.service.debian` 复制为 `/etc/systemd/system/x-ui.service`,然后 `systemctl daemon-reload && systemctl enable --now x-ui`。 - Debian/Ubuntu(systemd):把仓库的 `l-ui.service.debian` 复制为 `/etc/systemd/system/l-ui.service`,然后 `systemctl daemon-reload && systemctl enable --now l-ui`。
- OpenWrt(procd):用 init 脚本以 `/usr/local/x-ui/x-ui` 为命令启动,工作目录 `/usr/local/x-ui`。 - OpenWrt(procd):用 init 脚本以 `/usr/local/l-ui/l-ui` 为命令启动,工作目录 `/usr/local/l-ui`。
数据库在 `/etc/x-ui/x-ui.db`。面板端口按设置,默认 2053,首次登录默认账号 `admin` / `admin`,请登录后立即修改。 数据库在 `/etc/l-ui/l-ui.db`。面板端口按设置,默认 2053,首次登录默认账号 `admin` / `admin`,请登录后立即修改。
### Agent(节点鸡) ### Agent(节点鸡)
先在主控侧为该节点生成注册 token(建节点 → 用面板 API Token 签发绑定该节点的 agent token,完整步骤见 [docs/AGENT.md](docs/AGENT.md)),然后在节点鸡上: 先在主控侧为该节点生成注册 token(建节点 → 用面板 API Token 签发绑定该节点的 agent token,完整步骤见 [docs/AGENT.md](docs/AGENT.md)),然后在节点鸡上:
```bash ```bash
mkdir -p /usr/local/x-ui/bin /etc/x-ui mkdir -p /usr/local/l-ui/bin /etc/l-ui
# 1. 放同一个二进制(与主控同版本),在节点上改名为 xui-agent(与主控进程区分、避免同机覆盖) # 1. 放同一个二进制(与主控同版本),在节点上改名为 lui-agent(与主控进程区分、避免同机覆盖)
cp x-ui-linux-amd64 /usr/local/x-ui/xui-agent && chmod +x /usr/local/x-ui/xui-agent cp l-ui-linux-amd64 /usr/local/l-ui/lui-agent && chmod +x /usr/local/l-ui/lui-agent
# 2. 放 xray 二进制与 geo 文件(agent 不负责下载,需手动放置) # 2. 放 xray 二进制与 geo 文件(agent 不负责下载,需手动放置)
cp xray-linux-amd64 /usr/local/x-ui/bin/xray && chmod +x /usr/local/x-ui/bin/xray cp xray-linux-amd64 /usr/local/l-ui/bin/xray && chmod +x /usr/local/l-ui/bin/xray
cp geoip.dat geosite.dat /usr/local/x-ui/bin/ cp geoip.dat geosite.dat /usr/local/l-ui/bin/
# 3. 写 agent 配置 # 3. 写 agent 配置
cat > /etc/x-ui/agent.json <<'EOF' cat > /etc/l-ui/agent.json <<'EOF'
{ {
"master_url": "http://主控地址:2053", "master_url": "http://主控地址:2053",
"token": "<主控签发的注册 token>", "token": "<主控签发的注册 token>",
"node_name": "节点名" "node_name": "节点名"
} }
EOF EOF
chmod 600 /etc/x-ui/agent.json chmod 600 /etc/l-ui/agent.json
``` ```
- `master_url` 走内网用 `http://`;走 `https://` 需可信证书(自签连不上)。 - `master_url` 走内网用 `http://`;走 `https://` 需可信证书(自签连不上)。
- agent 另有独立的运行时配置 `config-agent.json`(生成于 `bin/`);`agent.json` 可选 `api_port` 指定 xray stats API 端口(部署口径 62790,metrics 端口为其下一位 62791)。 - agent 另有独立的运行时配置 `config-agent.json`(生成于 `bin/`);`agent.json` 可选 `api_port` 指定 xray stats API 端口(部署口径 62790,metrics 端口为其下一位 62791)。
- 启动:Debian 把仓库的 `systemd/x-ui-agent.service` 复制到 `/etc/systemd/system/` 后 `systemctl enable --now x-ui-agent`;OpenRC 用仓库的 `openrc/x-ui-agent` 放到 `/etc/init.d/x-ui-agent`。 - 启动:Debian 把仓库的 `systemd/lui-agent.service` 复制到 `/etc/systemd/system/` 后 `systemctl enable --now lui-agent`;OpenRC 用仓库的 `openrc/lui-agent` 放到 `/etc/init.d/lui-agent`。
agent 约 30 秒后拉到配置并启动 xray,节点在面板显示在线。更细的 agent 说明(出站/路由下发、验证、故障排查)见 [docs/AGENT.md](docs/AGENT.md)。 agent 约 30 秒后拉到配置并启动 xray,节点在面板显示在线。更细的 agent 说明(出站/路由下发、验证、故障排查)见 [docs/AGENT.md](docs/AGENT.md)。
@@ -74,20 +74,20 @@ agent 约 30 秒后拉到配置并启动 xray,节点在面板显示在线。
### 主控 ### 主控
```bash ```bash
# 先停服务:systemctl disable --now x-ui(或 /etc/init.d/x-ui stop) # 先停服务:systemctl disable --now l-ui(或 /etc/init.d/l-ui stop)
rm -f /etc/systemd/system/x-ui.service # 或删掉对应的 procd init 脚本 rm -f /etc/systemd/system/l-ui.service # 或删掉对应的 procd init 脚本
rm -rf /usr/local/x-ui /etc/x-ui rm -rf /usr/local/l-ui /etc/l-ui
``` ```
### Agent ### Agent
```bash ```bash
# 先停服务:systemctl disable --now x-ui-agent(或 rc-service x-ui-agent stop) # 先停服务:systemctl disable --now lui-agent(或 rc-service lui-agent stop)
rm -f /etc/systemd/system/x-ui-agent.service # 或 /etc/init.d/x-ui-agent rm -f /etc/systemd/system/lui-agent.service # 或 /etc/init.d/lui-agent
rm -rf /usr/local/x-ui /etc/x-ui rm -rf /usr/local/l-ui /etc/l-ui
``` ```
(`/etc/x-ui` 里含数据库与 token 配置,确认不再需要再删。) (`/etc/l-ui` 里含数据库与 token 配置,确认不再需要再删。)
## 使用流程 ## 使用流程
@@ -101,7 +101,7 @@ rm -rf /usr/local/x-ui /etc/x-ui
| | 内存 | | | 内存 |
|---|---| |---|---|
| agent + xray | 约 63MB | | agent + xray | 约 63MB |
| 完整 3x-ui 面板 | 130–160MB | | 完整 L-UI 面板 | 130–160MB |
另有路由器主控精简版构建(剥离 xray-core 库,见仓库内 PANEL-LITE-SPEC.md),面向纯控制面部署,内存显著更低。 另有路由器主控精简版构建(剥离 xray-core 库,见仓库内 PANEL-LITE-SPEC.md),面向纯控制面部署,内存显著更低。
+34 -34
View File
@@ -2,8 +2,8 @@
<p align="center"> <p align="center">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png"> <source media="(prefers-color-scheme: dark)" srcset="./media/L-UI-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png"> <img alt="L-UI" src="./media/L-UI-light.png">
</picture> </picture>
</p> </p>
@@ -64,7 +64,7 @@
## Быстрый старт ## Быстрый старт
```bash ```bash
bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-master.sh) bash <(curl -Ls https://git.881218.xyz/rogue/l-ui/raw/branch/main/install-master.sh)
``` ```
Чтобы установить конкретную версию, добавьте её тег (например, `v3.4.0`): Чтобы установить конкретную версию, добавьте её тег (например, `v3.4.0`):
@@ -79,16 +79,16 @@ bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install
# This fork provides no dev-channel one-click install; see the main README (README.md). # This fork provides no dev-channel one-click install; see the main README (README.md).
``` ```
Во время установки генерируются случайные имя пользователя, пароль и путь доступа. После установки выполните `x-ui`, чтобы открыть меню управления, где можно запускать/останавливать сервис, просматривать или сбрасывать учётные данные для входа, управлять SSL-сертификатами и многое другое. Во время установки генерируются случайные имя пользователя, пароль и путь доступа. После установки выполните `l-ui`, чтобы открыть меню управления, где можно запускать/останавливать сервис, просматривать или сбрасывать учётные данные для входа, управлять SSL-сертификатами и многое другое.
Полную документацию смотрите в [вики проекта](https://git.881218.xyz/rogue/3x-ui-agent). Полную документацию смотрите в [вики проекта](https://git.881218.xyz/rogue/l-ui).
### Автоматическая установка ### Автоматическая установка
Установщик также работает в **неинтерактивном** режиме для cloud-init. Установщик также работает в **неинтерактивном** режиме для cloud-init.
Задайте `XUI_NONINTERACTIVE=1` (или передайте по конвейеру без TTY), и установка пройдёт от начала до конца Задайте `LUI_NONINTERACTIVE=1` (или передайте по конвейеру без TTY), и установка пройдёт от начала до конца
без единого запроса: будут сгенерированы случайные учётные данные и записаны в без единого запроса: будут сгенерированы случайные учётные данные и записаны в
`/etc/x-ui/install-result.env`. Смотрите [`deploy/`](deploy/) для: `/etc/l-ui/install-result.env`. Смотрите [`deploy/`](deploy/) для:
- [Cloud-init user-data](deploy/cloud-init/) — автоматическая установка в любом облаке (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle) - [Cloud-init user-data](deploy/cloud-init/) — автоматическая установка в любом облаке (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle)
- [Заметки по Hetzner Cloud](deploy/marketplace/hetzner/) — развёртывание на Hetzner на базе cloud-init - [Заметки по Hetzner Cloud](deploy/marketplace/hetzner/) — развёртывание на Hetzner на базе cloud-init
@@ -103,29 +103,29 @@ bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install
3X-UI поддерживает два бэкенда, выбираемых при установке: 3X-UI поддерживает два бэкенда, выбираемых при установке:
- **SQLite** (по умолчанию) — единый файл по пути `/etc/x-ui/x-ui.db`. Без настройки, идеально для небольших и средних развёртываний. - **SQLite** (по умолчанию) — единый файл по пути `/etc/l-ui/l-ui.db`. Без настройки, идеально для небольших и средних развёртываний.
- **PostgreSQL** — рекомендуется при большом числе клиентов или конфигурациях с несколькими узлами. Установщик может установить PostgreSQL локально за вас или принять DSN к существующему серверу. - **PostgreSQL** — рекомендуется при большом числе клиентов или конфигурациях с несколькими узлами. Установщик может установить PostgreSQL локально за вас или принять DSN к существующему серверу.
Во время выполнения бэкенд выбирается через переменные окружения (установщик записывает их за вас в `/etc/default/x-ui`): Во время выполнения бэкенд выбирается через переменные окружения (установщик записывает их за вас в `/etc/default/l-ui`):
``` ```
XUI_DB_TYPE=postgres LUI_DB_TYPE=postgres
XUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable LUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable
``` ```
### Перенос существующей установки SQLite в PostgreSQL ### Перенос существующей установки SQLite в PostgreSQL
```bash ```bash
x-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable" l-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable"
# затем задайте XUI_DB_TYPE и XUI_DB_DSN в /etc/default/x-ui и перезапустите: # затем задайте LUI_DB_TYPE и LUI_DB_DSN в /etc/default/l-ui и перезапустите:
systemctl restart x-ui systemctl restart l-ui
``` ```
Исходный файл SQLite остаётся нетронутым; удалите его вручную после проверки нового бэкенда. Исходный файл SQLite остаётся нетронутым; удалите его вручную после проверки нового бэкенда.
### Docker ### Docker
Команда по умолчанию `docker compose up -d` продолжает использовать SQLite. Чтобы запустить со встроенным сервисом PostgreSQL, раскомментируйте две строки переменных окружения `XUI_DB_*` в `docker-compose.yml` и запустите с профилем: Команда по умолчанию `docker compose up -d` продолжает использовать SQLite. Чтобы запустить со встроенным сервисом PostgreSQL, раскомментируйте две строки переменных окружения `LUI_DB_*` в `docker-compose.yml` и запустите с профилем:
```bash ```bash
docker compose --profile postgres up -d docker compose --profile postgres up -d
@@ -134,29 +134,29 @@ docker compose --profile postgres up -d
Образ включает Fail2ban (включён по умолчанию) для применения **лимитов IP** по каждому клиенту. Fail2ban блокирует нарушителей с помощью `iptables`, что требует возможности `NET_ADMIN`. `docker-compose.yml` уже предоставляет её через `cap_add`; если вы вместо этого запускаете контейнер через `docker run`, добавьте возможности самостоятельно, иначе блокировки будут регистрироваться, но никогда не применяться: Образ включает Fail2ban (включён по умолчанию) для применения **лимитов IP** по каждому клиенту. Fail2ban блокирует нарушителей с помощью `iptables`, что требует возможности `NET_ADMIN`. `docker-compose.yml` уже предоставляет её через `cap_add`; если вы вместо этого запускаете контейнер через `docker run`, добавьте возможности самостоятельно, иначе блокировки будут регистрироваться, но никогда не применяться:
```bash ```bash
docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... 3x-ui-agent:local docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... L-UI:local
``` ```
## Переменные окружения ## Переменные окружения
| Переменная | Описание | По умолчанию | | Переменная | Описание | По умолчанию |
| --- | --- | --- | | --- | --- | --- |
| `XUI_DB_TYPE` | Бэкенд базы данных: `sqlite` или `postgres` | `sqlite` | | `LUI_DB_TYPE` | Бэкенд базы данных: `sqlite` или `postgres` | `sqlite` |
| `XUI_DB_DSN` | Строка подключения PostgreSQL (когда `XUI_DB_TYPE=postgres`) | — | | `LUI_DB_DSN` | Строка подключения PostgreSQL (когда `LUI_DB_TYPE=postgres`) | — |
| `XUI_DB_FOLDER` | Каталог для файла базы данных SQLite | `/etc/x-ui` | | `LUI_DB_FOLDER` | Каталог для файла базы данных SQLite | `/etc/l-ui` |
| `XUI_DB_MAX_OPEN_CONNS` | Максимум открытых соединений (пул PostgreSQL) | — | | `LUI_DB_MAX_OPEN_CONNS` | Максимум открытых соединений (пул PostgreSQL) | — |
| `XUI_DB_MAX_IDLE_CONNS` | Максимум простаивающих соединений (пул PostgreSQL) | — | | `LUI_DB_MAX_IDLE_CONNS` | Максимум простаивающих соединений (пул PostgreSQL) | — |
| `XUI_INIT_WEB_BASE_PATH` | Начальный URI-путь для веб-панели | `/` | | `LUI_INIT_WEB_BASE_PATH` | Начальный URI-путь для веб-панели | `/` |
| `XUI_ENABLE_FAIL2BAN` | Включить применение лимитов IP на основе Fail2ban | `true` | | `LUI_ENABLE_FAIL2BAN` | Включить применение лимитов IP на основе Fail2ban | `true` |
| `XUI_LOG_LEVEL` | Уровень логирования (`debug`, `info`, `warning`, `error`) | `info` | | `LUI_LOG_LEVEL` | Уровень логирования (`debug`, `info`, `warning`, `error`) | `info` |
| `XUI_DEBUG` | Включить режим отладки | `false` | | `LUI_DEBUG` | Включить режим отладки | `false` |
| `XUI_TUNNEL_HEALTH_MONITOR` | Включить монитор состояния туннеля (опрашивает URL и перезапускает xray после многократных сбоев; перезапуск отключает всех клиентов) | `false` | | `LUI_TUNNEL_HEALTH_MONITOR` | Включить монитор состояния туннеля (опрашивает URL и перезапускает xray после многократных сбоев; перезапуск отключает всех клиентов) | `false` |
| `XUI_TUNNEL_HEALTH_PROXY` | Прокси, через который отправляется проба; укажите локальный входящий xray, чтобы проба проверяла туннель (например, `socks5://127.0.0.1:1080`). Пустое значение означает, что проба проверяет только связь с хостом | — | | `LUI_TUNNEL_HEALTH_PROXY` | Прокси, через который отправляется проба; укажите локальный входящий xray, чтобы проба проверяла туннель (например, `socks5://127.0.0.1:1080`). Пустое значение означает, что проба проверяет только связь с хостом | — |
| `XUI_TUNNEL_HEALTH_URL` | URL, опрашиваемый для проверки состояния туннеля | `https://www.cloudflare.com/cdn-cgi/trace` | | `LUI_TUNNEL_HEALTH_URL` | URL, опрашиваемый для проверки состояния туннеля | `https://www.cloudflare.com/cdn-cgi/trace` |
| `XUI_TUNNEL_HEALTH_INTERVAL` | Интервал между пробами | `30s` | | `LUI_TUNNEL_HEALTH_INTERVAL` | Интервал между пробами | `30s` |
| `XUI_TUNNEL_HEALTH_TIMEOUT` | Таймаут на одну пробу | `10s` | | `LUI_TUNNEL_HEALTH_TIMEOUT` | Таймаут на одну пробу | `10s` |
| `XUI_TUNNEL_HEALTH_FAILURES` | Число последовательных сбоев до запуска перезапуска | `3` | | `LUI_TUNNEL_HEALTH_FAILURES` | Число последовательных сбоев до запуска перезапуска | `3` |
| `XUI_TUNNEL_HEALTH_COOLDOWN` | Минимальная задержка между последовательными перезапусками | `5m` | | `LUI_TUNNEL_HEALTH_COOLDOWN` | Минимальная задержка между последовательными перезапусками | `5m` |
## Поддерживаемые языки ## Поддерживаемые языки
@@ -179,9 +179,9 @@ English · فارسی · العربية · 中文(简体) · 中文(繁體
## Инструменты сообщества ## Инструменты сообщества
Инструменты и интеграции, созданные сообществом вокруг 3x-ui. Инструменты и интеграции, созданные сообществом вокруг L-UI.
- [terraform-provider-3x-ui](https://github.com/batonogov/terraform-provider-threexui) (Лицензия: **MIT**): _Управление входящими, клиентами, настройками панели и конфигурацией Xray через код с помощью Terraform / OpenTofu._ - [terraform-provider-L-UI](https://github.com/batonogov/terraform-provider-threexui) (Лицензия: **MIT**): _Управление входящими, клиентами, настройками панели и конфигурацией Xray через код с помощью Terraform / OpenTofu._
## Поддержка проекта ## Поддержка проекта
+34 -34
View File
@@ -2,8 +2,8 @@
<p align="center"> <p align="center">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png"> <source media="(prefers-color-scheme: dark)" srcset="./media/L-UI-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png"> <img alt="L-UI" src="./media/L-UI-light.png">
</picture> </picture>
</p> </p>
@@ -64,7 +64,7 @@ Orijinal X-UI projesinin geliştirilmiş bir çatallaması (fork) olarak inşa e
## Hızlı Başlangıç ## Hızlı Başlangıç
```bash ```bash
bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-master.sh) bash <(curl -Ls https://git.881218.xyz/rogue/l-ui/raw/branch/main/install-master.sh)
``` ```
Belirli bir sürümü kurmak için, etiketini (ör. `v3.4.0`) ekleyin: Belirli bir sürümü kurmak için, etiketini (ör. `v3.4.0`) ekleyin:
@@ -79,16 +79,16 @@ Sürekli güncellenen **dev** sürümünü (kararlı bir sürüm değil; `main`
# This fork provides no dev-channel one-click install; see the main README (README.md). # This fork provides no dev-channel one-click install; see the main README (README.md).
``` ```
Kurulum sırasında rastgele bir kullanıcı adı, şifre ve erişim yolu oluşturulur. Kurulumdan sonra, hizmeti başlatabileceğiniz/durdurabileceğiniz, giriş bilgilerinizi görüntüleyebileceğiniz veya sıfırlayabileceğiniz, SSL sertifikalarını yönetebileceğiniz ve çok daha fazlasını yapabileceğiniz yönetim menüsünü açmak için terminalde `x-ui` komutunu çalıştırın. Kurulum sırasında rastgele bir kullanıcı adı, şifre ve erişim yolu oluşturulur. Kurulumdan sonra, hizmeti başlatabileceğiniz/durdurabileceğiniz, giriş bilgilerinizi görüntüleyebileceğiniz veya sıfırlayabileceğiniz, SSL sertifikalarını yönetebileceğiniz ve çok daha fazlasını yapabileceğiniz yönetim menüsünü açmak için terminalde `l-ui` komutunu çalıştırın.
Tam dokümantasyon için lütfen [proje Wiki sayfasını](https://git.881218.xyz/rogue/3x-ui-agent) ziyaret edin. Tam dokümantasyon için lütfen [proje Wiki sayfasını](https://git.881218.xyz/rogue/l-ui) ziyaret edin.
### Etkileşimsiz kurulum ### Etkileşimsiz kurulum
Yükleyici, cloud-init için **etkileşimsiz** olarak da çalışır. Yükleyici, cloud-init için **etkileşimsiz** olarak da çalışır.
`XUI_NONINTERACTIVE=1` ayarlayın (veya TTY olmadan boru hattına aktarın); kurulum baştan `LUI_NONINTERACTIVE=1` ayarlayın (veya TTY olmadan boru hattına aktarın); kurulum baştan
sona hiçbir soru sormadan tamamlanır, rastgele kimlik bilgileri oluşturup bunları sona hiçbir soru sormadan tamamlanır, rastgele kimlik bilgileri oluşturup bunları
`/etc/x-ui/install-result.env` dosyasına yazar. Şunlar için [`deploy/`](deploy/) klasörüne bakın: `/etc/l-ui/install-result.env` dosyasına yazar. Şunlar için [`deploy/`](deploy/) klasörüne bakın:
- [Cloud-init user-data](deploy/cloud-init/) — herhangi bir bulutta etkileşimsiz kurulum (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle) - [Cloud-init user-data](deploy/cloud-init/) — herhangi bir bulutta etkileşimsiz kurulum (Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle)
- [Hetzner Cloud notları](deploy/marketplace/hetzner/) — Hetzner üzerinde cloud-init tabanlı dağıtım - [Hetzner Cloud notları](deploy/marketplace/hetzner/) — Hetzner üzerinde cloud-init tabanlı dağıtım
@@ -103,29 +103,29 @@ sona hiçbir soru sormadan tamamlanır, rastgele kimlik bilgileri oluşturup bun
3X-UI kurulum sırasında seçilebilecek iki arka uç (backend) destekler: 3X-UI kurulum sırasında seçilebilecek iki arka uç (backend) destekler:
- **SQLite** (varsayılan) — `/etc/x-ui/x-ui.db` konumunda tek bir dosya. Kurulum gerektirmez, küçük ve orta ölçekli dağıtımlar için idealdir. - **SQLite** (varsayılan) — `/etc/l-ui/l-ui.db` konumunda tek bir dosya. Kurulum gerektirmez, küçük ve orta ölçekli dağıtımlar için idealdir.
- **PostgreSQL** — Yüksek kullanıcı sayıları veya çoklu düğüm (multi-node) kurulumları için önerilir. Yükleyici sizin için yerel olarak PostgreSQL kurabilir veya mevcut bir sunucuya DSN bağlantısı kabul edebilir. - **PostgreSQL** — Yüksek kullanıcı sayıları veya çoklu düğüm (multi-node) kurulumları için önerilir. Yükleyici sizin için yerel olarak PostgreSQL kurabilir veya mevcut bir sunucuya DSN bağlantısı kabul edebilir.
Çalışma anında veritabanı türü ortam değişkenleri (environment variables) ile seçilir (yükleyici bunları sizin için `/etc/default/x-ui` dosyasına yazar): Çalışma anında veritabanı türü ortam değişkenleri (environment variables) ile seçilir (yükleyici bunları sizin için `/etc/default/l-ui` dosyasına yazar):
``` ```
XUI_DB_TYPE=postgres LUI_DB_TYPE=postgres
XUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable LUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable
``` ```
### Mevcut bir SQLite Kurulumunu PostgreSQL'e Taşıma ### Mevcut bir SQLite Kurulumunu PostgreSQL'e Taşıma
```bash ```bash
x-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable" l-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable"
# ardından /etc/default/x-ui içindeki XUI_DB_TYPE ve XUI_DB_DSN değerlerini ayarlayıp yeniden başlatın: # ardından /etc/default/l-ui içindeki LUI_DB_TYPE ve LUI_DB_DSN değerlerini ayarlayıp yeniden başlatın:
systemctl restart x-ui systemctl restart l-ui
``` ```
Kaynak SQLite dosyasına dokunulmaz; yeni veritabanının düzgün çalıştığını doğruladıktan sonra eski SQLite dosyasını manuel olarak silebilirsiniz. Kaynak SQLite dosyasına dokunulmaz; yeni veritabanının düzgün çalıştığını doğruladıktan sonra eski SQLite dosyasını manuel olarak silebilirsiniz.
### Docker ### Docker
Varsayılan `docker compose up -d` komutu SQLite kullanmaya devam eder. Birlikte paketlenmiş PostgreSQL servisi ile çalıştırmak için, `docker-compose.yml` dosyasındaki iki `XUI_DB_*` değişken satırının yorumunu kaldırın ve profille başlatın: Varsayılan `docker compose up -d` komutu SQLite kullanmaya devam eder. Birlikte paketlenmiş PostgreSQL servisi ile çalıştırmak için, `docker-compose.yml` dosyasındaki iki `LUI_DB_*` değişken satırının yorumunu kaldırın ve profille başlatın:
```bash ```bash
docker compose --profile postgres up -d docker compose --profile postgres up -d
@@ -134,29 +134,29 @@ docker compose --profile postgres up -d
Docker imajı, kullanıcı başına **IP limitlerini** zorunlu kılmak için Fail2ban ile (varsayılan olarak etkindir) paketlenmiştir. Fail2ban, ihlalcileri `iptables` ile engeller ve bunun için `NET_ADMIN` yetkisine ihtiyaç duyar. `docker-compose.yml` bunu zaten `cap_add` üzerinden vermektedir; ancak konteyneri bunun yerine `docker run` ile başlatırsanız bu yetkileri kendiniz eklemelisiniz, aksi takdirde yasaklamalar günlüğe kaydedilir ancak uygulanmaz: Docker imajı, kullanıcı başına **IP limitlerini** zorunlu kılmak için Fail2ban ile (varsayılan olarak etkindir) paketlenmiştir. Fail2ban, ihlalcileri `iptables` ile engeller ve bunun için `NET_ADMIN` yetkisine ihtiyaç duyar. `docker-compose.yml` bunu zaten `cap_add` üzerinden vermektedir; ancak konteyneri bunun yerine `docker run` ile başlatırsanız bu yetkileri kendiniz eklemelisiniz, aksi takdirde yasaklamalar günlüğe kaydedilir ancak uygulanmaz:
```bash ```bash
docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... 3x-ui-agent:local docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... L-UI:local
``` ```
## Ortam Değişkenleri (Environment Variables) ## Ortam Değişkenleri (Environment Variables)
| Değişken | Açıklama | Varsayılan | | Değişken | Açıklama | Varsayılan |
| --- | --- | --- | | --- | --- | --- |
| `XUI_DB_TYPE` | Veritabanı türü: `sqlite` veya `postgres` | `sqlite` | | `LUI_DB_TYPE` | Veritabanı türü: `sqlite` veya `postgres` | `sqlite` |
| `XUI_DB_DSN` | PostgreSQL bağlantı dizesi (eğer `XUI_DB_TYPE=postgres` ise) | — | | `LUI_DB_DSN` | PostgreSQL bağlantı dizesi (eğer `LUI_DB_TYPE=postgres` ise) | — |
| `XUI_DB_FOLDER` | SQLite veritabanı dizini | `/etc/x-ui` | | `LUI_DB_FOLDER` | SQLite veritabanı dizini | `/etc/l-ui` |
| `XUI_DB_MAX_OPEN_CONNS` | Maksimum açık bağlantı sayısı (PostgreSQL havuzu) | — | | `LUI_DB_MAX_OPEN_CONNS` | Maksimum açık bağlantı sayısı (PostgreSQL havuzu) | — |
| `XUI_DB_MAX_IDLE_CONNS` | Maksimum boşta bekleme bağlantısı (PostgreSQL havuzu) | — | | `LUI_DB_MAX_IDLE_CONNS` | Maksimum boşta bekleme bağlantısı (PostgreSQL havuzu) | — |
| `XUI_INIT_WEB_BASE_PATH` | Web paneli için başlangıç URI yolu | `/` | | `LUI_INIT_WEB_BASE_PATH` | Web paneli için başlangıç URI yolu | `/` |
| `XUI_ENABLE_FAIL2BAN` | Fail2ban tabanlı IP limit uygulamasını etkinleştir | `true` | | `LUI_ENABLE_FAIL2BAN` | Fail2ban tabanlı IP limit uygulamasını etkinleştir | `true` |
| `XUI_LOG_LEVEL` | Günlük (Log) ayrıntı seviyesi (`debug`, `info`, `warning`, `error`) | `info` | | `LUI_LOG_LEVEL` | Günlük (Log) ayrıntı seviyesi (`debug`, `info`, `warning`, `error`) | `info` |
| `XUI_DEBUG` | Hata ayıklama (debug) modunu etkinleştir | `false` | | `LUI_DEBUG` | Hata ayıklama (debug) modunu etkinleştir | `false` |
| `XUI_TUNNEL_HEALTH_MONITOR` | Tünel sağlık izleyicisini etkinleştir (bir URL'yi yoklar ve tekrarlanan başarısızlıklardan sonra xray'i yeniden başlatır; yeniden başlatma tüm istemcilerin bağlantısını düşürür) | `false` | | `LUI_TUNNEL_HEALTH_MONITOR` | Tünel sağlık izleyicisini etkinleştir (bir URL'yi yoklar ve tekrarlanan başarısızlıklardan sonra xray'i yeniden başlatır; yeniden başlatma tüm istemcilerin bağlantısını düşürür) | `false` |
| `XUI_TUNNEL_HEALTH_PROXY` | Yoklamanın gönderildiği proxy; yoklamanın tüneli test etmesi için bunu yerel bir xray gelen bağlantısına yönlendirin (ör. `socks5://127.0.0.1:1080`). Boş bırakılırsa yoklama yalnızca ana makine bağlantısını kontrol eder | — | | `LUI_TUNNEL_HEALTH_PROXY` | Yoklamanın gönderildiği proxy; yoklamanın tüneli test etmesi için bunu yerel bir xray gelen bağlantısına yönlendirin (ör. `socks5://127.0.0.1:1080`). Boş bırakılırsa yoklama yalnızca ana makine bağlantısını kontrol eder | — |
| `XUI_TUNNEL_HEALTH_URL` | Tünel sağlığı için yoklanan URL | `https://www.cloudflare.com/cdn-cgi/trace` | | `LUI_TUNNEL_HEALTH_URL` | Tünel sağlığı için yoklanan URL | `https://www.cloudflare.com/cdn-cgi/trace` |
| `XUI_TUNNEL_HEALTH_INTERVAL` | Yoklamalar arasındaki aralık | `30s` | | `LUI_TUNNEL_HEALTH_INTERVAL` | Yoklamalar arasındaki aralık | `30s` |
| `XUI_TUNNEL_HEALTH_TIMEOUT` | Yoklama başına zaman aşımı | `10s` | | `LUI_TUNNEL_HEALTH_TIMEOUT` | Yoklama başına zaman aşımı | `10s` |
| `XUI_TUNNEL_HEALTH_FAILURES` | Yeniden başlatma tetiklenmeden önceki ardışık başarısızlık sayısı | `3` | | `LUI_TUNNEL_HEALTH_FAILURES` | Yeniden başlatma tetiklenmeden önceki ardışık başarısızlık sayısı | `3` |
| `XUI_TUNNEL_HEALTH_COOLDOWN` | Ardışık yeniden başlatmalar arasındaki minimum gecikme | `5m` | | `LUI_TUNNEL_HEALTH_COOLDOWN` | Ardışık yeniden başlatmalar arasındaki minimum gecikme | `5m` |
## Desteklenen Diller ## Desteklenen Diller
@@ -179,9 +179,9 @@ Katkılarınızı her zaman bekliyoruz. Bir sorun (issue) açmadan veya pull req
## Topluluk Araçları ## Topluluk Araçları
3x-ui çevresindeki topluluk tarafından oluşturulmuş araçlar ve entegrasyonlar. L-UI çevresindeki topluluk tarafından oluşturulmuş araçlar ve entegrasyonlar.
- [terraform-provider-3x-ui](https://github.com/batonogov/terraform-provider-threexui) (Lisans: **MIT**): _Gelen bağlantılarnı, kullanıcıları, panel ayarlarını ve Xray yapılandırmasını Terraform / OpenTofu ile kod olarak (as code) yönetin._ - [terraform-provider-L-UI](https://github.com/batonogov/terraform-provider-threexui) (Lisans: **MIT**): _Gelen bağlantılarnı, kullanıcıları, panel ayarlarını ve Xray yapılandırmasını Terraform / OpenTofu ile kod olarak (as code) yönetin._
## Projeyi Destekleyin ## Projeyi Destekleyin
+34 -34
View File
@@ -2,8 +2,8 @@
<p align="center"> <p align="center">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="./media/3x-ui-dark.png"> <source media="(prefers-color-scheme: dark)" srcset="./media/L-UI-dark.png">
<img alt="3x-ui" src="./media/3x-ui-light.png"> <img alt="L-UI" src="./media/L-UI-light.png">
</picture> </picture>
</p> </p>
@@ -65,7 +65,7 @@
## 快速开始 ## 快速开始
```bash ```bash
bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-master.sh) bash <(curl -Ls https://git.881218.xyz/rogue/l-ui/raw/branch/main/install-master.sh)
``` ```
若要安装特定版本,请在命令后附加对应的标签(例如 `v3.4.0`): 若要安装特定版本,请在命令后附加对应的标签(例如 `v3.4.0`):
@@ -80,16 +80,16 @@ bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install
# This fork provides no dev-channel one-click install; see the main README (README.md). # This fork provides no dev-channel one-click install; see the main README (README.md).
``` ```
安装过程中会生成随机的用户名、密码和访问路径。安装完成后,运行 `x-ui` 打开管理菜单,您可以在其中启动/停止服务、查看或重置登录凭据、管理 SSL 证书等。 安装过程中会生成随机的用户名、密码和访问路径。安装完成后,运行 `l-ui` 打开管理菜单,您可以在其中启动/停止服务、查看或重置登录凭据、管理 SSL 证书等。
完整文档请参阅 [项目Wiki](https://git.881218.xyz/rogue/3x-ui-agent)。 完整文档请参阅 [项目Wiki](https://git.881218.xyz/rogue/l-ui)。
### 无人值守安装 ### 无人值守安装
安装程序也可以**非交互式**运行,适用于 cloud-init。 安装程序也可以**非交互式**运行,适用于 cloud-init。
设置 `XUI_NONINTERACTIVE=1`(或在无 TTY 的情况下通过管道传入),它就会全程 设置 `LUI_NONINTERACTIVE=1`(或在无 TTY 的情况下通过管道传入),它就会全程
零提示地完成端到端安装,生成随机凭据并写入 零提示地完成端到端安装,生成随机凭据并写入
`/etc/x-ui/install-result.env`。请参阅 [`deploy/`](deploy/): `/etc/l-ui/install-result.env`。请参阅 [`deploy/`](deploy/):
- [Cloud-init user-data](deploy/cloud-init/) — 在任意云平台上无人值守安装(Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle) - [Cloud-init user-data](deploy/cloud-init/) — 在任意云平台上无人值守安装(Hetzner/AWS/DO/Vultr/GCP/Azure/Oracle)
- [Hetzner Cloud 说明](deploy/marketplace/hetzner/) — 在 Hetzner 上基于 cloud-init 的部署 - [Hetzner Cloud 说明](deploy/marketplace/hetzner/) — 在 Hetzner 上基于 cloud-init 的部署
@@ -104,29 +104,29 @@ bash <(curl -Ls https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install
3X-UI 支持两种后端,可在安装时选择: 3X-UI 支持两种后端,可在安装时选择:
- **SQLite**(默认)— 位于 `/etc/x-ui/x-ui.db` 的单个文件。无需配置,适合中小型部署。 - **SQLite**(默认)— 位于 `/etc/l-ui/l-ui.db` 的单个文件。无需配置,适合中小型部署。
- **PostgreSQL** — 推荐用于大量客户端或多节点设置。安装程序可以为您在本地安装 PostgreSQL,或接受指向现有服务器的 DSN。 - **PostgreSQL** — 推荐用于大量客户端或多节点设置。安装程序可以为您在本地安装 PostgreSQL,或接受指向现有服务器的 DSN。
运行时通过环境变量选择后端(安装程序会为您写入 `/etc/default/x-ui`): 运行时通过环境变量选择后端(安装程序会为您写入 `/etc/default/l-ui`):
``` ```
XUI_DB_TYPE=postgres LUI_DB_TYPE=postgres
XUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable LUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable
``` ```
### 将现有的 SQLite 安装迁移到 PostgreSQL ### 将现有的 SQLite 安装迁移到 PostgreSQL
```bash ```bash
x-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable" l-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable"
# 然后在 /etc/default/x-ui 中设置 XUI_DB_TYPE 和 XUI_DB_DSN 并重启: # 然后在 /etc/default/l-ui 中设置 LUI_DB_TYPE 和 LUI_DB_DSN 并重启:
systemctl restart x-ui systemctl restart l-ui
``` ```
源 SQLite 文件保持不变;在确认新后端正常工作后,请手动删除它。 源 SQLite 文件保持不变;在确认新后端正常工作后,请手动删除它。
### Docker ### Docker
默认的 `docker compose up -d` 仍使用 SQLite。若要使用捆绑的 PostgreSQL 服务运行,请取消注释 `docker-compose.yml` 中的两行 `XUI_DB_*` 环境变量,并使用该 profile 启动: 默认的 `docker compose up -d` 仍使用 SQLite。若要使用捆绑的 PostgreSQL 服务运行,请取消注释 `docker-compose.yml` 中的两行 `LUI_DB_*` 环境变量,并使用该 profile 启动:
```bash ```bash
docker compose --profile postgres up -d docker compose --profile postgres up -d
@@ -135,29 +135,29 @@ docker compose --profile postgres up -d
该镜像捆绑了 Fail2ban(默认启用),用于强制执行按客户端的 **IP 限制**。Fail2ban 使用 `iptables` 封禁违规者,这需要 `NET_ADMIN` 权限。`docker-compose.yml` 已通过 `cap_add` 授予该权限;如果您改用 `docker run` 启动容器,请自行添加这些权限,否则封禁只会被记录而永远不会生效: 该镜像捆绑了 Fail2ban(默认启用),用于强制执行按客户端的 **IP 限制**。Fail2ban 使用 `iptables` 封禁违规者,这需要 `NET_ADMIN` 权限。`docker-compose.yml` 已通过 `cap_add` 授予该权限;如果您改用 `docker run` 启动容器,请自行添加这些权限,否则封禁只会被记录而永远不会生效:
```bash ```bash
docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... 3x-ui-agent:local docker run -d --cap-add=NET_ADMIN --cap-add=NET_RAW ... L-UI:local
``` ```
## 环境变量 ## 环境变量
| 变量 | 说明 | 默认值 | | 变量 | 说明 | 默认值 |
| --- | --- | --- | | --- | --- | --- |
| `XUI_DB_TYPE` | 数据库后端:`sqlite` 或 `postgres` | `sqlite` | | `LUI_DB_TYPE` | 数据库后端:`sqlite` 或 `postgres` | `sqlite` |
| `XUI_DB_DSN` | PostgreSQL 连接字符串(当 `XUI_DB_TYPE=postgres` 时) | — | | `LUI_DB_DSN` | PostgreSQL 连接字符串(当 `LUI_DB_TYPE=postgres` 时) | — |
| `XUI_DB_FOLDER` | SQLite 数据库文件所在目录 | `/etc/x-ui` | | `LUI_DB_FOLDER` | SQLite 数据库文件所在目录 | `/etc/l-ui` |
| `XUI_DB_MAX_OPEN_CONNS` | 最大打开连接数(PostgreSQL 连接池) | — | | `LUI_DB_MAX_OPEN_CONNS` | 最大打开连接数(PostgreSQL 连接池) | — |
| `XUI_DB_MAX_IDLE_CONNS` | 最大空闲连接数(PostgreSQL 连接池) | — | | `LUI_DB_MAX_IDLE_CONNS` | 最大空闲连接数(PostgreSQL 连接池) | — |
| `XUI_INIT_WEB_BASE_PATH` | Web 面板的初始 URI 路径 | `/` | | `LUI_INIT_WEB_BASE_PATH` | Web 面板的初始 URI 路径 | `/` |
| `XUI_ENABLE_FAIL2BAN` | 启用基于 Fail2ban 的 IP 限制 | `true` | | `LUI_ENABLE_FAIL2BAN` | 启用基于 Fail2ban 的 IP 限制 | `true` |
| `XUI_LOG_LEVEL` | 日志级别(`debug`、`info`、`warning`、`error`) | `info` | | `LUI_LOG_LEVEL` | 日志级别(`debug`、`info`、`warning`、`error`) | `info` |
| `XUI_DEBUG` | 启用调试模式 | `false` | | `LUI_DEBUG` | 启用调试模式 | `false` |
| `XUI_TUNNEL_HEALTH_MONITOR` | 启用隧道健康监控(探测某个 URL,在连续多次失败后重启 xray;重启会断开所有客户端) | `false` | | `LUI_TUNNEL_HEALTH_MONITOR` | 启用隧道健康监控(探测某个 URL,在连续多次失败后重启 xray;重启会断开所有客户端) | `false` |
| `XUI_TUNNEL_HEALTH_PROXY` | 探测请求所经过的代理;将其指向本地 xray 入站,使探测能够测试隧道(例如 `socks5://127.0.0.1:1080`)。留空表示探测仅检查主机连通性 | — | | `LUI_TUNNEL_HEALTH_PROXY` | 探测请求所经过的代理;将其指向本地 xray 入站,使探测能够测试隧道(例如 `socks5://127.0.0.1:1080`)。留空表示探测仅检查主机连通性 | — |
| `XUI_TUNNEL_HEALTH_URL` | 用于检测隧道健康状况的探测 URL | `https://www.cloudflare.com/cdn-cgi/trace` | | `LUI_TUNNEL_HEALTH_URL` | 用于检测隧道健康状况的探测 URL | `https://www.cloudflare.com/cdn-cgi/trace` |
| `XUI_TUNNEL_HEALTH_INTERVAL` | 两次探测之间的间隔 | `30s` | | `LUI_TUNNEL_HEALTH_INTERVAL` | 两次探测之间的间隔 | `30s` |
| `XUI_TUNNEL_HEALTH_TIMEOUT` | 单次探测的超时时间 | `10s` | | `LUI_TUNNEL_HEALTH_TIMEOUT` | 单次探测的超时时间 | `10s` |
| `XUI_TUNNEL_HEALTH_FAILURES` | 触发重启前的连续失败次数 | `3` | | `LUI_TUNNEL_HEALTH_FAILURES` | 触发重启前的连续失败次数 | `3` |
| `XUI_TUNNEL_HEALTH_COOLDOWN` | 两次连续重启之间的最小间隔 | `5m` | | `LUI_TUNNEL_HEALTH_COOLDOWN` | 两次连续重启之间的最小间隔 | `5m` |
## 支持的语言 ## 支持的语言
@@ -180,9 +180,9 @@ English · فارسی · العربية · 中文(简体) · 中文(繁體
## 社区工具 ## 社区工具
社区围绕 3x-ui 构建的工具和集成。 社区围绕 L-UI 构建的工具和集成。
- [terraform-provider-3x-ui](https://github.com/batonogov/terraform-provider-threexui) (许可证: **MIT**): _使用 Terraform / OpenTofu 通过代码管理入站、客户端、面板设置和 Xray 配置。_ - [terraform-provider-L-UI](https://github.com/batonogov/terraform-provider-threexui) (许可证: **MIT**): _使用 Terraform / OpenTofu 通过代码管理入站、客户端、面板设置和 Xray 配置。_
## 支持项目 ## 支持项目
+195
View File
@@ -0,0 +1,195 @@
# Renaming: 3x-ui / x-ui → L-UI / l-ui / lui-agent
Base: `8158ced` (panel V2.6.0 / agent A2.5.0). This batch is a pure
rename: **no version bump, no feature change, no production change,
no Gitea change, no release**. Versions stay V2.6.0 / A2.5.0; the
version bump is left to the release step (see Pending below).
## Mapping (exact — do not invent other aliases)
| old | new | where it shows up |
| --- | --- | --- |
| display brand `3x-ui` / `x-ui` | `L-UI` | panel UI, i18n, README, docs |
| panel binary / process | `l-ui` | release asset, `ps`, `/usr/bin/l-ui` (Docker), `l-ui setting …` |
| agent binary / process | `lui-agent` | release asset, `ps`, `lui-agent agent …` |
| install dir | `/usr/local/l-ui` | panel + agent binaries |
| config / state dir | `/etc/l-ui` | `agent.json`, `node_token_key.json`, env files |
| panel DB | `/etc/l-ui/l-ui.db` | driven by `internal/config/name` (`l-ui`) via `GetName()` + `GetDBFolderPath()` — no separate DB-name constant |
| probe DB | `/etc/l-ui/probe.db` | name unchanged, directory moved (`probe/store.go` joins `GetDBFolderPath()`) |
| cert dir | `/etc/l-ui/cert` | panel + subscription share it |
| binary dir | `/usr/local/l-ui/bin` | `DefaultBinFolder`; sing-box live config `config-singbox.json` lives here |
| log dir | `/var/log/l-ui` | panel log, agent log, sing-box log |
| panel service | `l-ui.service` | systemd units `l-ui.service.{debian,arch,rhel}`, OpenRC `l-ui.rc` |
| agent service | `lui-agent.service` | `systemd/lui-agent.service`, OpenRC `openrc/lui-agent` |
| management CLI | `l-ui.sh` | was `x-ui.sh`; Docker copies it to `/usr/bin/l-ui` |
| panel release assets | `l-ui-linux-amd64`, `l-ui-linux-arm64` (+ `.sha256`) | `scripts/release-build.sh`, `selfupdate.AssetName` |
| agent release assets | `lui-agent-linux-amd64`, `lui-agent-linux-arm64` (+ `.sha256`) | `scripts/release-build.sh`, `selfupdate.AgentAssetName` |
| agent version marker | `agent-version.txt` | name unchanged |
| env prefix | `LUI_` | every `XUI_` variable, code + scripts + docs + tests (inventory below) |
| source dir (Linux agent) | `cmd/lui-agent` | was `cmd/xui-agent`; `release-build.sh` builds `./cmd/lui-agent` |
| Gitea repo (PLACEHOLDER) | `rogue/l-ui` | see Pending — **not yet real** |
## Environment variables renamed
Code reads **only** the new `LUI_` prefix. There is no dual-read
fallback in code: an old unit file that still exports `XUI_*` will
silently lose those settings, which is why the migration doc
(`docs/migration-l-ui.md`) has an explicit unit-env translation
table. Old units must be replaced, not edited in place.
Full inventory (from a whole-tree scan; `LUI_DB_*` below is a docs
glob, not a variable):
`LUI_ACCESS_URL`, `LUI_ACME_EMAIL`, `LUI_ACME_HTTP_PORT`,
`LUI_API_TOKEN`, `LUI_B1_OLD_BACKUP`, `LUI_B2_OLD_DB`,
`LUI_BIN_FOLDER`, `LUI_DB_CACHE_MB`, `LUI_DB_DSN`,
`LUI_DB_FOLDER`, `LUI_DB_JOURNAL_MODE`, `LUI_DB_MAX_IDLE_CONNS`,
`LUI_DB_MAX_OPEN_CONNS`, `LUI_DB_MMAP_MB`, `LUI_DB_SYNCHRONOUS`,
`LUI_DB_TYPE`, `LUI_DEBUG`, `LUI_DOMAIN`, `LUI_ENABLE_FAIL2BAN`,
`LUI_GOGC`, `LUI_HOME` (install-agent.sh only), `LUI_INIT_SYSTEM`
(install-agent.sh only), `LUI_INIT_WEB_BASE_PATH`, `LUI_IN_DOCKER`,
`LUI_LOG_FOLDER`, `LUI_LOG_LEVEL`, `LUI_MAIN_FOLDER`,
`LUI_MEMORY_LIMIT`, `LUI_MEMORY_RELEASE_INTERVAL`,
`LUI_NODE_TOKEN_KEY`, `LUI_NODE_TOKEN_KEY_FILE`,
`LUI_NODE_TOKEN_KEY_TEST`, `LUI_NONINTERACTIVE`,
`LUI_ORPHAN_DUMMY`, `LUI_PANEL_PORT`, `LUI_PASSWORD`, `LUI_PORT`,
`LUI_PPROF`, `LUI_RELEASE_BASE_URL`, `LUI_RELEASE_LATEST_URL`,
`LUI_ROOT` (install-agent.sh only), `LUI_SCALE_DB_PATH`,
`LUI_SCALE_SIZES`, `LUI_SCALE_TEST`, `LUI_SELFUPDATE_SYSTEMD`,
`LUI_SERVER_IP`, `LUI_SERVICE`, `LUI_SERVICE_NAME`,
`LUI_SINGBOX_BIN`, `LUI_SKIP_HSTS`, `LUI_SMOKE_VERSION`,
`LUI_SOURCEMAP`, `LUI_SSL_IPV6`, `LUI_SSL_MODE`,
`LUI_TEST_PG_DSN`, `LUI_TUNNEL_HEALTH_COOLDOWN`,
`LUI_TUNNEL_HEALTH_FAILURES`, `LUI_TUNNEL_HEALTH_INTERVAL`,
`LUI_TUNNEL_HEALTH_MONITOR`, `LUI_TUNNEL_HEALTH_PROXY`,
`LUI_TUNNEL_HEALTH_TIMEOUT`, `LUI_TUNNEL_HEALTH_URL`,
`LUI_UPDATE_RUN_ID`, `LUI_UPDATE_STATUS_FILE`, `LUI_UPDATE_TAG`,
`LUI_URL` (install scripts only), `LUI_USERNAME`,
`LUI_WEB_BASE_PATH`.
## sing-box orphan-core check (special re-verification)
The orphan scan (`internal/agent/singbox.go`,
`singboxCmdlineMatchesConfig`) matches a core process by the exact
argv triple `run -c <live config path>`. Both sides use the same
source: the live path is `filepath.Join(config.GetBinFolderPath(),
"config-singbox.json")`, and the agent sets `LUI_BIN_FOLDER` to
`DefaultBinFolder` (`/usr/local/l-ui/bin`) when unset. So the rename
propagates to both the writer and the matcher automatically; there
is no hardcoded old path in `singbox.go`. After migration the only
cores the new agent will reap are cores started with
`/usr/local/l-ui/bin/config-singbox.json` — a core still running
the old `/usr/local/x-ui/bin/config-singbox.json` is **not** matched
and must be killed by the migration step (see migration doc), or it
will hold the inbound ports and the new core will fail to bind.
This is the one place where "rename both sides" is not enough: the
old core has to be stopped, not re-adopted.
## Tianyi update badge (same batch, panel side only)
- Backend: `NodeView.agentOs` (from `AgentNode.ProbeOS`), overlaid
in `annotateAgentTelemetry` ahead of the telemetry early-exit,
like `ProbeOnly`.
- Frontend: both badge sites in `NodeList.tsx` (list column +
detail) now gate on `!isWindowsAgentOS(agentOs)`, where the
helper (in `panel-version.ts`) is a case-insensitive `windows`
prefix test. Empty OS fails open (badge as before).
- Backend: `requestAgentUpdate` refuses Windows rows up front
("not available on Windows … re-running install-agent.ps1")
instead of recording an intent that would only age out. The
one-click action button itself is unchanged; clicking it on a
Windows row now errors clearly.
- Why ProbeOS is reliable: the frozen A2.2.1 Windows agent reports
`probeFacts.os` = `winOSName()` — registry ProductName
("Windows 10", "Windows 11", …) with DisplayVersion appended,
falling back to bare "Windows" — on register and on heartbeat,
and the panel persists it to `probe_os` (pinned by
`TestAgentLegacyWindows221Contract`). No fake version, no
per-node freeze switch, no Windows agent change, no new win asset.
- Tianyi's machine itself is untouched; its agent stays A2.2.1.
## Intentionally kept (not omissions)
- **Go module path `github.com/mhsanaei/3x-ui/v3`** — the upstream
import path. Renaming it would break every import and the
`-ldflags -X` injection paths; it is not user-visible.
- **Upstream mentions** — sentences that name the upstream original
("upstream 3x-ui", "stock 3x-ui", "based on upstream 3x-ui",
`ghcr.io/mhsanaei/3x-ui`, `raw.githubusercontent.com/mhsanaei/3x-ui`)
stay, because that is the upstream project's actual name.
- **Windows agent, frozen** — `cmd/xui-agent-windows/` untouched:
service name `x-ui-agent`, `C:\x-ui\agent.json`, display name
"3x-ui Agent", `x-ui-agent-windows.exe`. The shipped A2.2.1
binary cannot change without a new win release, which this batch
explicitly does not ship. Renaming its source would only make
the source lie about the shipped binary.
- **`install-agent.ps1` untouched** — see Pending.
- **Log filenames `3xui.log`, `3xipl.log`, `3xipl-banned.log` and
the fail2ban jail name `3x-ipl`** — only their directory moves
(`/var/log/l-ui/`). Renaming the files would break external
fail2ban configs beyond the directory move the migration
already requires.
- **Docker Postgres user/DB `xui`** — renaming them would orphan
existing `pgdata` volumes (a fresh empty DB would appear and
the panel would start empty). Service/container names were
renamed (`l-ui`, `l-ui_app`, `l-ui_postgres`); credentials kept.
- **Windows-only DB copy in `internal/config/config.go` `init()`** —
its source is now explicitly `/etc/x-ui/x-ui.db` (the only
pre-rename path left in Go code, as a copy source only). Normal
operation never reads it; operator migration moves the DB by mv.
- **`install-agent.sh` legacy-process kill** — it now kills both
`/usr/local/l-ui/l-ui agent` and `/usr/local/x-ui/x-ui agent`.
The old form is a one-time migration cleanup, not a runtime
dual-path fallback; it can be deleted once old forms are gone.
- **`frontend/src/generated/schemas.ts`** — generated by
`tools/openapigen`, marked DO NOT EDIT. Its three "3x-ui panel"
descriptions come from Go model comments and will refresh on
the next regeneration; hand-editing a generated file would be
overwritten anyway.
- **Tracked test binaries `x-ui-agent-test-amd64`,
`x-ui-master-new-amd64`, `x-ui-with-ui-amd64`** — stale ELF
artifacts committed earlier, not referenced by any script or by
`release-build.sh`, not release assets. Left untouched (not
rebuilt, not renamed); deleting committed binaries is a separate
cleanup decision, not part of this rename.
- **`docs/release.md` version-table examples (V2.4.0 / A2.3.0)** —
pre-existing stale examples, not version constants; left as-is
so this diff stays a rename. The agent-change glob there now
reads `cmd/lui-agent*`, which correctly excludes the frozen
Windows dir (Windows-only changes must not move the agent line).
## Pending / must be decided before any release
1. **Gitea repo spelling (BLOCKER).** `rogue/l-ui` is a placeholder.
The Gitea repo has NOT been renamed in this batch and must not
be assumed renamed. Before any release: user confirms the exact
spelling, then update `internal/selfupdate/selfupdate.go`
(annotated in code), `internal/web/service/panel/panel.go`,
`scripts/release-build.sh`, `install-agent.sh`,
`install-master.sh`, `update.sh`, `install.sh`, `docs/release.md`
and every `rogue/l-ui` URL in the tree to the confirmed spelling.
Until then, the renamed update check points at a repo that does
not exist yet — this branch must not be released as-is.
2. **Version bump.** Panel stays V2.6.0, agent stays A2.5.0 in this
diff. The release step must bump the panel line (and the agent
line only if agent code changed in the release commit) and
`install-agent.sh`'s `RELEASE_BASE`.
3. **`install-agent.ps1` (Windows, frozen, TYYUN only).** Untouched
on purpose: it is pinned to the V2.4.0 release base and
downloads `x-ui-agent-windows-amd64.exe` into `C:\x-ui`.
After the Gitea repo is renamed, that download URL
(`rogue/3x-ui-agent/releases/download/V2.4.0/…`) will 404
unless one of these is chosen: (a) leave ps1 alone and accept
that a future Windows reinstall needs a manual exe (the frozen
line needs no reinstall by design); (b) update only its repo
segment to the confirmed spelling, keeping the V2.4.0 pin and
the old asset name (the V2.4.0 release's assets keep their old
names only if the repo is renamed without re-uploading them —
verify before choosing); (c) unfreeze Windows and ship a new
win asset (out of scope for this batch). Do NOT quietly bump
its pin to a release that has no win asset.
4. **Generated schemas regeneration** — run `tools/openapigen`
at release time so `frontend/src/generated/schemas.ts`
descriptions pick up the L-UI wording.
5. **Tracked test binaries** — decide separately whether to delete
the three stale ELF files from the repo.
+2 -2
View File
@@ -1,6 +1,6 @@
# Review instructions # Review instructions
3x-ui is a Go (Gin + GORM) web panel that generates configuration, share links L-UI is a Go (Gin + GORM) web panel that generates configuration, share links
and subscriptions for other programs — Xray-core, mihomo, sing-box, mtg-multi — and subscriptions for other programs — Xray-core, mihomo, sing-box, mtg-multi —
and is deployed by operators who upgrade in place. Judge findings by what and is deployed by operators who upgrade in place. Judge findings by what
breaks for those consumers and operators, not by style. breaks for those consumers and operators, not by style.
@@ -111,7 +111,7 @@ near-certain about and that actually breaks something:
- "CI passed" is a claim too, and needs the same evidence: say it only of a - "CI passed" is a claim too, and needs the same evidence: say it only of a
run you actually read. A green one proves less here than it looks — only run you actually read. A green one proves less here than it looks — only
`postgres-durable-first` runs against PostgreSQL, `go-test` and `race` are `postgres-durable-first` runs against PostgreSQL, `go-test` and `race` are
SQLite, and `XRAY_E2E_BINARY` and `XUI_SCALE_TEST` are set by no job, so SQLite, and `XRAY_E2E_BINARY` and `LUI_SCALE_TEST` are set by no job, so
those tests have never run in CI at all. Where a change touches dialect, those tests have never run in CI at all. Where a change touches dialect,
migration or Xray gRPC code that no job exercised, say it is unverified migration or Xray gRPC code that no job exercised, say it is unverified
rather than repeating a green tick as proof. rather than repeating a green tick as proof.
+2 -2
View File
@@ -5,11 +5,11 @@
Do not open a public issue for anything you believe is exploitable — an Do not open a public issue for anything you believe is exploitable — an
authentication bypass, remote code execution, injection, secret or authentication bypass, remote code execution, injection, secret or
credential exposure, privilege escalation. A public report gives attackers credential exposure, privilege escalation. A public report gives attackers
a head start against every 3x-ui deployment. a head start against every L-UI deployment.
Instead, use GitHub's private vulnerability reporting: open this Instead, use GitHub's private vulnerability reporting: open this
repository's **Security** tab and click **Report a vulnerability**. Include repository's **Security** tab and click **Report a vulnerability**. Include
the affected 3x-ui version, reproduction steps, and the impact you see. the affected L-UI version, reproduction steps, and the impact you see.
You will receive replies in the advisory thread. You will receive replies in the advisory thread.
There is no bug-bounty program. Fixes ship in the next release, and the There is no bug-bounty program. Fixes ship in the next release, and the
+4 -2
View File
@@ -125,7 +125,9 @@ func TestBotContextSkipGatesExist(t *testing.T) {
table := section(t, doc, "**What CI does NOT prove.**", "Mutation testing") table := section(t, doc, "**What CI does NOT prove.**", "Mutation testing")
// [A-Z0-9_] and not [A-Z_]: XRAY_E2E_BINARY carries a digit, and excluding it // [A-Z0-9_] and not [A-Z_]: XRAY_E2E_BINARY carries a digit, and excluding it
// silently dropped that gate from the check instead of failing. // silently dropped that gate from the check instead of failing.
gates := regexp.MustCompile("`((?:XUI|XRAY)_[A-Z0-9_]+)`").FindAllStringSubmatch(table, -1) // LUI_ joins XUI_ here because the rename changed the env prefix; the
// old prefix stays so a stray XUI_ gate still gets checked, not ignored.
gates := regexp.MustCompile("`((?:LUI|XUI|XRAY)_[A-Z0-9_]+)`").FindAllStringSubmatch(table, -1)
if len(gates) < 5 { if len(gates) < 5 {
t.Fatalf("expected at least 5 skip-gate variables in %s, found %d", botContextPath, len(gates)) t.Fatalf("expected at least 5 skip-gate variables in %s, found %d", botContextPath, len(gates))
} }
@@ -171,7 +173,7 @@ func TestReviewNamesRealCIJobsAndGates(t *testing.T) {
} }
}) })
} }
for _, g := range regexp.MustCompile("`((?:XUI|XRAY)_[A-Z0-9_]+)`").FindAllStringSubmatch(doc, -1) { for _, g := range regexp.MustCompile("`((?:LUI|XUI|XRAY)_[A-Z0-9_]+)`").FindAllStringSubmatch(doc, -1) {
t.Run(g[1], func(t *testing.T) { t.Run(g[1], func(t *testing.T) {
if strings.Contains(ci, g[1]) { if strings.Contains(ci, g[1]) {
t.Errorf("%s claims %s is never set in CI, but %s sets it", reviewPath, g[1], ciWorkflowPath) t.Errorf("%s claims %s is never set in CI, but %s sets it", reviewPath, g[1], ciWorkflowPath)
+10 -10
View File
@@ -1,4 +1,4 @@
// Command xui-agent is the standalone Linux build of the 3x-ui node // Command lui-agent is the standalone Linux build of the L-UI node
// agent (agent/panel split, phase 1). Until the split, nodes ran the // agent (agent/panel split, phase 1). Until the split, nodes ran the
// panel binary under the "agent" subcommand, shipping the whole web // panel binary under the "agent" subcommand, shipping the whole web
// panel and the embedded frontend to every node. This entry links only // panel and the embedded frontend to every node. This entry links only
@@ -8,7 +8,7 @@
// replacement for it: // replacement for it:
// //
// - invocation is unchanged: service units run // - invocation is unchanged: service units run
// "xui-agent agent [-config /etc/x-ui/agent.json]" (the bare // "lui-agent agent [-config /etc/l-ui/agent.json]" (the bare
// "-config" form is also accepted for manual runs); // "-config" form is also accepted for manual runs);
// - agent.json, the traffic baseline and the other state files keep // - agent.json, the traffic baseline and the other state files keep
// their names, locations and formats; // their names, locations and formats;
@@ -61,7 +61,7 @@ func main() {
if len(args) > 0 && args[0] == "agent" { if len(args) > 0 && args[0] == "agent" {
args = args[1:] args = args[1:]
} else if len(args) > 0 && args[0][0] != '-' { } else if len(args) > 0 && args[0][0] != '-' {
fmt.Fprintf(os.Stderr, "xui-agent: unknown subcommand %q (this binary only runs the node agent)\n", args[0]) fmt.Fprintf(os.Stderr, "lui-agent: unknown subcommand %q (this binary only runs the node agent)\n", args[0])
os.Exit(2) os.Exit(2)
} }
@@ -73,14 +73,14 @@ func main() {
func runAgent(args []string) { func runAgent(args []string) {
agentCmd := flag.NewFlagSet("agent", flag.ExitOnError) agentCmd := flag.NewFlagSet("agent", flag.ExitOnError)
var configPath string var configPath string
agentCmd.StringVar(&configPath, "config", "/etc/x-ui/agent.json", "Path to agent config file") agentCmd.StringVar(&configPath, "config", "/etc/l-ui/agent.json", "Path to agent config file")
agentCmd.Parse(args) agentCmd.Parse(args)
// Agent mode always uses the panel's directory layout for the // Agent mode always uses the panel's directory layout for the
// xray binary, geo files and config.json. Scoped to agent mode // xray binary, geo files and config.json. Scoped to agent mode
// only so the panel's own relative "bin" default is untouched. // only so the panel's own relative "bin" default is untouched.
if os.Getenv("XUI_BIN_FOLDER") == "" { if os.Getenv("LUI_BIN_FOLDER") == "" {
_ = os.Setenv("XUI_BIN_FOLDER", agent.DefaultBinFolder) _ = os.Setenv("LUI_BIN_FOLDER", agent.DefaultBinFolder)
} }
cfg, err := agent.LoadConfig(configPath) cfg, err := agent.LoadConfig(configPath)
@@ -89,7 +89,7 @@ func runAgent(args []string) {
} }
// The acknowledged traffic baseline persists next to the agent // The acknowledged traffic baseline persists next to the agent
// config (its state home, e.g. /etc/x-ui), unless the config // config (its state home, e.g. /etc/l-ui), unless the config
// names a path. // names a path.
if cfg.BaselinePath == "" { if cfg.BaselinePath == "" {
cfg.BaselinePath = filepath.Join(filepath.Dir(configPath), "agent-traffic-baseline.json") cfg.BaselinePath = filepath.Join(filepath.Dir(configPath), "agent-traffic-baseline.json")
@@ -97,17 +97,17 @@ func runAgent(args []string) {
// Initialize logger // Initialize logger
logger.InitLogger(logging.INFO) logger.InitLogger(logging.INFO)
log.Printf("Starting 3x-ui agent (node: %s)", cfg.NodeName) log.Printf("Starting L-UI agent (node: %s)", cfg.NodeName)
// Agent memory profile (ITEM-P3 A1/M5): the same runtime tuning // Agent memory profile (ITEM-P3 A1/M5): the same runtime tuning
// family as the panel, with the agent's tighter budget, plus the // family as the panel, with the agent's tighter budget, plus the
// periodic release the panel runs through its job scheduler (the // periodic release the panel runs through its job scheduler (the
// agent has no scheduler), plus the panel's XUI_PPROF gate. // agent has no scheduler), plus the panel's LUI_PPROF gate.
for _, line := range memtuning.ApplyAgentMemoryTuning() { for _, line := range memtuning.ApplyAgentMemoryTuning() {
log.Println(line) log.Println(line)
} }
memtuning.StartPeriodicMemoryRelease() memtuning.StartPeriodicMemoryRelease()
if os.Getenv("XUI_PPROF") == "true" { if os.Getenv("LUI_PPROF") == "true" {
go func() { go func() {
log.Println("pprof profiling server listening on 127.0.0.1:6060") log.Println("pprof profiling server listening on 127.0.0.1:6060")
if err := http.ListenAndServe("127.0.0.1:6060", nil); err != nil { if err := http.ListenAndServe("127.0.0.1:6060", nil); err != nil {
+9 -9
View File
@@ -1,6 +1,6 @@
# Cloud deployment (unattended install) # Cloud deployment (unattended install)
Tooling to ship the 3x-ui panel via unattended install, with **per-instance Tooling to ship the L-UI panel via unattended install, with **per-instance
credentials generated on first boot** (never `admin/admin`, never a shared credentials generated on first boot** (never `admin/admin`, never a shared
session secret). Works on amd64 and arm64. session secret). Works on amd64 and arm64.
@@ -12,7 +12,7 @@ session secret). Works on amd64 and arm64.
## How it works ## How it works
`install.sh` runs unattended when `XUI_NONINTERACTIVE=1` or stdin is not a TTY. `install.sh` runs unattended when `LUI_NONINTERACTIVE=1` or stdin is not a TTY.
Each instance installs and configures itself with random credentials. See Each instance installs and configures itself with random credentials. See
[`cloud-init/README.md`](cloud-init/README.md). [`cloud-init/README.md`](cloud-init/README.md).
@@ -21,11 +21,11 @@ Each instance installs and configures itself with random credentials. See
`install.sh` reads these env vars in non-interactive mode (all optional; unset ⇒ `install.sh` reads these env vars in non-interactive mode (all optional; unset ⇒
secure random / default): secure random / default):
`XUI_USERNAME`, `XUI_PASSWORD`, `XUI_PANEL_PORT`, `XUI_WEB_BASE_PATH`, `LUI_USERNAME`, `LUI_PASSWORD`, `LUI_PANEL_PORT`, `LUI_WEB_BASE_PATH`,
`XUI_SSL_MODE` (`none`|`ip`|`domain`, default `none`), `XUI_DOMAIN`, `LUI_SSL_MODE` (`none`|`ip`|`domain`, default `none`), `LUI_DOMAIN`,
`XUI_ACME_EMAIL`, `XUI_ACME_HTTP_PORT` (ACME HTTP-01 listener port, default `80`), `LUI_ACME_EMAIL`, `LUI_ACME_HTTP_PORT` (ACME HTTP-01 listener port, default `80`),
`XUI_SSL_IPV6` (optional IPv6 address to add to an `ip`-mode cert), `LUI_SSL_IPV6` (optional IPv6 address to add to an `ip`-mode cert),
`XUI_SERVER_IP` (fallback IP for the displayed access URL when auto-detection fails), `LUI_SERVER_IP` (fallback IP for the displayed access URL when auto-detection fails),
`XUI_DB_TYPE` (`sqlite`|`postgres`), `XUI_DB_DSN`. `LUI_DB_TYPE` (`sqlite`|`postgres`), `LUI_DB_DSN`.
The resulting credentials are written to `/etc/x-ui/install-result.env` (mode 600). The resulting credentials are written to `/etc/l-ui/install-result.env` (mode 600).
+14 -14
View File
@@ -1,6 +1,6 @@
# 3x-ui via cloud-init # L-UI via cloud-init
A single [`cloud-init.yaml`](cloud-init.yaml) user-data file that installs 3x-ui A single [`cloud-init.yaml`](cloud-init.yaml) user-data file that installs L-UI
non-interactively on a fresh Ubuntu/Debian VM and generates **unique random non-interactively on a fresh Ubuntu/Debian VM and generates **unique random
credentials per instance**. It works on any cloud-init platform. credentials per instance**. It works on any cloud-init platform.
@@ -8,35 +8,35 @@ credentials per instance**. It works on any cloud-init platform.
1. The VM boots a stock Ubuntu/Debian cloud image. 1. The VM boots a stock Ubuntu/Debian cloud image.
2. cloud-init writes and runs `/opt/xui-bootstrap.sh`, which exports 2. cloud-init writes and runs `/opt/xui-bootstrap.sh`, which exports
`XUI_NONINTERACTIVE=1` and pipes the project's `install.sh` into `bash`. `LUI_NONINTERACTIVE=1` and pipes the project's `install.sh` into `bash`.
3. `install.sh` runs end-to-end with **zero prompts**, picking secure random 3. `install.sh` runs end-to-end with **zero prompts**, picking secure random
values for any credential you didn't pin. values for any credential you didn't pin.
4. The generated credentials are written to `/etc/x-ui/install-result.env` 4. The generated credentials are written to `/etc/l-ui/install-result.env`
(mode 600), echoed to the **serial console**, and appended to `/etc/motd`. (mode 600), echoed to the **serial console**, and appended to `/etc/motd`.
Retrieve them after boot with either: Retrieve them after boot with either:
```bash ```bash
sudo cat /etc/x-ui/install-result.env # over SSH sudo cat /etc/l-ui/install-result.env # over SSH
``` ```
…or read the provider's **serial console** output (handy before you have SSH). …or read the provider's **serial console** output (handy before you have SSH).
## Customising ## Customising
Edit the `export XUI_*` lines inside the `write_files` block of Edit the `export LUI_*` lines inside the `write_files` block of
[`cloud-init.yaml`](cloud-init.yaml). All knobs are optional; unset ⇒ random/secure default. [`cloud-init.yaml`](cloud-init.yaml). All knobs are optional; unset ⇒ random/secure default.
| Env var | Default | Meaning | | Env var | Default | Meaning |
| --- | --- | --- | | --- | --- | --- |
| `XUI_SSL_MODE` | `none` | `none` (plain HTTP), `ip` (Let's Encrypt IP cert), `domain` | | `LUI_SSL_MODE` | `none` | `none` (plain HTTP), `ip` (Let's Encrypt IP cert), `domain` |
| `XUI_USERNAME` | random | Admin username | | `LUI_USERNAME` | random | Admin username |
| `XUI_PASSWORD` | random | Admin password | | `LUI_PASSWORD` | random | Admin password |
| `XUI_PANEL_PORT` | random high port | Panel listen port | | `LUI_PANEL_PORT` | random high port | Panel listen port |
| `XUI_WEB_BASE_PATH` | random | Panel base path (obscures the URL) | | `LUI_WEB_BASE_PATH` | random | Panel base path (obscures the URL) |
| `XUI_DOMAIN` | — | Required when `XUI_SSL_MODE=domain` | | `LUI_DOMAIN` | — | Required when `LUI_SSL_MODE=domain` |
| `XUI_ACME_EMAIL` | — | Let's Encrypt account email (domain mode) | | `LUI_ACME_EMAIL` | — | Let's Encrypt account email (domain mode) |
| `XUI_DB_TYPE` / `XUI_DB_DSN` | `sqlite` | Set `postgres` + DSN to use PostgreSQL | | `LUI_DB_TYPE` / `LUI_DB_DSN` | `sqlite` | Set `postgres` + DSN to use PostgreSQL |
> **TLS note:** `none` serves the panel over plain HTTP on a random high port — > **TLS note:** `none` serves the panel over plain HTTP on a random high port —
> fine behind a reverse proxy or an SSH tunnel, but put TLS in front of it before > fine behind a reverse proxy or an SSH tunnel, but put TLS in front of it before
+26 -26
View File
@@ -1,19 +1,19 @@
#cloud-config #cloud-config
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Generic 3x-ui unattended install via cloud-init user-data. # Generic L-UI unattended install via cloud-init user-data.
# #
# Works on any cloud-init platform: Hetzner, AWS, DigitalOcean, Vultr, GCP, # Works on any cloud-init platform: Hetzner, AWS, DigitalOcean, Vultr, GCP,
# Azure, Oracle. Paste the whole file as the instance "user data". # Azure, Oracle. Paste the whole file as the instance "user data".
# #
# It installs the latest 3x-ui release NON-INTERACTIVELY, generating unique # It installs the latest L-UI release NON-INTERACTIVELY, generating unique
# random credentials per instance. Full credentials are surfaced ONLY on the # random credentials per instance. Full credentials are surfaced ONLY on the
# serial console (owner-only); /etc/motd (world-readable) shows just the access # serial console (owner-only); /etc/motd (world-readable) shows just the access
# URL + username. Nothing is baked in advance — every instance is unique. # URL + username. Nothing is baked in advance — every instance is unique.
# #
# Fork note (3x-ui-agent): the bootstrap below installs this fork's # Fork note (L-UI): the bootstrap below installs this fork's
# install-master.sh from its own Gitea repository. The fork installer does # install-master.sh from its own Gitea repository. The fork installer does
# NOT consume the XUI_* non-interactive knobs and does NOT write # NOT consume the LUI_* non-interactive knobs and does NOT write
# /etc/x-ui/install-result.env, so the XUI_* exports and the credential- # /etc/l-ui/install-result.env, so the LUI_* exports and the credential-
# surfacing block below are inert leftovers from the upstream installer. # surfacing block below are inert leftovers from the upstream installer.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -30,46 +30,46 @@ write_files:
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
# --- Non-interactive install knobs -------------------------------------- # --- Non-interactive install knobs --------------------------------------
export XUI_NONINTERACTIVE=1 export LUI_NONINTERACTIVE=1
# SSL mode: none (plain HTTP, default) | ip | domain # SSL mode: none (plain HTTP, default) | ip | domain
export XUI_SSL_MODE="${XUI_SSL_MODE:-none}" export LUI_SSL_MODE="${LUI_SSL_MODE:-none}"
# Pin credentials instead of random (leave unset for secure random values): # Pin credentials instead of random (leave unset for secure random values):
# export XUI_USERNAME="admin2" # export LUI_USERNAME="admin2"
# export XUI_PASSWORD="change-me-please" # export LUI_PASSWORD="change-me-please"
# export XUI_PANEL_PORT="2053" # export LUI_PANEL_PORT="2053"
# export XUI_WEB_BASE_PATH="panel" # export LUI_WEB_BASE_PATH="panel"
# Let's Encrypt domain certificate instead of plain HTTP: # Let's Encrypt domain certificate instead of plain HTTP:
# export XUI_SSL_MODE="domain" # export LUI_SSL_MODE="domain"
# export XUI_DOMAIN="panel.example.com" # export LUI_DOMAIN="panel.example.com"
# export XUI_ACME_EMAIL="you@example.com" # export LUI_ACME_EMAIL="you@example.com"
# PostgreSQL instead of SQLite: # PostgreSQL instead of SQLite:
# export XUI_DB_TYPE="postgres" # export LUI_DB_TYPE="postgres"
# export XUI_DB_DSN="postgres://user:pass@host:5432/db?sslmode=disable" # export LUI_DB_DSN="postgres://user:pass@host:5432/db?sslmode=disable"
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------
curl -fsSL https://git.881218.xyz/rogue/3x-ui-agent/raw/branch/main/install-master.sh | bash curl -fsSL https://git.881218.xyz/rogue/l-ui/raw/branch/main/install-master.sh | bash
# Surface the generated credentials. Full creds (incl. password + API token) # Surface the generated credentials. Full creds (incl. password + API token)
# go ONLY to the serial console (/dev/console, owner-only). /etc/motd is # go ONLY to the serial console (/dev/console, owner-only). /etc/motd is
# world-readable, so it gets just the access URL + username and a pointer # world-readable, so it gets just the access URL + username and a pointer
# to the root-only env file. # to the root-only env file.
if [ -r /etc/x-ui/install-result.env ]; then if [ -r /etc/l-ui/install-result.env ]; then
{ {
echo echo
echo "=== 3x-ui panel credentials (generated on first boot) ===" echo "=== L-UI panel credentials (generated on first boot) ==="
cat /etc/x-ui/install-result.env cat /etc/l-ui/install-result.env
echo "========================================================" echo "========================================================"
echo "Change the password after first login." echo "Change the password after first login."
} > /dev/console 2>/dev/null || true } > /dev/console 2>/dev/null || true
# shellcheck disable=SC1091 # shellcheck disable=SC1091
. /etc/x-ui/install-result.env . /etc/l-ui/install-result.env
{ {
echo echo
echo "=== 3x-ui panel (generated on first boot) ===" echo "=== L-UI panel (generated on first boot) ==="
echo "URL: ${XUI_ACCESS_URL:-unknown}" echo "URL: ${LUI_ACCESS_URL:-unknown}"
echo "Username: ${XUI_USERNAME:-unknown}" echo "Username: ${LUI_USERNAME:-unknown}"
echo "Password + API token: sudo cat /etc/x-ui/install-result.env" echo "Password + API token: sudo cat /etc/l-ui/install-result.env"
echo "=============================================" echo "============================================="
echo "Change the password after first login." echo "Change the password after first login."
} >> /etc/motd 2>/dev/null || true } >> /etc/motd 2>/dev/null || true
@@ -78,4 +78,4 @@ write_files:
runcmd: runcmd:
- [bash, /opt/xui-bootstrap.sh] - [bash, /opt/xui-bootstrap.sh]
final_message: "3x-ui installed — full credentials in /etc/x-ui/install-result.env (sudo); /etc/motd shows the URL + username only." final_message: "L-UI installed — full credentials in /etc/l-ui/install-result.env (sudo); /etc/motd shows the URL + username only."
+5 -5
View File
@@ -1,13 +1,13 @@
# 3x-ui on Hetzner Cloud # L-UI on Hetzner Cloud
Hetzner Cloud does **not** have a third-party image marketplace the way AWS does. Hetzner Cloud does **not** have a third-party image marketplace the way AWS does.
Ship 3x-ui via **cloud-init**: each instance installs non-interactively and Ship L-UI via **cloud-init**: each instance installs non-interactively and
generates unique per-instance credentials (no `admin/admin`, no shared secret). generates unique per-instance credentials (no `admin/admin`, no shared secret).
## cloud-init (no image build) ## cloud-init (no image build)
Use the generic user-data from [`../../cloud-init/`](../../cloud-init/). It installs Use the generic user-data from [`../../cloud-init/`](../../cloud-init/). It installs
3x-ui non-interactively and generates unique per-instance credentials. L-UI non-interactively and generates unique per-instance credentials.
Web console: **Create Server → Cloud config** → paste Web console: **Create Server → Cloud config** → paste
[`deploy/cloud-init/cloud-init.yaml`](../../cloud-init/cloud-init.yaml). [`deploy/cloud-init/cloud-init.yaml`](../../cloud-init/cloud-init.yaml).
@@ -25,13 +25,13 @@ hcloud server create \
After boot, fetch the generated credentials: After boot, fetch the generated credentials:
```bash ```bash
ssh root@<server-ip> 'cat /etc/x-ui/install-result.env' ssh root@<server-ip> 'cat /etc/l-ui/install-result.env'
``` ```
## "App"-style listing ## "App"-style listing
Hetzner's curated apps live in the community repo Hetzner's curated apps live in the community repo
[`github.com/hetznercloud/apps`](https://github.com/hetznercloud/apps): each app [`github.com/hetznercloud/apps`](https://github.com/hetznercloud/apps): each app
is essentially a documented cloud-init config plus metadata. To propose 3x-ui as is essentially a documented cloud-init config plus metadata. To propose L-UI as
a Hetzner app, follow that repo's contribution pattern and base the app's a Hetzner app, follow that repo's contribution pattern and base the app's
cloud-config on [`deploy/cloud-init/cloud-init.yaml`](../../cloud-init/cloud-init.yaml). cloud-config on [`deploy/cloud-init/cloud-init.yaml`](../../cloud-init/cloud-init.yaml).
+31 -31
View File
@@ -3,8 +3,8 @@
# smoke-noninteractive.sh — verify the non-interactive install path. # smoke-noninteractive.sh — verify the non-interactive install path.
# #
# Runs install.sh inside an Ubuntu container with NO TTY (piped) and # Runs install.sh inside an Ubuntu container with NO TTY (piped) and
# XUI_NONINTERACTIVE=1, then asserts: # LUI_NONINTERACTIVE=1, then asserts:
# * /etc/x-ui/install-result.env exists (mode 600) with random, non-default creds # * /etc/l-ui/install-result.env exists (mode 600) with random, non-default creds
# * the panel reports hasDefaultCredential: false (no admin/admin remains) # * the panel reports hasDefaultCredential: false (no admin/admin remains)
# * the panel HTTP server actually serves on the generated port/base path # * the panel HTTP server actually serves on the generated port/base path
# * with a [version] argument: the installed binary reports exactly that version # * with a [version] argument: the installed binary reports exactly that version
@@ -18,41 +18,41 @@ set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
IMAGE="${SMOKE_IMAGE:-ubuntu:24.04}" IMAGE="${SMOKE_IMAGE:-ubuntu:24.04}"
XUI_SMOKE_VERSION="${1:-}" LUI_SMOKE_VERSION="${1:-}"
if ! command -v docker > /dev/null 2>&1; then if ! command -v docker > /dev/null 2>&1; then
echo "ERROR: docker is required for this smoke test." >&2 echo "ERROR: docker is required for this smoke test." >&2
exit 1 exit 1
fi fi
echo "== non-interactive install smoke test (image: $IMAGE, version: ${XUI_SMOKE_VERSION:-latest}) ==" echo "== non-interactive install smoke test (image: $IMAGE, version: ${LUI_SMOKE_VERSION:-latest}) =="
docker run --rm \ docker run --rm \
-v "${REPO_ROOT}/install.sh:/root/install.sh:ro" \ -v "${REPO_ROOT}/install.sh:/root/install.sh:ro" \
-e XUI_NONINTERACTIVE=1 \ -e LUI_NONINTERACTIVE=1 \
-e XUI_SSL_MODE=none \ -e LUI_SSL_MODE=none \
-e XUI_SMOKE_VERSION="$XUI_SMOKE_VERSION" \ -e LUI_SMOKE_VERSION="$LUI_SMOKE_VERSION" \
-e DEBIAN_FRONTEND=noninteractive \ -e DEBIAN_FRONTEND=noninteractive \
"$IMAGE" bash -euo pipefail -c ' "$IMAGE" bash -euo pipefail -c '
apt-get update -qq apt-get update -qq
apt-get install -y -qq curl tar openssl ca-certificates > /dev/null apt-get install -y -qq curl tar openssl ca-certificates > /dev/null
echo "--- running install.sh piped (no TTY), version: ${XUI_SMOKE_VERSION:-latest} ---" echo "--- running install.sh piped (no TTY), version: ${LUI_SMOKE_VERSION:-latest} ---"
# Piping guarantees stdin is not a TTY, exercising the auto non-interactive path. # Piping guarantees stdin is not a TTY, exercising the auto non-interactive path.
if [ -n "${XUI_SMOKE_VERSION:-}" ]; then if [ -n "${LUI_SMOKE_VERSION:-}" ]; then
cat /root/install.sh | bash -s -- "$XUI_SMOKE_VERSION" cat /root/install.sh | bash -s -- "$LUI_SMOKE_VERSION"
else else
cat /root/install.sh | bash cat /root/install.sh | bash
fi fi
echo "--- assertions ---" echo "--- assertions ---"
if [ -n "${XUI_SMOKE_VERSION:-}" ]; then if [ -n "${LUI_SMOKE_VERSION:-}" ]; then
installed=$(/usr/local/x-ui/x-ui -v) installed=$(/usr/local/l-ui/l-ui -v)
[ "$installed" = "${XUI_SMOKE_VERSION#v}" ] \ [ "$installed" = "${LUI_SMOKE_VERSION#v}" ] \
|| { echo "FAIL: installed version $installed, want ${XUI_SMOKE_VERSION#v}"; exit 1; } || { echo "FAIL: installed version $installed, want ${LUI_SMOKE_VERSION#v}"; exit 1; }
fi fi
RESULT=/etc/x-ui/install-result.env RESULT=/etc/l-ui/install-result.env
test -f "$RESULT" || { echo "FAIL: $RESULT missing"; exit 1; } test -f "$RESULT" || { echo "FAIL: $RESULT missing"; exit 1; }
perms=$(stat -c %a "$RESULT") perms=$(stat -c %a "$RESULT")
@@ -60,23 +60,23 @@ docker run --rm \
# shellcheck disable=SC1090 # shellcheck disable=SC1090
. "$RESULT" . "$RESULT"
[ -n "${XUI_USERNAME:-}" ] && [ "$XUI_USERNAME" != "admin" ] \ [ -n "${LUI_USERNAME:-}" ] && [ "$LUI_USERNAME" != "admin" ] \
|| { echo "FAIL: username missing or still admin"; exit 1; } || { echo "FAIL: username missing or still admin"; exit 1; }
[ -n "${XUI_PASSWORD:-}" ] && [ "$XUI_PASSWORD" != "admin" ] \ [ -n "${LUI_PASSWORD:-}" ] && [ "$LUI_PASSWORD" != "admin" ] \
|| { echo "FAIL: password missing or still admin"; exit 1; } || { echo "FAIL: password missing or still admin"; exit 1; }
[ -n "${XUI_PANEL_PORT:-}" ] || { echo "FAIL: port missing"; exit 1; } [ -n "${LUI_PANEL_PORT:-}" ] || { echo "FAIL: port missing"; exit 1; }
# No default admin in the DB. # No default admin in the DB.
/usr/local/x-ui/x-ui setting -show | grep -q "hasDefaultCredential: false" \ /usr/local/l-ui/l-ui setting -show | grep -q "hasDefaultCredential: false" \
|| { echo "FAIL: hasDefaultCredential is not false"; exit 1; } || { echo "FAIL: hasDefaultCredential is not false"; exit 1; }
echo "--- verifying the panel serves HTTP ---" echo "--- verifying the panel serves HTTP ---"
cd /usr/local/x-ui cd /usr/local/l-ui
./x-ui > /tmp/xui.log 2>&1 & ./l-ui > /tmp/lui.log 2>&1 &
xpid=$! xpid=$!
for _ in $(seq 1 15); do for _ in $(seq 1 15); do
code=$(curl -s -o /dev/null -w "%{http_code}" \ code=$(curl -s -o /dev/null -w "%{http_code}" \
"http://127.0.0.1:${XUI_PANEL_PORT}/${XUI_WEB_BASE_PATH}/" 2>/dev/null || true) "http://127.0.0.1:${LUI_PANEL_PORT}/${LUI_WEB_BASE_PATH}/" 2>/dev/null || true)
case "$code" in 200|301|302|307|308) break ;; esac case "$code" in 200|301|302|307|308) break ;; esac
sleep 1 sleep 1
done done
@@ -84,28 +84,28 @@ docker run --rm \
echo "panel HTTP status: ${code:-none}" echo "panel HTTP status: ${code:-none}"
case "${code:-}" in case "${code:-}" in
200|301|302|307|308) : ;; 200|301|302|307|308) : ;;
*) echo "FAIL: panel did not serve (status ${code:-none})"; tail -n 30 /tmp/xui.log; exit 1 ;; *) echo "FAIL: panel did not serve (status ${code:-none})"; tail -n 30 /tmp/lui.log; exit 1 ;;
esac esac
echo "--- verifying a second install preserves custom bin/ files ---" echo "--- verifying a second install preserves custom bin/ files ---"
echo "custom-sentinel" > /usr/local/x-ui/bin/geoip_custom.dat echo "custom-sentinel" > /usr/local/l-ui/bin/geoip_custom.dat
geoip_sum_before=$(sha256sum /usr/local/x-ui/bin/geoip.dat | cut -d" " -f1) geoip_sum_before=$(sha256sum /usr/local/l-ui/bin/geoip.dat | cut -d" " -f1)
if [ -n "${XUI_SMOKE_VERSION:-}" ]; then if [ -n "${LUI_SMOKE_VERSION:-}" ]; then
cat /root/install.sh | bash -s -- "$XUI_SMOKE_VERSION" cat /root/install.sh | bash -s -- "$LUI_SMOKE_VERSION"
else else
cat /root/install.sh | bash cat /root/install.sh | bash
fi fi
test -f /usr/local/x-ui/bin/geoip_custom.dat \ test -f /usr/local/l-ui/bin/geoip_custom.dat \
|| { echo "FAIL: custom bin/ file did not survive a second install"; exit 1; } || { echo "FAIL: custom bin/ file did not survive a second install"; exit 1; }
[ "$(cat /usr/local/x-ui/bin/geoip_custom.dat)" = "custom-sentinel" ] \ [ "$(cat /usr/local/l-ui/bin/geoip_custom.dat)" = "custom-sentinel" ] \
|| { echo "FAIL: custom bin/ file content changed across a second install"; exit 1; } || { echo "FAIL: custom bin/ file content changed across a second install"; exit 1; }
geoip_sum_after=$(sha256sum /usr/local/x-ui/bin/geoip.dat | cut -d" " -f1) geoip_sum_after=$(sha256sum /usr/local/l-ui/bin/geoip.dat | cut -d" " -f1)
[ "$geoip_sum_after" = "$geoip_sum_before" ] \ [ "$geoip_sum_after" = "$geoip_sum_before" ] \
|| { echo "FAIL: bundled geoip.dat changed across a same-version reinstall"; exit 1; } || { echo "FAIL: bundled geoip.dat changed across a same-version reinstall"; exit 1; }
echo "SMOKE_PASS: user=$XUI_USERNAME port=$XUI_PANEL_PORT path=$XUI_WEB_BASE_PATH" echo "SMOKE_PASS: user=$LUI_USERNAME port=$LUI_PANEL_PORT path=$LUI_WEB_BASE_PATH"
' '
echo "== non-interactive smoke test PASSED ==" echo "== non-interactive smoke test PASSED =="
+15 -15
View File
@@ -1,14 +1,14 @@
services: services:
3xui: l-ui:
build: build:
context: . context: .
dockerfile: ./Dockerfile dockerfile: ./Dockerfile
container_name: 3xui_app container_name: l-ui_app
# hostname: yourhostname <- optional # hostname: yourhostname <- optional
# Optional hard memory cap. When set, the panel derives its Go soft limit # Optional hard memory cap. When set, the panel derives its Go soft limit
# (GOMEMLIMIT, ~90% of this cap) so it GCs before the OOM killer fires. # (GOMEMLIMIT, ~90% of this cap) so it GCs before the OOM killer fires.
# mem_limit: 512m # mem_limit: 512m
# The bundled Fail2ban (XUI_ENABLE_FAIL2BAN below) enforces the IP limit # The bundled Fail2ban (LUI_ENABLE_FAIL2BAN below) enforces the IP limit
# with iptables, which needs NET_ADMIN. Without these caps a ban is logged # with iptables, which needs NET_ADMIN. Without these caps a ban is logged
# and shown in fail2ban status but never actually applied. NET_RAW covers # and shown in fail2ban status but never actually applied. NET_RAW covers
# ip6tables. If you disable Fail2ban, you can drop cap_add. # ip6tables. If you disable Fail2ban, you can drop cap_add.
@@ -20,39 +20,39 @@ services:
- NET_ADMIN - NET_ADMIN
- NET_RAW - NET_RAW
volumes: volumes:
- $PWD/db/:/etc/x-ui/ - $PWD/db/:/etc/l-ui/
- $PWD/cert/:/root/cert/ - $PWD/cert/:/root/cert/
# Persists acme.sh state so certificate auto-renewal survives container # Persists acme.sh state so certificate auto-renewal survives container
# recreation (the entrypoint re-registers the renewal cron job from it). # recreation (the entrypoint re-registers the renewal cron job from it).
- $PWD/acme/:/root/.acme.sh/ - $PWD/acme/:/root/.acme.sh/
environment: environment:
XRAY_VMESS_AEAD_FORCED: "false" XRAY_VMESS_AEAD_FORCED: "false"
XUI_ENABLE_FAIL2BAN: "true" LUI_ENABLE_FAIL2BAN: "true"
# Memory tuning. The panel keeps RAM low via GOGC + periodic release; it no # Memory tuning. The panel keeps RAM low via GOGC + periodic release; it no
# longer sets a soft limit from total host RAM (no benefit, risks GC thrash). # longer sets a soft limit from total host RAM (no benefit, risks GC thrash).
# XUI_GOGC: "75" # lower = less RAM, slightly more CPU; GOGC env overrides # LUI_GOGC: "75" # lower = less RAM, slightly more CPU; GOGC env overrides
# XUI_MEMORY_RELEASE_INTERVAL: "10" # minutes between FreeOSMemory; 0 disables # LUI_MEMORY_RELEASE_INTERVAL: "10" # minutes between FreeOSMemory; 0 disables
# Go memory soft limit, only applied from an explicit budget below (or a # Go memory soft limit, only applied from an explicit budget below (or a
# real cgroup/mem_limit cap). Pin it with one of: # real cgroup/mem_limit cap). Pin it with one of:
# XUI_MEMORY_LIMIT: "400" # in MiB # LUI_MEMORY_LIMIT: "400" # in MiB
# GOMEMLIMIT: "400MiB" # Go syntax, takes precedence # GOMEMLIMIT: "400MiB" # Go syntax, takes precedence
# XUI_PPROF: "true" # expose pprof on 127.0.0.1:6060 for profiling # LUI_PPROF: "true" # expose pprof on 127.0.0.1:6060 for profiling
# XUI_INIT_WEB_BASE_PATH: "/" # LUI_INIT_WEB_BASE_PATH: "/"
# XUI_PORT: "8080" # LUI_PORT: "8080"
# To use PostgreSQL instead of the default SQLite, run: # To use PostgreSQL instead of the default SQLite, run:
# docker compose --profile postgres up -d # docker compose --profile postgres up -d
# and uncomment the two lines below. # and uncomment the two lines below.
# XUI_DB_TYPE: "postgres" # LUI_DB_TYPE: "postgres"
# XUI_DB_DSN: "postgres://xui:xui@postgres:5432/xui?sslmode=disable" # LUI_DB_DSN: "postgres://xui:xui@postgres:5432/xui?sslmode=disable" # postgres user/db kept: renaming them would orphan existing pgdata
tty: true tty: true
ports: ports:
# When XUI_PORT is set, publish the same container port (for example "8080:8080"). # When LUI_PORT is set, publish the same container port (for example "8080:8080").
- "2053:2053" - "2053:2053"
restart: unless-stopped restart: unless-stopped
postgres: postgres:
image: postgres:16-alpine image: postgres:16-alpine
container_name: 3xui_postgres container_name: l-ui_postgres
profiles: ["postgres"] profiles: ["postgres"]
environment: environment:
POSTGRES_USER: xui POSTGRES_USER: xui
+21 -21
View File
@@ -1,13 +1,13 @@
# 3x-ui Agent 模式安装说明 # L-UI Agent 模式安装说明
节点鸡不再跑完整 3x-ui 面板,只跑一个轻量 agent:用 token 向主控注册, 节点鸡不再跑完整 L-UI 面板,只跑一个轻量 agent:用 token 向主控注册,
主控下发完整 xray 配置(含入站、出站、路由规则),agent 写配置并管理 xray 进程, 主控下发完整 xray 配置(含入站、出站、路由规则),agent 写配置并管理 xray 进程,
每 60 秒向主控上报流量/在线数。 每 60 秒向主控上报流量/在线数。
## 架构 ## 架构
- 主控:完整 3x-ui(v3.7.0+agent 补丁),负责生成配置、下发、管理出站与路由规则。 - 主控:完整 L-UI(v3.7.0+agent 补丁),负责生成配置、下发、管理出站与路由规则。
- 节点:`x-ui agent` 二进制 + xray 二进制 + geo 文件,无面板、无数据库。 - 节点:`l-ui agent` 二进制 + xray 二进制 + geo 文件,无面板、无数据库。
- 出站/路由规则只能在主控上建和改(面板是唯一可信源),agent 只管应用下发 - 出站/路由规则只能在主控上建和改(面板是唯一可信源),agent 只管应用下发
的完整配置,不上报本地配置。 的完整配置,不上报本地配置。
@@ -35,24 +35,24 @@ curl -sk -H "Authorization: Bearer <PANEL_API_TOKEN>" \
## 二、节点安装 ## 二、节点安装
```bash ```bash
mkdir -p /usr/local/x-ui/bin /etc/x-ui mkdir -p /usr/local/l-ui/bin /etc/l-ui
# 1. 放 x-ui 二进制(agent 补丁版,与主控同版本),在节点上改名为 xui-agent(与主控进程区分) # 1. 放 l-ui 二进制(agent 补丁版,与主控同版本),在节点上改名为 lui-agent(与主控进程区分)
cp x-ui /usr/local/x-ui/xui-agent && chmod +x /usr/local/x-ui/xui-agent cp l-ui /usr/local/l-ui/lui-agent && chmod +x /usr/local/l-ui/lui-agent
# 2. 放 xray 二进制与 geo 文件(agent 不负责下载,手动放置) # 2. 放 xray 二进制与 geo 文件(agent 不负责下载,手动放置)
cp xray-linux-amd64 /usr/local/x-ui/bin/xray && chmod +x /usr/local/x-ui/bin/xray cp xray-linux-amd64 /usr/local/l-ui/bin/xray && chmod +x /usr/local/l-ui/bin/xray
cp geoip.dat geosite.dat /usr/local/x-ui/bin/ cp geoip.dat geosite.dat /usr/local/l-ui/bin/
# 3. 写 agent 配置 # 3. 写 agent 配置
cat > /etc/x-ui/agent.json <<'EOF' cat > /etc/l-ui/agent.json <<'EOF'
{ {
"master_url": "http://主控内网地址:2053", "master_url": "http://主控内网地址:2053",
"token": "<上一步生成的 token>", "token": "<上一步生成的 token>",
"node_name": "hk-node-1" "node_name": "hk-node-1"
} }
EOF EOF
chmod 600 /etc/x-ui/agent.json chmod 600 /etc/l-ui/agent.json
``` ```
说明: 说明:
@@ -60,27 +60,27 @@ chmod 600 /etc/x-ui/agent.json
- `master_url` 用 `http://`(内网)或 `https://`(需可信证书;自签证书连不上, - `master_url` 用 `http://`(内网)或 `https://`(需可信证书;自签证书连不上,
agent 默认校验 TLS)。 agent 默认校验 TLS)。
- `poll_interval` 可省略,默认 30 秒轮询一次配置。 - `poll_interval` 可省略,默认 30 秒轮询一次配置。
- 不要在节点上再启动完整面板(`x-ui` 不带 `agent` 参数的模式)。 - 不要在节点上再启动完整面板(`l-ui` 不带 `agent` 参数的模式)。
## 三、启动 agent ## 三、启动 agent
systemd(Debian/Ubuntu): systemd(Debian/Ubuntu):
```bash ```bash
cp systemd/x-ui-agent.service /etc/systemd/system/ cp systemd/lui-agent.service /etc/systemd/system/
systemctl daemon-reload systemctl daemon-reload
systemctl enable --now x-ui-agent systemctl enable --now lui-agent
journalctl -u x-ui-agent -f journalctl -u lui-agent -f
``` ```
OpenWrt(procd): OpenWrt(procd):
```bash ```bash
cp openrc/x-ui-agent /etc/init.d/x-ui-agent cp openrc/lui-agent /etc/init.d/lui-agent
chmod +x /etc/init.d/x-ui-agent chmod +x /etc/init.d/lui-agent
/etc/init.d/x-ui-agent enable /etc/init.d/lui-agent enable
/etc/init.d/x-ui-agent start /etc/init.d/lui-agent start
logread -f | grep x-ui-agent logread -f | grep lui-agent
``` ```
## 四、主控管理该节点的出站与路由规则 ## 四、主控管理该节点的出站与路由规则
@@ -120,6 +120,6 @@ curl -sk -H "Authorization: Bearer <PANEL_API_TOKEN>" \
|---|---| |---|---|
| `register failed ... 401` | token 贴错,或 token 没在主控生成 | | `register failed ... 401` | token 贴错,或 token 没在主控生成 |
| `config fetch failed ... 409` | token 未绑定节点(生成时没传 `node_id`) | | `config fetch failed ... 409` | token 未绑定节点(生成时没传 `node_id`) |
| xray 起不来 | `/usr/local/x-ui/bin/xray` 是否存在可执行;`xray -test -c /usr/local/x-ui/bin/config.json` 看配置报错 | | xray 起不来 | `/usr/local/l-ui/bin/xray` 是否存在可执行;`xray -test -c /usr/local/l-ui/bin/config.json` 看配置报错 |
| 流量不上报 | xray 的 api 入站端口是否被占用;agent 日志看 `Traffic report failed` | | 流量不上报 | xray 的 api 入站端口是否被占用;agent 日志看 `Traffic report failed` |
| 主控连不上 | `master_url` 拼错;https 自签证书改走 `http://` 内网地址 | | 主控连不上 | `master_url` 拼错;https 自签证书改走 `http://` 内网地址 |
+2 -2
View File
@@ -1,6 +1,6 @@
# Contributing to 3x-ui-docs # Contributing to L-UI-docs
Thanks for helping improve the 3x-ui documentation and product site! Thanks for helping improve the L-UI documentation and product site!
## Prerequisites ## Prerequisites
+6 -6
View File
@@ -2,22 +2,22 @@
<a href="https://docs.sanaei.dev"> <a href="https://docs.sanaei.dev">
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="public/logo-dark.png" /> <source media="(prefers-color-scheme: dark)" srcset="public/logo-dark.png" />
<img src="public/logo-light.png" alt="3x-ui" width="180" /> <img src="public/logo-light.png" alt="L-UI" width="180" />
</picture> </picture>
</a> </a>
</p> </p>
<h1 align="center">3x-ui Documentation</h1> <h1 align="center">L-UI Documentation</h1>
<p align="center"> <p align="center">
The official documentation and product site for The official documentation and product site for
<a href="https://github.com/MHSanaei/3x-ui"><b>3x-ui</b></a> — <a href="https://github.com/MHSanaei/L-UI"><b>L-UI</b></a> —
an advanced web panel for managing Xray-core servers. an advanced web panel for managing Xray-core servers.
</p> </p>
<p align="center"> <p align="center">
<a href="https://docs.sanaei.dev"><img src="https://img.shields.io/badge/docs-docs.sanaei.dev-22d3ee?style=flat-square" alt="Live site" /></a> <a href="https://docs.sanaei.dev"><img src="https://img.shields.io/badge/docs-docs.sanaei.dev-22d3ee?style=flat-square" alt="Live site" /></a>
<a href="https://github.com/MHSanaei/3x-ui/actions/workflows/docs-ci.yml"><img src="https://github.com/MHSanaei/3x-ui/actions/workflows/docs-ci.yml/badge.svg" alt="CI" /></a> <a href="https://github.com/MHSanaei/L-UI/actions/workflows/docs-ci.yml"><img src="https://github.com/MHSanaei/L-UI/actions/workflows/docs-ci.yml/badge.svg" alt="CI" /></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-GPL--3.0-blue?style=flat-square" alt="License: GPL-3.0" /></a> <a href="LICENSE"><img src="https://img.shields.io/badge/license-GPL--3.0-blue?style=flat-square" alt="License: GPL-3.0" /></a>
<img src="https://img.shields.io/badge/Next.js-16-black?style=flat-square&logo=next.js" alt="Next.js 16" /> <img src="https://img.shields.io/badge/Next.js-16-black?style=flat-square&logo=next.js" alt="Next.js 16" />
<img src="https://img.shields.io/badge/Fumadocs-16-0ea5e9?style=flat-square" alt="Fumadocs 16" /> <img src="https://img.shields.io/badge/Fumadocs-16-0ea5e9?style=flat-square" alt="Fumadocs 16" />
@@ -31,7 +31,7 @@
## Overview ## Overview
This directory (`docs/` in the [3x-ui](https://github.com/MHSanaei/3x-ui) monorepo) contains This directory (`docs/` in the [L-UI](https://github.com/MHSanaei/L-UI) monorepo) contains
the source for [docs.sanaei.dev](https://docs.sanaei.dev) — a static-first documentation and the source for [docs.sanaei.dev](https://docs.sanaei.dev) — a static-first documentation and
marketing site built with [Fumadocs](https://fumadocs.dev) on Next.js. It has **no backend, marketing site built with [Fumadocs](https://fumadocs.dev) on Next.js. It has **no backend,
no database, and no auth**: every page is prerendered and every tool runs entirely in the no database, and no auth**: every page is prerendered and every tool runs entirely in the
@@ -39,7 +39,7 @@ browser.
## What's inside ## What's inside
The documentation walks you through 3x-ui from first install to day-to-day operation: The documentation walks you through L-UI from first install to day-to-day operation:
- **Getting Started** — installation, first login, and updating or uninstalling the panel. - **Getting Started** — installation, first login, and updating or uninstalling the panel.
- **Configuration** — the panel, inbounds, REALITY, transports, clients, subscriptions, and share links. - **Configuration** — the panel, inbounds, REALITY, transports, clients, subscriptions, and share links.
+1 -1
View File
@@ -2,7 +2,7 @@
@import 'fumadocs-ui/css/neutral.css'; @import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css'; @import 'fumadocs-ui/css/preset.css';
/* 3x-ui brand: cyan / turquoise accent (matches the panel logo). */ /* L-UI brand: cyan / turquoise accent (matches the panel logo). */
:root { :root {
--color-fd-primary: hsl(190, 95%, 39%); --color-fd-primary: hsl(190, 95%, 39%);
--color-fd-primary-foreground: hsl(0, 0%, 100%); --color-fd-primary-foreground: hsl(0, 0%, 100%);
+19 -22
View File
@@ -1,4 +1,4 @@
# 3x-ui — Architecture & Code Map # L-UI — Architecture & Code Map
> Navigation map for contributors and AI coding agents (referenced from `CLAUDE.md`). > Navigation map for contributors and AI coding agents (referenced from `CLAUDE.md`).
> Goal: jump to the right file in one hop instead of grepping the whole tree. > Goal: jump to the right file in one hop instead of grepping the whole tree.
@@ -13,7 +13,7 @@
## 1. Mental model (the 30-second version) ## 1. Mental model (the 30-second version)
3x-ui is a **web control panel for [Xray-core](https://github.com/XTLS/Xray-core)**. The Go L-UI is a **web control panel for [Xray-core](https://github.com/XTLS/Xray-core)**. The Go
backend is the source of truth: it stores inbounds/clients/settings in a DB, renders an backend is the source of truth: it stores inbounds/clients/settings in a DB, renders an
Xray JSON config from that state, supervises the Xray child process, and exposes a REST + Xray JSON config from that state, supervises the Xray child process, and exposes a REST +
WebSocket API. A React SPA (built by Vite, embedded into the Go binary) is the UI. A second, WebSocket API. A React SPA (built by Vite, embedded into the Go binary) is the UI. A second,
@@ -41,7 +41,7 @@ Two key ideas that explain most of the complexity:
1. **The DB → Xray config pipeline.** Inbounds/clients live in the DB. On every change the 1. **The DB → Xray config pipeline.** Inbounds/clients live in the DB. On every change the
backend regenerates the Xray config and applies it — preferring a _hot diff_ (live gRPC backend regenerates the Xray config and applies it — preferring a _hot diff_ (live gRPC
API mutation) over a full process restart. See §5.1. API mutation) over a full process restart. See §5.1.
2. **The Runtime abstraction (multi-node).** A panel can manage remote "nodes" (other 3x-ui 2. **The Runtime abstraction (multi-node).** A panel can manage remote "nodes" (other L-UI
instances). Every state-changing inbound/client operation is dispatched through a instances). Every state-changing inbound/client operation is dispatched through a
`runtime.Runtime` interface that is either **`Local`** (this box's Xray gRPC API) or `runtime.Runtime` interface that is either **`Local`** (this box's Xray gRPC API) or
**`Remote`** (HTTPS call to a child node, with `verify`/`skip`/`pin`/`mtls` TLS modes). **`Remote`** (HTTPS call to a child node, with `verify`/`skip`/`pin`/`mtls` TLS modes).
@@ -54,7 +54,7 @@ Two key ideas that explain most of the complexity:
**Backend (Go 1.27):** **Backend (Go 1.27):**
- Web framework: **Gin** (`gin-gonic/gin`) + sessions (cookie store), gzip. - Web framework: **Gin** (`gin-gonic/gin`) + sessions (cookie store), gzip.
- ORM: **GORM** with **SQLite** (default) or **PostgreSQL** (`XUI_DB_TYPE=postgres`). - ORM: **GORM** with **SQLite** (default) or **PostgreSQL** (`LUI_DB_TYPE=postgres`).
- Scheduler: **robfig/cron/v3** (seconds-precision) for all background jobs. - Scheduler: **robfig/cron/v3** (seconds-precision) for all background jobs.
- Xray: **xtls/xray-core** vendored as a library; the panel talks to the running core over - Xray: **xtls/xray-core** vendored as a library; the panel talks to the running core over
its **gRPC API** and also shells out to manage the process. its **gRPC API** and also shells out to manage the process.
@@ -85,7 +85,7 @@ Browser (React, fetch)
→ POST {basePath}/panel/api/... → POST {basePath}/panel/api/...
→ Gin engine (internal/web/web.go: initRouter) → Gin engine (internal/web/web.go: initRouter)
→ middleware chain: SecurityHeaders → MaxBodyBytes (10 MiB; importDB exempt) → middleware chain: SecurityHeaders → MaxBodyBytes (10 MiB; importDB exempt)
→ [DomainValidator, if webDomain set] → gzip → sessions("3x-ui") → [DomainValidator, if webDomain set] → gzip → sessions("L-UI")
→ base-path/cache-control context → Localizer → base-path/cache-control context → Localizer
→ API routes add: ConfigEnvelope (zstd + SHA-256) → CSRF → API routes add: ConfigEnvelope (zstd + SHA-256) → CSRF
→ Controller (internal/web/controller/*.go) // HTTP concerns only: bind, validate, respond → Controller (internal/web/controller/*.go) // HTTP concerns only: bind, validate, respond
@@ -120,14 +120,14 @@ node heartbeat every 5s, periodic traffic resets (hourly/daily/weekly/monthly).
## 4. Directory map (what lives where) ## 4. Directory map (what lives where)
``` ```
3x-ui/ L-UI/
├── main.go # Entry point: CLI (run / migrate / migrate-db / setting / cert), ├── main.go # Entry point: CLI (run / migrate / migrate-db / setting / cert),
│ # bootstrap, signal handling, restart loop │ # bootstrap, signal handling, restart loop
├── go.mod / go.sum # Go deps (module path ends in /v3) ├── go.mod / go.sum # Go deps (module path ends in /v3)
│ │
├── internal/ # ALL backend Go code (private packages) ├── internal/ # ALL backend Go code (private packages)
│ ├── config/ # Env-var config: paths, DB kind/DSN, log level, version │ ├── config/ # Env-var config: paths, DB kind/DSN, log level, version
│ │ # Every XUI_* env var is read here (config.go) │ │ # Every LUI_* env var is read here (config.go)
│ ├── database/ │ ├── database/
│ │ ├── db.go # InitDB: connect, AutoMigrate, seeders (~1.4k lines). DB hotspot. │ │ ├── db.go # InitDB: connect, AutoMigrate, seeders (~1.4k lines). DB hotspot.
│ │ ├── migrate_data.go # Data migrations (seeders/normalizers beyond AutoMigrate) │ │ ├── migrate_data.go # Data migrations (seeders/normalizers beyond AutoMigrate)
@@ -139,7 +139,7 @@ node heartbeat every 5s, periodic traffic resets (hourly/daily/weekly/monthly).
│ ├── pia/ # PIA WireGuard protocol client (auth, signed server list, /addKey) │ ├── pia/ # PIA WireGuard protocol client (auth, signed server list, /addKey)
│ ├── eventbus/ # In-process pub/sub (buffered channel): outbound.down|up, │ ├── eventbus/ # In-process pub/sub (buffered channel): outbound.down|up,
│ │ # xray.crash, node.down|up, cpu.high, memory.high, login.attempt │ │ # xray.crash, node.down|up, cpu.high, memory.high, login.attempt
│ ├── tunnelmonitor/ # Optional tunnel health probe (XUI_TUNNEL_HEALTH_* env vars): │ ├── tunnelmonitor/ # Optional tunnel health probe (LUI_TUNNEL_HEALTH_* env vars):
│ │ # HTTP probe (default Cloudflare trace); repeated failures │ │ # HTTP probe (default Cloudflare trace); repeated failures
│ │ # trigger an Xray restart hook. Independent of panel settings. │ │ # trigger an Xray restart hook. Independent of panel settings.
│ ├── xray/ # Xray-core integration (the proxy engine wrapper) │ ├── xray/ # Xray-core integration (the proxy engine wrapper)
@@ -163,9 +163,9 @@ node heartbeat every 5s, periodic traffic resets (hourly/daily/weekly/monthly).
│ │ │ ├── node.go # /panel/api/nodes (multi-node management) │ │ │ ├── node.go # /panel/api/nodes (multi-node management)
│ │ │ ├── host.go # /panel/api/hosts (per-inbound subscription host overrides) │ │ │ ├── host.go # /panel/api/hosts (per-inbound subscription host overrides)
│ │ │ ├── server.go # /panel/api/server (status, xray version, certs, logs, DB import/export) │ │ │ ├── server.go # /panel/api/server (status, xray version, certs, logs, DB import/export)
│ │ │ ├── setting.go # /panel/api/setting (settings + API tokens) │ │ │ ├── setting.go # /panel/api/setting (settings)
│ │ │ ├── xray_setting.go # /panel/api/xray (raw Xray config editor, WARP/Nord/PIA, geodata) │ │ │ ├── xray_setting.go # /panel/api/xray (raw Xray config editor, WARP/Nord/PIA, geodata)
│ │ │ ├── api.go # /panel/api gateway (token auth, envelope + CSRF wiring) │ │ │ ├── api.go # /panel/api gateway (envelope + CSRF wiring)
│ │ │ ├── index.go # login/logout/csrf/2FA │ │ │ ├── index.go # login/logout/csrf/2FA
│ │ │ ├── spa.go # SPA fallback for /panel UI routes │ │ │ ├── spa.go # SPA fallback for /panel UI routes
│ │ │ └── websocket.go # WS upgrade endpoint │ │ │ └── websocket.go # WS upgrade endpoint
@@ -203,12 +203,11 @@ node heartbeat every 5s, periodic traffic resets (hourly/daily/weekly/monthly).
│ │ │ ├── port_conflict.go # Detect inbound port collisions │ │ │ ├── port_conflict.go # Detect inbound port collisions
│ │ │ ├── fallback.go # Xray fallback (SNI/ALPN routing on shared port) │ │ │ ├── fallback.go # Xray fallback (SNI/ALPN routing on shared port)
│ │ │ ├── email/ # Email notification service (SMTP) │ │ │ ├── email/ # Email notification service (SMTP)
│ │ │ ├── integration/ # External providers: warp.go, nord.go, pia.go │ │ │ ├── integration/ # External providers: warp.go
│ │ │ ├── outbound/ # Outbound config service │ │ │ ├── outbound/ # Outbound config service
│ │ │ ├── panel/ # Cross-cutting panel services: │ │ │ ├── panel/ # Cross-cutting panel services:
│ │ │ │ ├── panel.go # panel-level helpers │ │ │ │ ├── panel.go # panel-level helpers
│ │ │ │ ├── user.go # admin user auth (bcrypt) │ │ │ │ ├── user.go # admin user auth (bcrypt)
│ │ │ │ ├── api_token.go # API token CRUD (SHA-256 hashed)
│ │ │ │ └── websocket.go # WS hub / push service │ │ │ │ └── websocket.go # WS hub / push service
│ │ │ └── tgbot/ # Telegram bot command handlers │ │ │ └── tgbot/ # Telegram bot command handlers
│ │ ├── runtime/ # ⭐⭐ The Local/Remote node abstraction (see §5.2) │ │ ├── runtime/ # ⭐⭐ The Local/Remote node abstraction (see §5.2)
@@ -281,8 +280,8 @@ node heartbeat every 5s, periodic traffic resets (hourly/daily/weekly/monthly).
├── media/ # README images ├── media/ # README images
│ │
├── Dockerfile / docker-compose.yml / DockerEntrypoint.sh / DockerInit.sh # Container build/run ├── Dockerfile / docker-compose.yml / DockerEntrypoint.sh / DockerInit.sh # Container build/run
├── install.sh / update.sh / x-ui.sh # VPS install + management CLI ├── install.sh / update.sh / l-ui.sh # VPS install + management CLI
├── x-ui.service.* / x-ui.rc # systemd units (debian/rhel/arch) + rc script ├── l-ui.service.* / l-ui.rc # systemd units (debian/rhel/arch) + rc script
├── windows_files/ # Windows service support ├── windows_files/ # Windows service support
└── .github/workflows/ # CI: ci.yml, codeql.yml, docker.yml, release.yml, smoke.yml, └── .github/workflows/ # CI: ci.yml, codeql.yml, docker.yml, release.yml, smoke.yml,
# mutation.yml, cleanup_caches.yml, claude-bot.yml # mutation.yml, cleanup_caches.yml, claude-bot.yml
@@ -314,7 +313,7 @@ Restart is debounced via an atomic "need restart" flag (`SetToNeedRestart` /
### 5.2 Runtime abstraction — Local vs Remote (multi-node) ⭐ most important ### 5.2 Runtime abstraction — Local vs Remote (multi-node) ⭐ most important
A "node" (`model.Node`) is another 3x-ui instance this panel controls. Every state-changing A "node" (`model.Node`) is another L-UI instance this panel controls. Every state-changing
inbound/client operation goes through the `runtime.Runtime` interface so the _same service inbound/client operation goes through the `runtime.Runtime` interface so the _same service
code_ works whether the target is the local Xray or a remote node. code_ works whether the target is the local Xray or a remote node.
@@ -327,7 +326,7 @@ code_ works whether the target is the local Xray or a remote node.
- **TLS modes** (`tls_client.go`, per-node `TlsVerifyMode`): - **TLS modes** (`tls_client.go`, per-node `TlsVerifyMode`):
`verify` (system CAs, default) / `skip` (no validation) / `pin` (leaf cert SHA-256 must `verify` (system CAs, default) / `skip` (no validation) / `pin` (leaf cert SHA-256 must
match `PinnedCertSha256`) / `mtls` (master presents a client certificate; node cert checked match `PinnedCertSha256`) / `mtls` (master presents a client certificate; node cert checked
against system roots; API token optional). Master-side cert management: against system roots). Master-side cert management:
`service/node_mtls.go` + `service/setting_mtls.go`. `service/node_mtls.go` + `service/setting_mtls.go`.
- **Dispatch:** `manager.go` → `Manager.RuntimeFor(nodeID *int)`; `nil` nodeID → `Local`, - **Dispatch:** `manager.go` → `Manager.RuntimeFor(nodeID *int)`; `nil` nodeID → `Local`,
otherwise a cached/lazy-loaded `Remote`. `InvalidateNode(id)` drops a cached remote client. otherwise a cached/lazy-loaded `Remote`. `InvalidateNode(id)` drops a cached remote client.
@@ -431,7 +430,7 @@ notifications instead of importing notification services into producers.
### 5.8 Tunnel health monitor ### 5.8 Tunnel health monitor
`internal/tunnelmonitor/` is an optional watchdog configured **only via env vars** `internal/tunnelmonitor/` is an optional watchdog configured **only via env vars**
(`XUI_TUNNEL_HEALTH_*`, read in `internal/config/`), deliberately independent of panel (`LUI_TUNNEL_HEALTH_*`, read in `internal/config/`), deliberately independent of panel
settings so it can be enabled from a systemd `EnvironmentFile` even when the panel is settings so it can be enabled from a systemd `EnvironmentFile` even when the panel is
unreachable. It periodically probes an HTTP URL (default: Cloudflare trace endpoint) through unreachable. It periodically probes an HTTP URL (default: Cloudflare trace endpoint) through
the tunnel; after N successive failures (default 3) it fires a recovery callback wired to an the tunnel; after N successive failures (default 3) it fires a recovery callback wired to an
@@ -462,7 +461,6 @@ for AutoMigrate in `internal/database/db.go`.
| `OutboundTraffics` | Outbound counters | per outbound tag | | `OutboundTraffics` | Outbound counters | per outbound tag |
| `OutboundSubscription` | External provider subs | Warp/Nord style | | `OutboundSubscription` | External provider subs | Warp/Nord style |
| `Setting` | Key/value panel settings | everything configurable | | `Setting` | Key/value panel settings | everything configurable |
| `ApiToken` | REST API tokens | SHA-256 hash (plaintext shown once) |
| `InboundFallback` | Fallback routing on a shared port | SNI/ALPN/path → dest | | `InboundFallback` | Fallback routing on a shared port | SNI/ALPN/path → dest |
| `HistoryOfSeeders` | Seeder bookkeeping | prevents re-running one-off migrations | | `HistoryOfSeeders` | Seeder bookkeeping | prevents re-running one-off migrations |
@@ -490,7 +488,6 @@ for AutoMigrate in `internal/database/db.go`.
| **External subscription** import/aggregation | `sub/external_subscription.go`, `sub/external_config.go` | `sub/clash_external.go` | | **External subscription** import/aggregation | `sub/external_subscription.go`, `sub/external_config.go` | `sub/clash_external.go` |
| **Settings** not saving / defaults | `service/setting.go`, `controller/setting.go` | model `Setting` | | **Settings** not saving / defaults | `service/setting.go`, `controller/setting.go` | model `Setting` |
| **Login / 2FA / sessions / CSRF** | `controller/index.go`, `service/panel/user.go`, `middleware/` | `session/` | | **Login / 2FA / sessions / CSRF** | `controller/index.go`, `service/panel/user.go`, `middleware/` | `session/` |
| **API tokens** | `service/panel/api_token.go`, `controller/setting.go` | model `ApiToken` |
| **Port conflict** on inbound add | `service/port_conflict.go` | `controller/inbound.go` | | **Port conflict** on inbound add | `service/port_conflict.go` | `controller/inbound.go` |
| **Fallbacks** (shared 443, SNI routing) | `service/fallback.go`, `controller/inbound.go` | model `InboundFallback` | | **Fallbacks** (shared 443, SNI routing) | `service/fallback.go`, `controller/inbound.go` | model `InboundFallback` |
| **Geo category browser** empty / won't open | `xray/geodata/` (`Store`, `reader.go`), `service/geodata.go` | `controller/xray_setting.go` (`/panel/api/xray/geodata/*`), asset dir = `config.GetBinFolderPath()` | | **Geo category browser** empty / won't open | `xray/geodata/` (`Store`, `reader.go`), `service/geodata.go` | `controller/xray_setting.go` (`/panel/api/xray/geodata/*`), asset dir = `config.GetBinFolderPath()` |
@@ -498,7 +495,7 @@ for AutoMigrate in `internal/database/db.go`.
| **Telegram bot** commands | `service/tgbot/` | `job/stats_notify_job.go` | | **Telegram bot** commands | `service/tgbot/` | `job/stats_notify_job.go` |
| **Email notifications** | `service/email/` | `internal/eventbus/` (consumers) | | **Email notifications** | `service/email/` | `internal/eventbus/` (consumers) |
| **CPU / memory alerts** not firing | `job/check_cpu_usage.go`, `job/check_memory_usage.go` | `internal/eventbus/`, notifier settings in `service/setting.go` | | **CPU / memory alerts** not firing | `job/check_cpu_usage.go`, `job/check_memory_usage.go` | `internal/eventbus/`, notifier settings in `service/setting.go` |
| Xray auto-restart on **dead tunnel** | `internal/tunnelmonitor/` | `XUI_TUNNEL_HEALTH_*` in `internal/config/` | | Xray auto-restart on **dead tunnel** | `internal/tunnelmonitor/` | `LUI_TUNNEL_HEALTH_*` in `internal/config/` |
| **WARP / Nord / PIA** outbound integration | `service/integration/warp.go` / `nord.go` / `pia.go` | `internal/pia/`, `frontend/src/pages/xray/overrides/` | | **WARP / Nord / PIA** outbound integration | `service/integration/warp.go` / `nord.go` / `pia.go` | `internal/pia/`, `frontend/src/pages/xray/overrides/` |
| **MTProto** proxy issues | `internal/mtproto/manager.go`, `mtproto/process*.go` | `job/mtproto_job.go` | | **MTProto** proxy issues | `internal/mtproto/manager.go`, `mtproto/process*.go` | `job/mtproto_job.go` |
| **DB migration** / new column | `internal/database/db.go` (AutoMigrate list), `migrate_data.go` | `model/model.go` | | **DB migration** / new column | `internal/database/db.go` (AutoMigrate list), `migrate_data.go` | `model/model.go` |
@@ -580,8 +577,8 @@ root → `go build ./...` / `go run main.go`.
## 10. Gotchas & conventions ## 10. Gotchas & conventions
- **Module path is `.../v3`.** Internal imports use `github.com/mhsanaei/3x-ui/v3/internal/...`. - **Module path is `.../v3`.** Internal imports use `github.com/mhsanaei/3x-ui/v3/internal/...`.
- **SQLite vs Postgres.** Default is SQLite at `{XUI_DB_FOLDER}/x-ui.db`. Postgres via - **SQLite vs Postgres.** Default is SQLite at `{LUI_DB_FOLDER}/l-ui.db`. Postgres via
`XUI_DB_TYPE=postgres` + `XUI_DB_DSN`. Some SQL paths are dialect-aware (`database/dialect.go`); `LUI_DB_TYPE=postgres` + `LUI_DB_DSN`. Some SQL paths are dialect-aware (`database/dialect.go`);
test both when touching raw queries (there are `*_scale_postgres_test.go` suites). test both when touching raw queries (there are `*_scale_postgres_test.go` suites).
- **`Inbound.Settings` / `StreamSettings` / `Sniffing` are raw JSON strings**, not structured - **`Inbound.Settings` / `StreamSettings` / `Sniffing` are raw JSON strings**, not structured
columns. Parsing/validation happens in services and the `xray` package, not in GORM. columns. Parsing/validation happens in services and the `xray` package, not in GORM.
+3 -3
View File
@@ -1,15 +1,15 @@
import { cn } from '@/lib/cn'; import { cn } from '@/lib/cn';
// Official 3x-ui logo (media/3x-ui-{light,dark}.png from the upstream repo). // Official L-UI logo (media/L-UI-{light,dark}.png from the upstream repo).
// Theme-aware via Tailwind's `dark:` variant. Pass a height class (e.g. `h-6`); // Theme-aware via Tailwind's `dark:` variant. Pass a height class (e.g. `h-6`);
// width scales automatically (the artwork is 2:1). // width scales automatically (the artwork is 2:1).
export function Logo({ className }: { className?: string }) { export function Logo({ className }: { className?: string }) {
return ( return (
<> <>
{/* eslint-disable-next-line @next/next/no-img-element */} {/* eslint-disable-next-line @next/next/no-img-element */}
<img src="/logo-light.png" alt="3x-ui" className={cn('w-auto dark:hidden', className)} /> <img src="/logo-light.png" alt="L-UI" className={cn('w-auto dark:hidden', className)} />
{/* eslint-disable-next-line @next/next/no-img-element */} {/* eslint-disable-next-line @next/next/no-img-element */}
<img src="/logo-dark.png" alt="3x-ui" className={cn('hidden w-auto dark:block', className)} /> <img src="/logo-dark.png" alt="L-UI" className={cn('hidden w-auto dark:block', className)} />
</> </>
); );
} }
@@ -35,7 +35,7 @@ export function ApiRequestBuilder() {
return ( return (
<ToolFrame <ToolFrame
title="API request builder" title="API request builder"
description="Build an authenticated cURL command or fetch() snippet for any 3x-ui panel API endpoint under /panel/api/*." description="Build an authenticated cURL command or fetch() snippet for any L-UI panel API endpoint under /panel/api/*."
onReset={reset} onReset={reset}
> >
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2"> <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
+1 -1
View File
@@ -1,6 +1,6 @@
--- ---
title: AmneziaWG title: AmneziaWG
description: Set up an AmneziaWG inbound in 3x-ui — obfuscation parameters, native IPv6, per-client port-forwarding, and routing client traffic through Xray. description: Set up an AmneziaWG inbound in L-UI — obfuscation parameters, native IPv6, per-client port-forwarding, and routing client traffic through Xray.
icon: Lock icon: Lock
--- ---
+1 -1
View File
@@ -1,6 +1,6 @@
--- ---
title: Clients title: Clients
description: Manage 3x-ui clients — credentials, traffic and expiry limits, IP limits, groups, bulk actions, external links, and online status. description: Manage L-UI clients — credentials, traffic and expiry limits, IP limits, groups, bulk actions, external links, and online status.
icon: Users icon: Users
--- ---
+2 -2
View File
@@ -1,6 +1,6 @@
--- ---
title: Inbounds & Protocols title: Inbounds & Protocols
description: Create inbounds in 3x-ui — protocols, transports, traffic reset and expiry, and fallbacks that serve multiple protocols on one port. description: Create inbounds in L-UI — protocols, transports, traffic reset and expiry, and fallbacks that serve multiple protocols on one port.
icon: ArrowDownToLine icon: ArrowDownToLine
--- ---
@@ -75,7 +75,7 @@ The inbound editor accepts these protocols:
Fallbacks let a single TLS port (e.g. `443`) serve more than one protocol — for Fallbacks let a single TLS port (e.g. `443`) serve more than one protocol — for
example VLESS **and** Trojan — by routing unmatched handshakes to a child example VLESS **and** Trojan — by routing unmatched handshakes to a child
inbound. In 3x-ui, fallbacks are managed in the panel (a master inbound's inbound. In L-UI, fallbacks are managed in the panel (a master inbound's
**Fallbacks** list) rather than hand-written into JSON. **Fallbacks** list) rather than hand-written into JSON.
Fallbacks are available only when the master inbound is: Fallbacks are available only when the master inbound is:
+4 -4
View File
@@ -1,6 +1,6 @@
--- ---
title: Panel Settings title: Panel Settings
description: Every 3x-ui panel setting — web server, TLS, display, security, and notifications — with defaults from the source. description: Every L-UI panel setting — web server, TLS, display, security, and notifications — with defaults from the source.
icon: SlidersHorizontal icon: SlidersHorizontal
--- ---
@@ -14,7 +14,7 @@ browser in full.
| Setting | Default | Meaning | | Setting | Default | Meaning |
| ------------------- | ----------------------- | ----------------------------------------------------------------------- | | ------------------- | ----------------------- | ----------------------------------------------------------------------- |
| `webPort` | `2053` | Panel port (1–65535). The `XUI_PORT` env var overrides it at runtime. | | `webPort` | `2053` | Panel port (1–65535). The `LUI_PORT` env var overrides it at runtime. |
| `webListen` | _(all interfaces)_ | Bind the panel to a specific IP. | | `webListen` | _(all interfaces)_ | Bind the panel to a specific IP. |
| `webBasePath` | `/` | URL path the panel is served under (always normalized to `/…/`). | | `webBasePath` | `/` | URL path the panel is served under (always normalized to `/…/`). |
| `webCertFile` / `webKeyFile` | _(none)_ | TLS certificate + key. When both are set, the panel serves **HTTPS**. | | `webCertFile` / `webKeyFile` | _(none)_ | TLS certificate + key. When both are set, the panel serves **HTTPS**. |
@@ -24,12 +24,12 @@ browser in full.
After changing the port or base path, the panel URL becomes After changing the port or base path, the panel URL becomes
`http(s)://<server>:<port><web-base-path>`. You can preset the base path on first `http(s)://<server>:<port><web-base-path>`. You can preset the base path on first
launch with [`XUI_INIT_WEB_BASE_PATH`](/docs/reference/env-vars). launch with [`LUI_INIT_WEB_BASE_PATH`](/docs/reference/env-vars).
### TLS ### TLS
Serving the panel over HTTPS protects your credentials in transit. Either set Serving the panel over HTTPS protects your credentials in transit. Either set
`webCertFile` + `webKeyFile` — the [`x-ui` SSL menu](/docs/config/ssl-certificates) `webCertFile` + `webKeyFile` — the [`l-ui` SSL menu](/docs/config/ssl-certificates)
can obtain a Let's Encrypt certificate for you — or terminate TLS at a can obtain a Let's Encrypt certificate for you — or terminate TLS at a
[reverse proxy](/docs/operations/reverse-proxy). [reverse proxy](/docs/operations/reverse-proxy).
+2 -2
View File
@@ -1,6 +1,6 @@
--- ---
title: REALITY title: REALITY
description: Set up a VLESS + REALITY inbound with XTLS-Vision in 3x-ui — keys, short IDs, SNI, fingerprints, and common pitfalls. description: Set up a VLESS + REALITY inbound with XTLS-Vision in L-UI — keys, short IDs, SNI, fingerprints, and common pitfalls.
icon: ShieldCheck icon: ShieldCheck
--- ---
@@ -15,7 +15,7 @@ REALITY is used with **VLESS** (and Trojan). The recommended flow is
## Key settings ## Key settings
When you choose **REALITY** as the security mode on a VLESS inbound, 3x-ui When you choose **REALITY** as the security mode on a VLESS inbound, L-UI
exposes these fields: exposes these fields:
| Field | What it is | | Field | What it is |
+2 -2
View File
@@ -1,10 +1,10 @@
--- ---
title: Share Links title: Share Links
description: 3x-ui share-link formats (vless, vmess, trojan, ss, hysteria2, mtproto), the remark template variables, and an in-browser link inspector. description: L-UI share-link formats (vless, vmess, trojan, ss, hysteria2, mtproto), the remark template variables, and an in-browser link inspector.
icon: Link icon: Link
--- ---
3x-ui generates a **share link** (and QR code) for each client. Client apps such L-UI generates a **share link** (and QR code) for each client. Client apps such
as v2rayNG, Hiddify, and Mihomo import these links to configure themselves. as v2rayNG, Hiddify, and Mihomo import these links to configure themselves.
## Link formats ## Link formats
@@ -1,6 +1,6 @@
--- ---
title: SSL Certificates title: SSL Certificates
description: Get and renew TLS certificates for the 3x-ui panel and inbounds — with the x-ui ACME menu (domain or bare IP), a Cloudflare DNS-01 wildcard, or manual Certbot. description: Get and renew TLS certificates for the L-UI panel and inbounds — with the l-ui ACME menu (domain or bare IP), a Cloudflare DNS-01 wildcard, or manual Certbot.
icon: ShieldCheck icon: ShieldCheck
--- ---
@@ -8,7 +8,7 @@ A TLS certificate lets you serve the **panel** over HTTPS (so your login and API
traffic are encrypted) and terminate TLS on **inbounds** (VLESS-TLS, Trojan, traffic are encrypted) and terminate TLS on **inbounds** (VLESS-TLS, Trojan,
Shadowsocks-TLS, and friends). There are three ways to obtain one: Shadowsocks-TLS, and friends). There are three ways to obtain one:
- **The `x-ui` menu** — built-in [ACME](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment) - **The `l-ui` menu** — built-in [ACME](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment)
client. Easiest for a single domain or a bare IP. client. Easiest for a single domain or a bare IP.
- **Cloudflare DNS-01** — also from the menu; needed for **wildcard** certs or - **Cloudflare DNS-01** — also from the menu; needed for **wildcard** certs or
when port 80 is blocked / the server sits behind Cloudflare's proxy. when port 80 is blocked / the server sits behind Cloudflare's proxy.
@@ -22,9 +22,9 @@ Shadowsocks-TLS, and friends). There are three ways to obtain one:
inbounds. inbounds.
</Callout> </Callout>
## The `x-ui` SSL menu (Let's Encrypt) ## The `l-ui` SSL menu (Let's Encrypt)
Run `x-ui` and choose **`20` — SSL Certificate Management**. It drives Run `l-ui` and choose **`20` — SSL Certificate Management**. It drives
[acme.sh](https://github.com/acmesh-official/acme.sh) and offers: [acme.sh](https://github.com/acmesh-official/acme.sh) and offers:
| Option | What it does | | Option | What it does |
@@ -58,7 +58,7 @@ use. Stop anything bound to it for the duration, and allow it through the
<Step> <Step>
### Run the issuer ### Run the issuer
`x-ui` → `20` → **Get SSL (Domain)**, then enter the domain. acme.sh requests `l-ui` → `20` → **Get SSL (Domain)**, then enter the domain. acme.sh requests
the certificate and saves it under `/root/cert/<domain>/` as `fullchain.pem` the certificate and saves it under `/root/cert/<domain>/` as `fullchain.pem`
(the certificate chain) and `privkey.pem` (the private key). (the certificate chain) and `privkey.pem` (the private key).
</Step> </Step>
@@ -105,7 +105,7 @@ it. Copy the token — it's shown only once.
<Step> <Step>
### Run the Cloudflare issuer ### Run the Cloudflare issuer
`x-ui` → **`21` — Cloudflare SSL Certificate**. When asked, choose **`t`** for an `l-ui` → **`21` — Cloudflare SSL Certificate**. When asked, choose **`t`** for an
API token (the default) or **`g`** for the Global API Key, then enter your API token (the default) or **`g`** for the Global API Key, then enter your
domain (and, for the Global API Key, your account email and key). acme.sh creates domain (and, for the Global API Key, your account email and key). acme.sh creates
the TXT record, validates, and cleans it up. the TXT record, validates, and cleans it up.
+2 -2
View File
@@ -1,6 +1,6 @@
--- ---
title: Subscription title: Subscription
description: Run the 3x-ui subscription server — base64/JSON/Clash formats, ports and paths, TLS, response headers, and custom templates. description: Run the L-UI subscription server — base64/JSON/Clash formats, ports and paths, TLS, response headers, and custom templates.
icon: Rss icon: Rss
--- ---
@@ -58,7 +58,7 @@ page instead of the raw body.
The **Base64** body is just the newline-joined share links, standard-base64 The **Base64** body is just the newline-joined share links, standard-base64
encoded (toggle with `subEncrypt`). The **JSON** body wraps each client in a encoded (toggle with `subEncrypt`). The **JSON** body wraps each client in a
complete Xray client config — a fixed skeleton (local mixed/HTTP inbounds, DNS, complete Xray client config — a fixed skeleton (local mixed/HTTP inbounds, DNS,
routing, policy) plus a `proxy` outbound pointing at the inbound. 3x-ui emits a routing, policy) plus a `proxy` outbound pointing at the inbound. L-UI emits a
**single config object for one client and an array for several**, uses the flat **single config object for one client and an array for several**, uses the flat
outbound `settings` form (`address`/`port`/`id`, `level: 8`), and strips outbound `settings` form (`address`/`port`/`id`, `level: 8`), and strips
`sockopt` from `streamSettings`. `sockopt` from `streamSettings`.
+1 -1
View File
@@ -1,6 +1,6 @@
--- ---
title: Transports & Security title: Transports & Security
description: Every transport 3x-ui exposes — TCP, mKCP, WebSocket, gRPC, HTTPUpgrade, XHTTP, Hysteria — with their settings, plus FinalMask obfuscation, sockopt, TLS/REALITY, XTLS-Vision, and VLESS encryption. description: Every transport L-UI exposes — TCP, mKCP, WebSocket, gRPC, HTTPUpgrade, XHTTP, Hysteria — with their settings, plus FinalMask obfuscation, sockopt, TLS/REALITY, XTLS-Vision, and VLESS encryption.
icon: Network icon: Network
--- ---
+16 -16
View File
@@ -1,6 +1,6 @@
--- ---
title: First Login title: First Login
description: Find your generated 3x-ui credentials, reach the panel, enable two-factor auth, and harden it before exposing anything. description: Find your generated L-UI credentials, reach the panel, enable two-factor auth, and harden it before exposing anything.
icon: KeyRound icon: KeyRound
--- ---
@@ -24,25 +24,25 @@ path, so check your actual values.
A script install prints a credential summary when it finishes and also writes it A script install prints a credential summary when it finishes and also writes it
to a root-only file: to a root-only file:
```bash title="/etc/x-ui/install-result.env (mode 600)" ```bash title="/etc/l-ui/install-result.env (mode 600)"
XUI_USERNAME=... LUI_USERNAME=...
XUI_PASSWORD=... LUI_PASSWORD=...
XUI_PANEL_PORT=... LUI_PANEL_PORT=...
XUI_WEB_BASE_PATH=... LUI_WEB_BASE_PATH=...
XUI_ACCESS_URL=... LUI_ACCESS_URL=...
XUI_API_TOKEN=... LUI_API_TOKEN=...
XUI_DB_TYPE=sqlite LUI_DB_TYPE=sqlite
``` ```
If you missed them, use the management tools: If you missed them, use the management tools:
```bash ```bash
x-ui # menu → 11 (View Current Settings) l-ui # menu → 11 (View Current Settings)
x-ui settings # or the one-shot form l-ui settings # or the one-shot form
``` ```
For **Docker**, read the generated credentials from the container logs, or run For **Docker**, read the generated credentials from the container logs, or run
`docker exec -it <container> x-ui setting -show`. `docker exec -it <container> l-ui setting -show`.
<Callout type="warn"> <Callout type="warn">
If your panel still uses the default `admin` / `admin` (the panel warns when it If your panel still uses the default `admin` / `admin` (the panel warns when it
@@ -53,7 +53,7 @@ For **Docker**, read the generated credentials from the container logs, or run
A non-default port and a long, random **web base path** make the panel much A non-default port and a long, random **web base path** make the panel much
harder to find. Change them from **Panel Settings** in the UI, or from the harder to find. Change them from **Panel Settings** in the UI, or from the
`x-ui` menu: `l-ui` menu:
- **7 — Reset Username & Password** (optionally disabling 2FA at the same time) - **7 — Reset Username & Password** (optionally disabling 2FA at the same time)
- **8 — Reset Web Base Path** (randomizes it) - **8 — Reset Web Base Path** (randomizes it)
@@ -64,11 +64,11 @@ two-factor auth was on, disables it.
## Two-factor authentication (2FA) ## Two-factor authentication (2FA)
3x-ui supports TOTP two-factor auth (compatible with Google Authenticator, Aegis, L-UI supports TOTP two-factor auth (compatible with Google Authenticator, Aegis,
etc.). Enable it in **Panel Settings** — once enabled, the login page asks for a etc.). Enable it in **Panel Settings** — once enabled, the login page asks for a
6-digit code in addition to your password, and turning it on forces everyone to 6-digit code in addition to your password, and turning it on forces everyone to
log in again. You can disable it from the menu's **Reset Username & Password** log in again. You can disable it from the menu's **Reset Username & Password**
step or with `x-ui setting -resetTwoFactor`. step or with `l-ui setting -resetTwoFactor`.
## Built-in login protection ## Built-in login protection
@@ -105,7 +105,7 @@ Turn on 2FA so a leaked password alone can't grant access.
<Step> <Step>
### Put the panel behind TLS ### Put the panel behind TLS
Use a valid certificate (via the `x-ui` menu's SSL management, or a reverse Use a valid certificate (via the `l-ui` menu's SSL management, or a reverse
proxy) so the panel is only reachable over HTTPS. proxy) so the panel is only reachable over HTTPS.
</Step> </Step>
+6 -6
View File
@@ -1,10 +1,10 @@
--- ---
title: Meet 3x-ui title: Meet L-UI
description: A web panel for Xray-core — manage inbounds, protocols, clients, and subscriptions from your browser instead of editing JSON by hand. description: A web panel for Xray-core — manage inbounds, protocols, clients, and subscriptions from your browser instead of editing JSON by hand.
icon: Info icon: Info
--- ---
**3x-ui** is a web control panel that sits on top of **L-UI** is a web control panel that sits on top of
[Xray-core](https://github.com/XTLS/Xray-core), the proxy engine that actually [Xray-core](https://github.com/XTLS/Xray-core), the proxy engine that actually
moves your traffic. Instead of writing and reloading Xray's JSON configuration moves your traffic. Instead of writing and reloading Xray's JSON configuration
by hand, you manage everything — inbounds, protocols, clients, certificates, by hand, you manage everything — inbounds, protocols, clients, certificates,
@@ -15,7 +15,7 @@ subscriptions — from a browser dashboard.
<Mermaid <Mermaid
chart={` chart={`
flowchart LR flowchart LR
Admin["Admin browser"] -->|HTTPS panel| Panel["3x-ui panel"] Admin["Admin browser"] -->|HTTPS panel| Panel["L-UI panel"]
Panel -->|writes config, reloads| Xray["Xray-core"] Panel -->|writes config, reloads| Xray["Xray-core"]
Panel --- DB[("SQLite or PostgreSQL")] Panel --- DB[("SQLite or PostgreSQL")]
Clients["Client apps"] -->|VLESS / VMess / Trojan / ...| Xray Clients["Client apps"] -->|VLESS / VMess / Trojan / ...| Xray
@@ -52,18 +52,18 @@ flowchart LR
| Database | SQLite (default) or PostgreSQL | | Database | SQLite (default) or PostgreSQL |
| Proxy engine | Xray-core (bundled and managed by the panel) | | Proxy engine | Xray-core (bundled and managed by the panel) |
The default SQLite database lives at `/etc/x-ui/x-ui.db`, and the panel listens The default SQLite database lives at `/etc/l-ui/l-ui.db`, and the panel listens
on port **2053** by default. Both are configurable — see on port **2053** by default. Both are configurable — see
[First login](/docs/guide/first-login) and the environment variable reference. [First login](/docs/guide/first-login) and the environment variable reference.
## Who it's for ## Who it's for
3x-ui is aimed at anyone running their own Xray server: from a single personal L-UI is aimed at anyone running their own Xray server: from a single personal
VPS to operators managing many nodes and clients. If you want the power of VPS to operators managing many nodes and clients. If you want the power of
Xray-core without living in JSON config files, this is for you. Xray-core without living in JSON config files, this is for you.
<Callout type="info"> <Callout type="info">
3x-ui is an enhanced fork of the original X-UI project, adding broader protocol L-UI is an enhanced fork of the original X-UI project, adding broader protocol
support, improved stability, per-client traffic accounting, multi-node support, improved stability, per-client traffic accounting, multi-node
management, and many quality-of-life features. management, and many quality-of-life features.
</Callout> </Callout>
+18 -18
View File
@@ -1,17 +1,17 @@
--- ---
title: Installation title: Installation
description: Install 3x-ui via the official script (stable, pinned, or dev-latest), unattended/cloud-init, or Docker — and choose SQLite or PostgreSQL. description: Install L-UI via the official script (stable, pinned, or dev-latest), unattended/cloud-init, or Docker — and choose SQLite or PostgreSQL.
icon: Download icon: Download
--- ---
3x-ui runs on a wide range of Linux distributions — Ubuntu, Debian, Armbian, L-UI runs on a wide range of Linux distributions — Ubuntu, Debian, Armbian,
Fedora, CentOS, RHEL, AlmaLinux, Rocky Linux, Oracle Linux, Amazon Linux, Fedora, CentOS, RHEL, AlmaLinux, Rocky Linux, Oracle Linux, Amazon Linux,
Virtuozzo, Arch, Manjaro, openSUSE (Tumbleweed/Leap), Alpine — and Windows, Virtuozzo, Arch, Manjaro, openSUSE (Tumbleweed/Leap), Alpine — and Windows,
across `amd64`, `386`, `arm64`, `armv7`, `armv6`, `armv5`, and `s390x`. across `amd64`, `386`, `arm64`, `armv7`, `armv6`, `armv5`, and `s390x`.
<Callout type="warn"> <Callout type="warn">
Run the script installer as **root** (or with `sudo`). It installs a service, Run the script installer as **root** (or with `sudo`). It installs a service,
sets up the `x-ui` management command, and enables the panel on boot. sets up the `l-ui` management command, and enables the panel on boot.
</Callout> </Callout>
<Tabs items={['Script', 'Docker', 'Manual']}> <Tabs items={['Script', 'Docker', 'Manual']}>
@@ -20,7 +20,7 @@ across `amd64`, `386`, `arm64`, `armv7`, `armv6`, `armv5`, and `s390x`.
The official script is the recommended path. During installation it generates a The official script is the recommended path. During installation it generates a
**random** username, password, and access (web base) path, sets up the service, **random** username, password, and access (web base) path, sets up the service,
and installs the `x-ui` management command. and installs the `l-ui` management command.
```bash title="latest stable" ```bash title="latest stable"
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
@@ -39,8 +39,8 @@ Install the rolling **dev** build (the latest per-commit pre-release from `main`
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) dev-latest bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) dev-latest
``` ```
When it finishes, note the printed login details and run `x-ui` to open the When it finishes, note the printed login details and run `l-ui` to open the
[management menu](/docs/guide/update-uninstall#the-x-ui-management-menu), then [management menu](/docs/guide/update-uninstall#the-l-ui-management-menu), then
continue to [First login](/docs/guide/first-login). continue to [First login](/docs/guide/first-login).
</Tab> </Tab>
@@ -54,7 +54,7 @@ The default Compose setup uses SQLite. Clone the repo (or copy its
docker compose up -d docker compose up -d
``` ```
To run with the bundled **PostgreSQL** service, uncomment the two `XUI_DB_*` To run with the bundled **PostgreSQL** service, uncomment the two `LUI_DB_*`
lines in `docker-compose.yml` and start with the profile: lines in `docker-compose.yml` and start with the profile:
```bash ```bash
@@ -70,16 +70,16 @@ otherwise bans are logged but never applied:
docker run -d \ docker run -d \
--cap-add=NET_ADMIN \ --cap-add=NET_ADMIN \
--cap-add=NET_RAW \ --cap-add=NET_RAW \
-e XUI_ENABLE_FAIL2BAN=true \ -e LUI_ENABLE_FAIL2BAN=true \
-v $PWD/db/:/etc/x-ui/ \ -v $PWD/db/:/etc/l-ui/ \
-v $PWD/cert/:/root/cert/ \ -v $PWD/cert/:/root/cert/ \
--network=host \ --network=host \
--restart=unless-stopped \ --restart=unless-stopped \
--name 3x-ui \ --name L-UI \
ghcr.io/mhsanaei/3x-ui:latest ghcr.io/mhsanaei/3x-ui:latest
``` ```
The `db/` volume holds the SQLite database (`/etc/x-ui/x-ui.db`) and `cert/` The `db/` volume holds the SQLite database (`/etc/l-ui/l-ui.db`) and `cert/`
holds TLS certificates, so your data survives upgrades. holds TLS certificates, so your data survives upgrades.
</Tab> </Tab>
@@ -87,7 +87,7 @@ holds TLS certificates, so your data survives upgrades.
<Tab value="Manual"> <Tab value="Manual">
For advanced users, download a release archive for your architecture from the For advanced users, download a release archive for your architecture from the
[releases page](https://github.com/MHSanaei/3x-ui/releases), extract it, and run [releases page](https://github.com/MHSanaei/L-UI/releases), extract it, and run
the binary as a systemd service. The install script automates exactly these the binary as a systemd service. The install script automates exactly these
steps, so it's preferred unless you have a specific reason to install by hand. steps, so it's preferred unless you have a specific reason to install by hand.
@@ -105,7 +105,7 @@ Tailor the command to your setup:
You pick the storage backend at install time: You pick the storage backend at install time:
- **SQLite** (default) — a single file at `/etc/x-ui/x-ui.db`. Zero setup. - **SQLite** (default) — a single file at `/etc/l-ui/l-ui.db`. Zero setup.
- **PostgreSQL** — for high client counts or multi-node setups. The installer - **PostgreSQL** — for high client counts or multi-node setups. The installer
can install it locally or use a DSN you provide. can install it locally or use a DSN you provide.
@@ -115,15 +115,15 @@ migration.
## Unattended / cloud-init ## Unattended / cloud-init
The installer also runs **non-interactively** for automation. Set The installer also runs **non-interactively** for automation. Set
`XUI_NONINTERACTIVE=1` (or run with no TTY) and it installs end-to-end with zero `LUI_NONINTERACTIVE=1` (or run with no TTY) and it installs end-to-end with zero
prompts, generating random credentials and writing them to prompts, generating random credentials and writing them to
`/etc/x-ui/install-result.env`: `/etc/l-ui/install-result.env`:
```bash ```bash
XUI_NONINTERACTIVE=1 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) LUI_NONINTERACTIVE=1 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
``` ```
The repo's [`deploy/`](https://github.com/MHSanaei/3x-ui/tree/main/deploy) The repo's [`deploy/`](https://github.com/MHSanaei/L-UI/tree/main/deploy)
directory has ready-made **cloud-init** user-data for unattended installs on any directory has ready-made **cloud-init** user-data for unattended installs on any
cloud (Hetzner, AWS, DigitalOcean, Vultr, GCP, Azure, Oracle). cloud (Hetzner, AWS, DigitalOcean, Vultr, GCP, Azure, Oracle).
@@ -138,7 +138,7 @@ cloud (Hetzner, AWS, DigitalOcean, Vultr, GCP, Azure, Oracle).
<Card <Card
title="Update & uninstall" title="Update & uninstall"
href="/docs/guide/update-uninstall" href="/docs/guide/update-uninstall"
description="The x-ui menu, updates, and removal." description="The l-ui menu, updates, and removal."
/> />
<Card <Card
title="REALITY" title="REALITY"
+26 -26
View File
@@ -1,17 +1,17 @@
--- ---
title: Update & Uninstall title: Update & Uninstall
description: Manage 3x-ui with the x-ui menu and CLI — update (stable, dev, or legacy), change settings, and uninstall cleanly. description: Manage L-UI with the l-ui menu and CLI — update (stable, dev, or legacy), change settings, and uninstall cleanly.
icon: RefreshCw icon: RefreshCw
--- ---
After a script install, the `x-ui` command is your control center. Run it with After a script install, the `l-ui` command is your control center. Run it with
no arguments for the interactive menu, or pass a subcommand for a one-shot action. no arguments for the interactive menu, or pass a subcommand for a one-shot action.
```bash ```bash
x-ui l-ui
``` ```
## The `x-ui` management menu ## The `l-ui` management menu
The menu (items `0`–`28`) shows the panel/Xray status at the top, then: The menu (items `0`–`28`) shows the panel/Xray status at the top, then:
@@ -20,9 +20,9 @@ The menu (items `0`–`28`) shows the panel/Xray status at the top, then:
| 1 | Install | (Re)install from the remote script | | 1 | Install | (Re)install from the remote script |
| 2 | Update | Update to the latest **stable** release | | 2 | Update | Update to the latest **stable** release |
| 3 | Update to Dev Channel (latest commit) | Update to the rolling `dev-latest` build | | 3 | Update to Dev Channel (latest commit) | Update to the rolling `dev-latest` build |
| 4 | Update Menu | Update just the `x-ui` menu script | | 4 | Update Menu | Update just the `l-ui` menu script |
| 5 | Legacy Version | Install a specific older version (prompts for a tag) | | 5 | Legacy Version | Install a specific older version (prompts for a tag) |
| 6 | Uninstall | Remove 3x-ui (see below) | | 6 | Uninstall | Remove L-UI (see below) |
| 7 | Reset Username & Password | Set new credentials; optionally disable 2FA | | 7 | Reset Username & Password | Set new credentials; optionally disable 2FA |
| 8 | Reset Web Base Path | Randomize the web base path | | 8 | Reset Web Base Path | Randomize the web base path |
| 9 | Reset Settings | Reset panel settings (your account is preserved) | | 9 | Reset Settings | Reset panel settings (your account is preserved) |
@@ -51,29 +51,29 @@ Some of these have their own pages: [SSL certificates](/docs/config/ssl-certific
## CLI subcommands ## CLI subcommands
For scripts and quick actions, `x-ui` also takes a subcommand directly: For scripts and quick actions, `l-ui` also takes a subcommand directly:
| Command | Action | | Command | Action |
| -------------------------- | --------------------------------------------------- | | -------------------------- | --------------------------------------------------- |
| `x-ui start` / `stop` / `restart` | Control the service | | `l-ui start` / `stop` / `restart` | Control the service |
| `x-ui restart-xray` | Reload only Xray-core | | `l-ui restart-xray` | Reload only Xray-core |
| `x-ui status` | Show status | | `l-ui status` | Show status |
| `x-ui settings` | Show current settings | | `l-ui settings` | Show current settings |
| `x-ui enable` / `disable` | Toggle autostart on boot | | `l-ui enable` / `disable` | Toggle autostart on boot |
| `x-ui log` | Tail the debug log | | `l-ui log` | Tail the debug log |
| `x-ui banlog` | Show Fail2ban ban log | | `l-ui banlog` | Show Fail2ban ban log |
| `x-ui update` | Update to the latest stable release | | `l-ui update` | Update to the latest stable release |
| `x-ui update-dev` | Update to the rolling `dev-latest` build | | `l-ui update-dev` | Update to the rolling `dev-latest` build |
| `x-ui legacy` | Install a specific older version (prompts) | | `l-ui legacy` | Install a specific older version (prompts) |
| `x-ui update-all-geofiles` | Update all geo files, restart if changed | | `l-ui update-all-geofiles` | Update all geo files, restart if changed |
| `x-ui migrate-db --dsn …` | Migrate SQLite → PostgreSQL (see [Database](/docs/reference/database)) | | `l-ui migrate-db --dsn …` | Migrate SQLite → PostgreSQL (see [Database](/docs/reference/database)) |
| `x-ui install` / `uninstall` | Install / uninstall | | `l-ui install` / `uninstall` | Install / uninstall |
## Updating ## Updating
- **Stable:** menu option **2** or `x-ui update`. Re-running the install script - **Stable:** menu option **2** or `l-ui update`. Re-running the install script
also updates in place. also updates in place.
- **Dev channel:** menu option **3** or `x-ui update-dev` — the rolling - **Dev channel:** menu option **3** or `l-ui update-dev` — the rolling
`dev-latest` per-commit build (not a stable release). `dev-latest` per-commit build (not a stable release).
- **A specific older version:** menu option **5** (Legacy Version). - **A specific older version:** menu option **5** (Legacy Version).
@@ -83,17 +83,17 @@ Updating preserves your database and settings. Take a
<Callout type="info"> <Callout type="info">
Docker users update differently — pull the new image and recreate the Docker users update differently — pull the new image and recreate the
container (`docker compose pull && docker compose up -d`) rather than using the container (`docker compose pull && docker compose up -d`) rather than using the
`x-ui` update commands. `l-ui` update commands.
</Callout> </Callout>
## Uninstalling ## Uninstalling
Menu option **6** or `x-ui uninstall`. It stops and disables the service, removes Menu option **6** or `l-ui uninstall`. It stops and disables the service, removes
the service unit, and deletes `/etc/x-ui/` and the install folder. If the panel the service unit, and deletes `/etc/l-ui/` and the install folder. If the panel
used a locally-installed PostgreSQL, it offers to purge that too (a separate, used a locally-installed PostgreSQL, it offers to purge that too (a separate,
irreversible confirmation). irreversible confirmation).
<Callout type="warn"> <Callout type="warn">
Uninstalling removes the database (`/etc/x-ui/x-ui.db`) and your configuration. Uninstalling removes the database (`/etc/l-ui/l-ui.db`) and your configuration.
[Back up](/docs/operations/backup-restore) first if you might need it. [Back up](/docs/operations/backup-restore) first if you might need it.
</Callout> </Callout>
+6 -6
View File
@@ -1,28 +1,28 @@
--- ---
title: Contributing title: Contributing
description: How to contribute to 3x-ui and to translate this documentation. description: How to contribute to L-UI and to translate this documentation.
icon: GitPullRequestArrow icon: GitPullRequestArrow
--- ---
3x-ui is community-driven. Contributions to the panel and to these docs are L-UI is community-driven. Contributions to the panel and to these docs are
welcome. welcome.
## Support the developer ## Support the developer
3x-ui is free and open source, built and maintained in the open. If it's useful L-UI is free and open source, built and maintained in the open. If it's useful
to you, consider supporting continued development: to you, consider supporting continued development:
- **Donate** at [donate.sanaei.dev](https://donate.sanaei.dev/) — the page shows - **Donate** at [donate.sanaei.dev](https://donate.sanaei.dev/) — the page shows
current funding **goals and targets** you can help reach. current funding **goals and targets** you can help reach.
- **Star** the [repository](https://github.com/MHSanaei/3x-ui) and share the - **Star** the [repository](https://github.com/MHSanaei/L-UI) and share the
project. project.
- **Join** the Telegram channel [@XrayUI](https://t.me/XrayUI) to follow news and - **Join** the Telegram channel [@XrayUI](https://t.me/XrayUI) to follow news and
help others. help others.
## Contribute to 3x-ui ## Contribute to L-UI
- Read the project's `CONTRIBUTING.md` in the - Read the project's `CONTRIBUTING.md` in the
[repository](https://github.com/MHSanaei/3x-ui). [repository](https://github.com/MHSanaei/L-UI).
- Open issues for bugs and feature requests with clear reproduction steps. - Open issues for bugs and feature requests with clear reproduction steps.
- Use Conventional Commits and keep pull requests focused. - Use Conventional Commits and keep pull requests focused.
+9 -9
View File
@@ -1,13 +1,13 @@
--- ---
title: FAQ title: FAQ
description: Frequently asked questions about 3x-ui — licensing, supported systems, databases, and clients. description: Frequently asked questions about L-UI — licensing, supported systems, databases, and clients.
icon: CircleQuestionMark icon: CircleQuestionMark
--- ---
## Is 3x-ui free and open source? ## Is L-UI free and open source?
Yes. 3x-ui is open source under the GPL-3.0 license. The source is on Yes. L-UI is open source under the GPL-3.0 license. The source is on
[GitHub](https://github.com/MHSanaei/3x-ui). [GitHub](https://github.com/MHSanaei/L-UI).
## What systems does it run on? ## What systems does it run on?
@@ -18,7 +18,7 @@ It also runs as a Docker container. See [Installation](/docs/guide/installation)
## SQLite or PostgreSQL? ## SQLite or PostgreSQL?
SQLite is the default and is fine for most deployments. PostgreSQL is available SQLite is the default and is fine for most deployments. PostgreSQL is available
for larger setups via `XUI_DB_TYPE=postgres` and `XUI_DB_DSN` — see the for larger setups via `LUI_DB_TYPE=postgres` and `LUI_DB_DSN` — see the
[environment variables](/docs/reference/env-vars). [environment variables](/docs/reference/env-vars).
## Which client apps work with it? ## Which client apps work with it?
@@ -27,9 +27,9 @@ Any Xray-compatible client — for example v2rayNG, Hiddify, and Clash/Mihomo.
Import a client's share link or QR code, or use a Import a client's share link or QR code, or use a
[subscription](/docs/config/subscription). [subscription](/docs/config/subscription).
## How is 3x-ui different from x-ui? ## How is L-UI different from l-ui?
3x-ui is an enhanced fork of the original X-UI project. It adds broader protocol L-UI is an enhanced fork of the original X-UI project. It adds broader protocol
support, improved stability, per-client traffic accounting, multi-node support, improved stability, per-client traffic accounting, multi-node
management, a 13-language UI, and many quality-of-life features. management, a 13-language UI, and many quality-of-life features.
@@ -37,11 +37,11 @@ management, a 13-language UI, and many quality-of-life features.
Re-run the install script (it updates in place), or pull the new Docker image. Re-run the install script (it updates in place), or pull the new Docker image.
See [Installation](/docs/guide/installation) and the See [Installation](/docs/guide/installation) and the
[releases page](https://github.com/MHSanaei/3x-ui/releases). [releases page](https://github.com/MHSanaei/L-UI/releases).
## Where can I get help? ## Where can I get help?
Join the official Telegram channel [@XrayUI](https://t.me/XrayUI) for Join the official Telegram channel [@XrayUI](https://t.me/XrayUI) for
announcements and community support, or open an issue on announcements and community support, or open an issue on
[GitHub](https://github.com/MHSanaei/3x-ui/issues). For common problems, start [GitHub](https://github.com/MHSanaei/L-UI/issues). For common problems, start
with [Troubleshooting](/docs/help/troubleshooting). with [Troubleshooting](/docs/help/troubleshooting).
+8 -8
View File
@@ -1,6 +1,6 @@
--- ---
title: Migration title: Migration
description: Migrate to 3x-ui from x-ui, between servers, or between 3x-ui versions. description: Migrate to L-UI from l-ui, between servers, or between L-UI versions.
icon: ArrowRightLeft icon: ArrowRightLeft
--- ---
@@ -13,12 +13,12 @@ Moving to a new server is a database move:
<Step> <Step>
### Back up the old server ### Back up the old server
Copy the database (default `/etc/x-ui/x-ui.db`) and your certificates. See Copy the database (default `/etc/l-ui/l-ui.db`) and your certificates. See
[Backup & restore](/docs/operations/backup-restore). [Backup & restore](/docs/operations/backup-restore).
</Step> </Step>
<Step> <Step>
### Install 3x-ui on the new server ### Install L-UI on the new server
Use the same install method and a compatible version. See Use the same install method and a compatible version. See
[Installation](/docs/guide/installation). [Installation](/docs/guide/installation).
@@ -33,17 +33,17 @@ panel. Update any IP/domain-specific settings.
</Steps> </Steps>
## Between 3x-ui versions ## Between L-UI versions
Within the same backend, upgrading is usually just re-running the installer or Within the same backend, upgrading is usually just re-running the installer or
pulling a new image — the panel migrates its own database. Across **major** pulling a new image — the panel migrates its own database. Across **major**
versions, read the [release notes](https://github.com/MHSanaei/3x-ui/releases) versions, read the [release notes](https://github.com/MHSanaei/L-UI/releases)
first and take a backup. first and take a backup.
## From x-ui ## From l-ui
Importing an older x-ui panel's database directly into 3x-ui is **not Importing an older l-ui panel's database directly into L-UI is **not
supported** — the schemas differ. Install 3x-ui fresh and recreate supported** — the schemas differ. Install L-UI fresh and recreate
inbounds/clients, exporting share links from the old panel as you go. inbounds/clients, exporting share links from the old panel as you go.
<Callout type="warn"> <Callout type="warn">
@@ -1,17 +1,17 @@
--- ---
title: Troubleshooting title: Troubleshooting
description: Fix common 3x-ui problems — the panel won't start, 502 errors, certificate issues, and clients that can't connect. description: Fix common L-UI problems — the panel won't start, 502 errors, certificate issues, and clients that can't connect.
icon: Wrench icon: Wrench
--- ---
A checklist for the most common issues. When in doubt, raise the log level A checklist for the most common issues. When in doubt, raise the log level
(`XUI_LOG_LEVEL=debug`) and check the panel and Xray logs. (`LUI_LOG_LEVEL=debug`) and check the panel and Xray logs.
## The panel won't start ## The panel won't start
- Check the service status and logs (`x-ui` menu → status/logs). - Check the service status and logs (`l-ui` menu → status/logs).
- Make sure the **panel port isn't already in use** by another service. - Make sure the **panel port isn't already in use** by another service.
- Verify the database path is writable (default `/etc/x-ui/x-ui.db`). - Verify the database path is writable (default `/etc/l-ui/l-ui.db`).
## 502 / panel unreachable behind a proxy ## 502 / panel unreachable behind a proxy
@@ -37,6 +37,6 @@ A checklist for the most common issues. When in doubt, raise the log level
<Callout type="info"> <Callout type="info">
Still stuck? Search the Still stuck? Search the
[GitHub issues](https://github.com/MHSanaei/3x-ui/issues) — your symptom has [GitHub issues](https://github.com/MHSanaei/L-UI/issues) — your symptom has
probably been seen before. probably been seen before.
</Callout> </Callout>
+5 -5
View File
@@ -1,10 +1,10 @@
--- ---
title: 3x-ui Documentation title: L-UI Documentation
description: Official documentation for 3x-ui — an advanced web panel for managing Xray-core servers, proxies, clients, and subscriptions. description: Official documentation for L-UI — an advanced web panel for managing Xray-core servers, proxies, clients, and subscriptions.
icon: House icon: House
--- ---
**3x-ui** is an open-source web panel for deploying and managing **L-UI** is an open-source web panel for deploying and managing
[Xray-core](https://github.com/XTLS/Xray-core) servers. It gives you a modern [Xray-core](https://github.com/XTLS/Xray-core) servers. It gives you a modern
dashboard for inbounds, protocols, clients, traffic accounting, subscriptions, dashboard for inbounds, protocols, clients, traffic accounting, subscriptions,
and more — without hand-editing Xray JSON on the command line. and more — without hand-editing Xray JSON on the command line.
@@ -17,7 +17,7 @@ leaves the page.
<Cards> <Cards>
<Card <Card
title="What is 3x-ui?" title="What is L-UI?"
href="/docs/guide" href="/docs/guide"
description="The big picture: Xray-core, the panel, and who it's for." description="The big picture: Xray-core, the panel, and who it's for."
/> />
@@ -49,6 +49,6 @@ leaves the page.
- **Operations** — multi-node management, Telegram bot, backups, and a REST API. - **Operations** — multi-node management, Telegram bot, backups, and a REST API.
<Callout type="info"> <Callout type="info">
New to Xray? Read [What is 3x-ui?](/docs/guide) first — it explains how the panel, Xray-core, and New to Xray? Read [What is L-UI?](/docs/guide) first — it explains how the panel, Xray-core, and
your client apps fit together. your client apps fit together.
</Callout> </Callout>
@@ -1,6 +1,6 @@
--- ---
title: Backup & Restore title: Backup & Restore
description: Back up and restore your 3x-ui database and certificates, manually or via the Telegram bot. description: Back up and restore your L-UI database and certificates, manually or via the Telegram bot.
icon: DatabaseBackup icon: DatabaseBackup
--- ---
@@ -9,7 +9,7 @@ database. Back it up regularly so you can recover or migrate.
## What to back up ## What to back up
- **The database** — SQLite at `/etc/x-ui/x-ui.db` by default (or your - **The database** — SQLite at `/etc/l-ui/l-ui.db` by default (or your
PostgreSQL database if you use that backend). PostgreSQL database if you use that backend).
- **Certificates** — anything under `/root/cert/` (or wherever you store TLS - **Certificates** — anything under `/root/cert/` (or wherever you store TLS
certs). certs).
@@ -20,7 +20,7 @@ You can download a backup from the panel's overview, or copy the database file
directly from the server: directly from the server:
```bash title="copy the SQLite database" ```bash title="copy the SQLite database"
cp /etc/x-ui/x-ui.db /root/x-ui-backup-$(date +%F).db cp /etc/l-ui/l-ui.db /root/l-ui-backup-$(date +%F).db
``` ```
To restore, stop the panel, put the database back in place, and start it again. To restore, stop the panel, put the database back in place, and start it again.
@@ -41,12 +41,12 @@ can also request a backup on demand from the bot's menu.
## SQLite dump / restore ## SQLite dump / restore
The `x-ui migrate-db` command converts the SQLite database to and from a plain The `l-ui migrate-db` command converts the SQLite database to and from a plain
SQL text dump (handy for inspection or transferring between machines): SQL text dump (handy for inspection or transferring between machines):
```bash ```bash
x-ui migrate-db --dump /root/x-ui.sql # SQLite -> SQL text l-ui migrate-db --dump /root/l-ui.sql # SQLite -> SQL text
x-ui migrate-db --restore /root/x-ui.sql # SQL text -> SQLite l-ui migrate-db --restore /root/l-ui.sql # SQL text -> SQLite
``` ```
To move to PostgreSQL instead, see [Database](/docs/reference/database). To move to PostgreSQL instead, see [Database](/docs/reference/database).
@@ -1,15 +1,15 @@
--- ---
title: Multi-node & Managed Hosts title: Multi-node & Managed Hosts
description: Manage multiple 3x-ui panels from one master, with API-token or mTLS trust, heartbeats, and per-inbound host overrides for subscriptions. description: Manage multiple L-UI panels from one master, with API-token or mTLS trust, heartbeats, and per-inbound host overrides for subscriptions.
icon: Boxes icon: Boxes
--- ---
3x-ui can manage **multiple servers** from a single master panel, and override L-UI can manage **multiple servers** from a single master panel, and override
how each inbound is advertised in subscriptions with **managed hosts**. how each inbound is advertised in subscriptions with **managed hosts**.
## Nodes ## Nodes
A **node** is another 3x-ui panel that your master panel manages over the node's A **node** is another L-UI panel that your master panel manages over the node's
API. The master polls each node and shows its status, versions, CPU/memory, API. The master polls each node and shows its status, versions, CPU/memory,
uptime, and traffic in one place. uptime, and traffic in one place.
@@ -1,11 +1,11 @@
--- ---
title: Outbounds & Routing title: Outbounds & Routing
description: Shape egress in 3x-ui — WARP, NordVPN, PIA WireGuard, outbound subscriptions, routing rules, and load balancers. description: Shape egress in L-UI — WARP, NordVPN, PIA WireGuard, outbound subscriptions, routing rules, and load balancers.
icon: Route icon: Route
--- ---
Inbounds accept clients; **outbounds** decide where their traffic goes next. Inbounds accept clients; **outbounds** decide where their traffic goes next.
3x-ui can route traffic through Cloudflare WARP, NordVPN, Private Internet Access L-UI can route traffic through Cloudflare WARP, NordVPN, Private Internet Access
(WireGuard), or arbitrary outbound pools imported from a subscription, (WireGuard), or arbitrary outbound pools imported from a subscription,
and select between them with routing rules and balancers. and select between them with routing rules and balancers.
@@ -39,7 +39,7 @@ inbound's transport and security. Two outbounds are almost always present:
A **proxy** outbound (VLESS, VMess, Trojan, Shadowsocks) forwards to another A **proxy** outbound (VLESS, VMess, Trojan, Shadowsocks) forwards to another
server — handy for chaining or sending select traffic abroad. Mind the wire server — handy for chaining or sending select traffic abroad. Mind the wire
shapes 3x-ui uses: **VLESS is the flat form** (`address`/`port`/`id`/`flow`/ shapes L-UI uses: **VLESS is the flat form** (`address`/`port`/`id`/`flow`/
`encryption`), **VMess uses `settings.vnext[]`**, and **Trojan/Shadowsocks use `encryption`), **VMess uses `settings.vnext[]`**, and **Trojan/Shadowsocks use
`settings.servers[]`**. The `streamSettings` must mirror the destination's `settings.servers[]`**. The `streamSettings` must mirror the destination's
[transport and security](/docs/config/transports). [transport and security](/docs/config/transports).
@@ -50,7 +50,7 @@ Assemble any outbound below and paste the JSON into **Xray Settings → Outbound
## Cloudflare WARP ## Cloudflare WARP
WARP lets your server egress through Cloudflare's network. 3x-ui can register a WARP lets your server egress through Cloudflare's network. L-UI can register a
WARP account for you and wire it into a WireGuard outbound tagged **`warp`**: WARP account for you and wire it into a WireGuard outbound tagged **`warp`**:
<Steps> <Steps>
@@ -64,7 +64,7 @@ Create a WireGuard outbound with the tag `warp` in your Xray config.
<Step> <Step>
### Register WARP ### Register WARP
From the panel's WARP controls, register an account. 3x-ui fills the outbound's From the panel's WARP controls, register an account. L-UI fills the outbound's
keys, addresses, reserved bytes, and peer endpoint automatically. keys, addresses, reserved bytes, and peer endpoint automatically.
</Step> </Step>
@@ -82,13 +82,13 @@ with a routing rule.
## NordVPN ## NordVPN
3x-ui can fetch NordVPN (NordLynx/WireGuard) credentials from an access token (or L-UI can fetch NordVPN (NordLynx/WireGuard) credentials from an access token (or
accept a private key directly) and list countries/servers, so you can build a accept a private key directly) and list countries/servers, so you can build a
NordVPN outbound. NordVPN outbound.
## PIA WireGuard ## PIA WireGuard
3x-ui can sign in with a PIA username and password, list countries/regions/servers L-UI can sign in with a PIA username and password, list countries/regions/servers
from the signed PIA server list, and build a WireGuard outbound. Open from the signed PIA server list, and build a WireGuard outbound. Open
**Xray → Outbounds → More → PIA**, sign in, pick a server, and add the outbound. **Xray → Outbounds → More → PIA**, sign in, pick a server, and add the outbound.
You can add several servers (one outbound per hostname). The tag is You can add several servers (one outbound per hostname). The tag is
@@ -100,7 +100,7 @@ revoke the WireGuard peer on the PIA account.
The password is not stored. The PIA API token is stored with the same The password is not stored. The PIA API token is stored with the same
`NODE_TOKEN_ENCRYPTION` setting as node API tokens. If you retire an old `NODE_TOKEN_ENCRYPTION` setting as node API tokens. If you retire an old
`XUI_NODE_TOKEN_KEY` without signing into PIA again, Add/Reset fail until you `LUI_NODE_TOKEN_KEY` without signing into PIA again, Add/Reset fail until you
re-login. Peer `allowedIPs` is IPv4-only (`0.0.0.0/0`). re-login. Peer `allowedIPs` is IPv4-only (`0.0.0.0/0`).
## Outbound subscriptions (server pools) ## Outbound subscriptions (server pools)
@@ -1,13 +1,13 @@
--- ---
title: Reverse Proxy title: Reverse Proxy
description: Put the 3x-ui panel and subscription behind Nginx or Caddy with Let's Encrypt TLS. description: Put the L-UI panel and subscription behind Nginx or Caddy with Let's Encrypt TLS.
icon: Waypoints icon: Waypoints
--- ---
A reverse proxy lets you serve the panel and subscription on a clean domain with A reverse proxy lets you serve the panel and subscription on a clean domain with
automatic HTTPS, and hide the real ports behind ports 80/443. Prefer to let the automatic HTTPS, and hide the real ports behind ports 80/443. Prefer to let the
panel terminate TLS directly? Get a certificate with the panel terminate TLS directly? Get a certificate with the
[`x-ui` SSL menu](/docs/config/ssl-certificates) instead. [`l-ui` SSL menu](/docs/config/ssl-certificates) instead.
## Generate a config ## Generate a config
@@ -45,7 +45,7 @@ panel.example.com {
## Tips ## Tips
- Keep the panel's **web base path** even behind a proxy; defense in depth. - Keep the panel's **web base path** even behind a proxy; defense in depth.
- If you terminate TLS at the proxy, you may want `XUI_SKIP_HSTS=true` on the - If you terminate TLS at the proxy, you may want `LUI_SKIP_HSTS=true` on the
panel — see the [environment variables reference](/docs/reference/env-vars). panel — see the [environment variables reference](/docs/reference/env-vars).
- Proxy the [subscription](/docs/config/subscription) server too, so its contents - Proxy the [subscription](/docs/config/subscription) server too, so its contents
are served over HTTPS. are served over HTTPS.
+10 -10
View File
@@ -1,6 +1,6 @@
--- ---
title: Security title: Security
description: Harden 3x-ui — panel auth and 2FA, Fail2ban IP limits, firewall rules, BBR, and staying current. description: Harden L-UI — panel auth and 2FA, Fail2ban IP limits, firewall rules, BBR, and staying current.
icon: ShieldCheck icon: ShieldCheck
--- ---
@@ -21,15 +21,15 @@ See [First login](/docs/guide/first-login) for the full checklist.
Set an **IP limit** per client (see [Clients](/docs/config/clients)) to cap the Set an **IP limit** per client (see [Clients](/docs/config/clients)) to cap the
number of simultaneous source IPs. Enforcement is handled by **Fail2ban**, which number of simultaneous source IPs. Enforcement is handled by **Fail2ban**, which
3x-ui installs and configures for you (enabled by default on script installs, and L-UI installs and configures for you (enabled by default on script installs, and
on Docker via `XUI_ENABLE_FAIL2BAN=true`). on Docker via `LUI_ENABLE_FAIL2BAN=true`).
Manage it from the `x-ui` menu (**22 — IP Limit Management**): install/configure, Manage it from the `l-ui` menu (**22 — IP Limit Management**): install/configure,
change the ban duration (default **30 minutes**), ban/unban an IP, view ban logs, change the ban duration (default **30 minutes**), ban/unban an IP, view ban logs,
and check status. Under the hood: and check status. Under the hood:
- The jail is named **`3x-ipl`**; ban logs live at `/var/log/x-ui/3xipl.log` and - The jail is named **`3x-ipl`**; ban logs live at `/var/log/l-ui/3xipl.log` and
`/var/log/x-ui/3xipl-banned.log` (also via `x-ui banlog`). `/var/log/l-ui/3xipl-banned.log` (also via `l-ui banlog`).
- Bans cover all TCP/UDP **except** your SSH and panel ports, so a ban can't lock - Bans cover all TCP/UDP **except** your SSH and panel ports, so a ban can't lock
you out of the server or panel. you out of the server or panel.
@@ -43,7 +43,7 @@ and check status. Under the hood:
## Firewall ## Firewall
Open only the ports you actually use: SSH, the panel port, the subscription Open only the ports you actually use: SSH, the panel port, the subscription
port, and your inbound ports. The `x-ui` menu (**23 — Firewall Management**) wraps port, and your inbound ports. The `l-ui` menu (**23 — Firewall Management**) wraps
`ufw`, or generate rules here: `ufw`, or generate rules here:
<FirewallRulesGenerator /> <FirewallRulesGenerator />
@@ -55,12 +55,12 @@ port, and your inbound ports. The `x-ui` menu (**23 — Firewall Management**) w
## Network tuning (BBR) ## Network tuning (BBR)
The `x-ui` menu (**26 — Enable BBR**) toggles Google's BBR congestion control The `l-ui` menu (**26 — Enable BBR**) toggles Google's BBR congestion control
(`net.ipv4.tcp_congestion_control = bbr`, `net.core.default_qdisc = fq`), which (`net.ipv4.tcp_congestion_control = bbr`, `net.core.default_qdisc = fq`), which
often improves throughput on congested links. often improves throughput on congested links.
## Keep current ## Keep current
Update 3x-ui and Xray-core regularly — security fixes land in new releases. Watch Update L-UI and Xray-core regularly — security fixes land in new releases. Watch
the [releases page](https://github.com/MHSanaei/3x-ui/releases) and see the [releases page](https://github.com/MHSanaei/L-UI/releases) and see
[Update & uninstall](/docs/guide/update-uninstall). [Update & uninstall](/docs/guide/update-uninstall).
@@ -1,10 +1,10 @@
--- ---
title: Telegram Bot title: Telegram Bot
description: Connect a Telegram bot to 3x-ui for commands, periodic reports, event alerts (login, CPU, node up/down), backups, and client self-service. description: Connect a Telegram bot to L-UI for commands, periodic reports, event alerts (login, CPU, node up/down), backups, and client self-service.
icon: Send icon: Send
--- ---
3x-ui can drive a Telegram bot for monitoring, alerts, backups, and remote L-UI can drive a Telegram bot for monitoring, alerts, backups, and remote
management. Admins get full control; regular users (linked by Telegram ID) can management. Admins get full control; regular users (linked by Telegram ID) can
check their own usage and links. check their own usage and links.
@@ -1,56 +0,0 @@
---
title: API Tokens
description: Manage scoped Bearer tokens for programmatic auth. Tokens grant
admin, monitor, or node-sync access, may expire, and are stored as SHA-256
hashes. The plaintext is returned only once at creation.
full: true
_openapi:
preload:
- ./public/openapi.json
toc:
- depth: 2
title: List every API token, enabled or not. The token value is never returned —
only metadata.
url: '#list-every-api-token-enabled-or-not-the-token-value-is-never-returned--only-metadata'
- depth: 2
title: Mint a scoped API token. The server-generated plaintext is returned only
once and stored as a hash.
url: '#mint-a-scoped-api-token-the-server-generated-plaintext-is-returned-only-once-and-stored-as-a-hash'
- depth: 2
title: Permanently delete a token. Any caller using it stops authenticating
immediately.
url: '#permanently-delete-a-token-any-caller-using-it-stops-authenticating-immediately'
- depth: 2
title: Toggle a token enabled/disabled without deleting it. Disabled tokens are
rejected by checkAPIAuth on the next request.
url: '#toggle-a-token-enableddisabled-without-deleting-it-disabled-tokens-are-rejected-by-checkapiauth-on-the-next-request'
structuredData:
headings:
- content: List every API token, enabled or not. The token value is never returned
— only metadata.
id: list-every-api-token-enabled-or-not-the-token-value-is-never-returned--only-metadata
- content: Mint a scoped API token. The server-generated plaintext is returned
only once and stored as a hash.
id: mint-a-scoped-api-token-the-server-generated-plaintext-is-returned-only-once-and-stored-as-a-hash
- content: Permanently delete a token. Any caller using it stops authenticating
immediately.
id: permanently-delete-a-token-any-caller-using-it-stops-authenticating-immediately
- content: Toggle a token enabled/disabled without deleting it. Disabled tokens
are rejected by checkAPIAuth on the next request.
id: toggle-a-token-enableddisabled-without-deleting-it-disabled-tokens-are-rejected-by-checkapiauth-on-the-next-request
contents: []
---
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
export default function Layout(props) {
const { APIPage, OpenAPIPage } = props.components ?? {};
// "APIPage" is the old name from v10, this allows both for backward compatibility
const Comp = OpenAPIPage ?? APIPage;
return (
<>
{props.children}
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/setting/apiTokens","method":"get"},{"path":"/panel/api/setting/apiTokens/create","method":"post"},{"path":"/panel/api/setting/apiTokens/delete/{id}","method":"post"},{"path":"/panel/api/setting/apiTokens/setEnabled/{id}","method":"post"}]} showTitle />
</>
);
}
+2 -2
View File
@@ -1,10 +1,10 @@
--- ---
title: API Reference title: API Reference
description: The 3x-ui panel REST API — authentication, inbounds, clients, server stats, and more, generated from the OpenAPI spec. description: The L-UI panel REST API — authentication, inbounds, clients, server stats, and more, generated from the OpenAPI spec.
icon: Webhook icon: Webhook
--- ---
The 3x-ui panel exposes a REST API for automation. These pages are generated from The L-UI panel exposes a REST API for automation. These pages are generated from
the panel's OpenAPI specification, so they always match the documented schema. the panel's OpenAPI specification, so they always match the documented schema.
## Authentication ## Authentication
@@ -4,7 +4,6 @@
"pages": [ "pages": [
"index", "index",
"authentication", "authentication",
"api-tokens",
"inbounds", "inbounds",
"clients", "clients",
"server", "server",
+11 -17
View File
@@ -1,6 +1,6 @@
--- ---
title: Nodes title: Nodes
description: Manage remote 3x-ui panels acting as nodes for a central panel. All description: Manage remote L-UI panels acting as nodes for a central panel. All
endpoints under /panel/api/nodes. endpoints under /panel/api/nodes.
full: true full: true
_openapi: _openapi:
@@ -37,15 +37,12 @@ _openapi:
panel. panel.
url: '#fetch-a-nodes-own-web-tls-certificatekey-file-paths-proxied-to-the-node-used-by-the-inbound-forms-set-cert-from-panel-so-a-node-assigned-inbound-gets-paths-that-exist-on-the-node-not-the-central-panel' url: '#fetch-a-nodes-own-web-tls-certificatekey-file-paths-proxied-to-the-node-used-by-the-inbound-forms-set-cert-from-panel-so-a-node-assigned-inbound-gets-paths-that-exist-on-the-node-not-the-central-panel'
- depth: 2 - depth: 2
title: Register a new remote node. Provide its URL, write-only apiToken, and title: Register a new remote node. Provide its URL and optional remark /
optional remark / allowPrivateAddress flag. Responses expose hasApiToken allowPrivateAddress flag.
only. url: '#register-a-new-remote-node-provide-its-url-and-optional-remark--allowprivateaddress-flag'
url: '#register-a-new-remote-node-provide-its-url-write-only-apitoken-and-optional-remark--allowprivateaddress-flag-responses-expose-hasapitoken-only'
- depth: 2 - depth: 2
title: 'Replace a node’s connection details. apiToken is write-only: omit it or title: Replace a node’s connection details.
send an empty string to keep the stored token; set clearApiToken=true to url: '#replace-a-nodes-connection-details'
clear it.'
url: '#replace-a-nodes-connection-details-apitoken-is-write-only-omit-it-or-send-an-empty-string-to-keep-the-stored-token-set-clearapitokentrue-to-clear-it'
- depth: 2 - depth: 2
title: Delete a node. Inbounds bound to it are not auto-migrated. title: Delete a node. Inbounds bound to it are not auto-migrated.
url: '#delete-a-node-inbounds-bound-to-it-are-not-auto-migrated' url: '#delete-a-node-inbounds-bound-to-it-are-not-auto-migrated'
@@ -105,14 +102,11 @@ _openapi:
node-assigned inbound gets paths that exist on the node, not the node-assigned inbound gets paths that exist on the node, not the
central panel. central panel.
id: fetch-a-nodes-own-web-tls-certificatekey-file-paths-proxied-to-the-node-used-by-the-inbound-forms-set-cert-from-panel-so-a-node-assigned-inbound-gets-paths-that-exist-on-the-node-not-the-central-panel id: fetch-a-nodes-own-web-tls-certificatekey-file-paths-proxied-to-the-node-used-by-the-inbound-forms-set-cert-from-panel-so-a-node-assigned-inbound-gets-paths-that-exist-on-the-node-not-the-central-panel
- content: Register a new remote node. Provide its URL, write-only apiToken, and - content: Register a new remote node. Provide its URL and optional remark /
optional remark / allowPrivateAddress flag. Responses expose allowPrivateAddress flag.
hasApiToken only. id: register-a-new-remote-node-provide-its-url-and-optional-remark--allowprivateaddress-flag
id: register-a-new-remote-node-provide-its-url-write-only-apitoken-and-optional-remark--allowprivateaddress-flag-responses-expose-hasapitoken-only - content: Replace a node’s connection details.
- content: 'Replace a node’s connection details. apiToken is write-only: omit it id: replace-a-nodes-connection-details
or send an empty string to keep the stored token; set
clearApiToken=true to clear it.'
id: replace-a-nodes-connection-details-apitoken-is-write-only-omit-it-or-send-an-empty-string-to-keep-the-stored-token-set-clearapitokentrue-to-clear-it
- content: Delete a node. Inbounds bound to it are not auto-migrated. - content: Delete a node. Inbounds bound to it are not auto-migrated.
id: delete-a-node-inbounds-bound-to-it-are-not-auto-migrated id: delete-a-node-inbounds-bound-to-it-are-not-auto-migrated
- content: Pause or resume traffic sync with this node. - content: Pause or resume traffic sync with this node.
@@ -53,8 +53,8 @@ _openapi:
title: List Xray binary versions available for install on this host. title: List Xray binary versions available for install on this host.
url: '#list-xray-binary-versions-available-for-install-on-this-host' url: '#list-xray-binary-versions-available-for-install-on-this-host'
- depth: 2 - depth: 2
title: Check whether a newer 3x-ui release is available on GitHub. title: Check whether a newer L-UI release is available on GitHub.
url: '#check-whether-a-newer-3x-ui-release-is-available-on-github' url: '#check-whether-a-newer-L-UI-release-is-available-on-github'
- depth: 2 - depth: 2
title: Report the outcome of the most recently launched panel self-update (see title: Report the outcome of the most recently launched panel self-update (see
POST updatePanel). Compare the returned runId against the one POST updatePanel). Compare the returned runId against the one
@@ -218,8 +218,8 @@ _openapi:
id: time-series-of-observatory-probe-results-for-one-outbound-tag-same-t-v-shape-as-the-other-history-endpoints id: time-series-of-observatory-probe-results-for-one-outbound-tag-same-t-v-shape-as-the-other-history-endpoints
- content: List Xray binary versions available for install on this host. - content: List Xray binary versions available for install on this host.
id: list-xray-binary-versions-available-for-install-on-this-host id: list-xray-binary-versions-available-for-install-on-this-host
- content: Check whether a newer 3x-ui release is available on GitHub. - content: Check whether a newer L-UI release is available on GitHub.
id: check-whether-a-newer-3x-ui-release-is-available-on-github id: check-whether-a-newer-L-UI-release-is-available-on-github
- content: Report the outcome of the most recently launched panel self-update (see - content: Report the outcome of the most recently launched panel self-update (see
POST updatePanel). Compare the returned runId against the one POST updatePanel). Compare the returned runId against the one
updatePanel returned to tell this run apart from a stale result. updatePanel returned to tell this run apart from a stale result.
@@ -36,10 +36,10 @@ _openapi:
values on success. values on success.
url: '#change-the-panel-admin-username-and-password-requires-the-current-credentials-for-verification-the-session-is-refreshed-with-the-new-values-on-success' url: '#change-the-panel-admin-username-and-password-requires-the-current-credentials-for-verification-the-session-is-refreshed-with-the-new-values-on-success'
- depth: 2 - depth: 2
title: Restart the entire 3x-ui process after a 3-second grace period. The title: Restart the entire L-UI process after a 3-second grace period. The
connection drops immediately; the panel comes back online ~5-10 seconds connection drops immediately; the panel comes back online ~5-10 seconds
later. later.
url: '#restart-the-entire-3x-ui-process-after-a-3-second-grace-period-the-connection-drops-immediately-the-panel-comes-back-online-5-10-seconds-later' url: '#restart-the-entire-L-UI-process-after-a-3-second-grace-period-the-connection-drops-immediately-the-panel-comes-back-online-5-10-seconds-later'
- depth: 2 - depth: 2
title: Test SMTP connection with stage-by-stage reporting (connect, auth, send). title: Test SMTP connection with stage-by-stage reporting (connect, auth, send).
Returns structured result with stage and message. Returns structured result with stage and message.
@@ -76,10 +76,10 @@ _openapi:
credentials for verification. The session is refreshed with the new credentials for verification. The session is refreshed with the new
values on success. values on success.
id: change-the-panel-admin-username-and-password-requires-the-current-credentials-for-verification-the-session-is-refreshed-with-the-new-values-on-success id: change-the-panel-admin-username-and-password-requires-the-current-credentials-for-verification-the-session-is-refreshed-with-the-new-values-on-success
- content: Restart the entire 3x-ui process after a 3-second grace period. The - content: Restart the entire L-UI process after a 3-second grace period. The
connection drops immediately; the panel comes back online ~5-10 connection drops immediately; the panel comes back online ~5-10
seconds later. seconds later.
id: restart-the-entire-3x-ui-process-after-a-3-second-grace-period-the-connection-drops-immediately-the-panel-comes-back-online-5-10-seconds-later id: restart-the-entire-L-UI-process-after-a-3-second-grace-period-the-connection-drops-immediately-the-panel-comes-back-online-5-10-seconds-later
- content: Test SMTP connection with stage-by-stage reporting (connect, auth, - content: Test SMTP connection with stage-by-stage reporting (connect, auth,
send). Returns structured result with stage and message. send). Returns structured result with stage and message.
id: test-smtp-connection-with-stage-by-stage-reporting-connect-auth-send-returns-structured-result-with-stage-and-message id: test-smtp-connection-with-stage-by-stage-reporting-connect-auth-send-returns-structured-result-with-stage-and-message
+14 -14
View File
@@ -1,17 +1,17 @@
--- ---
title: Database title: Database
description: 3x-ui storage backends — SQLite (default) and PostgreSQL — the database path, connection pool, and SQLite-to-PostgreSQL migration. description: L-UI storage backends — SQLite (default) and PostgreSQL — the database path, connection pool, and SQLite-to-PostgreSQL migration.
icon: Database icon: Database
--- ---
3x-ui stores everything — inbounds, clients, settings — in a database. You choose L-UI stores everything — inbounds, clients, settings — in a database. You choose
the backend at install time; both are first-class. the backend at install time; both are first-class.
## SQLite (default) ## SQLite (default)
A single file at `/etc/x-ui/x-ui.db`. Zero setup, ideal for small and medium A single file at `/etc/l-ui/l-ui.db`. Zero setup, ideal for small and medium
deployments. The folder is configurable with deployments. The folder is configurable with
[`XUI_DB_FOLDER`](/docs/reference/env-vars#database) (on Windows it defaults next [`LUI_DB_FOLDER`](/docs/reference/env-vars#database) (on Windows it defaults next
to the binary). to the binary).
## PostgreSQL ## PostgreSQL
@@ -19,20 +19,20 @@ to the binary).
Recommended for high client counts or multi-node setups. The installer can 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 install PostgreSQL locally for you, or accept a DSN to an existing server. At
runtime the backend is selected via environment variables, which the installer runtime the backend is selected via environment variables, which the installer
writes to `/etc/default/x-ui`: writes to `/etc/default/l-ui`:
```bash title="/etc/default/x-ui" ```bash title="/etc/default/l-ui"
XUI_DB_TYPE=postgres LUI_DB_TYPE=postgres
XUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable LUI_DB_DSN=postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable
``` ```
Tune the connection pool with `XUI_DB_MAX_OPEN_CONNS` and Tune the connection pool with `LUI_DB_MAX_OPEN_CONNS` and
`XUI_DB_MAX_IDLE_CONNS`. `LUI_DB_MAX_IDLE_CONNS`.
### Docker ### Docker
`docker compose up -d` keeps using SQLite. To run with the bundled PostgreSQL `docker compose up -d` keeps using SQLite. To run with the bundled PostgreSQL
service, uncomment the two `XUI_DB_*` lines in `docker-compose.yml` and start service, uncomment the two `LUI_DB_*` lines in `docker-compose.yml` and start
with the profile: with the profile:
```bash ```bash
@@ -44,13 +44,13 @@ docker compose --profile postgres up -d
Move an existing SQLite install to PostgreSQL with the built-in command: Move an existing SQLite install to PostgreSQL with the built-in command:
```bash ```bash
x-ui migrate-db --dsn "postgres://xui:password@127.0.0.1:5432/xui?sslmode=disable" l-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: Then set `LUI_DB_TYPE` and `LUI_DB_DSN` in `/etc/default/l-ui` and restart:
```bash ```bash
systemctl restart x-ui systemctl restart l-ui
``` ```
<Callout type="info"> <Callout type="info">
+30 -30
View File
@@ -1,46 +1,46 @@
--- ---
title: Environment Variables title: Environment Variables
description: Complete reference for 3x-ui's XUI_* environment variables — database, panel, logging, memory, and the tunnel health monitor. description: Complete reference for L-UI's LUI_* environment variables — database, panel, logging, memory, and the tunnel health monitor.
icon: Variable icon: Variable
--- ---
3x-ui reads its runtime configuration from `XUI_*` environment variables. On a L-UI reads its runtime configuration from `LUI_*` environment variables. On a
script install the installer writes them to the service environment file script install the installer writes them to the service environment file
(`/etc/default/x-ui`, or `/etc/conf.d/x-ui` / `/etc/sysconfig/x-ui` depending on (`/etc/default/l-ui`, or `/etc/conf.d/l-ui` / `/etc/sysconfig/l-ui` depending on
the distro); for Docker you set them in `docker-compose.yml` or `docker run -e`. the distro); for Docker you set them in `docker-compose.yml` or `docker run -e`.
Defaults are sensible — set only what you need to change, then restart: Defaults are sensible — set only what you need to change, then restart:
`systemctl restart x-ui`. `systemctl restart l-ui`.
## Database ## Database
| Variable | Default | Description | | Variable | Default | Description |
| ------------------------ | ----------- | -------------------------------------------------------------------- | | ------------------------ | ----------- | -------------------------------------------------------------------- |
| `XUI_DB_TYPE` | `sqlite` | Backend: `sqlite`, or `postgres` (also accepts `postgresql` / `pg`). | | `LUI_DB_TYPE` | `sqlite` | Backend: `sqlite`, or `postgres` (also accepts `postgresql` / `pg`). |
| `XUI_DB_FOLDER` | `/etc/x-ui` | Folder for the SQLite database file (`x-ui.db`). | | `LUI_DB_FOLDER` | `/etc/l-ui` | Folder for the SQLite database file (`l-ui.db`). |
| `XUI_DB_DSN` | — | PostgreSQL connection string (used when `XUI_DB_TYPE=postgres`). | | `LUI_DB_DSN` | — | PostgreSQL connection string (used when `LUI_DB_TYPE=postgres`). |
| `XUI_DB_MAX_OPEN_CONNS` | — | Max open connections in the PostgreSQL pool. | | `LUI_DB_MAX_OPEN_CONNS` | — | Max open connections in the PostgreSQL pool. |
| `XUI_DB_MAX_IDLE_CONNS` | — | Max idle connections in the PostgreSQL pool. | | `LUI_DB_MAX_IDLE_CONNS` | — | Max idle connections in the PostgreSQL pool. |
The default SQLite database path is `/etc/x-ui/x-ui.db`. See The default SQLite database path is `/etc/l-ui/l-ui.db`. See
[Database](/docs/reference/database) for the SQLite ↔ PostgreSQL details. [Database](/docs/reference/database) for the SQLite ↔ PostgreSQL details.
## Panel ## Panel
| Variable | Default | Description | | Variable | Default | Description |
| ------------------------ | ------- | ------------------------------------------------------------------------ | | ------------------------ | ------- | ------------------------------------------------------------------------ |
| `XUI_PORT` | — | Override the panel port (1–65535). Takes precedence over the stored setting. | | `LUI_PORT` | — | Override the panel port (1–65535). Takes precedence over the stored setting. |
| `XUI_INIT_WEB_BASE_PATH` | `/` | Initial web base path on **first** launch (e.g. `/panel`). | | `LUI_INIT_WEB_BASE_PATH` | `/` | Initial web base path on **first** launch (e.g. `/panel`). |
| `XUI_ENABLE_FAIL2BAN` | `true` | Enable Fail2ban-based IP-limit enforcement. | | `LUI_ENABLE_FAIL2BAN` | `true` | Enable Fail2ban-based IP-limit enforcement. |
| `XUI_SKIP_HSTS` | `false` | Skip the HSTS header — set `true` when TLS is terminated by a reverse proxy. | | `LUI_SKIP_HSTS` | `false` | Skip the HSTS header — set `true` when TLS is terminated by a reverse proxy. |
## Logging & binaries ## Logging & binaries
| Variable | Default | Description | | Variable | Default | Description |
| ---------------- | ---------------- | ----------------------------------------------------------- | | ---------------- | ---------------- | ----------------------------------------------------------- |
| `XUI_LOG_LEVEL` | `info` | `debug`, `info`, `notice`, `warning`, or `error`. | | `LUI_LOG_LEVEL` | `info` | `debug`, `info`, `notice`, `warning`, or `error`. |
| `XUI_DEBUG` | `false` | Debug mode (forces log level to `debug`). | | `LUI_DEBUG` | `false` | Debug mode (forces log level to `debug`). |
| `XUI_LOG_FOLDER` | `/var/log/x-ui` | Log output directory. | | `LUI_LOG_FOLDER` | `/var/log/l-ui` | Log output directory. |
| `XUI_BIN_FOLDER` | `bin` | Folder for the Xray-core binary and geosite/geoip files. | | `LUI_BIN_FOLDER` | `bin` | Folder for the Xray-core binary and geosite/geoip files. |
## Memory & profiling ## Memory & profiling
@@ -49,11 +49,11 @@ knobs — leave them unset unless you're tuning a constrained host.
| Variable | Default | Description | | Variable | Default | Description |
| ----------------------------- | ------- | ----------------------------------------------------------------- | | ----------------------------- | ------- | ----------------------------------------------------------------- |
| `XUI_GOGC` | — | Go GC target percentage; lower = less RAM, slightly more CPU. | | `LUI_GOGC` | — | Go GC target percentage; lower = less RAM, slightly more CPU. |
| `XUI_MEMORY_RELEASE_INTERVAL` | — | Minutes between `FreeOSMemory` calls; `0` disables. | | `LUI_MEMORY_RELEASE_INTERVAL` | — | Minutes between `FreeOSMemory` calls; `0` disables. |
| `XUI_MEMORY_LIMIT` | — | Go soft memory limit in **MiB**. | | `LUI_MEMORY_LIMIT` | — | Go soft memory limit in **MiB**. |
| `GOMEMLIMIT` | — | Go-syntax soft limit (e.g. `400MiB`); takes precedence over above.| | `GOMEMLIMIT` | — | Go-syntax soft limit (e.g. `400MiB`); takes precedence over above.|
| `XUI_PPROF` | `false` | Expose pprof profiling on `127.0.0.1:6060`. | | `LUI_PPROF` | `false` | Expose pprof profiling on `127.0.0.1:6060`. |
## Xray ## Xray
@@ -69,16 +69,16 @@ clients, so enable it deliberately.
| Variable | Default | Description | | Variable | Default | Description |
| ----------------------------- | -------------------------------------------- | ----------------------------------------------------------------- | | ----------------------------- | -------------------------------------------- | ----------------------------------------------------------------- |
| `XUI_TUNNEL_HEALTH_MONITOR` | `false` | Enable the monitor. | | `LUI_TUNNEL_HEALTH_MONITOR` | `false` | Enable the monitor. |
| `XUI_TUNNEL_HEALTH_PROXY` | — | Proxy to send the probe through, e.g. `socks5://127.0.0.1:1080`. Empty = only checks host connectivity. | | `LUI_TUNNEL_HEALTH_PROXY` | — | Proxy to send the probe through, e.g. `socks5://127.0.0.1:1080`. Empty = only checks host connectivity. |
| `XUI_TUNNEL_HEALTH_URL` | `https://www.cloudflare.com/cdn-cgi/trace` | URL to probe. | | `LUI_TUNNEL_HEALTH_URL` | `https://www.cloudflare.com/cdn-cgi/trace` | URL to probe. |
| `XUI_TUNNEL_HEALTH_INTERVAL` | `30s` | Interval between probes. | | `LUI_TUNNEL_HEALTH_INTERVAL` | `30s` | Interval between probes. |
| `XUI_TUNNEL_HEALTH_TIMEOUT` | `10s` | Per-probe timeout. | | `LUI_TUNNEL_HEALTH_TIMEOUT` | `10s` | Per-probe timeout. |
| `XUI_TUNNEL_HEALTH_FAILURES` | `3` | Consecutive failures before a restart. | | `LUI_TUNNEL_HEALTH_FAILURES` | `3` | Consecutive failures before a restart. |
| `XUI_TUNNEL_HEALTH_COOLDOWN` | `5m` | Minimum delay between restarts. | | `LUI_TUNNEL_HEALTH_COOLDOWN` | `5m` | Minimum delay between restarts. |
## Unattended install ## Unattended install
| Variable | Description | | Variable | Description |
| -------------------- | -------------------------------------------------------------------------------------------- | | -------------------- | -------------------------------------------------------------------------------------------- |
| `XUI_NONINTERACTIVE` | Set to `1` (or run with no TTY) to install with zero prompts; generated credentials are written to `/etc/x-ui/install-result.env`. See [Installation](/docs/guide/installation#unattended--cloud-init). | | `LUI_NONINTERACTIVE` | Set to `1` (or run with no TTY) to install with zero prompts; generated credentials are written to `/etc/l-ui/install-result.env`. See [Installation](/docs/guide/installation#unattended--cloud-init). |
@@ -1,6 +1,6 @@
--- ---
title: Ports & Firewall title: Ports & Firewall
description: The ports 3x-ui uses by default and ready-made ufw / nftables rules to open them. description: The ports L-UI uses by default and ready-made ufw / nftables rules to open them.
icon: Network icon: Network
--- ---
@@ -32,5 +32,5 @@ Your actual inbound ports depend on the inbounds you create.
<Cards> <Cards>
<Card title="Security" href="/docs/operations/security" description="Fail2ban, IP limits, and hardening." /> <Card title="Security" href="/docs/operations/security" description="Fail2ban, IP limits, and hardening." />
<Card title="Environment variables" href="/docs/reference/env-vars" description="XUI_PORT and friends." /> <Card title="Environment variables" href="/docs/reference/env-vars" description="LUI_PORT and friends." />
</Cards> </Cards>
+1 -1
View File
@@ -1,6 +1,6 @@
--- ---
title: کلاینت‌ها title: کلاینت‌ها
description: مدیریت کلاینت‌های 3x-ui — اعتبارنامه‌ها، محدودیت ترافیک و انقضا، محدودیت IP، گروه‌ها، اقدامات گروهی، لینک‌های خارجی و وضعیت آنلاین. description: مدیریت کلاینت‌های L-UI — اعتبارنامه‌ها، محدودیت ترافیک و انقضا، محدودیت IP، گروه‌ها، اقدامات گروهی، لینک‌های خارجی و وضعیت آنلاین.
icon: Users icon: Users
--- ---
+2 -2
View File
@@ -1,6 +1,6 @@
--- ---
title: ورودی‌ها و پروتکل‌ها title: ورودی‌ها و پروتکل‌ها
description: ساخت ورودی‌ها در 3x-ui — پروتکل‌ها، انتقال‌ها، بازنشانی و انقضای ترافیک، و fallbackهایی که چند پروتکل را روی یک پورت سرویس می‌دهند. description: ساخت ورودی‌ها در L-UI — پروتکل‌ها، انتقال‌ها، بازنشانی و انقضای ترافیک، و fallbackهایی که چند پروتکل را روی یک پورت سرویس می‌دهند.
icon: ArrowDownToLine icon: ArrowDownToLine
--- ---
@@ -74,7 +74,7 @@ TLS یا REALITY) را انتخاب کنید. به [انتقال‌ها](/docs/c
Fallbackها به یک پورت TLS واحد (مثلاً `443`) اجازه می‌دهند بیش از یک پروتکل را Fallbackها به یک پورت TLS واحد (مثلاً `443`) اجازه می‌دهند بیش از یک پروتکل را
سرویس دهد — برای مثال VLESS **و** Trojan — با هدایت دست‌دادن‌های (handshake) سرویس دهد — برای مثال VLESS **و** Trojan — با هدایت دست‌دادن‌های (handshake)
ناهماهنگ به یک ورودی فرزند. در 3x-ui، fallbackها در پنل مدیریت می‌شوند (لیست ناهماهنگ به یک ورودی فرزند. در L-UI، fallbackها در پنل مدیریت می‌شوند (لیست
**Fallbacks** یک ورودی اصلی) به‌جای آنکه به‌صورت دستی در JSON نوشته شوند. **Fallbacks** یک ورودی اصلی) به‌جای آنکه به‌صورت دستی در JSON نوشته شوند.
Fallbackها تنها زمانی در دسترس‌اند که ورودی اصلی این‌گونه باشد: Fallbackها تنها زمانی در دسترس‌اند که ورودی اصلی این‌گونه باشد:
+4 -4
View File
@@ -1,6 +1,6 @@
--- ---
title: تنظیمات پنل title: تنظیمات پنل
description: تمام تنظیمات پنل 3x-ui — وب‌سرور، TLS، نمایش، امنیت و اعلان‌ها — همراه با مقادیر پیش‌فرض برگرفته از سورس. description: تمام تنظیمات پنل L-UI — وب‌سرور، TLS، نمایش، امنیت و اعلان‌ها — همراه با مقادیر پیش‌فرض برگرفته از سورس.
icon: SlidersHorizontal icon: SlidersHorizontal
--- ---
@@ -14,7 +14,7 @@ icon: SlidersHorizontal
| Setting | Default | Meaning | | Setting | Default | Meaning |
| ------------------- | ----------------------- | ----------------------------------------------------------------------- | | ------------------- | ----------------------- | ----------------------------------------------------------------------- |
| `webPort` | `2053` | پورت پنل (۱ تا ۶۵۵۳۵). متغیر محیطی `XUI_PORT` در زمان اجرا آن را بازنویسی می‌کند. | | `webPort` | `2053` | پورت پنل (۱ تا ۶۵۵۳۵). متغیر محیطی `LUI_PORT` در زمان اجرا آن را بازنویسی می‌کند. |
| `webListen` | _(همه‌ی واسط‌ها)_ | پنل را به یک IP مشخص مقید کنید. | | `webListen` | _(همه‌ی واسط‌ها)_ | پنل را به یک IP مشخص مقید کنید. |
| `webBasePath` | `/` | مسیر URLی که پنل زیر آن ارائه می‌شود (همیشه به شکل `/…/` نرمال‌سازی می‌شود). | | `webBasePath` | `/` | مسیر URLی که پنل زیر آن ارائه می‌شود (همیشه به شکل `/…/` نرمال‌سازی می‌شود). |
| `webCertFile` / `webKeyFile` | _(هیچ‌کدام)_ | گواهی + کلید TLS. وقتی هر دو تنظیم شوند، پنل با **HTTPS** ارائه می‌شود. | | `webCertFile` / `webKeyFile` | _(هیچ‌کدام)_ | گواهی + کلید TLS. وقتی هر دو تنظیم شوند، پنل با **HTTPS** ارائه می‌شود. |
@@ -24,12 +24,12 @@ icon: SlidersHorizontal
پس از تغییر پورت یا مسیر پایه، آدرس پنل به‌صورت پس از تغییر پورت یا مسیر پایه، آدرس پنل به‌صورت
`http(s)://<server>:<port><web-base-path>` درمی‌آید. می‌توانید مسیر پایه را در `http(s)://<server>:<port><web-base-path>` درمی‌آید. می‌توانید مسیر پایه را در
نخستین اجرا با [`XUI_INIT_WEB_BASE_PATH`](/docs/reference/env-vars) از پیش تعیین کنید. نخستین اجرا با [`LUI_INIT_WEB_BASE_PATH`](/docs/reference/env-vars) از پیش تعیین کنید.
### TLS ### TLS
ارائه‌ی پنل روی HTTPS از اطلاعات احراز هویت شما در حین انتقال محافظت می‌کند. یا ارائه‌ی پنل روی HTTPS از اطلاعات احراز هویت شما در حین انتقال محافظت می‌کند. یا
`webCertFile` + `webKeyFile` را تنظیم کنید — [منوی SSL در `x-ui`](/docs/config/ssl-certificates) `webCertFile` + `webKeyFile` را تنظیم کنید — [منوی SSL در `l-ui`](/docs/config/ssl-certificates)
می‌تواند یک گواهی Let's Encrypt برای شما تهیه کند — یا TLS را روی یک می‌تواند یک گواهی Let's Encrypt برای شما تهیه کند — یا TLS را روی یک
[پروکسی معکوس](/docs/operations/reverse-proxy) خاتمه دهید. [پروکسی معکوس](/docs/operations/reverse-proxy) خاتمه دهید.
+2 -2
View File
@@ -1,6 +1,6 @@
--- ---
title: REALITY title: REALITY
description: راه‌اندازی یک ورودی VLESS + REALITY همراه با XTLS-Vision در 3x-ui — کلیدها، short IDها، SNI، اثرانگشت‌ها و اشتباهات رایج. description: راه‌اندازی یک ورودی VLESS + REALITY همراه با XTLS-Vision در L-UI — کلیدها، short IDها، SNI، اثرانگشت‌ها و اشتباهات رایج.
icon: ShieldCheck icon: ShieldCheck
--- ---
@@ -15,7 +15,7 @@ REALITY همراه با **VLESS** (و Trojan) به‌کار می‌رود. جر
## تنظیمات کلیدی ## تنظیمات کلیدی
وقتی **REALITY** را به‌عنوان حالت امنیتی روی یک ورودی VLESS انتخاب می‌کنید، 3x-ui وقتی **REALITY** را به‌عنوان حالت امنیتی روی یک ورودی VLESS انتخاب می‌کنید، L-UI
این فیلدها را نمایش می‌دهد: این فیلدها را نمایش می‌دهد:
| فیلد | چیست | | فیلد | چیست |
+2 -2
View File
@@ -1,10 +1,10 @@
--- ---
title: لینک‌های اشتراک‌گذاری title: لینک‌های اشتراک‌گذاری
description: قالب‌های لینک اشتراک‌گذاری 3x-ui (vless، vmess، trojan، ss، hysteria2، mtproto)، متغیرهای قالب توضیحات، و بازرس لینک درون‌مرورگری. description: قالب‌های لینک اشتراک‌گذاری L-UI (vless، vmess، trojan، ss، hysteria2، mtproto)، متغیرهای قالب توضیحات، و بازرس لینک درون‌مرورگری.
icon: Link icon: Link
--- ---
3x-ui برای هر کلاینت یک **لینک اشتراک‌گذاری** (و کد QR) تولید می‌کند. برنامه‌های کلاینت L-UI برای هر کلاینت یک **لینک اشتراک‌گذاری** (و کد QR) تولید می‌کند. برنامه‌های کلاینت
مانند v2rayNG، Hiddify و Mihomo این لینک‌ها را برای پیکربندی خودشان وارد می‌کنند. مانند v2rayNG، Hiddify و Mihomo این لینک‌ها را برای پیکربندی خودشان وارد می‌کنند.
## قالب‌های لینک ## قالب‌های لینک
@@ -1,6 +1,6 @@
--- ---
title: گواهی‌های SSL title: گواهی‌های SSL
description: دریافت و تمدید گواهی‌های TLS برای پنل و ورودی‌های 3x-ui — با منوی ACME در x-ui (دامنه یا IP خام)، گواهی wildcard از طریق Cloudflare DNS-01، یا Certbot دستی. description: دریافت و تمدید گواهی‌های TLS برای پنل و ورودی‌های L-UI — با منوی ACME در l-ui (دامنه یا IP خام)، گواهی wildcard از طریق Cloudflare DNS-01، یا Certbot دستی.
icon: ShieldCheck icon: ShieldCheck
--- ---
@@ -8,7 +8,7 @@ icon: ShieldCheck
API شما رمزگذاری شود) و TLS را روی **ورودی‌ها** خاتمه دهید (VLESS-TLS، Trojan، API شما رمزگذاری شود) و TLS را روی **ورودی‌ها** خاتمه دهید (VLESS-TLS، Trojan،
Shadowsocks-TLS و موارد مشابه). سه راه برای به‌دست‌آوردن گواهی وجود دارد: Shadowsocks-TLS و موارد مشابه). سه راه برای به‌دست‌آوردن گواهی وجود دارد:
- **منوی `x-ui`** — کلاینت داخلی [ACME](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment). - **منوی `l-ui`** — کلاینت داخلی [ACME](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment).
آسان‌ترین گزینه برای یک دامنه‌ی واحد یا یک IP خام. آسان‌ترین گزینه برای یک دامنه‌ی واحد یا یک IP خام.
- **Cloudflare DNS-01** — این هم از همان منو؛ برای گواهی‌های **wildcard** یا - **Cloudflare DNS-01** — این هم از همان منو؛ برای گواهی‌های **wildcard** یا
زمانی که پورت 80 مسدود است / سرور پشت پراکسی Cloudflare قرار دارد لازم است. زمانی که پورت 80 مسدود است / سرور پشت پراکسی Cloudflare قرار دارد لازم است.
@@ -21,9 +21,9 @@ Shadowsocks-TLS و موارد مشابه). سه راه برای به‌دست‌
TLS یک سایت واقعی را قرض می‌گیرند. این صفحه برای پنل و برای ورودی‌های کلاسیک TLS است. TLS یک سایت واقعی را قرض می‌گیرند. این صفحه برای پنل و برای ورودی‌های کلاسیک TLS است.
</Callout> </Callout>
## منوی SSL در `x-ui` (Let's Encrypt) ## منوی SSL در `l-ui` (Let's Encrypt)
`x-ui` را اجرا کنید و **`20` — SSL Certificate Management** را انتخاب کنید. این گزینه `l-ui` را اجرا کنید و **`20` — SSL Certificate Management** را انتخاب کنید. این گزینه
[acme.sh](https://github.com/acmesh-official/acme.sh) را به کار می‌گیرد و موارد زیر را ارائه می‌دهد: [acme.sh](https://github.com/acmesh-official/acme.sh) را به کار می‌گیرد و موارد زیر را ارائه می‌دهد:
| گزینه | کاری که انجام می‌دهد | | گزینه | کاری که انجام می‌دهد |
@@ -57,7 +57,7 @@ Shadowsocks-TLS و موارد مشابه). سه راه برای به‌دست‌
<Step> <Step>
### صادرکننده را اجرا کنید ### صادرکننده را اجرا کنید
`x-ui` ← `20` ← **Get SSL (Domain)**، سپس دامنه را وارد کنید. acme.sh گواهی را `l-ui` ← `20` ← **Get SSL (Domain)**، سپس دامنه را وارد کنید. acme.sh گواهی را
درخواست می‌کند و آن را زیر `/root/cert/<domain>/` به‌صورت `fullchain.pem` درخواست می‌کند و آن را زیر `/root/cert/<domain>/` به‌صورت `fullchain.pem`
(زنجیره‌ی گواهی) و `privkey.pem` (کلید خصوصی) ذخیره می‌کند. (زنجیره‌ی گواهی) و `privkey.pem` (کلید خصوصی) ذخیره می‌کند.
</Step> </Step>
@@ -104,7 +104,7 @@ DNS دامنه‌ی شما باید توسط Cloudflare مدیریت شود و
<Step> <Step>
### صادرکننده‌ی Cloudflare را اجرا کنید ### صادرکننده‌ی Cloudflare را اجرا کنید
`x-ui` ← **`21` — Cloudflare SSL Certificate**. هنگام پرسش، **`t`** را برای یک `l-ui` ← **`21` — Cloudflare SSL Certificate**. هنگام پرسش، **`t`** را برای یک
توکن API (پیش‌فرض) یا **`g`** را برای Global API Key انتخاب کنید، سپس دامنه‌ی خود را توکن API (پیش‌فرض) یا **`g`** را برای Global API Key انتخاب کنید، سپس دامنه‌ی خود را
وارد کنید (و برای Global API Key، ایمیل حساب و کلید خود را). acme.sh رکورد TXT را وارد کنید (و برای Global API Key، ایمیل حساب و کلید خود را). acme.sh رکورد TXT را
می‌سازد، اعتبارسنجی می‌کند و آن را پاک‌سازی می‌کند. می‌سازد، اعتبارسنجی می‌کند و آن را پاک‌سازی می‌کند.
+2 -2
View File
@@ -1,6 +1,6 @@
--- ---
title: Subscription title: Subscription
description: راه‌اندازی سرور اشتراک 3x-ui — قالب‌های base64/JSON/Clash، پورت‌ها و مسیرها، TLS، هدرهای پاسخ و قالب‌های سفارشی. description: راه‌اندازی سرور اشتراک L-UI — قالب‌های base64/JSON/Clash، پورت‌ها و مسیرها، TLS، هدرهای پاسخ و قالب‌های سفارشی.
icon: Rss icon: Rss
--- ---
@@ -59,7 +59,7 @@ https://<sub-host>:<sub-port>/sub/<sub-id>
با standard-base64 رمزگذاری شده‌اند (با `subEncrypt` قابل تغییر است). بدنه‌ی **JSON** با standard-base64 رمزگذاری شده‌اند (با `subEncrypt` قابل تغییر است). بدنه‌ی **JSON**
هر کلاینت را در یک پیکربندی کامل کلاینت Xray می‌پیچد — یک اسکلت ثابت (ورودی‌های محلی هر کلاینت را در یک پیکربندی کامل کلاینت Xray می‌پیچد — یک اسکلت ثابت (ورودی‌های محلی
mixed/HTTP، DNS، مسیریابی، policy) به‌علاوه‌ی یک outbound از نوع `proxy` که به ورودی mixed/HTTP، DNS، مسیریابی، policy) به‌علاوه‌ی یک outbound از نوع `proxy` که به ورودی
اشاره می‌کند. 3x-ui **برای یک کلاینت یک شیء پیکربندی واحد و برای چند کلاینت یک آرایه** اشاره می‌کند. L-UI **برای یک کلاینت یک شیء پیکربندی واحد و برای چند کلاینت یک آرایه**
تولید می‌کند، از فرم تخت `settings` در outbound استفاده می‌کند تولید می‌کند، از فرم تخت `settings` در outbound استفاده می‌کند
(`address`/`port`/`id`، `level: 8`) و `sockopt` را از `streamSettings` حذف می‌کند. (`address`/`port`/`id`، `level: 8`) و `sockopt` را از `streamSettings` حذف می‌کند.
+1 -1
View File
@@ -1,6 +1,6 @@
--- ---
title: انتقال‌ها و امنیت title: انتقال‌ها و امنیت
description: هر انتقالی که 3x-ui ارائه می‌دهد — TCP، mKCP، WebSocket، gRPC، HTTPUpgrade، XHTTP، Hysteria — به‌همراه تنظیماتشان، و نیز مبهم‌سازی FinalMask، sockopt، TLS/REALITY، XTLS-Vision و رمزنگاری VLESS. description: هر انتقالی که L-UI ارائه می‌دهد — TCP، mKCP، WebSocket، gRPC، HTTPUpgrade، XHTTP، Hysteria — به‌همراه تنظیماتشان، و نیز مبهم‌سازی FinalMask، sockopt، TLS/REALITY، XTLS-Vision و رمزنگاری VLESS.
icon: Network icon: Network
--- ---
+16 -16
View File
@@ -1,6 +1,6 @@
--- ---
title: نخستین ورود title: نخستین ورود
description: مشخصات ورود تولیدشدهٔ 3x-ui را بیابید، به پنل دسترسی پیدا کنید، احراز هویت دومرحله‌ای را فعال کنید و پیش از در معرض قرار دادن هر چیزی، پنل را ایمن‌سازی کنید. description: مشخصات ورود تولیدشدهٔ L-UI را بیابید، به پنل دسترسی پیدا کنید، احراز هویت دومرحله‌ای را فعال کنید و پیش از در معرض قرار دادن هر چیزی، پنل را ایمن‌سازی کنید.
icon: KeyRound icon: KeyRound
--- ---
@@ -24,25 +24,25 @@ http://<your-server-ip>:<port>/<web-base-path>
نصب با اسکریپت پس از پایان، خلاصه‌ای از مشخصات ورود را چاپ می‌کند و آن را در یک نصب با اسکریپت پس از پایان، خلاصه‌ای از مشخصات ورود را چاپ می‌کند و آن را در یک
فایل ویژهٔ root نیز می‌نویسد: فایل ویژهٔ root نیز می‌نویسد:
```bash title="/etc/x-ui/install-result.env (mode 600)" ```bash title="/etc/l-ui/install-result.env (mode 600)"
XUI_USERNAME=... LUI_USERNAME=...
XUI_PASSWORD=... LUI_PASSWORD=...
XUI_PANEL_PORT=... LUI_PANEL_PORT=...
XUI_WEB_BASE_PATH=... LUI_WEB_BASE_PATH=...
XUI_ACCESS_URL=... LUI_ACCESS_URL=...
XUI_API_TOKEN=... LUI_API_TOKEN=...
XUI_DB_TYPE=sqlite LUI_DB_TYPE=sqlite
``` ```
اگر آن‌ها را از دست دادید، از ابزارهای مدیریتی استفاده کنید: اگر آن‌ها را از دست دادید، از ابزارهای مدیریتی استفاده کنید:
```bash ```bash
x-ui # menu → 11 (View Current Settings) l-ui # menu → 11 (View Current Settings)
x-ui settings # or the one-shot form l-ui settings # or the one-shot form
``` ```
برای **Docker**، مشخصات ورود تولیدشده را از لاگ‌های کانتینر بخوانید، یا دستور برای **Docker**، مشخصات ورود تولیدشده را از لاگ‌های کانتینر بخوانید، یا دستور
`docker exec -it <container> x-ui setting -show` را اجرا کنید. `docker exec -it <container> l-ui setting -show` را اجرا کنید.
<Callout type="warn"> <Callout type="warn">
اگر پنل شما هنوز از مقادیر پیش‌فرض `admin` / `admin` استفاده می‌کند (پنل در این اگر پنل شما هنوز از مقادیر پیش‌فرض `admin` / `admin` استفاده می‌کند (پنل در این
@@ -53,7 +53,7 @@ x-ui settings # or the one-shot form
یک پورت غیرپیش‌فرض و یک **مسیر پایهٔ وب** طولانی و تصادفی، یافتن پنل را بسیار یک پورت غیرپیش‌فرض و یک **مسیر پایهٔ وب** طولانی و تصادفی، یافتن پنل را بسیار
دشوارتر می‌کند. آن‌ها را از بخش **Panel Settings** در رابط کاربری، یا از منوی دشوارتر می‌کند. آن‌ها را از بخش **Panel Settings** در رابط کاربری، یا از منوی
`x-ui` تغییر دهید: `l-ui` تغییر دهید:
- **7 — Reset Username & Password** (با امکان غیرفعال‌سازی همزمان 2FA) - **7 — Reset Username & Password** (با امکان غیرفعال‌سازی همزمان 2FA)
- **8 — Reset Web Base Path** (آن را تصادفی می‌کند) - **8 — Reset Web Base Path** (آن را تصادفی می‌کند)
@@ -64,11 +64,11 @@ x-ui settings # or the one-shot form
## احراز هویت دومرحله‌ای (2FA) ## احراز هویت دومرحله‌ای (2FA)
‏3x-ui از احراز هویت دومرحله‌ای TOTP پشتیبانی می‌کند (سازگار با Google ‏L-UI از احراز هویت دومرحله‌ای TOTP پشتیبانی می‌کند (سازگار با Google
Authenticator، Aegis و غیره). آن را در بخش **Panel Settings** فعال کنید — پس از Authenticator، Aegis و غیره). آن را در بخش **Panel Settings** فعال کنید — پس از
فعال‌سازی، صفحهٔ ورود علاوه بر رمز عبور، یک کد ۶ رقمی نیز درخواست می‌کند و فعال‌سازی، صفحهٔ ورود علاوه بر رمز عبور، یک کد ۶ رقمی نیز درخواست می‌کند و
فعال کردن آن همه را وادار به ورود مجدد می‌کند. می‌توانید آن را از مرحلهٔ **Reset فعال کردن آن همه را وادار به ورود مجدد می‌کند. می‌توانید آن را از مرحلهٔ **Reset
Username & Password** در منو یا با دستور `x-ui setting -resetTwoFactor` غیرفعال Username & Password** در منو یا با دستور `l-ui setting -resetTwoFactor` غیرفعال
کنید. کنید.
## محافظت داخلی از ورود ## محافظت داخلی از ورود
@@ -106,7 +106,7 @@ Username & Password** در منو یا با دستور `x-ui setting -resetTwoFa
<Step> <Step>
### پنل را پشت TLS قرار دهید ### پنل را پشت TLS قرار دهید
از یک گواهی معتبر (از طریق مدیریت SSL در منوی `x-ui` یا یک reverse proxy) از یک گواهی معتبر (از طریق مدیریت SSL در منوی `l-ui` یا یک reverse proxy)
استفاده کنید تا پنل تنها از طریق HTTPS در دسترس باشد. استفاده کنید تا پنل تنها از طریق HTTPS در دسترس باشد.
</Step> </Step>
+6 -6
View File
@@ -1,10 +1,10 @@
--- ---
title: آشنایی با 3x-ui title: آشنایی با L-UI
description: یک پنل تحت وب برای Xray-core — ورودی‌ها، پروتکل‌ها، کلاینت‌ها و اشتراک‌ها را به‌جای ویرایش دستی JSON، از مرورگر خود مدیریت کنید. description: یک پنل تحت وب برای Xray-core — ورودی‌ها، پروتکل‌ها، کلاینت‌ها و اشتراک‌ها را به‌جای ویرایش دستی JSON، از مرورگر خود مدیریت کنید.
icon: Info icon: Info
--- ---
**3x-ui** یک پنل کنترل تحت وب است که روی **L-UI** یک پنل کنترل تحت وب است که روی
[Xray-core](https://github.com/XTLS/Xray-core)، همان موتور پروکسی که در واقع [Xray-core](https://github.com/XTLS/Xray-core)، همان موتور پروکسی که در واقع
ترافیک شما را جابه‌جا می‌کند، قرار می‌گیرد. به‌جای نوشتن و بارگذاری مجدد پیکربندی ترافیک شما را جابه‌جا می‌کند، قرار می‌گیرد. به‌جای نوشتن و بارگذاری مجدد پیکربندی
JSON ‏Xray به‌صورت دستی، همه‌چیز — ورودی‌ها، پروتکل‌ها، کلاینت‌ها، گواهی‌ها، JSON ‏Xray به‌صورت دستی، همه‌چیز — ورودی‌ها، پروتکل‌ها، کلاینت‌ها، گواهی‌ها،
@@ -15,7 +15,7 @@ JSON ‏Xray به‌صورت دستی، همه‌چیز — ورودی‌ها،
<Mermaid <Mermaid
chart={` chart={`
flowchart LR flowchart LR
Admin["Admin browser"] -->|HTTPS panel| Panel["3x-ui panel"] Admin["Admin browser"] -->|HTTPS panel| Panel["L-UI panel"]
Panel -->|writes config, reloads| Xray["Xray-core"] Panel -->|writes config, reloads| Xray["Xray-core"]
Panel --- DB[("SQLite or PostgreSQL")] Panel --- DB[("SQLite or PostgreSQL")]
Clients["Client apps"] -->|VLESS / VMess / Trojan / ...| Xray Clients["Client apps"] -->|VLESS / VMess / Trojan / ...| Xray
@@ -53,19 +53,19 @@ flowchart LR
| پایگاه‌داده | SQLite (پیش‌فرض) یا PostgreSQL | | پایگاه‌داده | SQLite (پیش‌فرض) یا PostgreSQL |
| موتور پروکسی | Xray-core (همراه و مدیریت‌شده توسط پنل) | | موتور پروکسی | Xray-core (همراه و مدیریت‌شده توسط پنل) |
پایگاه‌دادهٔ پیش‌فرض SQLite در مسیر `/etc/x-ui/x-ui.db` قرار دارد و پنل به‌صورت پایگاه‌دادهٔ پیش‌فرض SQLite در مسیر `/etc/l-ui/l-ui.db` قرار دارد و پنل به‌صورت
پیش‌فرض روی پورت **2053** گوش می‌دهد. هر دو قابل پیکربندی هستند — به پیش‌فرض روی پورت **2053** گوش می‌دهد. هر دو قابل پیکربندی هستند — به
[نخستین ورود](/docs/guide/first-login) و مرجع متغیرهای محیطی مراجعه کنید. [نخستین ورود](/docs/guide/first-login) و مرجع متغیرهای محیطی مراجعه کنید.
## برای چه کسانی است ## برای چه کسانی است
3x-ui برای هر کسی که سرور Xray خودش را اجرا می‌کند طراحی شده است: از یک L-UI برای هر کسی که سرور Xray خودش را اجرا می‌کند طراحی شده است: از یک
VPS شخصی منفرد تا اپراتورهایی که نودها و کلاینت‌های فراوانی را مدیریت می‌کنند. اگر VPS شخصی منفرد تا اپراتورهایی که نودها و کلاینت‌های فراوانی را مدیریت می‌کنند. اگر
قدرت Xray-core را می‌خواهید بدون اینکه در فایل‌های پیکربندی JSON زندگی کنید، این قدرت Xray-core را می‌خواهید بدون اینکه در فایل‌های پیکربندی JSON زندگی کنید، این
برای شماست. برای شماست.
<Callout type="info"> <Callout type="info">
3x-ui یک فورک ارتقایافته از پروژهٔ اصلی X-UI است که پشتیبانی گسترده‌تری از L-UI یک فورک ارتقایافته از پروژهٔ اصلی X-UI است که پشتیبانی گسترده‌تری از
پروتکل‌ها، پایداری بهبودیافته، حسابداری ترافیک به‌ازای هر کلاینت، مدیریت پروتکل‌ها، پایداری بهبودیافته، حسابداری ترافیک به‌ازای هر کلاینت، مدیریت
چندنودی و بسیاری از قابلیت‌های راحتی‌بخش را اضافه می‌کند. چندنودی و بسیاری از قابلیت‌های راحتی‌بخش را اضافه می‌کند.
</Callout> </Callout>
+18 -18
View File
@@ -1,17 +1,17 @@
--- ---
title: نصب title: نصب
description: نصب 3x-ui با اسکریپت رسمی (نسخهٔ پایدار، نسخهٔ مشخص یا dev-latest)، نصب خودکار/cloud-init یا Docker — و انتخاب میان SQLite و PostgreSQL. description: نصب L-UI با اسکریپت رسمی (نسخهٔ پایدار، نسخهٔ مشخص یا dev-latest)، نصب خودکار/cloud-init یا Docker — و انتخاب میان SQLite و PostgreSQL.
icon: Download icon: Download
--- ---
‏3x-ui روی طیف گسترده‌ای از توزیع‌های Linux اجرا می‌شود — Ubuntu، Debian، Armbian، ‏L-UI روی طیف گسترده‌ای از توزیع‌های Linux اجرا می‌شود — Ubuntu، Debian، Armbian،
Fedora، CentOS، RHEL، AlmaLinux، Rocky Linux، Oracle Linux، Amazon Linux، Fedora، CentOS، RHEL، AlmaLinux، Rocky Linux، Oracle Linux، Amazon Linux،
Virtuozzo، Arch، Manjaro، openSUSE (Tumbleweed/Leap)، Alpine — و همچنین Windows، Virtuozzo، Arch، Manjaro، openSUSE (Tumbleweed/Leap)، Alpine — و همچنین Windows،
روی معماری‌های `amd64`، `386`، `arm64`، `armv7`، `armv6`، `armv5` و `s390x`. روی معماری‌های `amd64`، `386`، `arm64`، `armv7`، `armv6`، `armv5` و `s390x`.
<Callout type="warn"> <Callout type="warn">
نصب‌کنندهٔ اسکریپتی را به‌صورت **root** (یا با `sudo`) اجرا کنید. این اسکریپت یک نصب‌کنندهٔ اسکریپتی را به‌صورت **root** (یا با `sudo`) اجرا کنید. این اسکریپت یک
سرویس نصب می‌کند، دستور مدیریتی `x-ui` را راه‌اندازی می‌کند و پنل را در زمان سرویس نصب می‌کند، دستور مدیریتی `l-ui` را راه‌اندازی می‌کند و پنل را در زمان
بوت فعال می‌سازد. بوت فعال می‌سازد.
</Callout> </Callout>
@@ -21,7 +21,7 @@ Virtuozzo، Arch، Manjaro، openSUSE (Tumbleweed/Leap)، Alpine — و همچن
اسکریپت رسمی مسیر توصیه‌شده است. این اسکریپت در طول نصب یک نام کاربری، رمز عبور و اسکریپت رسمی مسیر توصیه‌شده است. این اسکریپت در طول نصب یک نام کاربری، رمز عبور و
مسیر دسترسی (مسیر پایهٔ وب) **تصادفی** تولید می‌کند، سرویس را راه‌اندازی می‌کند و مسیر دسترسی (مسیر پایهٔ وب) **تصادفی** تولید می‌کند، سرویس را راه‌اندازی می‌کند و
دستور مدیریتی `x-ui` را نصب می‌کند. دستور مدیریتی `l-ui` را نصب می‌کند.
```bash title="latest stable" ```bash title="latest stable"
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
@@ -40,8 +40,8 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) dev-latest bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) dev-latest
``` ```
پس از پایان نصب، مشخصات ورود چاپ‌شده را یادداشت کنید و دستور `x-ui` را اجرا کنید تا پس از پایان نصب، مشخصات ورود چاپ‌شده را یادداشت کنید و دستور `l-ui` را اجرا کنید تا
[منوی مدیریت](/docs/guide/update-uninstall#the-x-ui-management-menu) باز شود، سپس [منوی مدیریت](/docs/guide/update-uninstall#the-l-ui-management-menu) باز شود، سپس
به [نخستین ورود](/docs/guide/first-login) ادامه دهید. به [نخستین ورود](/docs/guide/first-login) ادامه دهید.
</Tab> </Tab>
@@ -55,7 +55,7 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
docker compose up -d docker compose up -d
``` ```
برای اجرا با سرویس **PostgreSQL** همراه، دو خط `XUI_DB_*` را در برای اجرا با سرویس **PostgreSQL** همراه، دو خط `LUI_DB_*` را در
`docker-compose.yml` از حالت کامنت خارج کنید و با پروفایل مربوطه اجرا کنید: `docker-compose.yml` از حالت کامنت خارج کنید و با پروفایل مربوطه اجرا کنید:
```bash ```bash
@@ -71,16 +71,16 @@ docker compose --profile postgres up -d
docker run -d \ docker run -d \
--cap-add=NET_ADMIN \ --cap-add=NET_ADMIN \
--cap-add=NET_RAW \ --cap-add=NET_RAW \
-e XUI_ENABLE_FAIL2BAN=true \ -e LUI_ENABLE_FAIL2BAN=true \
-v $PWD/db/:/etc/x-ui/ \ -v $PWD/db/:/etc/l-ui/ \
-v $PWD/cert/:/root/cert/ \ -v $PWD/cert/:/root/cert/ \
--network=host \ --network=host \
--restart=unless-stopped \ --restart=unless-stopped \
--name 3x-ui \ --name L-UI \
ghcr.io/mhsanaei/3x-ui:latest ghcr.io/mhsanaei/3x-ui:latest
``` ```
والیوم `db/` پایگاه‌دادهٔ SQLite (`/etc/x-ui/x-ui.db`) را نگه می‌دارد و `cert/` والیوم `db/` پایگاه‌دادهٔ SQLite (`/etc/l-ui/l-ui.db`) را نگه می‌دارد و `cert/`
گواهی‌های TLS را، بنابراین داده‌های شما در ارتقاها حفظ می‌شوند. گواهی‌های TLS را، بنابراین داده‌های شما در ارتقاها حفظ می‌شوند.
</Tab> </Tab>
@@ -88,7 +88,7 @@ docker run -d \
<Tab value="Manual"> <Tab value="Manual">
برای کاربران پیشرفته، یک آرشیو انتشار متناسب با معماری خود را از برای کاربران پیشرفته، یک آرشیو انتشار متناسب با معماری خود را از
[صفحهٔ releases](https://github.com/MHSanaei/3x-ui/releases) دانلود کنید، آن را [صفحهٔ releases](https://github.com/MHSanaei/L-UI/releases) دانلود کنید، آن را
استخراج کنید و باینری را به‌عنوان یک سرویس systemd اجرا کنید. اسکریپت نصب دقیقاً استخراج کنید و باینری را به‌عنوان یک سرویس systemd اجرا کنید. اسکریپت نصب دقیقاً
همین مراحل را خودکار می‌کند، بنابراین مگر اینکه دلیل خاصی برای نصب دستی داشته همین مراحل را خودکار می‌کند، بنابراین مگر اینکه دلیل خاصی برای نصب دستی داشته
باشید، روش اسکریپتی ترجیح داده می‌شود. باشید، روش اسکریپتی ترجیح داده می‌شود.
@@ -107,7 +107,7 @@ docker run -d \
شما بک‌اند ذخیره‌سازی را در زمان نصب انتخاب می‌کنید: شما بک‌اند ذخیره‌سازی را در زمان نصب انتخاب می‌کنید:
- **SQLite** (پیش‌فرض) — یک فایل واحد در مسیر `/etc/x-ui/x-ui.db`. بدون نیاز به هیچ تنظیماتی. - **SQLite** (پیش‌فرض) — یک فایل واحد در مسیر `/etc/l-ui/l-ui.db`. بدون نیاز به هیچ تنظیماتی.
- **PostgreSQL** — برای تعداد کلاینت بالا یا پیکربندی‌های چندنودی. نصب‌کننده - **PostgreSQL** — برای تعداد کلاینت بالا یا پیکربندی‌های چندنودی. نصب‌کننده
می‌تواند آن را به‌صورت محلی نصب کند یا از یک DSN که شما ارائه می‌دهید استفاده کند. می‌تواند آن را به‌صورت محلی نصب کند یا از یک DSN که شما ارائه می‌دهید استفاده کند.
@@ -117,15 +117,15 @@ docker run -d \
## نصب خودکار / cloud-init ## نصب خودکار / cloud-init
نصب‌کننده برای خودکارسازی به‌صورت **غیرتعاملی** نیز اجرا می‌شود. نصب‌کننده برای خودکارسازی به‌صورت **غیرتعاملی** نیز اجرا می‌شود.
`XUI_NONINTERACTIVE=1` را تنظیم کنید (یا بدون TTY اجرا کنید) تا نصب به‌صورت `LUI_NONINTERACTIVE=1` را تنظیم کنید (یا بدون TTY اجرا کنید) تا نصب به‌صورت
سرتاسری و بدون هیچ پرسشی انجام شود، مشخصات تصادفی تولید کند و آن‌ها را در سرتاسری و بدون هیچ پرسشی انجام شود، مشخصات تصادفی تولید کند و آن‌ها را در
`/etc/x-ui/install-result.env` بنویسد: `/etc/l-ui/install-result.env` بنویسد:
```bash ```bash
XUI_NONINTERACTIVE=1 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) LUI_NONINTERACTIVE=1 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
``` ```
دایرکتوری [`deploy/`](https://github.com/MHSanaei/3x-ui/tree/main/deploy) در مخزن دایرکتوری [`deploy/`](https://github.com/MHSanaei/L-UI/tree/main/deploy) در مخزن
یک user-data آمادهٔ **cloud-init** برای نصب‌های خودکار روی هر ابری (Hetzner، AWS، یک user-data آمادهٔ **cloud-init** برای نصب‌های خودکار روی هر ابری (Hetzner، AWS،
DigitalOcean، Vultr، GCP، Azure، Oracle) دارد. DigitalOcean، Vultr، GCP، Azure، Oracle) دارد.
@@ -140,7 +140,7 @@ DigitalOcean، Vultr، GCP، Azure، Oracle) دارد.
<Card <Card
title="به‌روزرسانی و حذف نصب" title="به‌روزرسانی و حذف نصب"
href="/docs/guide/update-uninstall" href="/docs/guide/update-uninstall"
description="منوی x-ui، به‌روزرسانی‌ها و حذف." description="منوی l-ui، به‌روزرسانی‌ها و حذف."
/> />
<Card <Card
title="REALITY" title="REALITY"
+26 -26
View File
@@ -1,17 +1,17 @@
--- ---
title: به‌روزرسانی و حذف title: به‌روزرسانی و حذف
description: مدیریت 3x-ui با منوی x-ui و خط فرمان — به‌روزرسانی (پایدار، dev یا نسخه‌های قدیمی)، تغییر تنظیمات و حذف تمیز و کامل. description: مدیریت L-UI با منوی l-ui و خط فرمان — به‌روزرسانی (پایدار، dev یا نسخه‌های قدیمی)، تغییر تنظیمات و حذف تمیز و کامل.
icon: RefreshCw icon: RefreshCw
--- ---
پس از نصب با اسکریپت، دستور `x-ui` مرکز کنترل شماست. آن را بدون هیچ آرگومانی اجرا پس از نصب با اسکریپت، دستور `l-ui` مرکز کنترل شماست. آن را بدون هیچ آرگومانی اجرا
کنید تا منوی تعاملی باز شود، یا یک زیردستور به آن بدهید تا یک عملیات تک‌مرحله‌ای انجام شود. کنید تا منوی تعاملی باز شود، یا یک زیردستور به آن بدهید تا یک عملیات تک‌مرحله‌ای انجام شود.
```bash ```bash
x-ui l-ui
``` ```
## منوی مدیریت `x-ui` ## منوی مدیریت `l-ui`
منو (آیتم‌های `0`–`28`) وضعیت پنل/Xray را در بالا نشان می‌دهد و سپس: منو (آیتم‌های `0`–`28`) وضعیت پنل/Xray را در بالا نشان می‌دهد و سپس:
@@ -20,9 +20,9 @@ x-ui
| 1 | Install | (دوباره) نصب از روی اسکریپت راه دور | | 1 | Install | (دوباره) نصب از روی اسکریپت راه دور |
| 2 | Update | به‌روزرسانی به آخرین نسخهٔ **پایدار** | | 2 | Update | به‌روزرسانی به آخرین نسخهٔ **پایدار** |
| 3 | Update to Dev Channel (latest commit) | به‌روزرسانی به بیلد غلتان `dev-latest` | | 3 | Update to Dev Channel (latest commit) | به‌روزرسانی به بیلد غلتان `dev-latest` |
| 4 | Update Menu | به‌روزرسانی فقط اسکریپت منوی `x-ui` | | 4 | Update Menu | به‌روزرسانی فقط اسکریپت منوی `l-ui` |
| 5 | Legacy Version | نصب یک نسخهٔ قدیمی مشخص (تگ را می‌پرسد) | | 5 | Legacy Version | نصب یک نسخهٔ قدیمی مشخص (تگ را می‌پرسد) |
| 6 | Uninstall | حذف 3x-ui (در ادامه ببینید) | | 6 | Uninstall | حذف L-UI (در ادامه ببینید) |
| 7 | Reset Username & Password | تنظیم مشخصات جدید؛ اختیاراً غیرفعال‌کردن 2FA | | 7 | Reset Username & Password | تنظیم مشخصات جدید؛ اختیاراً غیرفعال‌کردن 2FA |
| 8 | Reset Web Base Path | تصادفی‌کردن مسیر پایهٔ وب | | 8 | Reset Web Base Path | تصادفی‌کردن مسیر پایهٔ وب |
| 9 | Reset Settings | بازنشانی تنظیمات پنل (حساب شما حفظ می‌شود) | | 9 | Reset Settings | بازنشانی تنظیمات پنل (حساب شما حفظ می‌شود) |
@@ -51,29 +51,29 @@ x-ui
## زیردستورهای خط فرمان ## زیردستورهای خط فرمان
برای اسکریپت‌ها و اقدام‌های سریع، `x-ui` یک زیردستور را هم مستقیماً می‌پذیرد: برای اسکریپت‌ها و اقدام‌های سریع، `l-ui` یک زیردستور را هم مستقیماً می‌پذیرد:
| دستور | عملیات | | دستور | عملیات |
| -------------------------- | --------------------------------------------------- | | -------------------------- | --------------------------------------------------- |
| `x-ui start` / `stop` / `restart` | کنترل سرویس | | `l-ui start` / `stop` / `restart` | کنترل سرویس |
| `x-ui restart-xray` | بارگذاری مجدد فقط Xray-core | | `l-ui restart-xray` | بارگذاری مجدد فقط Xray-core |
| `x-ui status` | نمایش وضعیت | | `l-ui status` | نمایش وضعیت |
| `x-ui settings` | نمایش تنظیمات فعلی | | `l-ui settings` | نمایش تنظیمات فعلی |
| `x-ui enable` / `disable` | فعال/غیرفعال‌کردن اجرای خودکار در زمان بوت | | `l-ui enable` / `disable` | فعال/غیرفعال‌کردن اجرای خودکار در زمان بوت |
| `x-ui log` | دنبال‌کردن لاگ دیباگ | | `l-ui log` | دنبال‌کردن لاگ دیباگ |
| `x-ui banlog` | نمایش لاگ مسدودسازی Fail2ban | | `l-ui banlog` | نمایش لاگ مسدودسازی Fail2ban |
| `x-ui update` | به‌روزرسانی به آخرین نسخهٔ پایدار | | `l-ui update` | به‌روزرسانی به آخرین نسخهٔ پایدار |
| `x-ui update-dev` | به‌روزرسانی به بیلد غلتان `dev-latest` | | `l-ui update-dev` | به‌روزرسانی به بیلد غلتان `dev-latest` |
| `x-ui legacy` | نصب یک نسخهٔ قدیمی مشخص (می‌پرسد) | | `l-ui legacy` | نصب یک نسخهٔ قدیمی مشخص (می‌پرسد) |
| `x-ui update-all-geofiles` | به‌روزرسانی همهٔ فایل‌های geo و راه‌اندازی مجدد در صورت تغییر | | `l-ui update-all-geofiles` | به‌روزرسانی همهٔ فایل‌های geo و راه‌اندازی مجدد در صورت تغییر |
| `x-ui migrate-db --dsn …` | مهاجرت SQLite ← PostgreSQL (نگاه کنید به [پایگاه‌داده](/docs/reference/database)) | | `l-ui migrate-db --dsn …` | مهاجرت SQLite ← PostgreSQL (نگاه کنید به [پایگاه‌داده](/docs/reference/database)) |
| `x-ui install` / `uninstall` | نصب / حذف | | `l-ui install` / `uninstall` | نصب / حذف |
## به‌روزرسانی ## به‌روزرسانی
- **پایدار:** گزینهٔ منوی **۲** یا `x-ui update`. اجرای دوبارهٔ اسکریپت نصب هم - **پایدار:** گزینهٔ منوی **۲** یا `l-ui update`. اجرای دوبارهٔ اسکریپت نصب هم
در همان محل به‌روزرسانی می‌کند. در همان محل به‌روزرسانی می‌کند.
- **کانال dev:** گزینهٔ منوی **۳** یا `x-ui update-dev` — بیلد غلتان - **کانال dev:** گزینهٔ منوی **۳** یا `l-ui update-dev` — بیلد غلتان
`dev-latest` به‌ازای هر کامیت (نه یک نسخهٔ پایدار). `dev-latest` به‌ازای هر کامیت (نه یک نسخهٔ پایدار).
- **یک نسخهٔ قدیمی مشخص:** گزینهٔ منوی **۵** (Legacy Version). - **یک نسخهٔ قدیمی مشخص:** گزینهٔ منوی **۵** (Legacy Version).
@@ -82,18 +82,18 @@ x-ui
<Callout type="info"> <Callout type="info">
کاربران Docker به شیوهٔ دیگری به‌روزرسانی می‌کنند — به‌جای استفاده از دستورهای کاربران Docker به شیوهٔ دیگری به‌روزرسانی می‌کنند — به‌جای استفاده از دستورهای
به‌روزرسانی `x-ui`، ایمیج جدید را pull کرده و کانتینر را از نو بسازید به‌روزرسانی `l-ui`، ایمیج جدید را pull کرده و کانتینر را از نو بسازید
(`docker compose pull && docker compose up -d`). (`docker compose pull && docker compose up -d`).
</Callout> </Callout>
## حذف ## حذف
گزینهٔ منوی **۶** یا `x-ui uninstall`. سرویس را متوقف و غیرفعال می‌کند، یونیت سرویس گزینهٔ منوی **۶** یا `l-ui uninstall`. سرویس را متوقف و غیرفعال می‌کند، یونیت سرویس
را حذف می‌کند و `/etc/x-ui/` و پوشهٔ نصب را پاک می‌کند. اگر پنل از یک PostgreSQL را حذف می‌کند و `/etc/l-ui/` و پوشهٔ نصب را پاک می‌کند. اگر پنل از یک PostgreSQL
نصب‌شده به‌صورت محلی استفاده می‌کرده، پیشنهاد می‌دهد آن را هم پاک‌سازی کند (یک تأیید نصب‌شده به‌صورت محلی استفاده می‌کرده، پیشنهاد می‌دهد آن را هم پاک‌سازی کند (یک تأیید
جداگانه و برگشت‌ناپذیر). جداگانه و برگشت‌ناپذیر).
<Callout type="warn"> <Callout type="warn">
حذف، پایگاه‌داده (`/etc/x-ui/x-ui.db`) و پیکربندی شما را پاک می‌کند. اگر ممکن است حذف، پایگاه‌داده (`/etc/l-ui/l-ui.db`) و پیکربندی شما را پاک می‌کند. اگر ممکن است
بعداً به آن نیاز داشته باشید، ابتدا [پشتیبان بگیرید](/docs/operations/backup-restore). بعداً به آن نیاز داشته باشید، ابتدا [پشتیبان بگیرید](/docs/operations/backup-restore).
</Callout> </Callout>
+6 -6
View File
@@ -1,28 +1,28 @@
--- ---
title: مشارکت title: مشارکت
description: چگونه در توسعه 3x-ui مشارکت کنید و این مستندات را ترجمه کنید. description: چگونه در توسعه L-UI مشارکت کنید و این مستندات را ترجمه کنید.
icon: GitPullRequestArrow icon: GitPullRequestArrow
--- ---
3x-ui یک پروژه جامعه‌محور است. مشارکت در پنل و در این مستندات با آغوش باز پذیرفته L-UI یک پروژه جامعه‌محور است. مشارکت در پنل و در این مستندات با آغوش باز پذیرفته
می‌شود. می‌شود.
## حمایت از توسعه‌دهنده ## حمایت از توسعه‌دهنده
3x-ui رایگان و متن‌باز است و به‌صورت عمومی ساخته و نگهداری می‌شود. اگر برایتان L-UI رایگان و متن‌باز است و به‌صورت عمومی ساخته و نگهداری می‌شود. اگر برایتان
مفید بوده است، حمایت از ادامه توسعه را در نظر بگیرید: مفید بوده است، حمایت از ادامه توسعه را در نظر بگیرید:
- در [donate.sanaei.dev](https://donate.sanaei.dev/) **کمک مالی** کنید — این صفحه - در [donate.sanaei.dev](https://donate.sanaei.dev/) **کمک مالی** کنید — این صفحه
**اهداف و سقف‌های** جاری تأمین مالی را که می‌توانید در رسیدن به آن‌ها کمک کنید نشان می‌دهد. **اهداف و سقف‌های** جاری تأمین مالی را که می‌توانید در رسیدن به آن‌ها کمک کنید نشان می‌دهد.
- به [مخزن](https://github.com/MHSanaei/3x-ui) **ستاره** بدهید و پروژه را به اشتراک - به [مخزن](https://github.com/MHSanaei/L-UI) **ستاره** بدهید و پروژه را به اشتراک
بگذارید. بگذارید.
- به کانال Telegram یعنی [@XrayUI](https://t.me/XrayUI) **بپیوندید** تا اخبار را - به کانال Telegram یعنی [@XrayUI](https://t.me/XrayUI) **بپیوندید** تا اخبار را
دنبال کنید و به دیگران کمک کنید. دنبال کنید و به دیگران کمک کنید.
## مشارکت در 3x-ui ## مشارکت در L-UI
- فایل `CONTRIBUTING.md` پروژه را در - فایل `CONTRIBUTING.md` پروژه را در
[مخزن](https://github.com/MHSanaei/3x-ui) بخوانید. [مخزن](https://github.com/MHSanaei/L-UI) بخوانید.
- برای باگ‌ها و درخواست‌های امکانات جدید، با گام‌های بازتولید روشن، issue باز کنید. - برای باگ‌ها و درخواست‌های امکانات جدید، با گام‌های بازتولید روشن، issue باز کنید.
- از Conventional Commits استفاده کنید و pull requestها را متمرکز نگه دارید. - از Conventional Commits استفاده کنید و pull requestها را متمرکز نگه دارید.
+9 -9
View File
@@ -1,13 +1,13 @@
--- ---
title: سؤالات متداول title: سؤالات متداول
description: پرسش‌های پرتکرار درباره 3x-ui — مجوز، سیستم‌های پشتیبانی‌شده، پایگاه‌های داده و کلاینت‌ها. description: پرسش‌های پرتکرار درباره L-UI — مجوز، سیستم‌های پشتیبانی‌شده، پایگاه‌های داده و کلاینت‌ها.
icon: CircleQuestionMark icon: CircleQuestionMark
--- ---
## آیا 3x-ui رایگان و متن‌باز است؟ ## آیا L-UI رایگان و متن‌باز است؟
بله. 3x-ui تحت مجوز GPL-3.0 متن‌باز است. کد منبع آن روی بله. L-UI تحت مجوز GPL-3.0 متن‌باز است. کد منبع آن روی
[GitHub](https://github.com/MHSanaei/3x-ui) در دسترس است. [GitHub](https://github.com/MHSanaei/L-UI) در دسترس است.
## روی چه سیستم‌هایی اجرا می‌شود؟ ## روی چه سیستم‌هایی اجرا می‌شود؟
@@ -18,7 +18,7 @@ Fedora، Arch، Alpine و موارد دیگر) روی معماری‌های `amd
## SQLite یا PostgreSQL؟ ## SQLite یا PostgreSQL؟
SQLite گزینه پیش‌فرض است و برای بیشتر استقرارها مناسب است. PostgreSQL برای SQLite گزینه پیش‌فرض است و برای بیشتر استقرارها مناسب است. PostgreSQL برای
راه‌اندازی‌های بزرگ‌تر از طریق `XUI_DB_TYPE=postgres` و `XUI_DB_DSN` در دسترس است — به راه‌اندازی‌های بزرگ‌تر از طریق `LUI_DB_TYPE=postgres` و `LUI_DB_DSN` در دسترس است — به
[متغیرهای محیطی](/docs/reference/env-vars) مراجعه کنید. [متغیرهای محیطی](/docs/reference/env-vars) مراجعه کنید.
## کدام اپلیکیشن‌های کلاینت با آن کار می‌کنند؟ ## کدام اپلیکیشن‌های کلاینت با آن کار می‌کنند؟
@@ -27,9 +27,9 @@ SQLite گزینه پیش‌فرض است و برای بیشتر استقراره
لینک اشتراک‌گذاری یا کد QR یک کلاینت را وارد کنید، یا از لینک اشتراک‌گذاری یا کد QR یک کلاینت را وارد کنید، یا از
[سابسکریپشن](/docs/config/subscription) استفاده کنید. [سابسکریپشن](/docs/config/subscription) استفاده کنید.
## 3x-ui چه تفاوتی با x-ui دارد؟ ## L-UI چه تفاوتی با l-ui دارد؟
3x-ui یک فورک ارتقایافته از پروژه اصلی X-UI است. این پروژه پشتیبانی گسترده‌تری از L-UI یک فورک ارتقایافته از پروژه اصلی X-UI است. این پروژه پشتیبانی گسترده‌تری از
پروتکل‌ها، پایداری بهبودیافته، حسابداری ترافیک به‌ازای هر کلاینت، مدیریت چندنودی، پروتکل‌ها، پایداری بهبودیافته، حسابداری ترافیک به‌ازای هر کلاینت، مدیریت چندنودی،
یک رابط کاربری ۱۳ زبانه و بسیاری از امکانات رفاهی را اضافه می‌کند. یک رابط کاربری ۱۳ زبانه و بسیاری از امکانات رفاهی را اضافه می‌کند.
@@ -37,11 +37,11 @@ SQLite گزینه پیش‌فرض است و برای بیشتر استقراره
اسکریپت نصب را دوباره اجرا کنید (به‌صورت درجا به‌روزرسانی می‌شود)، یا ایمیج جدید Docker را دریافت کنید. اسکریپت نصب را دوباره اجرا کنید (به‌صورت درجا به‌روزرسانی می‌شود)، یا ایمیج جدید Docker را دریافت کنید.
به [نصب](/docs/guide/installation) و به [نصب](/docs/guide/installation) و
[صفحه نسخه‌ها](https://github.com/MHSanaei/3x-ui/releases) مراجعه کنید. [صفحه نسخه‌ها](https://github.com/MHSanaei/L-UI/releases) مراجعه کنید.
## از کجا می‌توانم کمک بگیرم؟ ## از کجا می‌توانم کمک بگیرم؟
به کانال رسمی Telegram با نشانی [@XrayUI](https://t.me/XrayUI) برای به کانال رسمی Telegram با نشانی [@XrayUI](https://t.me/XrayUI) برای
اطلاعیه‌ها و پشتیبانی انجمن بپیوندید، یا یک ایشو روی اطلاعیه‌ها و پشتیبانی انجمن بپیوندید، یا یک ایشو روی
[GitHub](https://github.com/MHSanaei/3x-ui/issues) باز کنید. برای مشکلات رایج، با [GitHub](https://github.com/MHSanaei/L-UI/issues) باز کنید. برای مشکلات رایج، با
[عیب‌یابی](/docs/help/troubleshooting) شروع کنید. [عیب‌یابی](/docs/help/troubleshooting) شروع کنید.
+8 -8
View File
@@ -1,6 +1,6 @@
--- ---
title: مهاجرت title: مهاجرت
description: مهاجرت به 3x-ui از x-ui، بین سرورها یا بین نسخه‌های 3x-ui. description: مهاجرت به L-UI از l-ui، بین سرورها یا بین نسخه‌های L-UI.
icon: ArrowRightLeft icon: ArrowRightLeft
--- ---
@@ -13,12 +13,12 @@ icon: ArrowRightLeft
<Step> <Step>
### از سرور قدیمی نسخه پشتیبان بگیرید ### از سرور قدیمی نسخه پشتیبان بگیرید
از پایگاه‌داده (به‌صورت پیش‌فرض `/etc/x-ui/x-ui.db`) و گواهی‌نامه‌های خود یک کپی تهیه کنید. از پایگاه‌داده (به‌صورت پیش‌فرض `/etc/l-ui/l-ui.db`) و گواهی‌نامه‌های خود یک کپی تهیه کنید.
[پشتیبان‌گیری و بازیابی](/docs/operations/backup-restore) را ببینید. [پشتیبان‌گیری و بازیابی](/docs/operations/backup-restore) را ببینید.
</Step> </Step>
<Step> <Step>
### 3x-ui را روی سرور جدید نصب کنید ### L-UI را روی سرور جدید نصب کنید
از همان روش نصب و یک نسخهٔ سازگار استفاده کنید. از همان روش نصب و یک نسخهٔ سازگار استفاده کنید.
[نصب](/docs/guide/installation) را ببینید. [نصب](/docs/guide/installation) را ببینید.
@@ -32,17 +32,17 @@ icon: ArrowRightLeft
</Steps> </Steps>
## بین نسخه‌های 3x-ui ## بین نسخه‌های L-UI
در محدودهٔ یک backend یکسان، ارتقا معمولاً تنها به اجرای دوبارهٔ نصب‌کننده یا در محدودهٔ یک backend یکسان، ارتقا معمولاً تنها به اجرای دوبارهٔ نصب‌کننده یا
کشیدن یک image جدید خلاصه می‌شود — پنل خودش پایگاه‌داده‌اش را مهاجرت می‌دهد. هنگام تغییر بین نسخه‌های **اصلی**، کشیدن یک image جدید خلاصه می‌شود — پنل خودش پایگاه‌داده‌اش را مهاجرت می‌دهد. هنگام تغییر بین نسخه‌های **اصلی**،
ابتدا [یادداشت‌های انتشار](https://github.com/MHSanaei/3x-ui/releases) ابتدا [یادداشت‌های انتشار](https://github.com/MHSanaei/L-UI/releases)
را بخوانید و یک نسخهٔ پشتیبان تهیه کنید. را بخوانید و یک نسخهٔ پشتیبان تهیه کنید.
## از x-ui ## از l-ui
وارد کردن مستقیم پایگاه‌دادهٔ یک پنل قدیمی x-ui به 3x-ui **پشتیبانی نمی‌شود** — وارد کردن مستقیم پایگاه‌دادهٔ یک پنل قدیمی l-ui به L-UI **پشتیبانی نمی‌شود** —
چون ساختار schema آن‌ها متفاوت است. 3x-ui را از نو نصب کنید و inboundها/کلاینت‌ها را چون ساختار schema آن‌ها متفاوت است. L-UI را از نو نصب کنید و inboundها/کلاینت‌ها را
دوباره بسازید و در همین حین لینک‌های اشتراک‌گذاری را از پنل قدیمی خروجی بگیرید. دوباره بسازید و در همین حین لینک‌های اشتراک‌گذاری را از پنل قدیمی خروجی بگیرید.
<Callout type="warn"> <Callout type="warn">
@@ -1,17 +1,17 @@
--- ---
title: عیب‌یابی title: عیب‌یابی
description: رفع مشکلات رایج 3x-ui — اجرا نشدن پنل، خطاهای 502، مشکلات گواهی و کلاینت‌هایی که نمی‌توانند متصل شوند. description: رفع مشکلات رایج L-UI — اجرا نشدن پنل، خطاهای 502، مشکلات گواهی و کلاینت‌هایی که نمی‌توانند متصل شوند.
icon: Wrench icon: Wrench
--- ---
فهرستی برای رسیدگی به رایج‌ترین مشکلات. هرگاه مطمئن نبودید، سطح لاگ را بالا ببرید فهرستی برای رسیدگی به رایج‌ترین مشکلات. هرگاه مطمئن نبودید، سطح لاگ را بالا ببرید
(`XUI_LOG_LEVEL=debug`) و لاگ‌های پنل و Xray را بررسی کنید. (`LUI_LOG_LEVEL=debug`) و لاگ‌های پنل و Xray را بررسی کنید.
## پنل اجرا نمی‌شود ## پنل اجرا نمی‌شود
- وضعیت سرویس و لاگ‌ها را بررسی کنید (منوی `x-ui` ← وضعیت/لاگ‌ها). - وضعیت سرویس و لاگ‌ها را بررسی کنید (منوی `l-ui` ← وضعیت/لاگ‌ها).
- مطمئن شوید که **پورت پنل از قبل توسط سرویس دیگری اشغال نشده** باشد. - مطمئن شوید که **پورت پنل از قبل توسط سرویس دیگری اشغال نشده** باشد.
- بررسی کنید که مسیر دیتابیس قابل نوشتن باشد (پیش‌فرض `/etc/x-ui/x-ui.db`). - بررسی کنید که مسیر دیتابیس قابل نوشتن باشد (پیش‌فرض `/etc/l-ui/l-ui.db`).
## خطای 502 / در دسترس نبودن پنل پشت یک پروکسی ## خطای 502 / در دسترس نبودن پنل پشت یک پروکسی
@@ -37,6 +37,6 @@ icon: Wrench
<Callout type="info"> <Callout type="info">
همچنان به مشکل خورده‌اید؟ در میان همچنان به مشکل خورده‌اید؟ در میان
[مسائل GitHub](https://github.com/MHSanaei/3x-ui/issues) جست‌وجو کنید — احتمالاً [مسائل GitHub](https://github.com/MHSanaei/L-UI/issues) جست‌وجو کنید — احتمالاً
علامت مشکل شما قبلاً دیده شده است. علامت مشکل شما قبلاً دیده شده است.
</Callout> </Callout>
+5 -5
View File
@@ -1,10 +1,10 @@
--- ---
title: مستندات 3x-ui title: مستندات L-UI
description: مستندات رسمی 3x-ui — یک پنل وب پیشرفته برای مدیریت سرورهای Xray-core، پروکسی‌ها، کلاینت‌ها و سابسکریپشن‌ها. description: مستندات رسمی L-UI — یک پنل وب پیشرفته برای مدیریت سرورهای Xray-core، پروکسی‌ها، کلاینت‌ها و سابسکریپشن‌ها.
icon: House icon: House
--- ---
**3x-ui** یک پنل وب متن‌باز برای استقرار و مدیریت سرورهای **L-UI** یک پنل وب متن‌باز برای استقرار و مدیریت سرورهای
[Xray-core](https://github.com/XTLS/Xray-core) است. این پنل یک داشبورد مدرن برای [Xray-core](https://github.com/XTLS/Xray-core) است. این پنل یک داشبورد مدرن برای
اینباندها، پروتکل‌ها، کلاینت‌ها، حسابداری ترافیک، سابسکریپشن‌ها و موارد دیگر در اینباندها، پروتکل‌ها، کلاینت‌ها، حسابداری ترافیک، سابسکریپشن‌ها و موارد دیگر در
اختیار شما می‌گذارد — بدون نیاز به ویرایش دستی JSON مربوط به Xray از طریق خط فرمان. اختیار شما می‌گذارد — بدون نیاز به ویرایش دستی JSON مربوط به Xray از طریق خط فرمان.
@@ -17,7 +17,7 @@ icon: House
<Cards> <Cards>
<Card <Card
title="3x-ui چیست؟" title="L-UI چیست؟"
href="/docs/guide" href="/docs/guide"
description="نمای کلی: Xray-core، پنل، و اینکه برای چه کسانی مناسب است." description="نمای کلی: Xray-core، پنل، و اینکه برای چه کسانی مناسب است."
/> />
@@ -49,6 +49,6 @@ icon: House
- **عملیات** — مدیریت چندنودی، ربات Telegram، پشتیبان‌گیری و یک REST API. - **عملیات** — مدیریت چندنودی، ربات Telegram، پشتیبان‌گیری و یک REST API.
<Callout type="info"> <Callout type="info">
با Xray تازه آشنا شده‌اید؟ ابتدا [3x-ui چیست؟](/docs/guide) را بخوانید — توضیح می‌دهد که پنل، Xray-core و با Xray تازه آشنا شده‌اید؟ ابتدا [L-UI چیست؟](/docs/guide) را بخوانید — توضیح می‌دهد که پنل، Xray-core و
اپلیکیشن‌های کلاینت شما چگونه در کنار هم کار می‌کنند. اپلیکیشن‌های کلاینت شما چگونه در کنار هم کار می‌کنند.
</Callout> </Callout>
@@ -1,6 +1,6 @@
--- ---
title: پشتیبان‌گیری و بازیابی title: پشتیبان‌گیری و بازیابی
description: از پایگاه‌داده و گواهی‌های 3x-ui خود به‌صورت دستی یا از طریق ربات Telegram پشتیبان بگیرید و آن‌ها را بازیابی کنید. description: از پایگاه‌داده و گواهی‌های L-UI خود به‌صورت دستی یا از طریق ربات Telegram پشتیبان بگیرید و آن‌ها را بازیابی کنید.
icon: DatabaseBackup icon: DatabaseBackup
--- ---
@@ -9,7 +9,7 @@ icon: DatabaseBackup
## از چه چیزی پشتیبان بگیریم ## از چه چیزی پشتیبان بگیریم
- **پایگاه‌داده** — به‌صورت پیش‌فرض یک SQLite در `/etc/x-ui/x-ui.db` (یا پایگاه‌داده‌ی - **پایگاه‌داده** — به‌صورت پیش‌فرض یک SQLite در `/etc/l-ui/l-ui.db` (یا پایگاه‌داده‌ی
PostgreSQL شما اگر از آن backend استفاده می‌کنید). PostgreSQL شما اگر از آن backend استفاده می‌کنید).
- **گواهی‌ها** — هر چیزی که زیر `/root/cert/` (یا هر جایی که گواهی‌های TLS را نگه می‌دارید) - **گواهی‌ها** — هر چیزی که زیر `/root/cert/` (یا هر جایی که گواهی‌های TLS را نگه می‌دارید)
قرار دارد. قرار دارد.
@@ -20,7 +20,7 @@ icon: DatabaseBackup
مستقیماً از سرور کپی نمایید: مستقیماً از سرور کپی نمایید:
```bash title="copy the SQLite database" ```bash title="copy the SQLite database"
cp /etc/x-ui/x-ui.db /root/x-ui-backup-$(date +%F).db cp /etc/l-ui/l-ui.db /root/l-ui-backup-$(date +%F).db
``` ```
برای بازیابی، پنل را متوقف کنید، پایگاه‌داده را سر جای خود برگردانید و دوباره آن را اجرا کنید. برای بازیابی، پنل را متوقف کنید، پایگاه‌داده را سر جای خود برگردانید و دوباره آن را اجرا کنید.
@@ -41,12 +41,12 @@ cp /etc/x-ui/x-ui.db /root/x-ui-backup-$(date +%F).db
## دامپ / بازیابی SQLite ## دامپ / بازیابی SQLite
دستور `x-ui migrate-db` پایگاه‌داده‌ی SQLite را به یک دامپ متنی SQL ساده و بالعکس تبدیل دستور `l-ui migrate-db` پایگاه‌داده‌ی SQLite را به یک دامپ متنی SQL ساده و بالعکس تبدیل
می‌کند (برای بررسی یا انتقال میان دستگاه‌ها کاربردی است): می‌کند (برای بررسی یا انتقال میان دستگاه‌ها کاربردی است):
```bash ```bash
x-ui migrate-db --dump /root/x-ui.sql # SQLite -> SQL text l-ui migrate-db --dump /root/l-ui.sql # SQLite -> SQL text
x-ui migrate-db --restore /root/x-ui.sql # SQL text -> SQLite l-ui migrate-db --restore /root/l-ui.sql # SQL text -> SQLite
``` ```
برای مهاجرت به PostgreSQL، به [پایگاه‌داده](/docs/reference/database) مراجعه کنید. برای مهاجرت به PostgreSQL، به [پایگاه‌داده](/docs/reference/database) مراجعه کنید.
@@ -1,14 +1,14 @@
--- ---
title: چندنودی و میزبان‌های مدیریت‌شده title: چندنودی و میزبان‌های مدیریت‌شده
description: مدیریت چند پنل 3x-ui از یک مستر، با اعتماد مبتنی بر توکن API یا mTLS، ضربان قلب، و بازنویسی میزبان برای هر inbound جهت اشتراک‌ها. description: مدیریت چند پنل L-UI از یک مستر، با اعتماد مبتنی بر توکن API یا mTLS، ضربان قلب، و بازنویسی میزبان برای هر inbound جهت اشتراک‌ها.
icon: Boxes icon: Boxes
--- ---
3x-ui می‌تواند **چندین سرور** را از یک پنل مستر واحد مدیریت کند و با **میزبان‌های مدیریت‌شده** نحوهٔ معرفی هر inbound در اشتراک‌ها را بازنویسی کند. L-UI می‌تواند **چندین سرور** را از یک پنل مستر واحد مدیریت کند و با **میزبان‌های مدیریت‌شده** نحوهٔ معرفی هر inbound در اشتراک‌ها را بازنویسی کند.
## نودها ## نودها
یک **نود** پنل 3x-ui دیگری است که پنل مستر شما آن را از طریق API نود مدیریت می‌کند. مستر هر نود را فراخوانی (poll) می‌کند و وضعیت، نسخه‌ها، CPU/حافظه، آپ‌تایم و ترافیک آن را در یک مکان نمایش می‌دهد. یک **نود** پنل L-UI دیگری است که پنل مستر شما آن را از طریق API نود مدیریت می‌کند. مستر هر نود را فراخوانی (poll) می‌کند و وضعیت، نسخه‌ها، CPU/حافظه، آپ‌تایم و ترافیک آن را در یک مکان نمایش می‌دهد.
### افزودن یک نود ### افزودن یک نود
@@ -1,11 +1,11 @@
--- ---
title: خروجی‌ها و مسیریابی title: خروجی‌ها و مسیریابی
description: مدیریت ترافیک خروجی در 3x-ui — خروجی‌های WARP، NordVPN، WireGuard PIA، اشتراک‌های خروجی (مجموعه سرورها)، قواعد مسیریابی و متعادل‌کننده‌های بار. description: مدیریت ترافیک خروجی در L-UI — خروجی‌های WARP، NordVPN، WireGuard PIA، اشتراک‌های خروجی (مجموعه سرورها)، قواعد مسیریابی و متعادل‌کننده‌های بار.
icon: Route icon: Route
--- ---
ورودی‌ها کلاینت‌ها را می‌پذیرند؛ **خروجی‌ها** تعیین می‌کنند ترافیک آن‌ها در ادامه به کجا برود. ورودی‌ها کلاینت‌ها را می‌پذیرند؛ **خروجی‌ها** تعیین می‌کنند ترافیک آن‌ها در ادامه به کجا برود.
3x-ui می‌تواند ترافیک را از طریق Cloudflare WARP، NordVPN، Private Internet Access L-UI می‌تواند ترافیک را از طریق Cloudflare WARP، NordVPN، Private Internet Access
(خروجی WireGuard) یا مجموعه‌های خروجی دلخواه (خروجی WireGuard) یا مجموعه‌های خروجی دلخواه
وارد‌شده از یک اشتراک مسیریابی کند و با قواعد مسیریابی و متعادل‌کننده‌ها میان آن‌ها وارد‌شده از یک اشتراک مسیریابی کند و با قواعد مسیریابی و متعادل‌کننده‌ها میان آن‌ها
انتخاب نماید. انتخاب نماید.
@@ -39,7 +39,7 @@ icon: Route
``` ```
یک خروجی **proxy** (VLESS، VMess، Trojan، Shadowsocks) به سرور دیگری ارسال می‌کند — یک خروجی **proxy** (VLESS، VMess، Trojan، Shadowsocks) به سرور دیگری ارسال می‌کند —
که برای زنجیره‌کردن یا فرستادن ترافیک منتخب به خارج مفید است. به شکل‌های سیمی که 3x-ui که برای زنجیره‌کردن یا فرستادن ترافیک منتخب به خارج مفید است. به شکل‌های سیمی که L-UI
استفاده می‌کند توجه کنید: **VLESS شکل تخت است** (`address`/`port`/`id`/`flow`/ استفاده می‌کند توجه کنید: **VLESS شکل تخت است** (`address`/`port`/`id`/`flow`/
`encryption`)، **VMess از `settings.vnext[]` استفاده می‌کند**، و **Trojan/Shadowsocks از `encryption`)، **VMess از `settings.vnext[]` استفاده می‌کند**، و **Trojan/Shadowsocks از
`settings.servers[]` استفاده می‌کنند**. مقدار `streamSettings` باید با `settings.servers[]` استفاده می‌کنند**. مقدار `streamSettings` باید با
@@ -51,7 +51,7 @@ icon: Route
## Cloudflare WARP ## Cloudflare WARP
WARP به سرور شما امکان می‌دهد ترافیک خود را از طریق شبکه Cloudflare خارج کند. 3x-ui می‌تواند WARP به سرور شما امکان می‌دهد ترافیک خود را از طریق شبکه Cloudflare خارج کند. L-UI می‌تواند
یک حساب WARP برای شما ثبت کند و آن را به یک خروجی WireGuard با برچسب **`warp`** متصل نماید: یک حساب WARP برای شما ثبت کند و آن را به یک خروجی WireGuard با برچسب **`warp`** متصل نماید:
<Steps> <Steps>
@@ -65,7 +65,7 @@ WARP به سرور شما امکان می‌دهد ترافیک خود را از
<Step> <Step>
### ثبت WARP ### ثبت WARP
از کنترل‌های WARP در پنل، یک حساب ثبت کنید. 3x-ui کلیدها، نشانی‌ها، بایت‌های رزروشده و نقطه از کنترل‌های WARP در پنل، یک حساب ثبت کنید. L-UI کلیدها، نشانی‌ها، بایت‌های رزروشده و نقطه
انتهایی peer مربوط به خروجی را به‌صورت خودکار پر می‌کند. انتهایی peer مربوط به خروجی را به‌صورت خودکار پر می‌کند.
</Step> </Step>
@@ -83,13 +83,13 @@ WARP به سرور شما امکان می‌دهد ترافیک خود را از
## NordVPN ## NordVPN
3x-ui می‌تواند اعتبارنامه‌های NordVPN (NordLynx/WireGuard) را از یک توکن دسترسی دریافت کند (یا L-UI می‌تواند اعتبارنامه‌های NordVPN (NordLynx/WireGuard) را از یک توکن دسترسی دریافت کند (یا
یک کلید خصوصی را مستقیماً بپذیرد) و کشورها/سرورها را فهرست کند تا بتوانید یک خروجی NordVPN یک کلید خصوصی را مستقیماً بپذیرد) و کشورها/سرورها را فهرست کند تا بتوانید یک خروجی NordVPN
بسازید. بسازید.
## خروجی WireGuard PIA ## خروجی WireGuard PIA
3x-ui می‌تواند با نام کاربری و رمز عبور PIA وارد شود، کشورها/منطقه‌ها/سرورها را L-UI می‌تواند با نام کاربری و رمز عبور PIA وارد شود، کشورها/منطقه‌ها/سرورها را
از فهرست امضاشده نشان دهد و یک خروجی WireGuard بسازد. از از فهرست امضاشده نشان دهد و یک خروجی WireGuard بسازد. از
**Xray → خروجی‌ها → بیشتر → PIA** وارد شوید، سرور را انتخاب کنید و خروجی را **Xray → خروجی‌ها → بیشتر → PIA** وارد شوید، سرور را انتخاب کنید و خروجی را
اضافه کنید. می‌توان چند سرور افزود (هر hostname یک خروجی). برچسب اضافه کنید. می‌توان چند سرور افزود (هر hostname یک خروجی). برچسب
@@ -100,7 +100,7 @@ Reset یا حذف، peer مربوط به WireGuard را در حساب PIA باط
گذرواژه ذخیره نمی‌شود. توکن API مربوط به PIA با همان تنظیم گذرواژه ذخیره نمی‌شود. توکن API مربوط به PIA با همان تنظیم
`NODE_TOKEN_ENCRYPTION` گره‌ها ذخیره می‌شود. اگر کلید قدیمی `NODE_TOKEN_ENCRYPTION` گره‌ها ذخیره می‌شود. اگر کلید قدیمی
`XUI_NODE_TOKEN_KEY` را بدون ورود دوباره به PIA کنار بگذارید، Add/Reset `LUI_NODE_TOKEN_KEY` را بدون ورود دوباره به PIA کنار بگذارید، Add/Reset
تا ورود مجدد شکست می‌خورد. `allowedIPs` فقط تا ورود مجدد شکست می‌خورد. `allowedIPs` فقط
`0.0.0.0/0` است. `0.0.0.0/0` است.
@@ -1,13 +1,13 @@
--- ---
title: پراکسی معکوس title: پراکسی معکوس
description: قرار دادن پنل و اشتراک 3x-ui پشت Nginx یا Caddy همراه با TLS از Let's Encrypt. description: قرار دادن پنل و اشتراک L-UI پشت Nginx یا Caddy همراه با TLS از Let's Encrypt.
icon: Waypoints icon: Waypoints
--- ---
پراکسی معکوس به شما امکان می‌دهد پنل و اشتراک را روی یک دامنه تمیز با HTTPS خودکار پراکسی معکوس به شما امکان می‌دهد پنل و اشتراک را روی یک دامنه تمیز با HTTPS خودکار
ارائه دهید و پورت‌های واقعی را پشت پورت‌های 80/443 پنهان کنید. ترجیح می‌دهید خودِ ارائه دهید و پورت‌های واقعی را پشت پورت‌های 80/443 پنهان کنید. ترجیح می‌دهید خودِ
پنل مستقیماً TLS را مدیریت کند؟ به‌جای آن، گواهی را از طریق پنل مستقیماً TLS را مدیریت کند؟ به‌جای آن، گواهی را از طریق
[منوی SSL در `x-ui`](/docs/config/ssl-certificates) دریافت کنید. [منوی SSL در `l-ui`](/docs/config/ssl-certificates) دریافت کنید.
## ساخت یک پیکربندی ## ساخت یک پیکربندی
@@ -45,7 +45,7 @@ panel.example.com {
## نکته‌ها ## نکته‌ها
- حتی پشت یک پراکسی هم **مسیر پایه وب** پنل را حفظ کنید؛ دفاع لایه‌به‌لایه. - حتی پشت یک پراکسی هم **مسیر پایه وب** پنل را حفظ کنید؛ دفاع لایه‌به‌لایه.
- اگر TLS را در پراکسی مدیریت می‌کنید، ممکن است بخواهید `XUI_SKIP_HSTS=true` را روی - اگر TLS را در پراکسی مدیریت می‌کنید، ممکن است بخواهید `LUI_SKIP_HSTS=true` را روی
پنل تنظیم کنید — به [مرجع متغیرهای محیطی](/docs/reference/env-vars) مراجعه کنید. پنل تنظیم کنید — به [مرجع متغیرهای محیطی](/docs/reference/env-vars) مراجعه کنید.
- سرور [اشتراک](/docs/config/subscription) را هم پراکسی کنید تا محتوای آن نیز روی - سرور [اشتراک](/docs/config/subscription) را هم پراکسی کنید تا محتوای آن نیز روی
HTTPS ارائه شود. HTTPS ارائه شود.
+7 -7
View File
@@ -1,6 +1,6 @@
--- ---
title: امنیت title: امنیت
description: سخت‌سازی 3x-ui — احراز هویت پنل و 2FA، محدودیت IP با Fail2ban، قوانین فایروال، BBR و به‌روز ماندن. description: سخت‌سازی L-UI — احراز هویت پنل و 2FA، محدودیت IP با Fail2ban، قوانین فایروال، BBR و به‌روز ماندن.
icon: ShieldCheck icon: ShieldCheck
--- ---
@@ -17,11 +17,11 @@ icon: ShieldCheck
## Fail2ban و محدودیت‌های IP ## Fail2ban و محدودیت‌های IP
برای هر کلاینت یک **محدودیت IP** تنظیم کنید (به [کلاینت‌ها](/docs/config/clients) مراجعه کنید) تا تعداد IPهای مبدأ همزمان محدود شود. اعمال این محدودیت توسط **Fail2ban** انجام می‌شود که 3x-ui آن را برای شما نصب و پیکربندی می‌کند (در نصب‌های اسکریپتی به‌طور پیش‌فرض فعال است و در Docker از طریق `XUI_ENABLE_FAIL2BAN=true`). برای هر کلاینت یک **محدودیت IP** تنظیم کنید (به [کلاینت‌ها](/docs/config/clients) مراجعه کنید) تا تعداد IPهای مبدأ همزمان محدود شود. اعمال این محدودیت توسط **Fail2ban** انجام می‌شود که L-UI آن را برای شما نصب و پیکربندی می‌کند (در نصب‌های اسکریپتی به‌طور پیش‌فرض فعال است و در Docker از طریق `LUI_ENABLE_FAIL2BAN=true`).
آن را از منوی `x-ui` مدیریت کنید (**۲۲ — IP Limit Management**): نصب/پیکربندی، تغییر مدت مسدودسازی (پیش‌فرض **۳۰ دقیقه**)، مسدودسازی/رفع مسدودی یک IP، مشاهده لاگ‌های مسدودسازی و بررسی وضعیت. در پشت صحنه: آن را از منوی `l-ui` مدیریت کنید (**۲۲ — IP Limit Management**): نصب/پیکربندی، تغییر مدت مسدودسازی (پیش‌فرض **۳۰ دقیقه**)، مسدودسازی/رفع مسدودی یک IP، مشاهده لاگ‌های مسدودسازی و بررسی وضعیت. در پشت صحنه:
- این jail با نام **`3x-ipl`** شناخته می‌شود؛ لاگ‌های مسدودسازی در `/var/log/x-ui/3xipl.log` و `/var/log/x-ui/3xipl-banned.log` قرار دارند (همچنین از طریق `x-ui banlog`). - این jail با نام **`3x-ipl`** شناخته می‌شود؛ لاگ‌های مسدودسازی در `/var/log/l-ui/3xipl.log` و `/var/log/l-ui/3xipl-banned.log` قرار دارند (همچنین از طریق `l-ui banlog`).
- مسدودسازی‌ها همه TCP/UDP را پوشش می‌دهند **به‌جز** پورت‌های SSH و پنل شما، بنابراین یک مسدودسازی نمی‌تواند شما را از سرور یا پنل بیرون بیندازد. - مسدودسازی‌ها همه TCP/UDP را پوشش می‌دهند **به‌جز** پورت‌های SSH و پنل شما، بنابراین یک مسدودسازی نمی‌تواند شما را از سرور یا پنل بیرون بیندازد.
<Callout type="warn"> <Callout type="warn">
@@ -33,7 +33,7 @@ icon: ShieldCheck
## فایروال ## فایروال
تنها پورت‌هایی را باز کنید که واقعاً استفاده می‌کنید: SSH، پورت پنل، پورت اشتراک و پورت‌های inbound خود. منوی `x-ui` (**۲۳ — Firewall Management**) ابزار `ufw` را در بر می‌گیرد، یا اینجا قوانین را تولید کنید: تنها پورت‌هایی را باز کنید که واقعاً استفاده می‌کنید: SSH، پورت پنل، پورت اشتراک و پورت‌های inbound خود. منوی `l-ui` (**۲۳ — Firewall Management**) ابزار `ufw` را در بر می‌گیرد، یا اینجا قوانین را تولید کنید:
<FirewallRulesGenerator /> <FirewallRulesGenerator />
@@ -45,9 +45,9 @@ icon: ShieldCheck
## تنظیم شبکه (BBR) ## تنظیم شبکه (BBR)
منوی `x-ui` (**۲۶ — Enable BBR**) کنترل ازدحام BBR گوگل را فعال/غیرفعال می‌کند منوی `l-ui` (**۲۶ — Enable BBR**) کنترل ازدحام BBR گوگل را فعال/غیرفعال می‌کند
(`net.ipv4.tcp_congestion_control = bbr`، `net.core.default_qdisc = fq`) که اغلب توان عملیاتی را روی لینک‌های شلوغ بهبود می‌بخشد. (`net.ipv4.tcp_congestion_control = bbr`، `net.core.default_qdisc = fq`) که اغلب توان عملیاتی را روی لینک‌های شلوغ بهبود می‌بخشد.
## به‌روز ماندن ## به‌روز ماندن
3x-ui و Xray-core را به‌طور منظم به‌روزرسانی کنید — اصلاحات امنیتی در نسخه‌های جدید منتشر می‌شوند. [صفحه انتشارها](https://github.com/MHSanaei/3x-ui/releases) را دنبال کنید و به [به‌روزرسانی و حذف نصب](/docs/guide/update-uninstall) مراجعه کنید. L-UI و Xray-core را به‌طور منظم به‌روزرسانی کنید — اصلاحات امنیتی در نسخه‌های جدید منتشر می‌شوند. [صفحه انتشارها](https://github.com/MHSanaei/L-UI/releases) را دنبال کنید و به [به‌روزرسانی و حذف نصب](/docs/guide/update-uninstall) مراجعه کنید.

Some files were not shown because too many files have changed in this diff Show More