Sign inSign up

moelin/deepseek-harness

By moelin

Updated 3 days ago

DeepSeek Harness (DSH) + Web Login | DeepSeek Harness Docker 镜像,支持网页登录

Image
1

10K+

moelin/deepseek-harness repository overview

DeepSeek Harness

Docker Pulls Docker Stars latest size workstation size runtime build workstation build

DeepSeek Harness on Docker Hub publishes two image families:

  • a lightweight runtime image for normal deployments
  • a workstation image with development tools, a persistent HOME volume for user-installed toolchains, and the same /data application-state bind

Both variants are built from the same release pipeline and are published as multi-arch images for linux/amd64 and linux/arm64.

The browser authentication layer is provided by a custom Caddy build with caddy-security and caddy-ratelimit. Its entry point is a standard username/password web form, not WebAuthn or passkeys, so browser password managers can autofill it. Built-in, proxy-aware limits protect username and password submissions at the image boundary.

Current Release

runtime version workstation version

These badges show the current non-floating release values automatically. Use the value shown in the badge when you want to pin a specific runtime or workstation release.

Tags

TagPurpose
latestRuntime floating alias
workstationWorkstation floating alias
<DSH_VERSION> / <DSH_VERSION>-workstationVersioned release tags generated by the release pipeline

Persistence Requirement

Important for upgrades: the application-state persistence path has changed to /data. Both image variants require /data to be an exact bind mount or named-volume mount. Mounting only the legacy /home/node/.local/share/deepseek-harness path does not persist the current layout. To prevent silent state loss, the container prints a bilingual migration error and exits when /data is not mounted; recreate it with a persistent /data mount.

Both variants use /workspace as the image working directory and DSH_WORKSPACE default. The web Add workspace dialog opens at /workspace, and its Home shortcut also resolves there. In the workstation image, /home/node remains the user HOME and persistent tool volume; it is not the default project directory.

Quick Start

Runtime
docker pull moelin/deepseek-harness:latest

# Replace /opt/deepseek-harness with any persistent host directory you control.
sudo install -d -m 0750 /opt/deepseek-harness/data /opt/deepseek-harness/workspace

docker run -d \
  --name deepseek-harness \
  --restart unless-stopped \
  -p 127.0.0.1:56789:8080 \
  -e PUBLIC_URL=https://dsh.example.com \
  -e AUTH_USERNAME=admin \
  -e AUTH_PASSWORD=replace-with-a-unique-password-of-at-least-12-characters \
  -v /opt/deepseek-harness/data:/data \
  -v /opt/deepseek-harness/workspace:/workspace \
  moelin/deepseek-harness:latest

The runtime requires a persistent mount at /data; the host bind shown above is the recommended layout for normal deployments. It stores:

  • /data/auth: authentication users and the persistent JWT signing key
  • /data/caddy: Caddy configuration and certificates/state
  • /data/dsh: DeepSeek Harness application state

The entrypoint normalizes the bind root and creates the required directories and files for the node user (UID/GID 1000:1000). Keep the bind source a regular directory and preserve its ownership and permissions when copying or restoring data.

Workstation
docker pull moelin/deepseek-harness:workstation

# Replace /opt/deepseek-harness with any persistent host directory you control.
docker run -d \
  --name deepseek-harness-workstation \
  --restart unless-stopped \
  -p 127.0.0.1:56789:8080 \
  -e PUBLIC_URL=https://dsh.example.com \
  -e AUTH_USERNAME=admin \
  -e AUTH_PASSWORD=replace-with-a-unique-password-of-at-least-12-characters \
  -v /opt/deepseek-harness/data:/data \
  -v dsh-home:/home/node \
  -v /opt/deepseek-harness/workspace:/workspace \
  moelin/deepseek-harness:workstation

The workstation persists application state under /data, keeps user-installed pnpm, pipx, Cargo, and Go tools in the named dsh-home volume, and stores projects through the direct /workspace bind.

To migrate an older workstation deployment, keep its existing /home/node volume or direct /home/node/.local/share/deepseek-harness mount attached for the first start and add the new /data mount. When /data/auth is empty, the entrypoint copies the legacy workstation application state into /data. Subsequent containers still require /data; the legacy mount cannot replace it. The old path is not deleted automatically, so remove it only after you confirm the migrated /data copy is working.

If you are moving from an older runtime named volume such as dsh-data, copy its contents into the new host data directory before switching tags so the same authentication and JWT state is reused.

