DeepSeek Harness on headless Linux: dsh web setup

Install & Get StartedPublished 2026-10-19Author: DeepSeek Plugin Market
DeepSeek HarnessDSH pluginheadless Linuxdsh webport forwardingremote
DeepSeek Harness on a headless Linux box: verify the host, tunnel dsh web over SSH, split blank-page failures, then add a proxy, containers and DSH plugins.

The server arrived as an SSH login with no monitor, no desktop session, and no sympathy for GUI instructions. DeepSeek Harness installed and ran anyway, because the only thing a headless host truly lacks is a way to show the page. This is the order I did things on that box, including the blank screen that wasted an hour.

I verify the host before installing anything for DeepSeek Harness

A headless box lacks a graphical shell, not a runtime, and a few checks prove it is ready.

My first instinct was to search for a desktop build, which was a waste of an afternoon. What the machine needed was Node, a free port and enough memory, all of which I could check from the shell. Stopping to verify those four things took five minutes and saved a confused install. A missing dependency found now is a sentence in a log; found later, it becomes a fake plugin problem.

Node came first, and the version mattered more than the presence of the binary. An old runtime can install the package successfully and then fail at startup with a message that mentions neither Node nor the plugin. The next check was command resolution, because a working binary in the wrong PATH looks like a broken install. Running npx @deepseek-ai/dsh --version proved that the package resolves and that the shell agrees with npm.

Port and memory were the quiet failures. I used ss -ltnp to see whether anything already owned the default port, since a stale process produces a page that loads and then disconnects. Memory and disk checks came last, because a small box happily opens the Web UI and then dies in the middle of a long session. Desktop windows, trays and notifications simply do not exist here, so I stopped looking for their settings and moved on.

The first tunnel brings DeepSeek Harness dsh web to my laptop

SSH local forwarding is the default path on a headless host, because it keeps the service on loopback.

Binding the service to every interface on day one is the shortcut I avoided. The narrow path starts the Web UI on the server and leaves it listening only where SSH can reach it. That one decision removes a whole category of accidental exposure while I am still learning the tool.

bash
npx @deepseek-ai/dsh web

On my laptop, a second terminal opened the tunnel and mapped the remote port to the same local port. The address I typed was the local one, not the server's public hostname, because the browser never talks to the server directly. If the mapping uses a different local port, the URL has to change with it.

bash
ssh -L 3080:127.0.0.1:3080 user@server

I confirmed the service itself with a header request on the server before trusting the browser. Keeping the forward alive under tmux or autossh mattered, because the page dies the moment the SSH session closes. The setup was finished only when a session could be created and the plugin list loaded through the tunnel.

I split the blank page into layers instead of reinstalling DeepSeek Harness

A blank page is several failures wearing one symptom, so I peel from the inside out.

Reinstalling at the first white screen is the expensive habit. The service can be down, the tunnel can be wrong, an asset can be missing, or a browser proxy can be intercepting loopback traffic. Each cause leaves a different trace, and the traces are cheap to collect in order.

I started with the service and ran a header request on the server itself. No response meant the process, port or Node runtime was at fault, and nothing about the browser mattered yet. The same request from my laptop then tested the tunnel, because a working server and a failing local request isolate the forward.

  1. Request headers on the server to prove the service is alive.
  2. Repeat the same request locally to test the forward.
  3. Open the Network panel and look for missing assets or a WebSocket that never upgrades.
  4. Check proxy settings only when a reverse proxy is actually in the path.
  5. Re-run the matching request after each change and name the layer that flipped.

The most common misdiagnosis on a corporate laptop is a browser proxy pretending to be a server fault. 127.0.0.1 can be intercepted too, so the tunnel looks healthy while the page spins forever. Changing one variable at a time is slower to describe and much faster to finish.

When a teammate joins, DeepSeek Harness needs a domain

Serving a second person means adding authentication and TLS, not handing out another SSH account.

