---
title: "Deploy DeepSeek Harness | (Just Updated) DeepSeek's Own Coding Agent, Gated"
description: "DeepSeek's own coding agent, always on and behind a password."
category: "AI/ML"
url: https://railway.com/deploy/deepseek-harness-or-just-updated-deepsee
---

# Deploy DeepSeek Harness | (Just Updated) DeepSeek's Own Coding Agent, Gated

DeepSeek's own coding agent, always on and behind a password.

**[Deploy DeepSeek Harness | (Just Updated) DeepSeek's Own Coding Agent, Gated on Railway](https://railway.com/template/deepseek-harness-or-just-updated-deepsee)**

- **Creator:** SuperSlowSloth
- **Category:** AI/ML
- **Total deploys:** 8

## Template content

### deepseek-harness

- **Image:** ghcr.io/bon5co/deepseek-harness-railway:0.1.0-rc.6
- **Health check:** /healthz
- **Public domain:** Yes

## Documentation

# Deploy and Host DeepSeek Harness on Railway

DeepSeek Harness (`dsh`) is DeepSeek's own open-source agent harness — the layer that turns a model
into an agent that can read your files, run shell commands, search the web, and keep working across
a long task. Everything in it is a plugin: models, tools, skills, sessions, sandboxes, storage,
loops, scheduling, and the UI itself.

Upstream ships it as `npx @deepseek-ai/dsh web`, which serves the Web UI on `127.0.0.1:3080` — your
laptop, while your laptop is awake. This template runs that same Web UI on Railway, always on,
reachable from any browser, **behind a password**.

## About Hosting DeepSeek Harness

The hard part of hosting this is not the app, it is the exposure.

DeepSeek Harness has no authentication. Upstream states this plainly — "No TLS, auth, or origin
policy" — and its CLI *refuses* to bind a public address, erroring with "it would expose remote
code execution to the network". That refusal is correct: an agent with a shell tool on an open URL
is a remote-code-execution box on your Railway account, and a persistent volume means anyone who
finds it keeps their foothold across your redeploys.

So this template does not bypass that refusal. `dsh` stays bound to loopback exactly as upstream
intends, and a Caddy reverse proxy owns the public port, enforces HTTP basic auth, and forwards to
loopback — rewriting `Host` and `Origin` so the harness's own anti-DNS-rebinding fence stays
satisfied through the proxy. The agent is never reachable from outside; the only public surface is
the authenticated proxy.

The gate cannot be switched off. Leave the password blank and the container generates a strong one
on first boot, stores it on the volume, and prints it once to your deploy log.

Also handled for you: the container listens on Railway's injected `PORT`; the healthcheck path is
answered by the proxy, since Railway's health prober cannot present credentials; the agent and the
proxy supervise each other, so if the agent dies the container exits and Railway restarts it rather
than serving a green healthcheck over a dead agent; and `node-pty` gets a real toolchain, without
which the image does not even build.

Runs on Ubuntu 24.04 with Node 24 and a full apt userland, so the agent can `apt-get install` what
it needs mid-session. There is a companion template, **DeepSeek Harness on NixOS**, that swaps the
base for the nix package manager — same gate, same persistence, reproducible pinned packages from
nixpkgs instead of apt.

Measured at 164 MiB idle under a 1 GB cap, so it fits Railway's Trial and Hobby plans comfortably.

## Why Deploy DeepSeek Harness on Railway

- **Always on, and reachable from anything.** The upstream quick start dies when you close your
  laptop. Here the agent keeps its session, its memory, and its workspace on a volume, and you pick
  the task back up from your phone.
- **Gated by default, provably.** Unauthenticated requests to the UI, to the API, and to the
  WebSocket all return `401` — including requests that forge a loopback `Host` header to try to
  satisfy the harness's own fence. Verified, not asserted.
- **One volume covers everything.** Sessions, config, credentials, and the agent's files all live
  under a single mount, so a redeploy does not wipe the work.
- **Nothing to fill in but your model key.** Every platform setting is baked into the image rather
  than dumped on the deploy form as blank required fields.
- **Pinned, not floating.** The harness is in developer preview and upstream warns of
  compatibility-breaking changes, so the version is pinned — your deploy does not break the next
  time upstream ships.

## Common Use Cases

- **A coding agent that outlives your laptop** — hand it a long refactor or a migration, close the
  lid, check the trajectory view from your phone later.
- **A shared team agent box** — one gated URL your team can open, with an append-only session log
  of everything the model saw, so a run can be inspected, resumed, forked, or replayed.
- **A harness development sandbox** — DSH is a plugin system in developer preview, and Creator mode
  is built for authoring and testing Cordis plugins. A disposable hosted instance is a safer place
  to experiment than your own machine.
- **A scratch environment you do not mind breaking** — the agent gets a real shell in a container
  that is one redeploy away from clean.

## Dependencies for DeepSeek Harness Hosting

- A **DeepSeek API key** from [platform.deepseek.com](https://platform.deepseek.com). Other
  providers work too — DSH resolves each provider's key from a variable that provider's own entry
  in `settings.yaml` names.
- A **volume mounted at `/home/dsh`**, for sessions, config, credentials and the workspace.

### Deployment Dependencies

- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — the upstream project (MIT)
- [Product page](https://deepseek.com/harness/en/) — modes, plugin model, trajectory view
- [`@deepseek-ai/dsh`](https://www.npmjs.com/package/@deepseek-ai/dsh) — the published CLI
- [Caddy](https://caddyserver.com/) — the authenticating reverse proxy in front of it
- [DeepSeek Platform](https://platform.deepseek.com) — where the API key comes from

### Implementation Details

Set the access gate at deploy time, or let it generate one:

| Variable | Default | Purpose |
| --- | --- | --- |
| `DEEPSEEK_API_KEY` | — | Model access. The UI loads without it; the agent cannot answer. |
| `DSH_USERNAME` | `admin` | Basic-auth user. |
| `DSH_PASSWORD` | generated | Basic-auth password. Blank means *generated*, never *disabled*. |
| `DEEPSEEK_BASE_URL` | DeepSeek API | Point at a gateway or proxy instead. |

The request path:

```
browser ──TLS──> Railway edge ──> Caddy on $PORT   (basic auth; 401 without credentials)
                                       │
                                       └──> dsh web on 127.0.0.1:3080  (never reachable outside)
```

To retrieve a generated password, open the deploy logs and look for the `[entrypoint]` lines on
first boot. To stop it appearing in logs at all, set `DSH_PASSWORD` as a service variable.

**One caveat, stated plainly.** This is a single shared password over Railway's TLS. That is the
right gate for one operator running their own agent box. It is not multi-user access control, and
it does not protect you from someone who already has the password. If the workspace will hold
anything sensitive, put Cloudflare Access or a VPN in front as well.


## Similar templates

- [Chat Chat](https://railway.com/deploy/-WWW5r) — Chat Chat, your own unified chat and search to AI platform.
- [stella](https://railway.com/deploy/stella) — Self-host stella with web, API, Postgres, Redis, and object storage.
- [Hermes Agent | OpenClaw Alternative with Dashboard](https://railway.com/deploy/hermes-agent-or-openclaw-alternative-wit) — Self-Hosted Hermes AI Agent for Telegram, Discord & Slack

Open this page in a browser: https://railway.com/deploy/deepseek-harness-or-just-updated-deepsee
