mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-17 03:15:01 +03:00
54d1712544
* fix(clients): clarify renewal preview times and estimates The preview rendered RFC3339 strings directly and labeled the server's Local zone without explaining which clock it represented. Its renewal count also looked like a record of renewals already performed. Display readable dates with an explicit UTC offset while preserving the server's wall time, per-date DST offset and fractional cutoff precision. Explain the panel/server timezone and read-only preview, and label the renewal count as estimated allowance consumption in all 13 locales. Let the first-cutoff button wrap on narrow screens and update the English and Chinese client documentation plus display/form regression coverage. This changes presentation only: renewal calculations, stored expiry values, API payloads and first-use behavior remain unchanged. * test(clients): remove redundant renewal preview copy checks The locale-only preview case repeated the Local timezone branch without covering a distinct behavior. Exact textContent comparisons after matching the same text with getByText also only pinned constant wording, contrary to the repository's testing guidance. Remove that duplicate case, its locale setup and the redundant copy assertions. Keep the UTC, per-boundary DST offset, fractional precision and original datetime checks, together with the existing real form-save tests. Production rendering, translations and renewal behavior are unchanged. --------- Co-authored-by: JacktheRanger <219502738+JacktheRanger@users.noreply.github.com>
140 lines
8.1 KiB
Plaintext
140 lines
8.1 KiB
Plaintext
---
|
||
title: Clients
|
||
description: Manage 3x-ui clients — credentials, traffic and expiry limits, IP limits, groups, bulk actions, external links, and online status.
|
||
icon: Users
|
||
---
|
||
|
||
A **client** is a single user, identified by a unique **email**. In the current
|
||
panel, clients are first-class records that can be attached to **multiple
|
||
inbounds** at once, with per-client traffic accounting.
|
||
|
||
## Client fields
|
||
|
||
| Field | Applies to | Meaning |
|
||
| -------------- | --------------------- | ------------------------------------------------------------------ |
|
||
| **Email** | all | Unique identifier used for accounting and lookups. |
|
||
| **ID (UUID)** | VLESS, VMess, TUIC | The client credential. |
|
||
| **Password** | Trojan, Shadowsocks, TUIC | The client credential. |
|
||
| **Auth** | Hysteria2 | The client credential. |
|
||
| **Flow** | VLESS | XTLS flow, e.g. `xtls-rprx-vision`. |
|
||
| **Limit IP** | all (except TUIC) | Max simultaneous source IPs (enforced via Fail2ban). |
|
||
| **Total (GB)** | all | Traffic quota; the client is disabled when exhausted. |
|
||
| **Expiry** | all | Date after which the client stops working. |
|
||
| **Auto renewal** | all | Disabled, fixed interval in days, calendar weekly, or calendar monthly. |
|
||
| **Telegram ID**| all | Links the client to a Telegram user for self-service/notifications.|
|
||
| **Sub ID** | all | Subscription identifier grouping this client's links. |
|
||
| **Group** | all | Optional client group for organization and bulk filtering. |
|
||
| **Comment** | all | Free-text note. |
|
||
|
||
<Callout type="info">
|
||
Reaching the **traffic** or **expiry** limit disables the client, and a client
|
||
disabled or deleted by hand counts too; the panel restarts Xray then
|
||
(`restartXrayOnClientDisable`, on by default).
|
||
</Callout>
|
||
|
||
## Limits and IP control
|
||
|
||
- **Traffic / expiry** caps disable the client when hit; a **Reset** period
|
||
auto-renews the quota.
|
||
- **Limit IP** caps simultaneous source IPs. Enforcement relies on Fail2ban —
|
||
see [Security](/docs/operations/security). You can view a client's recent IPs
|
||
and clear them from the client's actions.
|
||
- **Online status** and **last-online** times are tracked per client (and per
|
||
node in multi-node setups).
|
||
|
||
## Automatic renewal
|
||
|
||
The individual and bulk-create forms offer one renewal mode at a time:
|
||
|
||
| Mode | API fields | Schedule |
|
||
| --- | --- | --- |
|
||
| Disabled | `reset=0`, `resetDay=0`, `resetWeekday=0` | The expiry is not renewed. |
|
||
| Fixed interval | `reset=N`, other two fields `0` | Add exactly N × 24 hours to the previous cutoff. |
|
||
| Calendar weekly | `resetWeekday=1..7`, other two fields `0` | Renew at panel-local midnight on Monday (1) through Sunday (7). |
|
||
| Calendar monthly | `resetDay=1..31`, `resetWeekday=0` | Renew at panel-local midnight on that day; missing dates clamp to the month's last day without losing the configured day. |
|
||
|
||
Calendar weeks stay on the selected weekday across daylight-saving changes;
|
||
they are not equivalent to a fixed seven-day interval. A skipped midnight uses
|
||
the first valid instant of that date; a repeated midnight uses the first one.
|
||
If a timezone skips the entire selected date, the next matching week is used.
|
||
Existing monthly clients
|
||
that also have `reset` set retain monthly precedence. The API rejects weekly
|
||
renewal combined with a positive `reset` or `resetDay`.
|
||
|
||
For a full calendar month, select **monthly, day 1** and set the initial cutoff
|
||
to the next month's first midnight. For example, `2030-09-01 00:00:00` is valid
|
||
through `2030-08-31 23:59:59`. Day 31 renews at the **start** of the 31st and is
|
||
not the same schedule. The existing optional month-end subscription-header
|
||
display remains a separate setting and is not enabled by this form.
|
||
|
||
The preview uses the panel's timezone and the same calendar/catch-up calculation
|
||
as automatic renewal. It shows the cutoff, last valid second, next expiry, and
|
||
allowances needed. It is informational: it does not save, activate, reserve, or
|
||
guarantee a future renewal. When no expiry is set, auto-renewal cannot run; an
|
||
explicit button can set the first calendar cutoff. Selecting a mode alone never
|
||
rewrites an existing expiry. First-use clients keep their initial duration, and
|
||
their calendar dates are available after activation.
|
||
|
||
Preview dates use the Gregorian format `YYYY-MM-DD HH:mm:ss UTC±HH:mm`,
|
||
preserving any fractional seconds in the cutoff. Each date includes its own
|
||
UTC offset, so a daylight-saving change can show different offsets before and
|
||
after renewal. The heading identifies the panel time zone; **Server local time**
|
||
means the server's `Local` setting, not the browser's time zone. For example,
|
||
`2026-09-27 05:00:00 UTC+00:00` is 13:00 in UTC+08:00. **Estimated renewals used**
|
||
is the allowance this preview would consume, including any catch-up periods,
|
||
not a count of renewals already performed. The first-cutoff button uses the same
|
||
date format; clicking it still requires saving the form to persist the change.
|
||
|
||
For legacy last-second calendar cutoffs, the renewal boundary includes the
|
||
existing free alignment to the following midnight. The last-valid-second
|
||
preview still uses the **stored expiry**, not that alignment: an exclusive
|
||
`23:59:59` cutoff is valid through `23:59:58`. Use a next-midnight cutoff for
|
||
full-day validity; the preview itself does not repair the initial expiry.
|
||
|
||
`resetMax=0` means unlimited renewals. A positive limit counts **each elapsed
|
||
period**, including offline catch-up, not each scheduler tick or attached inbound.
|
||
If the remaining allowances cannot reach a future cutoff, the client stays
|
||
expired and its traffic is not reset. Operator-disabled clients stay disabled.
|
||
|
||
Renewal already resets client traffic. The separate **periodic traffic reset**
|
||
does not move the expiry and is unchanged; keep it disabled unless you intend an
|
||
additional reset. Quarterly, yearly, and every-N-week/month schedules are not
|
||
part of these modes.
|
||
|
||
<Callout type="warn">
|
||
Upgrade the main panel and every participating node before enabling weekly
|
||
renewal. Older versions ignore `resetWeekday`; a weekly-only client would not
|
||
auto-renew and, after its expiry or quota is exhausted, can be deleted by
|
||
**delete depleted clients** because older versions lack the weekly protection.
|
||
Back up the database and convert weekly schedules to a renewal mode supported
|
||
by every participating version before downgrading. Merely disabling weekly
|
||
renewal does not protect a depleted client from deletion. Avoid depleted-client
|
||
cleanup while a mixed-version fleet or unconverted weekly clients remain.
|
||
Database upgrades default this new field to `0` and preserve existing limits
|
||
and dates.
|
||
</Callout>
|
||
|
||
## Share links and external links
|
||
|
||
Every client has share links and a QR code for its inbounds, plus a combined
|
||
[subscription](/docs/config/subscription). You can also attach **external
|
||
links** to a client — extra `vless://`, `vmess://`, `trojan://`, `ss://`,
|
||
`hysteria2://`, or `wireguard://` links, or a remote subscription URL — so they
|
||
appear alongside the panel-generated ones in the client's subscription.
|
||
|
||
To inspect exactly what a link contains, paste it into the
|
||
[share-link inspector](/docs/config/share-links).
|
||
|
||
## Bulk actions
|
||
|
||
For managing many clients at once, the panel supports bulk **create, enable,
|
||
disable, delete, attach/detach** (to inbounds), **reset traffic**, and
|
||
**adjust** (add days / add bytes / set flow). Maintenance actions also let you
|
||
delete **depleted** clients (quota/expiry exhausted) and **orphaned** clients
|
||
(not attached to any inbound).
|
||
|
||
<Callout type="warn">
|
||
A client's share link contains its credential. Treat links and QR codes like
|
||
passwords, and rotate the credential if one leaks.
|
||
</Callout>
|