Skip to content

dsh-ssh-forward

Verified

dsh-ssh-forward · v0.2.0 · MIT · Web UI

Keep an SSH local port forward (for example searxng on 127.0.0.1:8080) alive for DeepSeek Harness — configured entirely from a built-in Settings page, with lease-based ownership so several profiles can run at once.

Install

dsh plugin add dsh-ssh-forward

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Published to npm without a public repository. Inspect the package contents before installing.

Tags

Creators

Readme

dsh-ssh-forward

Keep a local SSH port forward alive for DeepSeek Harness — typically 127.0.0.1:8080 → <host>:127.0.0.1:8080 so the searxng behind a private host is reachable from dsh-thin-search.

Everything is configured from the DSH UI. The plugin ships its own Settings page (Plugins → this plugin → Configure); saving writes the current profile and restarts the tunnel. No YAML, no JSON, no hand editing. It is a standard DSH plugin: a cordis entry plus a bundle patch, no native code, no build step, nothing written into the DSH installation directory.

What it does

  • Owner / adopter. Exactly one host owns the tunnel. The owner writes a lease ($DSH_HOME/ssh-tunnel/lease.json, pid + heartbeat), spawns ssh, and removes the lease plus the child on exit. Every other host adopts an already-listening port and never kills it.
  • keepAlive — desktop (default: only the desktop profile creates it), any (first host wins), none (reuse only). The default keeps the tunnel's lifetime attached to DSH desktop.
  • Stale leases are reclaimed by rename, so two hosts can never both reap the same record.
  • Failure is never fatal — a missing ssh, a bad host or a timeout only logs a warning; the watch pass retries later.

Settings page

Section Contents
Connection source system ~/.ssh/config · a custom config file · DSH-only (generated)
Host & forward Host alias (dropdown parsed from that file); forward mode: the config's LocalForward or an explicit -L
DSH-only fields shown only for the DSH source: host name, user, port, identity file, ProxyJump
Behaviour who may own the tunnel, auto-repair, tunnel_status tool, connect timeout
Advanced ssh executable, extra args, readiness timeout, watch interval

The status card on top shows state, listen address, lease owner, last error, config problems, and a Restart tunnel button.

Connection sources:

  • system — reads ~/.ssh/config as-is; ssh finds it itself; the host dropdown is parsed from it.
  • custom — an absolute path passed with -F.
  • DSH-only — the plugin generates $DSH_HOME/ssh-forward/ssh_config from the form fields, for people who do not want to touch the system config or want separate credentials for DSH.

Install

dsh plugin --profile desktop add dsh-ssh-forward
dsh plugin --profile web     add dsh-ssh-forward

Restart DSH, then fill in the connection fields on the Settings page.

Development

pnpm install
pnpm test           # unit: lease, probe, state machine, ssh config parsing, argv
pnpm integration    # real child process + real port + real lease (owner path)
pnpm check          # syntax + unit + integration
pnpm e2e            # boots a real DSH host through the full lifecycle (needs a normal shell)

Layout:

lib/index.js           cordis entry: volatile Config, manager wiring, settings bridge, restart
lib/client.js          browser half: the Settings page (plugins.row.config slot)
lib/manager.js         the state machine (dependency-injected, unit tested)
lib/lease.js           lease: liveness, heartbeat, stale reclaim
lib/config.js          config snapshot, normalisation, validation
lib/sshconfig.js       ssh config parsing / DSH-only generation / argv
lib/settings-bridge.js /api/dsh-ssh-forward-settings/* routes
lib/probe.js           TCP readiness probe
lib/spawner.js         ctx.subprocess or child_process

Publish

The registry on this machine is an install mirror, so publishing must be explicit:

pnpm login --registry=https://registry.npmjs.org
pnpm publish --registry=https://registry.npmjs.org --access public --no-git-checks

License

MIT. See LICENSE.