Skip to content

Latest commit

 

History

History
186 lines (132 loc) · 9.05 KB

File metadata and controls

186 lines (132 loc) · 9.05 KB

English | 简体中文

dsh-container 使用指南

本指南介绍 dsh-container 的持久化部署、局域网访问、配置、WebUI 管理、安全边界和更新方法。项目概览与最短启动命令见项目首页

Warning

请勿将本服务直接暴露到公网。 可选共享密钥适用于可信局域网,或已有外部 HTTPS 和访问策略的单管理员场景;它不提供多账号、角色、数据隔离或公共互联网加固。通过认证的客户端可以修改设置与凭据,并驱动 Agent 在容器内执行命令。

Docker 运行

临时体验

docker run -d --name dsh-container --restart unless-stopped -p 127.0.0.1:3080:3080 -e "DSH_CONTAINER_TRUSTED_HOSTS=localhost,127.0.0.1" ghcr.io/omdsh-dev/dsh-container:latest

健康检查通过后访问 http://localhost:3080。设置与工作区保存在容器内部,删除容器后会丢失。

持久化运行

使用命名卷分别保存工作区和 DSH 配置:

docker run -d \
  --name dsh-container \
  --restart unless-stopped \
  --init \
  --read-only \
  --cap-drop ALL \
  --security-opt no-new-privileges:true \
  --stop-timeout 20 \
  -p 127.0.0.1:3080:3080 \
  -e "DSH_CONTAINER_TRUSTED_HOSTS=localhost,127.0.0.1" \
  --tmpfs /tmp:rw,nosuid,nodev,size=512m,mode=1777 \
  -v dsh-workspace:/home/node \
  -v dsh-config:/home/node/.dsh \
  ghcr.io/omdsh-dev/dsh-container:latest

Docker 会以正确的属主初始化命名卷。

如需让 Agent 直接操作宿主机目录,可将命名卷替换为绑定挂载:

mkdir -p .dsh workspace
sudo chown -R 1000:1000 .dsh workspace

-v "$(pwd)/workspace:/home/node" \
-v "$(pwd)/.dsh:/home/node/.dsh" \

镜像以 UID 1000 运行,绑定目录必须允许该用户写入。

Docker Compose

仓库中的 Compose 文件会在本地构建镜像,不使用 GHCR:

cp .env.example .env
mkdir -p .dsh workspace
sudo chown -R 1000:1000 .dsh workspace
# 浏览器使用其他主机名或 IP 时,先编辑 .env。
docker compose up -d --build
docker compose ps

Compose 默认启用持久化绑定挂载、只读根文件系统、no-new-privileges、删除全部 Linux capabilities,并使用 unless-stopped 重启策略。

局域网访问

所有示例默认只绑定 127.0.0.1。如需从局域网中的其他设备访问,必须同时开放监听地址并配置信任的 Host:

  • Docker Run:将端口映射改为 -p 3080:3080,并将 DSH_CONTAINER_TRUSTED_HOSTS 设置为浏览器实际使用的所有主机名或 IP。
  • Docker Compose:在 .env 中将 DSH_CONTAINER_BIND_ADDRESS 设为 0.0.0.0,并更新 DSH_CONTAINER_TRUSTED_HOSTS

示例:

DSH_CONTAINER_BIND_ADDRESS=0.0.0.0
DSH_CONTAINER_TRUSTED_HOSTS=192.168.1.100,dsh.local

多个 trusted hosts 使用逗号分隔,可以填写主机名、IP 或 host:port。不带端口的值匹配该主机的任意端口。trusted-host 只是可达性和同源边界,不是身份认证。

管理员密钥认证

在 Docker Run 中增加 -e "DSH_CONTAINER_KEY=你的私有密钥",或在 Compose 使用的 .env 中设置:

DSH_CONTAINER_KEY=replace-with-a-private-key

未定义该变量时保持原有无认证行为。变量已定义但值为空、纯空白、包含控制字符或超过 4096 个 UTF-8 字节时,容器会按配置错误退出;其他值按原始字符串比较,不自动去除空格,也不设置最低强度。启用后,除登录和退出接口外的页面、静态资源、API 与 WebSocket 都需要认证。不可信 Host、跨站 Fetch Metadata 或不匹配的 Origin 会先返回 403,有效 Cookie 不会绕过这些检查。

登录页根据 Accept-Language 选择简体中文或英文,也可手动切换。成功登录会写入名为 dsh_container_session 的长期 HttpOnlyPath=/SameSite=Lax Cookie;令牌由随机 nonce 和 HMAC-SHA256 组成,服务端不设置时间失效。浏览器仍可缩短保留时间或淘汰 Cookie。容器重启不会使 Cookie 失效,轮换 DSH_CONTAINER_KEY 会使旧 Cookie 立即失效。

管理员密钥登录页

