Skip to content

Releases: shenaba/2s-ui

v1.6.2

Choose a tag to compare

@shenaba shenaba released this 30 Jul 15:24
8e68ef4

Bug Fixes

Reverse proxy #80

The TLS terminated by reverse proxy switch is usable again, and can no longer take down what it is protecting.

  • Switching it on failed on every install that had used the feature before the vhost was renamed — the old file collided with the new one on 443, and every retry replayed it. Both prefixes are swept now
  • Switching it off deadlocked: the vhost was deleted before the save that travelled over it, leaving the vhost gone and the setting unsaved. That cleanup now runs after the restart
  • Changing the panel's path or domain while the proxy is on no longer moves the nginx location out from under the request still in flight
  • Three ways a working vhost got destroyed are closed: a duplicate server_name on :80 misread as a 443 conflict, an enabled side with no domain skipped silently, and a failed settings read at startup reconciling as "disabled"
  • The settings page reports drift between nginx and the saved settings on load, and ACME HTTP-01 validation no longer mistakes the proxy's 443-only vhost for a :80 block

Panel URI vs. panel path #80

Panel URI only decides where the redirect goes after a restart; the path the panel actually serves comes from Panel Path. Editing the former to move the panel sent the user to a 404 with no way back, since the only page that could undo it was the one that no longer loaded. Both are now refused at save time, with nothing written, and the same guard covers Subscription URI, where a mismatch is silent — the panel keeps working while every client stops updating.

Frontend #77

  • Recovering from a failed chunk load returned to the route being left instead of the one that was clicked
  • out/OutTLS crashed on an entity with no tls key
  • Dates ignored the language switch until reload; seven render sites pointed at i18n keys that do not exist
  • Build assets are named by content hash instead of a per-build id, so Cache-Control: max-age=31536000 stops serving stale bundles across releases

Enhancements

  • First paint is roughly half the payload — the single 2.1 MB chunk is split, and the unused woff fallback is dropped from the font CSS #77
  • The in/ and out/ form duplicates (Dial, Multiplex, Listen, Transport, Headers, Network, UoT) are merged, and DnsServerDrawer reuses them #77

Chores

  • Every GitHub Action is pinned to a commit SHA, and dependabot updates are grouped into one PR per ecosystem #71
  • Release and Windows builds no longer run the full matrix twice on a merge-then-publish #74
  • Dependency bumps: frontend group (11) #73, gomod group (2) #72, sing-vmess #70, docker/login-action #76

Full Changelog: v1.6.1...v1.6.2

v1.6.1

Choose a tag to compare

@shenaba shenaba released this 24 Jul 12:32

Enhancements

  • Automatic nginx reverse proxy with a new Domains & Certificates tab — generate and manage vhosts and certificates straight from the panel, key each vhost by its domain, and optionally put the sub server behind the proxy too #68

Bug Fixes

  • Complete the actions.* i18n keys across all six locales, so success toasts and the Changes audit log no longer render raw keys such as actions.reconcileNode into the UI #69 (fixes #66)
  • Drop the duplicate success toast on node reconcile / adopt — the shared response handler already shows one, so the hand-rolled component toast was firing a second time #69
  • Fall back to the raw action name when an actions.* key is missing (matching Home.vue), so a future unkeyed action degrades to a plain name instead of leaking the actions. prefix #69

Full Changelog: v1.6.0...v1.6.1

v1.6.0

Choose a tag to compare

@shenaba shenaba released this 21 Jul 08:30

Two large subsystems land in this release — cluster management and one-click ACME. Both are shipping for the first time here and have not had a real-world shakedown yet. Back up your db/ folder before upgrading, and read the two warnings below.

⚠️ Before you upgrade

Downgrading is one-way once you have adopted a cluster node. Older binaries don't know the node_id column. Roll a database that contains adopted replicas back to 1.5.x and the old binary hands the remote node's ports to its own local core, putting the panel into a ~15s restart loop. De-adopt every node before downgrading.

