Releases: NIyueeE/dsh-container
Release list
v0.1.3
What's new in v0.1.3
This release makes remote access noticeably faster, makes the proxy self-healing, hardens the
dsh auto-update path, and documents the requirements for putting an external TLS proxy in front.
Fixes & improvements
- gzip compression on the proxy — UI assets (~1.3 MB uncompressed) are now served
gzip-compressed (~360 KB), cutting remote page loads to roughly a quarter of the bytes. SSE and
WebSocket streams remain unbuffered (verified against Caddy 2.6:text/event-streamflushes
immediately, WebSocket passes through untouched). - Caddy crash self-healing — the entrypoint now watches the proxy and restarts it within
seconds if it dies (zombie-safe liveness check); config errors still fail fast at startup, and a
persistently broken proxy is surfaced by the container HEALTHCHECK. - dsh auto-update only upgrades —
dsh-updatenow compares versions with semver semantics and
never downgrades a version pinned at build time; installs (build-time and runtime) explicitly
allow install scripts, sincenpm approve-scriptsdoes not support global installs and the
previous allow-list line was dead code. --portvalidation — non-numeric--portvalues fail with a clear error instead of a
confusing Caddy config dump.WORKDIRfix — the image no longer hardcodes/home/codespace/workspace, which broke
docker execon legacy 2.x base images.- Caddyfile formatting — the generated config now matches
caddy fmtstyle, removing the
"Caddyfile input is not formatted" warning from startup logs.
CI
- The smoke test now exercises the real update path: uninstall dsh, run
dsh-update(uid-1000
global npm install including native-module install scripts), verify the version and idempotency.
Previously only the "already up to date" no-op path was covered. - Workflow permissions are read-only by default;
packages/contentswrite scopes are granted
only where needed; same-ref runs are serialized to avoid racing thelatesttag.
Documentation
- New "External reverse proxy with TLS (WAN)" section in the deployment guide with a working
nginx example: WebSocket upgrade headers (proxy_set_header Upgrade $http_upgrade/
proxy_set_header Connection "upgrade"),proxy_buffering off, and raised idle timeouts.
Proxies that strip these headers silently break the UI's event streams (426 Upgrade Required
from dsh, periodicaborting with incomplete responsein the journal) — the exact failure mode
fixed in this cycle. - README (EN/ZH), security notes, deployment guide, and the Compose/Quadlet examples synced with
the above.
Upgrade notes
- No configuration changes required. If you use an external TLS proxy in front of port
3081,
make sure it forwards the WebSocket upgrade headers and does not buffer or time out quiet
streams (see the deployment guide).
v0.1.2
What's new in v0.1.2
This release replaces the socat forwarder with a Caddy reverse proxy that makes remote access
fully functional — including settings and credentials — and establishes the proxy as the security
boundary.
Fixes & improvements
- Caddy reverse proxy instead of socat — the container now runs a Caddy proxy on
0.0.0.0:3081
that rewritesHost/Originto loopback before forwarding todsh webon127.0.0.1:3080.
dsh itself still listens on loopback only (both npm releases and upstreammainreject
--host 0.0.0.0— an intentional upstream safety design; verified against the upstream source). - Remote access now works for every endpoint — dsh's
/apibrowser-trust fence checks HTTP
headers only, so the loopback rewrite lets remote browsers pass everything, including
settings.*,credentials.*,agentPreset.*,host.pickDirectory/host.openPathand
llm.discoverModels, which upstream hard-pins to loopback. The
transport failure for /api/settings.describe: HTTP 403errors over remote access are gone. - The proxy is the security boundary — because the rewrite bypasses the loopback pin, anyone
who can reach port3081can read and modify all settings and credentials, not just drive the
agent. Enable basic auth withDSH_PROXY_USER/DSH_PROXY_PASSWORD(recommended for any
non-loopback deployment) and keep the port firewalled. DSH_TRUSTED_HOSTSremoved — the header rewrite makes trust configuration unnecessary; the
compatibility layer is gone and the proxy is the one and only exposure path.- Docs, examples, and CI aligned — README (EN + 中文), deployment and security guides,
compose/Quadlet examples, the CI smoke test (settings.describe through the proxy returns 200;
basic auth returns 401 without / 200 with credentials), and AGENTS.md all reflect the
proxy-only design.
Breaking changes (vs v0.1.1)
DSH_TRUSTED_HOSTS/--trusted-hostare no longer supported — remove them from your
configuration (they are no longer needed).- Exposure port stays
3081; port mappings are unchanged. - Anyone reaching
3081now also gets settings/credentials access — enable
DSH_PROXY_USER/DSH_PROXY_PASSWORDfor non-loopback deployments.
Upgrade note
Pull the new image and recreate the container. Remove DSH_TRUSTED_HOSTS and, if you expose the
port beyond loopback, add DSH_PROXY_USER / DSH_PROXY_PASSWORD (basic auth).
v0.1.1
What's new in v0.1.1
This release fixes the /api browser-trust fence (HTTP 403) pain point for network access and
simplifies the port-exposure design.
Fixes & improvements
DSH_TRUSTED_HOSTSenvironment variable — declare thehost[:port]authorities the/api
browser-trust fence accepts (space- or comma-separated list; each entry is passed as
--trusted-hosttodsh web). Required when browsers reach the UI from a non-loopback address
(LAN IP, domain name, or a Host-preserving reverse proxy); loopback access needs no configuration.
This addresses thetransport failure for /api/host.listDirectory: HTTP 403errors seen when
opening the UI over the network.- Simplified port exposure — the socat forwarder now listens on
0.0.0.0:3081inside the
container and forwards to dsh's127.0.0.1:3080. Because the two ports differ, the forwarder can
bind the wildcard address directly, and the previous container-IP detection workaround is gone.
The exposed port is now 3081 (update host mappings: compose"3081:3081", Quadlet
PublishPort=3081:3081). DSH_WEB_HOSTremoved — the loopback-only toggle is gone. For loopback-only use, simply don't
publish the port: the/apitrust fence already only allows loopback hosts unless
DSH_TRUSTED_HOSTSdeclares otherwise.- Home-based defaults —
DSH_HOMEnow defaults to$HOME/dshand the newDSH_WORKSPACE
defaults to$HOME/workspace(/home/codespace/dshand/home/codespace/workspaceon the
universal 6.x base). The entrypoint creates both and runs dsh from the workspace. Legacy 2.x
base images (vscodeuser) automatically follow their own home. - Docs & examples updated — README (EN + 中文), deployment and security guides, the
compose/Quadlet examples, and the CI smoke test all reflect the new layout. Raw
--trusted-hostpassthrough viacommand/Exec=still works alongside the env var. - AGENTS.md added — guidelines for agents and contributors working on this repository.
Breaking changes (vs v0.1.0)
- Exposed port changed from
3080to3081; update your port mappings. DSH_WEB_HOSTenvironment variable removed.
Upgrade note
Rebuild or pull the new image and recreate the container — the entrypoint, environment variables,
and exposed port have all changed.
v0.1.0
Full Changelog: https://github.com/NIyueeE/dsh-container/commits/v0.1.0