🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

多租户实例门户 vocsong/deepseek-harness-portal

DeepSeek Harness
vocsong77 天前有提交已提供中文文档扫描:含敏感能力

为每位用户分配独立容器并统一登录与路由

33.4/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/9/19 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查未通过:仓库根目录及浅层子目录均无 dsh 插件清单,无法用 dsh 插件安装命令安装。以下命令仍可尝试,但可能失败。
无法用 dsh 插件命令安装(仓库内无 dsh 插件清单)
git clone https://github.com/vocsong/deepseek-harness-portal.git
按该仓库 README 的原生方式安装;若作者另行发布了 DSH 插件包,请以其文档为准

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · ui
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 77 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/27) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

仓库根目录及浅层子目录均无 dsh 插件清单,无法用 dsh 插件安装命令安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包deepseek-harness-portal(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/29 11:43:52

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件写入剪贴板(不计风险)读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 6 处,展示前 6 条)
  • 发起网络请求
    portal/public/app.js:54
    const res = await fetch(path, {
  • 写入剪贴板
    portal/public/app.js:398
    try { await navigator.clipboard.writeText($('#i-url').textContent); toast('URL copied', 'ok') }
  • 写入剪贴板
    portal/public/app.js:497
    try { await navigator.clipboard.writeText(v); toast('Invitation code copied', 'ok') }
  • 读取密钥环境变量
    portal/src/config.js:74
    adminPassword: process.env.ADMIN_PASSWORD ?? '',
  • 写入本地文件
    portal/src/db.js:8
    mkdirSync(config.dataDir, { recursive: true })
  • 发起网络请求
    portal/src/orchestrator.js:212
    const req = http.get(
扫描于 2026/11/3(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 按用户分配独立容器
  • 实例路由隔离
  • 统一登录入口

多租户平台,按用户分配并路由隔离的 DeepSeek Harness(dsh)实例,一人一容器。

README

由 DeepSeek 最新模型翻译生成
DeepSeek Harness Portal 一个多租户平台,在单个 Cloudflare Tunnel 后面为每个用户提供一个隔离的 DeepSeek Harness(dsh)实例——每个用户一个容器。 Internet │ (portal: login, admin, user dashboard) │ . (one instance per user) ▼ Cloudflare Tunnel (cloudflared, one named tunnel) │ ▼ Portal (Node + Fastify + SQLite) ── auth + reverse proxy + orchestrator │ ├─► container dsh- (dsh web on :3000 inside, published 127.0.0.1:18xxx) ├─► container dsh- ... └─► ... Portal 是唯一的认证入口。它负责注册、登录、角色以及每个实例的访问控制。 认证模型 - 注册:邮箱 + 一次性验证码(OTP),注册时可选设置用户名 + 密码(这样新用户可以立即使用凭据登录)。当管理员设置了邀请码时,会强制要求填写邀请码。 - 注册后:个人资料可以更改姓名、用户名、密码和邮箱。
展开完整文档(README 剩余 1 节)
DeepSeek Harness Portal

一个多租户平台,在单个 Cloudflare Tunnel 后面为每个用户提供一个隔离的 DeepSeek Harness(dsh)实例——每个用户一个容器。

Internet
│ (portal: login, admin, user dashboard)
│ . (one instance per user)
▼
Cloudflare Tunnel (cloudflared, one named tunnel)
│
▼
Portal (Node + Fastify + SQLite) ── auth + reverse proxy + orchestrator
│
├─► container dsh- (dsh web on :3000 inside, published 127.0.0.1:18xxx)
├─► container dsh- ...
└─► ...

Portal 是唯一的认证入口。它负责注册、登录、角色以及每个实例的访问控制。

认证模型

- 注册:邮箱 + 一次性验证码(OTP),注册时可选设置用户名 + 密码(这样新用户可以立即使用凭据登录)。当管理员设置了邀请码时,会强制要求填写邀请码。
- 注册后:个人资料可以更改姓名、用户名、密码和邮箱。更换邮箱需要分别从当前邮箱和新邮箱获取验证码,并会撤销所有其他会话。
- 登录:用户名/密码或“给我发邮件验证码”(OTP 备用方式)。
- 管理员控制(Settings 标签页):邮箱域名白名单、邀请码、OTP 注册开关、密码登录开关。

OTP 发送使用 SMTP(nodemailer),在生产环境中为必需项。只有在明确仅限本地的开发组合 NODE_ENV=development、DOMAIN=localhost 和 OTP_DEV_MODE=true 下才可记录验证码日志;API 永远不会返回 OTP 值。

架构

| 组件 | 位置 | 作用 |
| Portal 应用 | portal/ | Fastify 服务器:认证(OTP + 密码、bcrypt、会话 cookie)、管理员/用户 JSON API、静态仪表盘、子域名反向代理 |
| 编排器 | portal/src/orchestrator.js | podman CLI 封装:run/start/stop/rm/logs、端口分配、健康轮询、后台配置 |
| 存储 | portal/data/portal.db | SQLite(better-sqlite3):users、otps、settings、instances、sessions |
| dsh 镜像 | image/Dockerfile | 从已审核的上游提交、一个依赖安全补丁和两个有文档记录的源码补丁构建经过审查的 dsh 镜像;标记为 dsh:47f9438-node24(Debian 13 trixie 上的 Node 24 LTS),并通过其 sha256: 摘要进行部署 |
| dsh 克隆 | dsh/ | 全新的 deepseek-harness 检出(构建上下文,已被 gitignore) |

每实例模型

每个用户恰好获得一个实例(1 user : 1 instance):

- 容器 dsh-,CPU/内存/交换/PID 限制,只读根文件系统 + 有界 tmpfs/logs,无 capabilities,no-new-privileges,显式隔离的 pasta 网络,--restart unless-stopped
- 两个卷:-home(挂载到 /home/dsh —— 用户的可写主目录,包括用于会话、设置和凭据的 $DSH_HOME=/home/dsh/.dsh)和 -workspace(挂载到 /workspace —— 代理的持久化 cwd)
- 发布在 127.0.0.1: 上(绝不暴露到主机之外);门户会代理到它
- 代理将到实例的流量呈现为回环(changeOrigin 将 Host 重写为 127.0.0.1:,并且浏览器的 Origin 被丢弃),以便 dsh 仅限回环的设置/凭据方法可以工作;TRUSTED_HOST=. 仍作为回退传递
- 用户的 DeepSeek API 密钥在其实例内部输入(Settings → Models),并且仅存在于该实例的 home 卷中

对 dsh 的构建时更改(参见 image/Dockerfile)

- image/dsh-security.patch 应用经过审查的传递依赖最低版本以及匹配的冻结 lockfile(生产审计:审查时零已知安全公告)。
- 身份开场白 → "You are an AI agent."(品牌化)。
- 允许 --host 0.0.0.0 → 这是必需的,以便发布的端口能够到达容器内的 dsh(出于 LAN 安全考虑,其 CLI 默认拒绝 0.0.0.0;在容器内,只有回环发布的端口可被访问)。

构建脚本要求使用确切批准的上游提交,并且如果源代码/补丁校验发生漂移就会失败。

使用子域,而非路径

实例使用一级子域(.),而不是 /。有两个原因:

1. dsh 的 SPA 调用 /api 并加载 /assets,这些绝对路径在构建时就被写死 —— 基于路径的路由需要重写 HTML 并拦截 SPA 的绝对 /api 调用(在多标签页情况下很脆弱)。
2. Cloudflare 免费套餐的 Universal SSL 通配符仅覆盖一个标签(.example.com),因此 .. 没有有效的 TLS 证书。-deepseek slug 后缀既保留了品牌,又保持为一个标签。

先决条件

- Podman 以及正在运行的虚拟机:podman machine start
- Node.js 22+ 和 npm
- cloudflared(cloudflared tunnel --version)
- 你账户上的一个 Cloudflare 区域,并且隧道已经过身份验证

设置

1. 克隆 dsh(全新上游)

git clone --depth 1 https://github.com/deepseek-ai/deepseek-harness.git dsh
git -C dsh fetch --depth 1 origin 47f943859bef60e4160492346772ded9b24f765a
git -C dsh checkout --detach 47f943859bef60e4160492346772ded9b24f765a

2. 构建 dsh 镜像

./build-image.sh

始终使用该脚本:它会验证批准的提交和补丁,校验上下文策略,并从干净的 git archive 构建。直接运行 podman build 会绕过这些控制。将脚本打印出的 DSH_IMAGE=sha256:... 行复制到 .env 中;生产环境会拒绝可变镜像标签。

首次构建很慢(pnpm install + 完整 harness 构建);结果约为 2.5 GB。

3. 安装门户依赖

cd portal && npm install && cd ..

4. 配置

cp .env.example .env # 然后编辑 .env(DOMAIN、INSTANCE_DOMAIN、ADMIN_、SMTP_)

5. Cloudflare 路由(一次性)

cloudflared tunnel route dns '.'
cloudflared tunnel route dns

隧道配置(~/.cloudflared/.yml):

tunnel:
credentials-file: '~/.cloudflared/.json'
ingress:
- hostname:
service: http://127.0.0.1:8080
- hostname: '.'
service: http://127.0.0.1:8080
- service: http_status:404

cloudflared tunnel --config ~/.cloudflared/.yml run

6. 运行门户

./run-portal.sh

首次启动时根据 ADMIN_EMAIL / ADMIN_NAME / ADMIN_PASSWORD 初始化管理员账户。密码必须显式设置、非占位符,且至少 16 个字符;启动时会拒绝不安全的引导配置。

run-portal.sh 首先应用租户出口防火墙(firewall/apply.sh),如果 Podman 虚拟机未运行则安全失败(fail closed)。

配置(环境变量)

参见 .env.example。重要的变量如下:

| 变量 | 默认值 | 含义 |
| NODE_ENV | production | 仅在本地测试时使用 development |
| DOMAIN | example.com | 门户顶级域名 |
| PORTAL_ORIGIN | https:// | 用于变更/CSRF 校验的精确受信任浏览器来源 |
| INSTANCE_DOMAIN | example.com | . 的基础域名 |
| INSTANCE_SLUG_SUFFIX | -deepseek | 追加到 slug 后 |
| COOKIE_DOMAIN | (空)* | 会话 cookie 域(必须覆盖顶级域名和实例) |
| SESSION_ABSOLUTE_TTL_MS / SESSION_IDLE_TTL_MS | 7 天 / 24 小时 | 服务器强制执行的会话生命周期和空闲过期时间 |
| PORT | 8080 | 门户监听端口(cloudflared 连接到此端口) |
| ADMIN_EMAIL / ADMIN_NAME / ADMIN_PASSWORD | (空) | 首次启动管理员;密码必须显式设置且至少 16 个字符 |
| SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM | (空) | 生产环境 OTP 投递;host/from 必填,认证值需成对提供 |
| OTP_TTL_MS / OTP_MAX_ATTEMPTS | 10 分钟 / 5 | OTP 有效期和每个验证码的尝试上限 |
| AUTH_RATE_WINDOW_MS / AUTH_RATE_BLOCK_MS | 15 分钟 / 15 分钟 | 持久化认证限流窗口/封禁时长 |
| OTP_RESEND_COOLDOWN_MS | 60000 | 每个地址/用途之间 OTP 请求的最小间隔 |
| PORT_RANGE_START / END | 18000 / 18100 | 主机回环端口池 |
| DSH_IMAGE | 必填 | 由 ./build-image.sh 输出的不可变 sha256:... 镜像 ID;生产环境拒绝可变标签 |
| PODMAN_COMMAND_TIMEOUT_MS | 60000 | 每次 podman 调用的子进程超时时间 |
| INSTANCE_CPUS / INSTANCE_MEMORY / INSTANCE_MEMORY_SWAP | 2 / 2g / 2g | 每个实例的计算资源限制 |
| INSTANCE_PIDS_LIMIT | 512 | 每个容器的进程数限制 |
| INSTANCE_NETWORK | pasta | 必需的隔离无根网络模式 |
| INSTANCE_LOG_SIZE / INSTANCE_TMPFS_SIZE | 10mb / 64m | 有界的运行时日志和临时存储 |
| INSTANCE_READ_ONLY_ROOT | true | 以只读根文件系统运行租户容器 |

测试

cd portal && npm test

针对 portal/test/ 中的临时 SQLite 数据库运行隔离的事务性回归测试套件(电子邮件更改证明绑定、尝试次数统计以及唯一性/会话回滚)。它不会触碰实时数据、发送电子邮件,也不要求 Podman。

运维

- 管理员:以管理员身份登录 → 设置选项卡 → 电子邮件域白名单、邀请码、身份验证开关。实例选项卡 → 重新配置/删除、查看日志、使用情况(请求数 + 最后活跃时间)。用户选项卡 → 列出用户。
- 用户:注册(电子邮件 OTP,可选设置用户名/密码)→ 实例自动配置 → 仪表板显示 URL + 状态。实例在启动时自动启动,并在空闲超时后自动停止。
- 启动:https://. —— 门户进行身份验证 + 授权,然后代理到容器。
- API 密钥:在 dsh 内按实例设置(设置 → 模型)。

重启后重新启动

podman machine start # 1) 容器运行时 cloudflared tunnel --config ~/.cloudflared/.yml run ./run-portal.sh # 2) 门户(前台运行;用 nohup/& 包装以在后台运行)

容器带有 --restart unless-stopped;WSL 机器重启后的平台行为仍可能导致它们处于停止状态。门户在启动时会自动启动已授权用户的容器,并在启动时重新排队任何处于 provisioning 状态的实例。run-portal.sh 在每次启动时重新应用租户出口防火墙(幂等);如果你在门户已在运行时重启 Podman 机器,请手动运行 firewall/apply.sh。

故障排除

症状: 租户子域无法加载,容器在 podman ps 中显示 Up,但从 Windows 执行 curl http://127.0.0.1: 失败(而在发行版内部通过 podman machine ssh 'curl http://127.0.0.1:/' 返回 200)。

原因: WSL2 的 localhost 转发器(wslrelay.exe)在经过多次容器停止/启动循环(空闲停止 + 自动启动)后,可能会卡住一个过期的端口转发条目。过期的 wslrelay 进程和孤立的 pasta 进程会不断累积。

修复: 重启 WSL2 VM 并重新配置已停止的租户:

wsl.exe --shutdown
podman machine start
重新配置(或直接启动每个租户;门户会在访问时自动启动) ./run-portal.sh

将 WSL 引擎更新到最新版本(目前因 Windows Installer 重启而被阻止)是针对底层 wslrelay 过期问题的持久修复方案。

安全模型

- 会话 cookie:HttpOnly、SameSite=Lax,当设置了 COOKIE_DOMAIN 时为 Secure;持有者令牌在 SQLite 中以 SHA-256 摘要形式存储,并由服务器强制执行 7 天绝对过期和 24 小时空闲过期。
- 密码:bcrypt。OTP 验证码:加盐 SHA-256,10 分钟过期,尝试次数上限,恒定时间比较;登录/OTP/邀请流程使用持久的按 IP 和按账户限流。
- 每个子域请求在到达容器之前都要经过身份验证(会话)和授权(所有者或管理员);门户 cookie 和网关身份标头在 HTTP/WebSocket 转发之前会被剥离。
- 门户变更操作要求精确的门户 Origin 和每会话 CSRF 令牌;租户同级子域被视为不受信任。
- 实例相互隔离:私有主目录 + 工作区卷、CPU/内存上限、dsh 自带的沙箱。
- 租户出口防火墙:容器无法访问 RFC1918 私有地址范围(你的局域网、10/8、172.16/12);仅允许公共互联网出口。由 Podman 机器上的 nftables 强制执行(firewall/tenant-egress.nft),并由 run-portal.sh 自动应用。
- 门户是唯一的认证层(没有 Cloudflare Access)。

文件

deepseek-portal/
portal/ Fastify 应用 + 静态仪表盘 src/ 后端模块(auth、db、otp、mailer、proxy、orchestrator、email-change) test/ 事务性回归测试套件(npm test) image/ Dockerfile + start.sh + dsh-security.patch(dsh 镜像) firewall/ 租户出口防火墙(nftables)+ apply.sh dsh/ 全新上游克隆(构建上下文,已 gitignore) build-image.sh run-portal.sh 应用出口防火墙,然后启动门户 .env.example README.md SECURITY_AUDIT.md 完整审计、发现项和修复状态 SECURITY.md 漏洞披露政策
预览分享卡片长什么样 ↓vocsong/deepseek-harness-portal
分享 · DeepSeek Harness Hub
vocsong/deepseek-harness-portal

为每位用户分配独立容器并统一登录与路由

这是你的仓库?认领条目

回到顶部