If your panel already has webNginx set, check its scheme after upgrading. Earlier versions turned webNginx on automatically whenever nginx was detected on the host, so some installs carry the flag without ever having chosen it. Those panels keep serving plain HTTP after the upgrade, and in reverse-proxy mode the certificate-path inputs are hidden — so a stale value cannot be cleared from the UI. If that locks you out, SSH in and run UPDATE settings SET value='false' WHERE key='webNginx'; against the panel database, then restart. While diagnosing, don't rely on sui uri — it was reworked in this release — check ss -lntp and curl -I directly.

Cluster management #29 #53

Run several 2S-UI panels from one master. A node is just another full 2S-UI install: the master drives it through the node's existing apiv2 with a Token header, so nodes need no agent and no upgrade — older versions can be adopted as they are.

  • 5s heartbeat monitoring for every node
  • Adopt a node's inbounds into the master, which then holds the single authoritative ledger for users
  • Shared clients across nodes, with node traffic reconciled back into the master's ledger by baseline diffing, plus cluster-wide quota and enable/disable
  • Node routes are aggregated into the master's subscription as [node name] tag entries
  • Deleting a node that still has live replicas is refused — de-adopt first

One-click ACME certificates #55

Issue a certificate from the panel with the validation method picked automatically — standalone, or an nginx block when a reverse proxy fronts the panel — and an automatic proxy reload on renewal.

  • sui uri now reports the configured panel URI and the subscription address, and no longer claims https for a panel that a proxy fronts
  • Standalone validation binds IPv6 on v6-only hosts
  • Failures name the actual cause — missing conf.d, denied :80 — instead of failing generically
  • ACME is hidden on Windows, where it does not apply

Enhancements #61

  • Latency test for endpoints, one at a time or all at once
  • Enable or disable a client straight from the client list
  • Hysteria port hopping on the outbound form
  • Shadowsocks plugin and plugin_opts support
  • The panel reports the server OS

Bug Fixes

  • Editing one user no longer disconnects every other user on the same inbound. Users are now updated in place instead of rebuilding the listener, which used to destroy the QUIC session for anytls, hysteria, hysteria2, tuic, vless, vmess and trojan #60
  • Rework Clash proxy-group assembly and ws headers, emit max-early-data, and stop aliasing the default group slice #59
  • Carry ws early data into generated share links #59
  • Omit a disabled tls block from the core config #59
  • Keep the ACME section visible when it is already configured #61

v1.5.7

Choose a tag to compare

@shenaba shenaba released this 17 Jul 08:12
cfce478

Bug Fixes

  • Strip server-only TLS fields (certificate_path, key, acme) from client-facing configs — a leaked certificate_path made sing-box clients fail outright on per-domain TLS, with a migration to clean existing rows #52
  • Stop the self-update modal spinning forever after a successful update — it now reloads into the new version and times out after 120s instead #44

Enhancements

  • Check for a new release on every page load instead of caching the result for 24h #44

Dependencies

  • Bump vue to 3.5.40, qrcode.vue to 3.10.0, eslint-plugin-vue to 10.9.2, @babel/types to 8.0.4, and actions/setup-go to v7 #45 #46 #47 #48 #49

v1.5.6

Choose a tag to compare

@shenaba shenaba released this 16 Jul 06:12
229627d

This release brings in-panel self-update, inlines the frontend into the main repository, and refreshes the whole frontend dependency stack. No database migration is required.

Upgrading from v1.5.5 is a manual install — self-update ships in this release, so 1.5.5 panels do not have it yet. From v1.5.6-alpha.1, the in-panel updater will offer this build.

Features

  • In-panel self-update. Check, download and apply a new panel release from the dashboard — no shell, no s-ui update. The archive is verified against the release SHA256SUMS before the running binary is replaced, and the panel restarts itself on success. #30
  • Self-update works in Docker too, not just on systemd hosts. The container path swaps the binary in the writable layer and re-execs the entrypoint; the confirm dialog spells out that recreating the container reverts it. #30
  • Update surfacing in the UI: a sidebar version pill with an update popover (manual re-check included), and an update-available chip on the dashboard server card. The GitHub release lookup runs from the browser and is cached for 24h, so the panel host never needs outbound access. #30

