资讯动态

DeepTutor v1.4.10 解读:个人头像与资料页、单端口 rootless 容器化与多用户 MCP 工具默认拒绝

发布时间:2026/9/9 20:12:28 来源:尧图企业网站定制
DeepTutor v1.4.10 解读个人头像与资料页、单端口 rootless 容器化与多用户 MCP 工具默认拒绝【免费下载链接】DeepTutorDeepTutor: Lifelong Personalized Tutoring. https://deeptutor.info/.项目地址: https://gitcode.com/GitHub_Trending/dee/DeepTutor导读DeepTutor v1.4.10 是面向部署形态与账号体系的一次「收尾型」版本为每个已登录用户提供自助 Profile 页面与头像、重构容器发布链路使整个应用可以以 rootless 只读根文件系统的方式在单端口:3782背后运行、并在多用户模式下把 MCP 工具访问收紧为「默认拒绝」。本文以 v1.4.10 发布说明 为核心结合 CONTAINERIZATION.md、compose.yaml、web/proxy.ts、deeptutor/api/main.py 与 deeptutor/multi_user/tool_access.py 等仓库实现讲解每个改动的原理、配置方式与升级影响帮助你理解并复现这一版本的部署与权限模型。版本定位与影响范围官方发布说明将该版本定位为 v1.4.9 的部署与账号跟进版本核心包含四块能力带头像的自助Profile 个人资料页一套可直接 rootless 运行的容器化方案单端口、无构建期 API 地址、无启动期sed多用户模式下收紧的 MCP 工具访问非管理员默认拒绝管理员放行后再授予更安静的访问日志例行200不再刷屏。发布说明特别强调该版本对绝大多数用户是drop-in可直接替换唯一的行为变更局限在多用户模式下针对非管理员用户的 MCP 工具策略上。升级不涉及数据迁移也不需要修改既有配置。自助 Profile 页与头像体系功能概览从 v1.4.10 起每个已登录用户都会获得一个自助Profile页面支持从内置图标列表中选择一个头像可搭配颜色或上传自定义图片作为头像查看自己的账号信息与角色直接登出账号。头像会随后出现在侧边栏中管理员账号会被一个「admin 环」标记出来便于一眼识别身份。仓库中的实现证据头像在前端的落点可以在以下文件中追踪web/components/UserAvatar.tsx头像组件负责把头像标记avatar marker渲染为图标或图片并在空标记时回退到确定性 fallbackweb/lib/avatar.ts头像标记解析与确定性回退的纯逻辑发布说明中提到的测试 web/tests/avatar.test.ts 与之一一对应web/lib/profile-api.tsProfile 与头像上传相关的客户端 API。后端与权限侧可在 tests/multi_user/test_profile_avatar.py 与 tests/multi_user/test_profile_router.py 看到围绕头像与 Profile 路由的契约测试。发布说明还包含两个细节修复未知颜色导致的头像渲染异常会安全回退不再出现隐身头像以及auth-status 拉取被去重避免同一会话重复请求。单端口容器化从「构建期 URL」到「请求期代理」为什么这是一个架构级变化v1.4.10 之前前端通常需要在构建时写入后端 API 地址形如NEXT_PUBLIC_API_BASE占位符 启动时sed -i替换打包产物浏览器因此要直连后端端口容器需要暴露两个端口、并依赖宿主机上的多次改写。v1.4.10 将「URL 知识」从前端产物中整体移除改为请求期转发前端包不再包含任何NEXT_PUBLIC_API_BASE占位符也没有对构建产物的sed改写web/lib/api.ts 中apiUrl与wsUrl退化为一行透传——浏览器始终以前端 origin 下的相对路径发起请求如:3782/api/...、/ws/...既有调用点无需修改即可继续工作web/proxy.ts 作为 Next.js 中间件在每次请求时拦截/api/*与/ws/*读取DEEPTUTOR_API_BASE_URL并将其 rewrite 到后端。其效果正如发布说明所述浏览器只与一个端口:3782通信没有烧进 JS 包的 API URL也没有启动期的sed映射单个端口即可完成部署。请求期 URL 解析链路从源码看URL 的解析链路是容器入口entrypoint每次启动时读取数据目录中的data/user/settings/system.json导出环境变量DEEPTUTOR_API_BASE_URLweb/proxy.ts 读取它作为 rewrite 目标缺省回退到http://localhost:8001const API_BASE_URL process.env.DEEPTUTOR_API_BASE_URL ?? http://localhost:8001;解析优先级为next_public_api_base→next_public_api_base_external→http://localhost:8001proxy.ts对isBackendPath(pathname)命中的路径执行NextResponse.rewrite(new URL(pathname search, API_BASE_URL))。因此只有前后端分离部署后端跑在独立容器中才需要显式设置 API 基址。在镜像内置后端的单容器场景下浏览器只需对 UI 所在 origin 发起相对请求由容器内中间件把请求转到localhost:8001{ next_public_api_base: http://backend:8001 }public_api_base作为兼容别名被接受保存时会归一化为next_public_api_base_external。注意因为代理发生在服务端DEEPTUTOR_API_BASE_URL是前端服务器访问后端所用的内网地址浏览器永远看不到它。CORS 走的是前端origin而非 API URL启用 auth 时在system.json中写入精确 origin 即可{ cors_origins: [https://deeptutor.example.com] }镜像与进程模型按 CONTAINERIZATION.md 的说明发布镜像ghcr.io/hkuds/deeptutor:latest在同一容器内通过supervisord同时托管 FastAPI 后端:8001与 Next.js 前端:3782底层是python:3.11-slim。全部状态settings、工作区、memory、知识库、日志收敛在一棵数据树/app/data中bind-mount 这棵数据树到宿主机即可持久化。关键安全设计supervisord作为 PID 1 以 root 启动但通过逐程序user指令把后端、前端子进程降权到非 root 的deeptutor用户UID 1000在 rootless userns_mode: keep-id下该 UID 映射到宿主用户 UID容器逃逸落地后也是宿主用户权限而非 root[supervisord]段不带user指令早期设计固定userroot在 rootless keep-id 下 PID 1 是非 root 宿主用户、缺少CAP_SETUIDsupervisord 会以Cant drop privilege as nonroot user启动失败supervisord pidfile 写到/tmp/supervisord.pidmode1777任意配置下均可写避免早期版本/var/run/supervisord.pid在 rootless 下因属主/权限导致的 cosmetic 错误。三种容器部署形态形态命令/文件特征docker run单容器命令rootful、可写 rootfs、单个 bind mount/app/datadocker composedocker-compose.yml同镜像 PocketBase 与 sandbox-runner 旁车podman composecompose.yaml加固路径rootless 只读 rootfs tmpfs 系统目录最简单的docker run部署docker run --rm --name deeptutor \ -p 127.0.0.1:3782:3782 \ -v deeptutor-data:/app/data \ ghcr.io/hkuds/deeptutor:latest只需发布3782需要直连 APIcurl/调试时可额外-p 127.0.0.1:8001:8001。宿主机跑本地模型服务Ollama/LM Studio/llama.cpp/vLLM/Lemonade时用--add-hosthost.docker.internal:host-gateway并把 Base URL 指到http://host.docker.internal:portLinux 下也可--networkhost直接共享宿主网络。rootless 加固路径compose.yamlv1.4.10 发布说明 所指的加固容器故事集中体现在 compose.yamlcp .env.example .env # 按需编辑 podman compose -f compose.yaml up -d podman compose -f compose.yaml ps podman compose -f compose.yaml logs -f deeptutor可用podman info | grep -i rootless验证 rootless 是否生效。compose.yaml的关键取舍文件头部注释有完整论证每个服务read_only: truerootfs 只读唯一可写面是各服务声明的tmpfs:挂载与 bind mount 的./datauserns_mode: keep-id 所有卷挂载的:U后缀容器 UID 1000 映射宿主 UID 1000由 podman 自动 chown bind mount 目标tmpfs:覆盖系统运行目录/tmpPython/Node 临时区 supervisord pidfile、/run、/var/runpidfile、/var/log、/root、/home容量给得较宽裕可按需收紧不使用命名卷keep-id 下 podman 以 userns 映射的 rootUID 100000自动创建命名卷755 权限 属主错配会在首次 JSON 写入时报PermissionError宿主自有的 bind mount 目录则干净可用端口仅绑定回环127.0.0.1:去掉前缀即暴露到所有网卡不含 sandbox-runner 旁车docker-compose.yml形态额外提供在最小权限容器中运行模型生成代码的加固旁车podman 形态下主应用回退到bwrap镜像内含且为 Linux或由system.json的sandbox_allow_subprocess控制的受限子进程后端。不依赖compose.yaml时也可以用等价的podman run直驱含:U、--read-only与各 tmpfs 参数。启动后podman exec deeptutor ps -o user,pid,comm会看到uvicorn/node子进程都以deeptutorUID 1000运行。PocketBase 可选旁车与挂载修正PocketBase 是可选 auth storage 旁车在data/user/settings/integrations.json中设置integrations.pocketbase_url http://pocketbase:8090并启动pocketbase服务后账号与会话即存入 PocketBase否则回退到 SQLite 单用户布局。compose.yaml与修正后的 docker-compose.yml 把./data下三个子目录——/pb_data、/pb_public、/pb_hooks——bind mount 进容器。发布说明特别指出 v1.4.10 修复了此前docker-compose.yml中 PocketBase 挂载路径错误旧示例挂在/pb/pb_data首启会因只读 rootfs 报mkdir /pb_data: read-only file system。对多用户部署而言除非已接外部用户存储建议保持pocketbase_url为空。运行时配置入口按 CONTAINERIZATION.md 的运行期配置章节几乎所有可调项都位于数据树data/user/settings/下容器入口每次启动都会 unset相关环境变量BACKEND_PORT、FRONTEND_PORT、NEXT_PUBLIC_API_BASE、AUTH_ENABLED、POCKETBASE_URL等再从 JSON 重新导出因此正确做法是「改 JSON → 重启」而不是用 compose 环境变量驱动文件用途system.json前后端端口、public API base、CORS、SSL 校验、附件目录auth.json可选 auth 开关、用户名、口令哈希、token/cookie 设置integrations.json可选 PocketBase 与 sidecar 集成设置model_catalog.jsonLLM / embedding / 搜索 provider 配置、API key、激活模型interface.jsonUI 语言 / 主题 / 侧边栏偏好main.yaml运行时行为默认值与路径注入agents.yamlcapability/tool 的温度与 token 设置新装最关心的两个键是system.json中的next_public_api_base内网/next_public_api_base_external外部覆盖以及backend_port/frontend_port改动后需同步所有-p映射右侧或HOST_PORT_*环境变量。项目根目录的.env文件被有意忽略为应用配置源推荐用 WebSettings页面编辑这些 JSON/YAML。多用户模式下 MCP 工具「默认拒绝」变更语义这是 v1.4.10唯一的行为变更且被刻意限定在多用户模式下的非管理员范围内非管理员用户无法再发现discover或加载load部署级 MCP 主机工具直到管理员在对应账号的 grant 中显式授予具体工具名管理员不受限单用户 / 无 auth 部署不受影响——它们的会话按管理员运行。源码级原理deeptutor/multi_user/tool_access.py 的模块 docstring 说明了设计动因MCP 工具可以通过配置的 MCP 服务器代理宿主机能力因此对非管理员真实用户而言grant 中缺失 MCP 条目即默认拒绝def allowed_mcp_tools() - set[str] | None: Whitelist of MCP (deferred) tool names. None means unrestricted and is reserved for administrators. Real non-admin users fail closed when the grant omits mcp_tools so a chat turn cannot discover or load deployment-wide MCP host tools until an admin explicitly grants the tool names. grant _current_grant() if grant is None: return None value grant.get(mcp_tools) if value is None: return set() return {str(name) for name in value}对应的执行点见 tool_access.py docstring 与 deeptutor/multi_user/grants.pyallowed_optional_toolsturn 运行时对每轮的tools载荷做过滤全 capability 的唯一收口点tools router 对/settings/tools列表做同样过滤保证 UI 与后端一致allowed_mcp_toolschat 管线在构建 deferred-tool loader 之前先与调用方作用域的mcp_tools_filter求交集被拒绝的 MCP 工具既不能列出也不能加载allowed_cli_apps对已安装 CLI 应用采取同样的默认拒绝姿态已安装应用会在沙箱内运行第三方代码。empty_grantgrants.py中mcp_tools默认为None_normalize_tool_list会规范化enabled_tools/mcp_tools/cli_apps三个名单。因此多用户部署的运维动作是在用户 grant 中显式写入具体 MCP 工具名例如{ mcp_tools: [web_search, file_read, rag_query] }实际工具名以你部署的 MCP 服务器暴露的 deferred tool 名为准。管理员界面中的 grant 编辑器会与内置工具白名单并列呈现 MCP 工具授权便于逐用户核对与配置可达范围。更安静的日志只留非 200例行前端轮询/settings、/tools、/knowledge/list等会制造大量无意义的200日志。v1.4.10 在所有启动路径deeptutor start、launcher、Docker 入口上关闭了 uvicorn 的逐请求 access log并由单个中间件只暴露非200响应。源码证据位于 deeptutor/api/main.pydeeptutor.accesslogger 配置了独立的 INFO stdout handler避免被全局 WARNING 级 root handler 吞掉中间件selective_access_log在response.status_code ! 200时才写一条 5 元组格式的访问日志。配合 deeptutor/api/run_server.py 的access_logFalse与 deeptutor/runtime/launcher.py 的--no-access-log所有启动路径行为一致tests/api/test_selective_access_log.py 对该中间件的输出格式做了契约级验证。结果是日志行数大幅下降留下的都是真正值得关注的错误状态。升级指引与注意点官方声明从 v1.4.9 升级为 drop-inpip install -U deeptutorDocker 用户拉取ghcr.io/hkuds/deeptutor:latest即可。无迁移、无配置变更。唯一需要操作的情形多用户部署下若非管理员用户依赖 MCP 工具请逐用户授予具体工具名——在授权之前它们会保持「默认拒绝」。v1.4.10 附带修复回顾客户端 auth 状态改为经新代理在请求期解析代理同时为上传统计请求体大小头像图片、附件未知颜色的头像渲染安全回退auth-status 请求去重docker-compose.yml 中 PocketBase 挂载路径修正。如果你想深入了解镜像的详细运行形态与故障排查例如页面能开但 Settings 报 Backend unreachable、命名卷下首次 JSON 写入 Permission denied、podman 宿主上 Cannot connect to the Docker daemon等场景的成因与解法可以直接阅读仓库根目录的 CONTAINERIZATION.md 及其 Troubleshooting 与 Security notes 章节。【免费下载链接】DeepTutorDeepTutor: Lifelong Personalized Tutoring. https://deeptutor.info/.项目地址: https://gitcode.com/GitHub_Trending/dee/DeepTutor创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价