Files
l-ui/docs/migration-l-ui.md
T
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

11 KiB

Migration: x-ui → l-ui (operator runbook, no code runs this)

This document is the only migration mechanism. The renamed code does not auto-migrate old paths at startup (except the Windows-only DB copy safety net noted in RENAMING.md) and does not read old XUI_* variables. Every old path below must be moved by the operator, on each machine, in the order given.

Applies to: panel hosts (systemd), agent nodes (systemd / OpenRC / procd), and the master host that also runs a local agent. It does not apply to the frozen Windows agent (TYYUN): that machine is untouched — its panel-side update badge is suppressed by the panel, its agent stays A2.2.1, no file on it moves.

0. Before anything

  • Confirm the Gitea repo spelling first (see RENAMING.md pending item 1). The renamed binaries' update check points at the placeholder rogue/l-ui; do not roll the renamed build out while that placeholder is still in place, or the first update check after migration will 404.
  • Confirm the release version for this migration (panel line, and agent line only if agent code changed). The rename diff itself keeps V2.6.0 / A2.5.0; the migration runs against the release that actually ships the rename, whatever its number is.
  • One machine at a time. Never migrate the whole fleet at once: a panel/agent restart interrupts that machine's inbounds for seconds, and a bad step must be caught on the pilot before it can repeat everywhere.

1. Per-machine move table (mv, never cp)

Stop the old service first, then move, then install the new binary + unit, then start. mv keeps the data in one place; cp leaves two copies and is how stale-DB incidents happen.

old new notes
/usr/local/x-ui/ /usr/local/l-ui/ panel binary, bin/ (sing-box, geo, config-singbox.json)
/etc/x-ui/ /etc/l-ui/ l-ui.db is the renamed file: move x-ui.db → l-ui.db inside the move (see §2)
/etc/x-ui/x-ui.db /etc/l-ui/l-ui.db the panel DB; see §2 for the file rename
/etc/x-ui/probe.db /etc/l-ui/probe.db name unchanged, directory moved
/etc/x-ui/cert/ /etc/l-ui/cert/ panel + subscription certs move with the dir
/etc/x-ui/agent.json /etc/l-ui/agent.json agent nodes
/etc/x-ui/node_token_key.json /etc/l-ui/node_token_key.json panel hosts
/var/log/x-ui/ /var/log/l-ui/ log filenames inside (3xui.log, 3xipl.log) do NOT change
/usr/local/x-ui/bin/config-singbox.json /usr/local/l-ui/bin/config-singbox.json the live config the orphan scan matches on (see §5)
/etc/systemd/system/x-ui.service /etc/systemd/system/l-ui.service delete the old unit file, install the new one from the repo — do not edit the old file in place
/etc/systemd/system/x-ui-agent.service /etc/systemd/system/lui-agent.service same: delete old, install new
/etc/init.d/x-ui-agent (OpenRC) /etc/init.d/lui-agent same: delete old, install new
/etc/init.d/x-ui (OpenRC panel, if present) /etc/init.d/l-ui from l-ui.rc
/etc/default/x-ui /etc/default/l-ui env file, with translation in §3
/etc/conf.d/x-ui /etc/conf.d/l-ui Arch/Alpine env file, with translation in §3
/etc/sysconfig/x-ui /etc/sysconfig/l-ui RHEL env file, with translation in §3
/usr/bin/x-ui (Docker management CLI) /usr/bin/l-ui Docker images only; from l-ui.sh
/tmp/xui.log (install-master scratch) /tmp/lui.log scratch only; delete, don't migrate

Pure-probe nodes (56HL-NAT, AX6600, WW39, TYYUN excepted as frozen): same table, minus inbounds — they have no core config to worry about, which is why they go first (§6). AX6600 and 56HL-NAT carry a probeOnly preset in agent.json; it moves with the file.

2. Database file rename

The panel DB file itself is renamed, not just its directory:

mv /etc/x-ui/x-ui.db /etc/l-ui/l-ui.db

(probe.db keeps its name.) If the move is done as a whole-dir mv /etc/x-ui /etc/l-ui followed by mv /etc/l-ui/x-ui.db /etc/l-ui/l-ui.db, the result is identical. Do not leave a copy of x-ui.db behind "just in case" — the backup in §4 is the just-in-case copy, and it is deleted after acceptance.

Postgres deployments: the DB name/user (xui) is intentionally unchanged (RENAMING.md), so no database rename is needed there; only the env prefix in the unit changes (LUI_DB_TYPE, LUI_DB_DSN).

3. Unit environment translation (XUI_ → LUI_)

Old units must be replaced with the new units from the repo. If a host has a local env-file override, translate every line:

XUI_...  →  LUI_...

i.e. XUI_DB_FOLDER → LUI_DB_FOLDER, XUI_MAIN_FOLDER → LUI_MAIN_FOLDER, XUI_LOG_FOLDER → LUI_LOG_FOLDER, XUI_BIN_FOLDER → LUI_BIN_FOLDER, and so on for the full inventory in RENAMING.md. There is no fallback: a leftover XUI_DB_FOLDER pointing at /etc/x-ui will simply be ignored by the new binary, which will then open the default /etc/l-ui/l-ui.db — that looks like "the panel lost its data" when it is really "the env file was never translated". After installing the new unit, run systemctl daemon-reload (systemd) or the OpenRC equivalent, and verify with systemctl cat l-ui / systemctl cat lui-agent that no XUI_ line remains.