Bug Fixes

  • Fix ERESOLVE on every npm install build path (release, Windows, Docker, build.sh) after the pinia 4 bump — vue-router 5.0.7 declared peerOptional pinia@^3.0.4. Bumped to vue-router 5.2.0, which widens the range to ^3.0.4 || ^4.0.2. #39
  • The documented legacy-install command now works. The README example passed VERSION=1.0.0 — no v prefix, and a tag that never existed in this repo. install.sh interpolates the argument verbatim into both the raw.githubusercontent.com ref and the release download URL, and every tag here is vX.Y.Z, so both 404'd. Corrected across all six locales. #41
  • install.sh no longer prints s-ui vv1.5.6. It kept a v-prefixed tag in one code path and a bare version in the other, while every message hardcoded its own v. The prefix is now normalised, so both 1.5.6 and v1.5.6 work as the version argument. #41
  • Drop an API dedup interceptor that never actually ran. #30

Frontend

  • New VersionMenu popover and UpdateModal, backed by a dedicated version store; update strings added across all six locales (en / fa / vi / ru / zh-CN / zh-TW). #30
  • Dependency refresh: pinia 4.0.2, vue-router 5.2.0, vite 8.1.4, axios 1.18.1, vue-i18n 11.4.6, eslint 10.7.0, vue-tsc 3.3.7, @vitejs/plugin-vue 6.0.8, typescript-eslint 8.64.0, @types/node 26.1.1, globals 17.7.0.
  • @vue/devtools-api is now declared explicitly. pinia 4 requires it as a non-optional peer, and until now it resolved only because vue-router happens to depend on it directly — the range was inherited rather than owned. #41
  • form-data 4.0.6, up from 4.0.5 (GHSA-hmw2-7cc7-3qxx). Hygiene rather than a security fix: it reaches the tree through axios but never shipped — the browser build uses the native FormData, and the Node adapter that imports the package is tree-shaken out. The bundle is byte-identical before and after. #41

Maintenance

  • The frontend is now inlined under frontend/. It used to be a submodule (shenaba/2s-ui-frontend); a plain git clone now gives you the whole tree, with no submodule update --init. Build scripts and docs are rewired accordingly. #33
  • CI now runs go vet, a tagged Go build, and vue-tsc + vite build on every pull request. #31
  • Bump golang.org/x/crypto to 0.54.0, actions/setup-node to v7.

Full changelog: v1.5.5...v1.5.6

v1.5.6-alpha.1

v1.5.6-alpha.1 Pre-release
Pre-release

Choose a tag to compare

@shenaba shenaba released this 16 Jul 03:09
d7fd8cc

This is a pre-release. v1.5.5 stays the stable Latest. GitHub's releases/latest API excludes pre-releases, and that is the endpoint both the in-panel updater and the dashboard update check read — so panels running 1.5.5 are not offered this build and will not pull it. Install it deliberately, or wait for v1.5.6.

Enhancements

  • In-panel self-update. Check, download and apply a new panel release from the dashboard — no shell, no s-ui update. The archive is verified against the release SHA256SUMS before the running binary is replaced, and the panel restarts itself on success. #30
  • Self-update works in Docker too, not just on systemd hosts. The container path swaps the binary in the writable layer and re-execs the entrypoint; the confirm dialog spells out that recreating the container reverts it. #30
  • Update surfacing in the UI: a sidebar version pill with an update popover (manual re-check included), and an update-available chip on the dashboard server card. The GitHub release lookup runs from the browser and is cached for 24h, so the panel host never needs outbound access. #30

Frontend

  • New VersionMenu popover and UpdateModal, backed by a dedicated version store; update strings added across all six locales (en / fa / vi / ru / zh-CN / zh-TW). #30
  • Dependency refresh: pinia 4.0.2, vue-router 5.2.0, vite 8.1.4, axios 1.18.1, vue-i18n 11.4.6, eslint 10.7.0, vue-tsc 3.3.7, @vitejs/plugin-vue 6.0.8, typescript-eslint 8.64.0, @types/node 26.1.1, globals 17.7.0.

