* feat(terminal): keep ssh sessions alive server-side with reattach
Split the terminal ws handling into a Session (pty + ssh backend) and an
Attachment (one websocket). A session outlives its websocket: a clean close
(1000) ends the pty, any other disconnect keeps it for a 30-minute grace
period and it can be reattached via `?session=<id>`. Output goes through a
fixed 128KB ring buffer so a reattaching client gets the recent tail, with a
truncation marker if it fell behind. Sessions are owner-scoped; a second
attachment kicks the first (4409), unknown ids get 4404.
New endpoints under /hosts/terminal/sessions (search, close) let the
frontend list and recover sessions after a tab or browser is closed.
* feat(terminal): floating terminal dock with session recovery
Terminals now live in a layout-level host and are teleported into whichever
view shows them, so leaving the terminal page no longer kills them. A dock
handle on the right edge opens a non-modal dialog from any page with every
live session, a picker for local shell / ssh hosts, minimize, and
close-all. On page load the store recovers sessions the server still holds,
so an accidentally closed tab or browser can resume within the grace period.
The menu-tab label shows the live session count.
* fix(terminal): page re-claims its slots under a locked menu tab
With the terminal menu tab locked (keep-alive), leaving the page deactivates
it instead of unmounting it, so the slot ref callback never re-runs on
return. After the dock had taken the Terminal over and released it, nobody
claimed it for the page again and it stayed parked in the hidden host.
Claim/release slots explicitly on mount, activated, deactivated and unmount,
the same ownership rule the dock uses, instead of relying on the ref callback.
* fix(terminal): logout closes every kept-alive terminal session
A logged-out panel has nobody watching it, so nothing it left running should
survive: core now tells the local agent to close all terminal sessions when the
user logs out, changes the password, or changes the bind domain. Until now the
teardown relied on the logging-out tab sending close code 1000; a second tab or
a websocket held outside the SPA kept its shell after logout.
Agent: terminal.CloseAll and POST /hosts/terminal/sessions/closeAll.
Core: LogOut / deleteCurrentSession / BindDomain call it via proxy_local,
best effort.
* fix(terminal): pin a local shell to the node it was opened on
The node a local shell connects to was resolved from the current node every
time the websocket was built, so after switching nodes a reconnect carried the
old session id to the new node (4404) and then opened a shell there instead.
Store the operateNode on the entry when it is created; ssh shells keep going to
the master. Shells on a non-master node get the node name in their title so a
restore in another node's view can tell them apart.
llmman (https://github.com/llmmanorg/llmman) is a local model runner
serving Ollama- and OpenAI-compatible routes on 127.0.0.1:17434.
Register it in the agent provider catalog next to Ollama and extend
every Ollama special case (no API key, verification skipped, OpenClaw
placeholder key, manual initial model) to cover it as well.
Fail2ban UI currently keys isActive only on systemd fail2ban.service.
If the daemon is alive under another process manager, whitelist and
blacklist stay disabled. Detect liveness with fail2ban-client ping.
Fixes#13678
Co-authored-by: zhudaguaneren <218366267+zhudaguaneren@users.noreply.github.com>
* feat: enhance archiving and extraction capabilities with additional compression formats and ownership preservation
* feat: enhance archiving and extraction capabilities with additional compression formats and ownership preservation
* feat: enhance archiving and extraction capabilities with additional compression formats and ownership preservation
Port forwarding no longer shares the filter client. FilterClient keeps only
filter capabilities, and forwarding gets its own adapter, service and boot
replay:
- utils/firewall/forwarding holds the provider adapters. firewalld uses native
forward-port, ufw and iptables share the NAT implementation moved out of
client/iptables/forward.go.
- service/forwarding.go owns base info, search, operate, enable and replay.
The API keeps its routes and dispatches on name/type/operate.
- init/firewall replays forwarding through that service instead of loading NAT
rule files inline.
Also adds 1PANEL_FORWARD to the IptablesOp name enum: the frontend already
sends {"name":"1PANEL_FORWARD","operate":"init-forward"} and the validator
rejected it with 400 before reaching the service. Besides that, the only
observable difference is that a forward-tab search no longer triggers the
port/address record cleanup goroutine on the side.
* feat: support dynamic module build for OpenResty
* feat: add dynamic module build page for OpenResty
* refactor: drop auto fallback, gate dynamic build by version support
- remove auto-to-static fallback; dynamic build failure now reports the
error and hints switching to static build manually
- gate dynamic builds on module support files (Dockerfile.modules +
module.catalog.json) instead of version numbers, expose
dynamicSupported in the modules API
- collect repeated path/status/operate strings into constants
- move nginx module regex patterns into utils/re with semantic helpers
- reorganize nginx_module.go around the main build flows and inline
single-use thin helpers
* feat: limit nginx module build mode options by version support
- build mode radio offers only dynamic and static (auto maps to dynamic
for legacy data)
- disable the dynamic option with a hint when the installed OpenResty
version lacks dynamic build support
* feat: complete i18n for nginx module pages
Fill in the new nginx module keys for all eleven language files
(translations other than zh/en are draft machine translations).
* feat: probe dynamic module support on load and drop the auto build mode
- probe each non-static module's configure params when loading the
module list and report dynamicSupport=supported/unsupported up front
- normalize the legacy auto build mode to dynamic
* feat: clarify module build modes in the UI
- build drawer lists dynamic modules (tagged, hot-reload) and static
modules (tagged, full rebuild + container restart) separately
- disable the dynamic option per module when its params do not support
dynamic build, distinct from the version gate hint
- drop the auto build mode wording everywhere and sync all eleven
language files
* feat: clarify purpose of the nginx module build drawer
- add a purpose hint explaining dynamic (hot reload) vs static (full
rebuild + container restart)
- drop the per-module mode tags now that section headers carry the
semantics
- allow submitting with zero dynamic modules selected when static
modules are present, so static-only users can trigger a build
* feat: pass apt mirror through to dynamic module builds
The mirror selected in the build dialog (or CONTAINER_PACKAGE_URL in the
app env as fallback) is now forwarded as a build arg so the module
builder uses the same apt source as the static build path. test-builder
gains a --mirror option.
* feat: add Lao translations for nginx module pages