dsh-remote-access
Out-of-tree deepseek-harness web-profile bundle that lets the dsh --profile web GUI listen on all interfaces (0.0.0.0) so you can open it from another device — while keeping the built-in ?token= BrowserAuth and never touching authentication.
It is intentionally tiny: one webserver row. Unlike earlier plugins, it does not fork web-startup / webserver / connection and does not invent its own token gate. That is precisely why it survives dsh upgrades: the auth and the LAN ?token= URL printing already come from dsh itself; this bundle only lets host be non-loopback.
How it works
- dsh's
BrowserAuth(client/connection) issues a host-bound cookie (dsh-auth-<sha256(authority)>) when you open the printed?token=URL. It already works for a LAN bind. web-appprints the LAN URL(LAN: http://<ip>:<port>/?token=...)whenever the server binds0.0.0.0.- The only blocker in stock dsh is
web-startuprefusing--host 0.0.0.0. This bundle does not unblock that flag; instead it overrides thewebserverrow'shostfrom an env var, so you never pass--host. - Result: zero third-party, zero plugins that own the auth, and a profile-level patch the loader re-reads on every boot — so it needs no re-apply after a dsh upgrade.
Install
# from a git checkout
dsh plugin --profile web install github:sysit/dsh-remote-access
# or from a local path (e.g. while developing)
dsh plugin --profile web install file:/Users/xiphis/projects/dsh-remote-access
That adds @sysit/dsh-remote-access to the profile's dsh.profile.bundles (after dsh-web-app, so its webserver override wins).
Use
| Want | Command |
|---|---|
| Remote (default when set) | export DSH_WEB_HOST=0.0.0.0 && dsh --profile web --no-open |
| Loopback only | unset DSH_WEB_HOST, or DSH_WEB_HOST=127.0.0.1 dsh --profile web |
| launchd/KeepAlive | add export DSH_WEB_HOST="\${DSH_WEB_HOST:-0.0.0.0}" to the launch script |
On a remote bind the startup log prints both:
dsh web: http://127.0.0.1:3080/?token=eqeU… (LAN: http://192.168.1.5:3080/?token=eqeU…)
Open the LAN: URL on another device — no 401, no plugin auth, no relay. The token is per-process (changes each restart); the browser cookie is valid up to cookieMaxAgeDays (default 30 days), so an already-open tab keeps working across restarts.
Upgrade handling
Nothing to re-apply. The patch is a declarative layer in ~/.dsh/profiles/<profile>/ (outside the dsh repo), re-read on every boot. After a dsh upgrade, smoke-check:
launchctl kickstart -k gui/$(id -u)/com.deepseek-ai.dsh-web # restart your web service
tail -5 ~/Library/Logs/dsh/web.out.log # expect `?token=` + `(LAN: ...)`
If dsh ever renames the webserver row id or its config keys, regenerate the row from the current official patch:
dsh --profile web --dump-config # current webserver keys
cat packages/bundle/web-app/cordis.patch.yml # official webserver row
Security notes
0.0.0.0exposes the harness to your network. The?token=gate + host-bound cookie are the auth; treat the printed token as a secret and use--no-openwhen remote.- Cross-site/DNS-rebinding defense stays on (dsh
api-request-trust);trustedHostsstill pick up LAN literals automatically. - The
/apiRPC surface is only as exposed as you make it — prefer SSH forwarding or a VPN if the network is not trusted.
License
MIT
No comments yet. Be the first to write one.