If you run the repository Compose files locally, they already use the package-local ./data/data, ./data/workspace, and dsh-home layout with the same split between application state, workspace files, and user-installed tools.

Configuration

Core settings
VariableMeaning
PUBLIC_URLRequired browser origin, for example https://dsh.example.com. Use the exact public origin, not a subpath.
AUTH_MODELogin mode. Default caddy-security; none is only for deployments with another auth layer; dsh is reserved and fails closed.
AUTH_USERNAMESingle login username. Default admin.
AUTH_PASSWORDPlaintext password, at least 12 characters. Set exactly one credential source.
AUTH_PASSWORD_FILEReadable secret file path for the password source.
AUTH_PASSWORD_HASHbcrypt:<cost>:<hash> form generated by Caddy.
AUTH_TOKEN_LIFETIMEToken and cookie lifetime in seconds. Valid range: 300 to 2592000.
CADDY_TRUSTED_PROXIESSpace-separated trusted proxy CIDRs, private_ranges (default), or none for direct client connections.
AUTH_COOKIE_INSECUREfalse for normal HTTPS deployments. true only for isolated HTTP tests, where cookies lose Secure and HttpOnly.
DSH_TRUSTED_HOSTSOptional comma-separated extra Host authorities when the app is reached through additional trusted origins.

Recommended defaults:

VariableDefaultMeaning
PORT8080Container port where Caddy listens. Publish it through a loopback host port or private network.
DSH_INTERNAL_PORT3080Internal DeepSeek Harness loopback port inside the container. Do not publish it directly.
GOMEMLIMIT128MiBSoft memory limit for Caddy's Go runtime only. It does not cap DSH workloads.
GOMAXPROCS2Caddy Go runtime CPU scheduling limit.
DSH_TELEMETRY_DISABLED1Disables DSH telemetry.

The default login username is admin. There is no built-in default password; set exactly one credential source with AUTH_PASSWORD, AUTH_PASSWORD_FILE, or AUTH_PASSWORD_HASH.

Authentication rate limiting

The image limits username-stage POSTs to 10 per minute and password-stage POSTs to 10 per 10 minutes for each resolved client IP. Rejected requests return HTTP 429 with Retry-After. These budgets are fixed image defaults rather than runtime settings; changing them requires a custom rebuild and smoke test.

CADDY_TRUSTED_PROXIES controls which proxy hops Caddy trusts while resolving X-Forwarded-For from right to left. The default private_ranges matches the documented loopback/private reverse-proxy deployment. Set it to none when clients connect directly to Caddy. When a CDN or another proxy sits in front of 1Panel/OpenResty, normalize the real client IP in that outer proxy or list every trusted proxy range. Unrestricted /0 ranges are rejected. Keep a matching limit in the outer WAF or reverse proxy as defense in depth.

Backup and lifecycle

Stop the container before backing up /opt/deepseek-harness/data to obtain a consistent archive:

docker stop deepseek-harness

sudo tar -C /opt/deepseek-harness/data \
  -czf /opt/deepseek-harness/dsh-data.tar.gz .

docker start deepseek-harness

Restore only while the container is stopped, preferably into an empty data directory. A bind-mounted /data directory is not a Docker volume, so docker compose down --volumes, docker volume rm, and docker volume prune do not delete it. Remove the host directory separately only when its data is no longer needed.

The workstation dsh-home named volume must be backed up separately. Ordinary container removal and docker compose down preserve named volumes; docker compose down --volumes can remove them.

Notes

  • Keep the container port loopback-bound and place it behind 1Panel/OpenResty or another reverse proxy that forwards Host, X-Forwarded-Proto, a trustworthy X-Forwarded-For chain, and WebSocket upgrade headers.
  • PUBLIC_URL must match the browser-visible origin exactly. If you use an IP address or a private certificate, the browser must trust that certificate chain first.
  • Plain HTTP is only for isolated test networks, and it requires AUTH_COOKIE_INSECURE=true.
  • The workstation image includes Python, Go, Rust, Docker CLI client tools, and common build utilities, but no Docker daemon.
  • Mount /var/run/docker.sock only when host Docker control is intentionally required.

Source

Tag summary

Content type

Image

Digest

sha256:27afe99d0

Size

227.6 MB

Last updated

3 days ago

docker pull moelin/deepseek-harness