dsh's webserver schema only accepts 127.0.0.1 or 0.0.0.0; the CLI refuses 0.0.0.0 by design. Seed $DSH_HOME/profiles/web/cordis.patch.yml (the supported override) from the entrypoint instead. Verified: UI serves 200 through a published port, /api trust fence 403s unknown Hosts, and --trusted-host pass-through lifts it. Co-Authored-By: Claude Fable 5 <[email protected]>
deepseek-harness — trusted mirror & container build
Mirror of the official deepseek-ai/deepseek-harness with a locally-built, auditable container image for homelab use (Unraid).
Branch layout
| Branch | Contents |
|---|---|
master |
Exact mirror of upstream master (plus all dsh-v* tags). Never edited locally. |
main |
This branch: Dockerfile, entrypoint, and the sync/build workflow. |
Image
gitea.milesward.dev/mward4/deepseek-harness:<version>
gitea.milesward.dev/mward4/deepseek-harness:latest
Built from node:22-bookworm-slim + the official @deepseek-ai/dsh npm
release, pinned to the exact version. Upstream publishes no container image;
third-party images on public registries (e.g. the now-removed
unzhliu/deepseek-harness) are not built from a verifiable source and should
not be trusted — this repo exists so the image provenance is:
upstream tag → upstream npm release → this Dockerfile → this registry.
No upstream code is modified. Upstream deliberately refuses --host 0.0.0.0
on the CLI (the web UI can execute code, so exposing it to a network is a
deliberate opt-in); the supported opt-in is the profile patch layer, so the
entrypoint seeds $DSH_HOME/profiles/web/cordis.patch.yml with
host: 0.0.0.0 on first start (never overwriting your edits). The UI is
reachable only through ports you explicitly publish, and the /api trust
fence still refuses any Host it doesn't know (see below).
Run on Unraid
- Repository:
gitea.milesward.dev/mward4/deepseek-harness:latest - Port mapping: host
3080→ container3080 - Volume:
/home/node→ wherever you want dsh state kept - Post-arguments:
--trusted-host <how-you-reach-it>for every hostname or IP you'll open the UI at, e.g.--trusted-host tower.local --trusted-host 192.168.1.50(port-less entries match any port). Without this, anything but a loopback Host header gets a 403 from/api— that's upstream's DNS-rebinding/CSRF fence, working as intended.
Keeping current
.gitea/workflows/sync-upstream.yml
runs every 6 hours on the Gitea Actions runners:
- Force-syncs upstream
masteranddsh-v*tags into this repo. - Resolves the official npm
latestversion of@deepseek-ai/dsh. - If the registry lacks an image for that version, builds and pushes it,
moving
:latestalong with it.
Validating an image
To compare any third-party deepseek-harness image against this trusted one:
# Digests will differ (different base layers); compare the installed package:
docker run --rm --entrypoint sh <image> -c \
'cat /usr/local/lib/node_modules/@deepseek-ai/dsh/package.json'
# Full content diff of the installed dsh package between two images:
docker create --name suspect <suspect-image>
docker create --name trusted gitea.milesward.dev/mward4/deepseek-harness:latest
docker export suspect | tar -tv | sort > /tmp/suspect.lst
docker export trusted | tar -tv | sort > /tmp/trusted.lst
diff /tmp/suspect.lst /tmp/trusted.lst
docker rm suspect trusted
Red flags in third-party builds: patched-out 0.0.0.0 refusal, added startup
scripts/cron entries, modified lib/bin.js, or npm packages not published by
deepseek-ai.