每个实际 TCP 对端可连续失败 5 次,之后每 60 秒恢复一次尝试;成功登录会重置该对端记录。设置页的「退出本设备」只清除当前浏览器 Cookie,不维护服务端撤销列表。已经复制的 Cookie 在轮换密钥前仍可重放。程序客户端必须通过 GET|POST /_dsh-container/auth/login 获取 Cookie 并随请求发送;不支持 Bearer 认证。POST /_dsh-container/auth/logout 清除当前 Cookie。未认证响应为 401,并携带 X-DSH-Container-Auth: required

DSH_CONTAINER_KEY 按已确认的运行模型保留在 DSH 进程环境中,因此容器内 Agent 可以读取并外传该密钥。不要在不可信任务、工作区或插件可访问该环境时把它视为不可提取的秘密。它是单管理员入口控制,不是 Agent 隔离边界。

HTTPS 反向代理

直接 HTTP 登录不会设置 Secure;当 relay 收到 Forwarded: proto=httpsX-Forwarded-Proto: https 时,登录 Cookie 会增加 Secure。HTTPS 代理必须覆盖客户端提供的协议头,并原样保留 Host 和 Origin。以下 Nginx 示例同时支持流式请求和 WebSocket:

map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}

server {
  listen 443 ssl;
  server_name dsh.example.com;

  location / {
    proxy_pass http://127.0.0.1:3080;
    proxy_http_version 1.1;
    proxy_set_header Host $http_host;
    proxy_set_header Origin $http_origin;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_request_buffering off;
    proxy_buffering off;
  }
}

DSH_CONTAINER_TRUSTED_HOSTS 必须包含浏览器实际使用的 dsh.example.com。如果代理未覆盖协议头,直接客户端可以伪造该头让浏览器收到不适用于 HTTP 的 Secure Cookie;如果代理未传递正确 Host/Origin,请求会按设计返回 403

配置

变量 默认值 用途
DSH_CONTAINER_TRUSTED_HOSTS 必填 DSH 接受的主机名、IP 或 host:port
DSH_CONTAINER_KEY 未设置 可选单管理员共享密钥;设置后启用全入口 Cookie 认证。
DSH_CONTAINER_BIND_ADDRESS 127.0.0.1 Compose 发布端口的宿主机监听地址。
DSH_CONTAINER_PORT 3080 Compose 发布到宿主机的端口。
DSH_CONTAINER_RELAY_PORT 3080 容器内中继服务端口,通常无需修改。
DSH_CONTAINER_INTERNAL_PORT 3081 容器内 DSH 服务端口,通常无需修改。
DSH_CONTAINER_IMAGE dsh-container Compose 构建和运行使用的镜像名。
DSH_CONTAINER_DSH_VERSION latest 构建时安装的 DSH npm 版本或 dist-tag。
TZ Compose:Asia/Shanghai 容器时区;直接使用 Docker Run 时沿用镜像默认值。
DEEPSEEK_API_KEY 未设置 可选 API 密钥,也可以在 WebUI 中保存。
DEEPSEEK_BASE_URL 官方 API 可选的 OpenAI 兼容端点。
HTTP_PROXY / HTTPS_PROXY / NO_PROXY 未设置 可选网络代理配置。

Compose 的完整示例值和注释见 .env.examplelatest 只会在构建缓存失效或显式跳过缓存时重新解析 npm 最新版本。

WebUI 容器管理

WebUI 设置中提供只读的「DSH 容器」页面,显示 DSH 版本、端口、trusted hosts、运行用户、权限模式、遥测和认证状态。启用认证时还提供「退出本设备」。

DSH 容器设置页

「重启容器」会请求当前进程平滑退出,但仍会中断正在运行的 Agent、终端和网络连接。要让容器自动恢复,Docker restart policy 必须为 on-failure[:max-retries]alwaysunless-stopped;配置为 no 或未设置时,容器会保持停止。

安全说明

  • 镜像以非 root 用户运行,UID 和 GID 均为 1000。
  • 推荐部署使用只读根文件系统、删除全部 Linux capabilities、启用 no-new-privileges,且不挂载 Docker socket。
  • 较旧内核可能不支持 DSH 所需的 Landlock 或非特权 Bubblewrap,因此镜像在容器内使用 DSH_PERMISSION_MODE=danger-full-access
  • 共享管理员密钥不提供用户身份、角色授权或 Agent 隔离,并且对容器内 Agent 可见。
  • 容器加固和共享密钥都不能替代 HTTPS 与网络访问控制。不要直接暴露到公共互联网;远程访问应放在外部 HTTPS 和访问策略之后。

镜像与更新

GHCR 为 linux/amd64linux/arm64 发布 latest、DSH 精确版本和 sha-<commit> 标签。

更新使用命名卷或绑定挂载的容器:

docker pull ghcr.io/omdsh-dev/dsh-container:latest
docker rm -f dsh-container
# 使用原来的持久化参数重新运行容器。

数据保存在外部卷或宿主机目录中,不会随旧容器删除。源码构建需要跳过缓存,才能重新解析 npm latest

docker compose build --no-cache dsh
docker compose up -d dsh