4. Backup, and deleting it

Before the move, on each machine:

cp -a /etc/x-ui /root/l-ui-migration-bak-$(date +%F)
cp -a /usr/local/x-ui /root/l-ui-migration-bin-bak-$(date +%F)   # panel hosts only if bin/ holds local files worth keeping

(Adjust the backup root if /root is small; the panel DB is the critical part.) The backup exists only until that machine passes §7. After acceptance, delete it. A backup left in /root indefinitely is residual garbage by definition, and a later operator can mistake it for the live directory. Do not keep x-ui.db copies, .bak binaries, or old units "for safety" past acceptance — acceptance is the safety check.

5. Old cores: stop them, do not re-adopt them

The renamed agent's orphan scan matches only cores started with /usr/local/l-ui/bin/config-singbox.json (exact argv triple run -c <path>). A core still running the old /usr/local/x-ui/bin/config-singbox.json will not be matched and will keep holding the inbound ports, so the new core will fail to bind and the agent will roll back every 30 s. Before starting the new agent, confirm no old core survives:

ps -ef | grep -F "config-singbox.json" | grep -v grep
# any line with /usr/local/x-ui/bin/config-singbox.json must be
# stopped (kill it; SIGTERM, then SIGKILL if it survives 5 s)
# before the new agent starts. Do NOT kill a core whose config
# path belongs to another panel/agent/router (e.g. amo, momo).

The same rule applies to the panel's own old process: stop x-ui / xui-agent processes before starting l-ui / lui-agent. install-agent.sh's legacy kill covers the dual-mode x-ui agent form as a one-time cleanup, but the migration step above is the authoritative check — do not rely on the installer to notice a stray core.

6. Rollback (before acceptance only)

If a machine fails §7, roll it back before moving on:

systemctl stop l-ui lui-agent 2>/dev/null
mv /etc/l-ui /etc/x-ui
mv /etc/x-ui/l-ui.db /etc/x-ui/x-ui.db   # if the DB file was renamed
mv /usr/local/l-ui /usr/local/x-ui
mv /var/log/l-ui /var/log/x-ui
# reinstall the OLD unit files and the OLD binary, then:
systemctl daemon-reload
systemctl start x-ui x-ui-agent  # only the units that existed before

Rollback after acceptance is not a plan — it is a new migration in reverse, and it needs the backup from §4, which acceptance deletes. That is intentional: acceptance must mean "this machine is good on the new names".

7. Per-machine acceptance checklist (all must pass)

  • ps shows l-ui / lui-agent, and no x-ui / xui-agent process remains (except unrelated amo/momo cores, identified by their own config paths).
  • No old directory remains: ls /usr/local/x-ui /etc/x-ui /var/log/x-ui all fail with "No such file or directory".
  • No old unit remains: systemctl list-unit-files | grep x-ui empty; /etc/init.d/ has no x-ui* file.
  • No XUI_ line remains in the active unit / env file (systemctl cat l-ui, systemctl cat lui-agent).
  • Panel answers on its usual port; login works; node list shows the machine with its agent version (A-line) and probe data (CPU/mem/uptime) updating.
  • Inbounds on the machine accept a real client connection (not just "port listening" — the Oracle 27084 lesson: a bound port is not a working inbound).
  • Probe reporting is normal on the panel (history continues, no gap longer than the machine's normal heartbeat interval).
  • Subscription endpoint serves (panel hosts: the usual subscription URL returns a non-empty list for a test client).
  • Update check no longer points at the old repo: panel update info resolves against the confirmed repo spelling (placeholder rogue/l-ui must be gone before rollout).
  • Backup from §4 deleted.

Only after every box is ticked is the machine done. Do not tick "probe normal" from a single heartbeat — watch at least two intervals.

8. Pilot order (suggested)

  1. One pure-probe node first (e.g. 56HL-NAT or WW39): no inbounds, so a failure costs nothing but probe history, and it proves the agent rename + telemetry + probe path end to end.
  2. The master (HW-SG) second, including its local agent: the master is the only machine whose failure blocks every other machine's verification, so it goes early but never first — the pilot must have proven the agent binary first.
  3. Remaining nodes one by one, core nodes before probe-only leftovers, each fully through §7 before the next starts. Never two at once: if a step is wrong, exactly one machine is in the broken state, and its §6 rollback is still available.
  4. TYYUN (Windows) last and untouched: verify only that its panel row shows A2.2.1 with no orange update badge, and that probe data still updates. No file moves, no exe swap, no service change on that machine.

9. What this migration deliberately does not do

  • It does not rename the Gitea repo (see RENAMING.md pending item 1) — the repo rename, if confirmed, is a separate step with its own verification (new clone, new release read-back).
  • It does not touch the frozen Windows agent or its service.
  • It does not rename Docker Postgres credentials, log filenames, or the fail2ban jail (RENAMING.md, intentionally kept).
  • It does not "fix" unrelated stale items found on a machine (e.g. the old install-master.sh xray download, the legacy GitHub Actions workflow). Note them, don't bundle them.