DSH ghcr.io/meixu6693/dsh:latest https://github.com/MeiXu6693/dsh-docker/pkgs/container/dsh bridge bash false https://forums.unraid.net/topic/200908-support-dsh-deepseek-harness-ai-coding-agent-in-your-browser/ https://github.com/deepseek-ai/deepseek-harness MIT deepseek harness dsh coding agent ai agent cli Docker;请保留模板自带的 Extra Parameters(两个 --security-opt),否则命令沙箱不可用 | Docker; keep the template's Extra Parameters or the command sandbox is unavailable 跟随上游 @deepseek-ai/dsh 自动重建,发布说明见 Releases:https://github.com/MeiXu6693/dsh-docker/releases | Rebuilt automatically for every upstream release; release notes: https://github.com/MeiXu6693/dsh-docker/releases DSH(DeepSeek Harness)是开源 AI 编码智能体:在浏览器里与它协作,读写你的项目、执行命令、管理模型与会话历史。本镜像为 Unraid 准备——自动跟随上游发版重建,内置命令沙箱所需的 bubblewrap,使它在没有 Landlock 的内核上也能正常执行命令,并集成 [dsh-remote-signin](https://github.com/MeiXu6693/dsh-remote-signin) 插件:在局域网、Tailscale 或反向代理后面,用 DeepSeek 账号登录也能正常走完(只在最后多一步粘贴,粘贴框会自己出现在页面上)。 容器内置 Caddy 反向代理与可选口令门禁(也可设为 none 交给你现有的 SSO),以非 root 身份(PUID/PGID,默认 99:100;UMASK=022)运行。 | DSH (DeepSeek Harness) is an open-source AI coding agent you drive from the browser: it works on your projects, runs commands and keeps your session history. Built for Unraid — rebuilt automatically for every upstream release, with the bubblewrap sandbox bundled so commands work even on kernels without Landlock, and with the [dsh-remote-signin](https://github.com/MeiXu6693/dsh-remote-signin) plugin integrated: a DeepSeek account sign-in also works over the LAN, Tailscale or behind a reverse proxy (it adds one paste, into a box that appears in the page). The container bundles its own reverse proxy and an optional password gate (or set none and delegate to your SSO), and runs unprivileged as a non-root uid (PUID/PGID, 99:100 on Unraid; UMASK=022). Tools: http://[IP]:[PORT:8080] https://raw.githubusercontent.com/MeiXu6693/unraid-templates/main/templates/dsh.xml https://gh-proxy.com/https://raw.githubusercontent.com/MeiXu6693/unraid-templates/main/README.md https://gh-proxy.com/https://raw.githubusercontent.com/MeiXu6693/unraid-templates/main/templates/img/dsh.png --security-opt seccomp=unconfined --security-opt systempaths=unconfined --restart=unless-stopped DSH(DeepSeek Harness)是开源的编码智能体,界面就在浏览器里:它能读改你的项目文件、执行命令、管理模型与会话历史,工具与能力都通过插件扩展。 **为什么用这个镜像** - 自动跟随上游:镜像每天检查上游版本,一有新版本就构建、冒烟测试并推送;你只要在 Docker 页点一次更新,不用改任何配置。 - 命令沙箱真的能用:Unraid 内核没有启用 Landlock,DSH 的沙箱只剩 bubblewrap 一条腿。镜像内置 bubblewrap,模板默认带上它需要的两个启动参数,因此工具不会因为缺少沙箱而拒绝执行。 - 以非 root 身份运行(PUID / PGID,默认 99:100;UMASK 022)、多架构(amd64 / arm64)、**默认开启内置口令门禁**:`Authentication Mode=builtin` 时必须提供 **Password**;模板自带默认值 12345678,请第一时间改掉。若前面已有反向代理 / SSO 做认证,把 **Authentication Mode** 改为 none,这时用户名/口令都不需要。 **整体方案**:容器内置 Caddy 反向代理——对外只开你发布的那个端口,DSH 自身只监听回环,安全响应头、Host/Origin 校验与 `ALLOWED_CLIENTS` 白名单都在这一层完成。认证是可选的:默认 `builtin` 会像 Basic Auth 一样要一次口令(之后用 Cookie 保持,含 WebSocket 握手),设为 `none` 则交给前面的反向代理或 SSO——**不要叠两层登录**。容器以非 root 身份运行,不挂 docker socket,除你映射的两个卷外不碰宿主目录。 **运行身份(PUID / PGID / UMASK)**:非 root 运行,身份由 **PUID** / **PGID** 决定,模板默认 **99:100**(Unraid 的 `nobody:users`)与 **UMASK=022**;compose / 通用部署可用 1000:1000。容器每次启动都会把 /data、/workspace 与 HOME 交给这对值,改完重启即可。 **三步开始** 1. 安装并打开 http://<你的服务器IP>:8080 :浏览器先弹出登录框,用户名 dsh,口令是 **Password** 字段的值——**模板自带默认值 12345678,请第一时间改成只有你知道的口令**(Docker 页 → 该容器 → Edit → 改 Password → Apply)。在改掉之前,同网络里知道这个公开默认值的人都能操作你的智能体。顺带说明:用户名字段默认 dsh,也可自行修改。登录后会自动完成令牌引导。口令至少 8 位;builtin 下没有口令容器会拒绝启动(模板的默认值 12345678 会一直提供,所以装完先改它)。 2. 状态与项目分别放在 /data 与 /workspace(默认映射到 appdata/dsh/...),升级容器不会丢会话。 3. 放在反向代理之后时,把 PUBLIC_URL 设为对外地址(例如 https://dsh.example.com),容器就只接受该来源的请求;纯内网可留空。**若该代理本身已经做了认证(如 SWAG + Authelia),请把 **Authentication Mode** 改成 none**,否则会连着弹两次登录框。 模型凭据在应用界面里配置,本模板不要求填写任何密钥。 **用 DeepSeek 账号登录(而非 API Key)**:登录标签页最后会停在一个打不开的 `127.0.0.1` 页面上——这是上游的限制(平台只允许登录结果回到回环地址)。这时 DSH 页面右下角会**自动出现粘贴框**,把那个页面的地址复制进去即可完成登录;把本模板的 **Remote sign-in** 设为 off 可回到上游「只有回环地址下的浏览器能登录」的行为。镜像文档:https://github.com/MeiXu6693/dsh-docker/blob/main/docs/remote-signin.zh-CN.md。 **页面提示 “dsh web authentication required”**:通常**自动**恢复(DSH 对文档请求回 401 时会被自动引到 `/renew` 重放启动 token,只绕一次、不会成环);也可手动打开 `http://<你的地址>:<端口>/renew`,或清掉该站点的 Cookie。 **排障** - docker logs <容器名> | head -30 :启动日志会写明运行模式(edge / lan)、上游版本与启动结果。 - 命令工具报 SANDBOX_UNAVAILABLE :说明模板自带的 Extra Parameters 被删掉了,恢复那两个 --security-opt 即可。 上游项目:https://github.com/deepseek-ai/deepseek-harness · 文档与排障:https://github.com/MeiXu6693/dsh-docker --- DSH (DeepSeek Harness) is an open-source coding agent whose interface is a browser tab: it reads and edits your project files, runs commands, and manages models and session history, with everything extensible through plugins. **Why this image** - Automatic updates: a daily upstream check rebuilds, smoke-tests and publishes whenever a new version lands. You just hit update in the Docker tab. - A command sandbox that actually works: Unraid kernels ship without Landlock, which leaves bubblewrap as the only rung for DSH's sandbox. bubblewrap is bundled and the template carries the two launch options it needs, so commands never refuse to run for lack of isolation. - Runs as non-root (PUID / PGID, default 99:100; UMASK 022), multi-arch (amd64 / arm64), and **serves its own password gate by default**: `Authentication Mode=builtin` requires a **Password**; the template ships 12345678 as its default — change it. If a reverse proxy or SSO already authenticates, set **Authentication Mode** to none and leave username/password alone. **How it is put together**: the container bundles Caddy as its reverse proxy — the port you publish is the only way in, DSH itself listens on loopback only, and the security headers, host/origin checks and the `ALLOWED_CLIENTS` allowlist all happen at that layer. Authentication is optional: `builtin` (the default) asks for a password once, like basic auth, and then keeps you signed in with a cookie that also covers the WebSocket handshake; `none` hands that job to your own reverse proxy or SSO — do not stack two logins. The container runs unprivileged, mounts no docker socket, and touches no host directory beyond the two volumes you map. **The identity it runs as (PUID / PGID / UMASK)**: it runs unprivileged, as the **PUID** / **PGID** the template sets; the Unraid defaults are **99:100** (`nobody:users`) with **UMASK=022** (use 1000:1000 for compose or generic deployments). At every start the container hands /data, /workspace and HOME over to that pair, so a change needs only a restart. **Get started in three steps** 1. Install, then open http://<your-server>:8080 — the browser asks for a login first: user dsh, password from the **Password** field (`DSH_PASSWORD`). **The template ships 12345678 as a default: change it to something only you know before you go further** (Docker tab -> the container -> Edit -> Password -> Apply). Until you do, anybody on your network who knows this public default can drive the agent. The user name field defaults to dsh and can be changed. The token bootstrap then completes automatically. The password must be at least 8 characters; builtin mode without a password refuses to start (the template default 12345678 is always supplied, so change it). 2. State and projects live in /data and /workspace (mapped to appdata/dsh/... by default), so upgrading the container keeps your sessions. 3. Behind a reverse proxy, set PUBLIC_URL to the public origin (for example https://dsh.example.com) so the container only answers for that authority; leave it empty on a trusted LAN. If that proxy already authenticates (SWAG + Authelia, Authentik, ...), also set **Authentication Mode** (`AUTH_MODE`) to none so the browser is not asked to log in twice. Model credentials are configured inside the app; this template never asks for a key. **Signing in with a DeepSeek account (rather than an API key)**: the login tab ends on a dead `127.0.0.1` page — that is upstream's restriction (the platform only returns a login to a loopback address). A paste panel appears in the DSH page by itself; drop that address into it (the paste box appears in the page by itself). Set **Remote sign-in** to off for upstream's loopback-only behaviour. Repository documentation: https://github.com/MeiXu6693/dsh-docker/blob/main/docs/remote-signin.md. **Page says “dsh web authentication required”**: it now recovers **automatically** (a 401 on the document is redirected through `/renew`, once, without looping); you can also open `http://<your-address>:<port>/renew` yourself or clear that site's cookies. **Troubleshooting** - docker logs <container> | head -30 — the entrypoint prints the mode (edge / lan), the upstream version and the startup result. - Tools reporting SANDBOX_UNAVAILABLE mean the template's Extra Parameters were removed; restore the two --security-opt values. Upstream project: https://github.com/deepseek-ai/deepseek-harness · Documentation and troubleshooting: https://github.com/MeiXu6693/dsh-docker 0.0.0.0:8080 /mnt/user/appdata/dsh/data /mnt/user/appdata/dsh/workspace 99 100 022 127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,100.64.0.0/10,fc00::/7,fe80::/10 dsh builtin on Asia/Shanghai