The first question is whether the second person can simply use a tunnel. For a small group, one forwarded port per person is still the least work and the least attack surface. The answer changes when someone needs a phone, a stable URL or access from outside the network.

At that point the service stays on loopback and a reverse proxy moves to the same host. The proxy has to forward WebSocket upgrades and allow long streaming responses, or the UI connects and then freezes mid-answer. TLS and authentication belong in front of the proxy, not bolted onto the application after the fact.

I verified that path from outside with a header request, then asked a long question in the browser to watch for truncation. A page that loads is not the same as a stream that survives, and the difference only shows on a real answer. Once the domain works, the SSH tunnel becomes a debugging tool rather than the daily route.

Containers and DSH plugins come after the host works

A container reproduces state well and preserves it badly, so data and ports become your job.

Publishing the port is mandatory, because a service listening inside the container is invisible to the host. Mounting the data directory matters just as much, since deleting the container otherwise deletes sessions and installed plugins. I use containers for version experiments and plugin conflicts, then remove them when the question is answered. Daily work stays on the host, where upgrades and logs are easier to reason about.

Installing DSH plugins on a headless box has two doors and one checklist. The browser door is DSH Plugin Hub, where I search the package and check the version before installing. The CLI door is better for scripts, because the same command can be repeated on the next rebuild. Either way, dsh plugin list has to show the package and version, and a DeepSeek Harness plugin has to reach ACTIVE after a restart rather than sitting in PENDING.

I keep four facts in one file beside the deployment notes: Node version, dsh version, tunnel port and the data directory. The next rebuild then takes minutes instead of another afternoon of searching. That file is the real product of this exercise, because the commands are easy to find and the local decisions are not.

FAQ

Can DeepSeek Harness really run on a Linux server with no desktop at all?

DeepSeek Harness runs fine on a headless Linux server because it needs Node and a browser, not a local graphical session. Only desktop windows, the tray icon and system shortcuts are unavailable; models, sessions and plugins all work.

DeepSeek Harness dsh web is running, but my local browser cannot open it. What first?

When DeepSeek Harness dsh web is running but the browser cannot open it, curl the server port locally before touching the tunnel. Checking in the wrong order turns a forwarding problem into a fake reinstall.

Why is the DeepSeek Harness page still blank after an ssh -L tunnel?

A blank DeepSeek Harness page after ssh -L usually means the forwarded port differs from the port dsh web actually listens on, or the browser uses a proxy. Curl the mapped local port first and only then blame frontend assets.

Does a team still use SSH tunnels for shared DeepSeek Harness access?

A team can keep using SSH tunnels for DeepSeek Harness when the group is small, though one account per person is simpler. Add a reverse proxy with authentication once you need a domain, HTTPS or outside members.

On headless Linux, should I install DSH plugins from the browser or the CLI?

DSH plugins can be installed from either the browser or the CLI on headless Linux, and the CLI is better for reproducible setups. Finish with dsh plugin list so the package and version are confirmed outside the UI.

Related Terms

dsh web (Web startup command)
dsh web starts the DeepSeek Harness Web UI on a local port. It does not require a desktop environment, which makes it the main entry on headless Linux.— https://deepseek-harness.github.io/deepseek-harness/guide/quickstart
SSH local forwarding (port tunnel)
SSH local forwarding maps a remote port to a local port so the browser believes the service is local. It is the simplest way to reach a remote dsh web instance.— https://github.com/deepseek-ai/deepseek-harness
reverse proxy (Nginx or Caddy)
A reverse proxy accepts requests for a domain and forwards them to dsh web, adding TLS and access control. It must preserve WebSocket upgrades and streaming responses.— https://www.npmjs.com/package/@deepseek-ai/dsh
headless (no graphical session)
Headless means a server has no monitor or desktop session and is reached through a terminal or network. DeepSeek Harness still runs, but desktop-only features are unavailable.— https://deepseek-harness.github.io/deepseek-harness/guide/quickstart

Sources