Bug Fixes

  • Fix ERESOLVE on every npm install build path (release, Windows, Docker, build.sh) after the pinia 4 bump — vue-router 5.0.7 declared peerOptional pinia@^3.0.4. Bumped to vue-router 5.2.0, which widens the range to ^3.0.4 || ^4.0.2. #39
  • Drop an API dedup interceptor that never actually ran. #30

Maintenance

  • The frontend is now inlined under frontend/. It used to be a submodule (shenaba/2s-ui-frontend); a plain git clone now gives you the whole tree, with no submodule update --init. Build scripts and docs are rewired accordingly. #33
  • CI now runs go vet, a tagged Go build, and vue-tsc + vite build on every pull request. #31
  • Bump golang.org/x/crypto to 0.54.0, actions/setup-node to v7.

Full changelog: v1.5.5...v1.5.6-alpha.1

v1.5.5

Choose a tag to compare

@shenaba shenaba released this 07 Jul 07:25

This release brings full parity with upstream s-ui v1.5.3, an update notice on the dashboard, a six-language management script, and a round of dependency updates. No database migration is required.

Features

  • Update-available notice on the dashboard. The server card shows an amber chip when a newer 2s-ui release is out, linking straight to the release page. The check runs in your browser against the GitHub API (no server egress), is cached for 24 hours, and stays silent when GitHub is unreachable.
  • Optional Clash default groups (upstream #1155): a new setting skips injecting the default Proxy/Auto proxy-groups so fully custom configs stay untouched, and a case-insensitive all entry inside a custom proxy-group expands to every generated proxy tag. Both toggles live in Settings → Subscription → Clash.
  • Management script in six languages: s-ui.sh now speaks English, 简体中文, 繁體中文, Русский, فارسی and Tiếng Việt — same coverage as the panel. The language menu always lists languages by their native names so anyone can find their way back.

Fixes

  • Timezones no longer depend on OS data (upstream #1166): the timezone database is embedded in the binary; the installer and Docker image no longer need the OS tzdata package.
  • Share-link certificate pin key follows each protocol's convention (upstream #1093 follow-up): pinSHA256 on Hysteria/Hysteria2 links, pcs on Xray-based protocols — matching what the client apps actually parse.
  • Dev-only: the dashboard demo data (API mock) works again when the backend isn't running behind the Vite proxy.

Dependencies

  • golang.org/x/crypto 0.53.0 — ships a batch of SSH security fixes (ssh/agent constraint handling, @revoked known-hosts keys, channel-handling DoS issues) relevant to the embedded sing-box SSH outbound. bcrypt, used for panel passwords, is unchanged.
  • gopsutil 4.26.6 (system-stats bugfixes) and certmagic 0.25.4 (memory-leak and handshake-waiter fixes on the ACME path).
  • CI: actions/checkout v7 and actions/cache v6.

v1.5.4

Choose a tag to compare

@shenaba shenaba released this 03 Jul 07:37

This release syncs everything from upstream s-ui v1.5.0 through v1.5.2 into 2s-ui, on top of our own fixes. Full parity with upstream v1.5.2, plus a few corrections upstream doesn't have yet.

Security

  • Panel passwords are now stored as bcrypt hashes instead of plaintext (upstream #1159). Existing databases are migrated automatically; passwords keep working unchanged. s-ui admin -show no longer prints the password — use s-ui admin -username <user> -password <pass> to set a new one.
  • SQL injection fix in the changes-log query (upstream #1131).
  • Unknown-SNI TLS handshakes are rejected when a panel/sub domain is configured with manual certificates. If you connect by raw IP over HTTPS, either use the domain or leave the domain setting empty.
  • Dependency security updates: sing-box v1.13.14, golang.org/x/crypto and friends.

Features (from upstream v1.5.0–v1.5.2)

  • External JSON subscriptions with connection timeout and optional default routing rules.
  • Client enhancements: creation time and remark fields, improved bulk add.
  • Reset all clients' traffic — manual API and scheduled (globalReset cron setting); re-enables depleted clients and restarts the core.
  • TLS certificate hot reload for panel and subscription servers — renewed certificates are picked up without a restart.
  • Automatic SHA256 pinning for self-signed certificates, applied to configs and share links (with back-fill migration).
  • CLI backup command: s-ui backup -output <file|-> [-exclude changes,stats].
  • Configurable traffic sampling (statsBucketSeconds) with deduplicated storage.
  • getCertPing API returns the leaf certificate SPKI hash of a remote TLS endpoint.
  • Subscription improvements: Content-Disposition filename, Clash default groups only injected when referenced, TUIC udp_relay_mode on links.

Fixes

  • VLESS over plain TCP+TLS keeps flow: xtls-rprx-vision in generated Clash/JSON configs (upstream #1156).
  • Share links carry the correct certificate pin: hex fingerprint under the standard pinSHA256 key. (Upstream v1.5.2 emits this under a pcs key that clients don't recognize — we kept the standard name.)
  • getCertPing hardening over upstream: no crash on CN-only certificates (no SANs), and the probe connection is closed properly.
  • External subscriptions with no outbounds now return a real error instead of silently succeeding with empty data.
  • Traffic chart adapts its resolution to the stored bucket size, so raising the sampling interval can't blank the dashboard charts (upstream #1150).
  • h3 ALPN in Clash subs, Clash sub headers, WARP connection timeout, stricter VLESS flow validation (upstream v1.5.0).

Upgrade notes

  • Docker: migrations run automatically via the entrypoint. Nothing to do.
  • Bare-metal (systemd): run s-ui migrate once after upgrading. Without it, plaintext passwords are still upgraded lazily on each successful login, but the self-signed-certificate pin back-fill only runs through the migration.
  • The stats table is deduplicated and gains a unique index on first start after the upgrade; on very large databases the first start may take a little longer.

v1.5.3

Choose a tag to compare

@shenaba shenaba released this 02 Jul 11:37

Fixes

  • Docker — published images could not start (#24): entrypoint.sh was tracked in git without the execute bit and both Dockerfiles copied it verbatim, so images shipped /app/entrypoint.sh as non-executable and the exec-form ENTRYPOINT failed with permission denied. The script is now tracked as executable and both Dockerfiles use COPY --chmod=755, so containers from GHCR / Docker Hub start normally with the stock docker-compose.yml.
  • Dashboard — Network throughput chart losing its right margin (#15): a bare 1fr grid track mins at auto, so the fixed-width SVG that ECharts renders could widen its own column; the chart then re-measured against the inflated width and never shrank back, and the card's overflow clipping left the plot hugging the card's right edge. Chart grid columns are now floored at 0 (minmax(0, 1fr)), including the narrow-viewport breakpoints.

v1.5.2

Choose a tag to compare

@shenaba shenaba released this 18 Jun 13:25

Features

  • Certificates — Force Renew: added a Force Renew button next to Issue Certificate that runs acme.sh --issue --force, so you can renew early even when the domain still has a valid, not-yet-expiring certificate (which acme.sh otherwise skips). A confirmation dialog warns that --force counts against Let's Encrypt's duplicate-certificate rate limit (~5/week).
  • Clients — redesigned dialog & page: the client dialog now folds Inbounds & Limits into a wider, two-column General tab (UUID/password and Links stay as separate tabs); inbound selection is a compact multi-select dropdown; new clients default to a 30-day auto-reset period. The page is retitled User Management.

Fixes

  • Dashboard — charts overflowing their card (#15): toggling a dashboard tile (e.g. hiding Traffic then showing it again) shrank a neighbouring chart's column, but the ECharts SVG kept its widened size and spilled past the card border. Charts now re-measure on the next animation frame using their container's explicit width/height, and dashboard cards clip overflow as a hard backstop.