Files
dsh-web/OPERATIONS.md
T

17 KiB

本机或可信团队试运行运维

本版本面向本机或受信任团队,不应直接用于公网不可信租户。DSH 与面板使用同源路径代理;Docker socket 权限等价于宿主 root。

启动

  1. 复制 .env.example 为 .env,填写专用绝对目录 DSH_HOST_DATA_ROOT 和 12–72 字节的随机管理员密码。限制 .env 的读取权限,不要提交。管理员账号创建后该密码不再被读取,应从 .env 中移除,再运行 docker compose up -d --force-recreate panel 重建面板容器,清除容器环境变量中保留的明文密码(docker inspect 可见)。仅修改 .env 或重启原容器不会更新其环境变量;重建面板会短暂中断面板访问。
  2. 面板以 UID/GID 1000 运行。首次部署前由管理员创建专用数据目录并赋予 1000:1000 所有权、0700 权限;不要对已有未知目录递归改权限。将 stat -c %g /var/run/docker.sock 的结果填入 .env 的 DOCKER_GID,以附加组访问 socket。然后运行 docker compose up --build -d。默认访问 http://127.0.0.1:8088;远程管理优先使用 SSH 本地端口转发,保留此访问地址。Compose 定义了 dsh-mgr -healthcheck 健康检查(探测本机 /healthz);进程无响应时容器会被标记为 unhealthy,配合 restart: unless-stopped 在退出时自动拉起。
  3. 登录后在镜像页提交精确 DSH 版本或查询最新版再手动构建。已有本地镜像会复用,但必须通过启动验证才允许创建实例。镜像不推送至仓库。
  4. 创建实例后从面板进入 DSH。不要给 runtime 发布宿主端口或挂载 Docker socket。

首次启动创建管理员。修改环境变量不会重设已有账号密码。容器内 /data 必须对应 HOST_DATA_ROOT 指向的同一宿主目录,否则 sibling 容器会挂载错误数据。

新镜像构建前必须检查 Docker 存储空间:将 docker info --format '{{.DockerRootDir}}' 返回的绝对目录填入 DSH_DOCKER_ROOT_DIR。Compose 将该目录以相同路径只读挂载,面板只用 statfs 检查至少 2 GiB 可用空间;这不是授权浏览或修改 Docker 内部文件。映射无法确认、不可访问或空间不足时,新构建拒绝,已有本地镜像复用仍可进行。不要用面板数据盘冒充 Docker 存储盘。

公网 HTTPS 入口(仅可信账号)

反向代理与证书由部署管理员管理,面板仍建议只监听代理可达的私有入口。设置 PANEL_PUBLIC_URL=https://你的域名(仅 origin,不含业务子路径);Compose 默认值仍为本机 HTTP。此值决定 Cookie 的 Secure 属性及 Origin/CSRF 校验,不从客户端的 X-Forwarded-Proto/Host 推断。

默认只按直连来源 IP 限流,不信任 X-Forwarded-For。经反代部署时,设置 TRUSTED_PROXY_CIDRS 为面板实际看到的代理来源地址/CIDR,且确保只有这些代理能连接后端、代理正确维护转发链;不要填写全网 CIDR。未设置时,代理后所有用户将共享该代理来源的每分钟登录额度。公网开放前应实际验证不同客户端来源识别、登录/刷新/退出、DSH iframe、WS/SSE及插件设置接口。

账号由管理员创建,不支持不可信租户。软配额、同源插件与 Docker socket 权限边界不因 HTTPS 而改变;本版本不承诺抵御分布式拒绝服务。

配置与全量备份

实例所有者有完整 home 读写权限,包括自己的凭据。通用文件管理、DSH 终端及 agent 不受专用 Profile 编辑器的 YAML 校验或停机流程限制;这不是 write-only 凭据系统。文件下载和目录 ZIP 可包含明文密钥,不等同于下述加密配置备份。提示可帮助避免误操作,但无法阻止所有者导出凭据。共享下载文件前应自行检查,修改运行中配置前建议先停机和备份。

面板提供加密配置与资源备份:固定配置、插件清单/锁文件、skins、pets、agent-presets、.agent-presets及manifest;不包含会话、node_modules或工作区。新包用创建时的登录密码经Argon2id派生密钥、AES-GCM加密,不依赖或创建 backup.key。导入/恢复使用原备份密码;修改登录密码不会重加密旧包。旧版密钥包仍兼容,只有这类包依赖原 backup.key,应单独安全保管,不能因升级删除。所有包均可能含凭据。

配置备份自动停止原运行实例并恢复运行;恢复先校验包,再快照、写入、启动验证,失败尝试回滚,成功保留原运行/停止状态。当前模板7启动前按清单协调插件;历史跨版本及离线失败验证范围见 ACCEPTANCE.md,不保证任意第三方插件兼容。配置内容上限32 MiB/4096文件,备份入口最多保留20个包;快照和保留上限需管理员监控清理。此流程不能代替全量备份。

要获得一致的全量备份,先通过面板停止所有实例,再停止面板,使用宿主备份工具复制专用数据目录(包含数据库、可能存在的 WAL 文件、工作区、实例 home、快照和密钥)。只停止面板不会自动停止 sibling 实例。恢复时保留权限和所有权,将整个目录恢复到同一部署的配置路径;不要将运行中的数据库文件单独覆盖。备份应在隔离环境定期验证。

升级与故障

镜像兼容验收与准入

管理员实验构建只负责生成并执行基础验证,不代表上线批准。准入前应在独立测试环境核验精确镜像的启动、认证/代理、终端与流式连接、文件读写、插件协调、配置备份恢复,以及所需升级/回滚路径;记录版本、模板、平台、镜像ID、测试范围和证据位置。不要在验收依据中粘贴凭据,也不要仅填写“构建成功”。本次实现不自动启动待验收镜像供普通用户使用,不自动运行真实部署测试。

在镜像页“准入管理”选择推荐或兼容并填写依据,后端还会检查精确镜像身份、成功验证记录和可支持的挂载布局。审批只作用于该镜像;新镜像需要自己的验证与审批。退为仅存量后不允许新建/升级目标;标为禁止使用还阻止新的启动/重启及受控配置修改、备份/恢复写操作,避免其自动重启绕过禁用。已有配置读取和通用home文件管理仍保留,不会自动停止正在运行的实例。若需要立即隔离已运行实例,管理员必须另行确认并执行停止操作。

历史home布局不同:模板7使用完整home作为 /workspace,受支持旧模板使用独立 /data/dsh-home 与用户共享 /workspace。不要把旧模板准入理解为数据布局可任意互换;不支持的反向迁移仍会拒绝,先做好完整备份。

运行时认证材料由面板首次成功连接实例时提取,并使用 auth-signing.key 派生的密钥加密保存在数据根的 runtime-auth/(不在用户home内)。按容器 ID 和启动时间绑定,不会将旧启动周期凭据用于新容器;不同 Host 分别缓存 cookie。全量备份应连同签名密钥和该目录保存,不要向用户公开。

运行时返回401/403时会使该Host的cookie缓存失效,下次请求重新交换。不会自动重放写请求,避免插件操作重复执行;遇到认证失败请重新加载页面后确认操作结果。若runtime自行轮转了启动token且旧token也不可交换,需要管理员处理,不能保证任意上游认证机制变更自动恢复。

升级到本版本后应在维护窗口逐个访问现有实例,完成首次认证持久化。若在首次成功连接前,启动token已被Docker日志轮转删除,本版本无法凭空恢复;先保存工作,再由管理员安排重启相关实例并访问验证。不要为此删除或重建实例。初次日志扫描上限64 MiB,常规每文件10 MiB/3份保留在此范围内。

  • 实例升级选择已经启动验证的本地镜像并提供当前登录密码,面板自动停机、创建密码配置备份与home快照、启动验证及失败回滚,无需先手动停止。home快照最大1 GiB;允许受约束的内部相对链接以支持pnpm,拒绝不安全链接/特殊文件。模板7的 /workspace 是实例home,包含在home回滚内;旧共享数据不回滚。跨DSH版本历史验证范围见 ACCEPTANCE.md。
  • Profile是例外:当前需先停止实例,再使用“保存并启动”;页面包含Monaco和脱敏配置预览。不要把备份/升级自动停启理解为Profile可在线改写。
  • 若实例进入 error,不要直接修改数据库状态强制启动。保留原容器、实例目录与 upgrade_journal 记录,检查实际容器与 journal 的旧/新容器 ID、阶段、快照路径是否一致。
  • 人工恢复前停止相关容器并另做完整备份。中断点不同,不能统一用一次目录覆盖或状态修改处理;当前无自动灾难恢复命令。
  • 删除实例会删除其容器与网络,但保留数据目录。升级快照暂无自动清理;不要删除仍被未完成 journal 引用的快照。

Git 分支发布运行镜像构建配置

发布源默认为本仓库 https://git.misaka.ren/m1saka/dsh-web.git 的 dockerfile 分支,通过 DSH_RELEASE_REPOSITORY / DSH_RELEASE_BRANCH 配置。它发布的是构建文件,不是预构建镜像,也不是面板程序自身的更新。修改配置后需重新创建面板容器。

直接运行面板二进制时需要安装 git;面板 Dockerfile 已包含该依赖。当前通道仅支持无需认证的 HTTPS 仓库,不读取宿主 Git 凭据、不跟随重定向,也不支持 SSH 或 URL 内嵌令牌。私有仓库认证需另行扩展,不能把访问令牌写入仓库地址。

分支根目录放 release.json,完整构建目录放 image/。本仓库提供初始描述文件;发布时一起提交 Dockerfile、Caddyfile、entrypoint 和全部安装/适配脚本。只把 Dockerfile 单独放到分支上是不完整的发布。不要把 .env、私钥、凭据、用户数据或 .git 放进构建目录;.dockerignore 只是辅助措施,发布者仍须审查内容。

Git 通道直接向 Docker API 发送构建上下文,不执行 Docker CLI 的 .dockerignore 过滤。面板会排除 .git、.env 系列和常见凭据文件,并拒绝链接、特殊文件及越界路径,但不能识别任意文件名下的秘密。构建归档最大 32 MiB;Git 获取有 45 秒超时及文件大小限制,建议发布分支仅保留发布所需文件。

release.json 示例:

{
  "schema_version": 1,
  "release_id": "runtime-7.1",
  "version": "0.2.0-rc.2",
  "deployment_schema": 7,
  "platforms": ["linux/amd64"]
}

version 是精确 DSH 版本;release_id 是构建配置发布编号,修改脚本或 Dockerfile 后即使 DSH 版本不变,也应使用新的编号。deployment_schema 声明运行布局兼容协议,当前 Git 发布通道支持协议 7:实例 home 挂载 /workspace、共享目录 /shared、代理端口 8080,并保留现有认证与启动约定。它不应随普通构建修订递增;不兼容的运行约定需要面板新增支持。platforms 只能声明发布者实际验证的平台。

首次发布时,在独立 checkout 或 worktree 准备 dockerfile 分支,将 release.json 和完整 image/ 目录提交并推送到同一远程仓库。无需切换正在开发的主工作目录,也无需 CI。此功能的代码安装本身不会替你创建或推送远程分支;分支未发布前,检查失败是预期状态,旧实例与旧构建入口不受影响。

管理员打开镜像页会检查 Git 发布,页面保持打开时每五分钟复查,也可手动刷新。确认构建后面板以固定 commit 获取文件;确认期间分支发生变化会拒绝并要求重新检查。构建任务记录发布编号、仓库和 commit,同一 DSH 版本的新构建发布不会误用旧版本构建任务。构建与验证成功后才可选择镜像;不会自动升级任何已有实例,升级仍走密码确认、备份、快照和失败回滚流程。

该分支是可执行代码信任边界:限制写权限,发布前审查 Dockerfile 与脚本,不向不可信仓库开放构建。可信发布只替代内置版本名单,不替代完整的上线验收;应在发布前验证启动、代理/认证、文件访问、插件以及升级恢复。管理员对精确镜像设置的禁用策略仍然有效。上游依赖、基础镜像和网络变化可能影响重建结果,commit 固定并不意味着所有外部依赖都已固定。Git 故障不会停止已有实例。

创建与构建恢复记录

创建失败不代表 Docker 没有创建资源。面板在发请求前记录 runtime_creates(实例 ID、容器/网络结果待确认标志及其置位时间)及 image_build_checks(构建 ID、镜像 ID、已确认的验证容器 ID、记录创建时间),已确认网络身份保存在 runtime_networks。资源可见后按身份校验再清理;已记录 ID 时按 ID 查询,不能把名称消失当成资源删除。身份不一致时拒绝删除。构建验证残留在启动时及后台重试回收,无需新建构建任务触发。

创建请求失联后,确定性名称的 404 仍视为结果不确定,不会仅因经过一分钟而清除恢复依据:实例保持 error 并占用名额,资源迟到出现后可重试删除并按身份清理;验证容器的不确定记录保留并后台降频重试、审计记录 build.cleanup_error,不会每秒新增审计。即使恢复记录的时间戳缺失或损坏,也不能据此推断创建已结束。一直未出现的资源需要按下述人工确认流程处理,不能保证所有失联创建自动释放预约。删除实例成功后总是清理其 runtime_creates/runtime_networks 行。数据库暂时不可写时,构建终态事务独立重试,不阻挡后续构建;面板退出后未提交的任务按中断失败处理,不承诺恢复为成功。

人工确认流程(仅部署管理员,不能因单次404直接改库):

  1. 停止面板接收新操作并停止面板进程,备份数据库(含 WAL)及相关恢复记录。确认 Docker daemon 健康,并结合 daemon 日志确认原创建请求已结束;必要的 daemon 维护会影响其他容器,应单独安排。
  2. 根据精确实例/构建 ID 核查 dsh-inst-<instance-id> 网络与容器,或 dsh-build-check-<build-id> 验证容器;已记录容器 ID 时还必须按 ID 查询,不能仅按名称判断不存在。核对归属标签、镜像及名称,不运行全局 prune。
  3. 资源存在且身份一致时,优先恢复面板并走正常删除/自动回收;身份冲突则保留记录,先调查冲突来源。
  4. 只有确认原请求终结、对应资源确实不存在后,才可在维护备份基础上用 SQLite 事务清除该精确 ID 的待确认标志,或删除该精确 build ID 的 image_build_checks 行。不得批量清空恢复表,不修改实例为 running。重新启动面板后重试正常删除,并核对实例名额、构建状态与 Docker 资源。

容量与网络

实例文件请求只在检查归属和登记使用状态时取得生命周期锁,上传/下载期间不持全局生命周期锁。同一实例存在文件操作时,启停、删除、配置修改、恢复及升级返回 409,等待传输结束后重试。文件树单目录最多列出 10000 项,超限返回 413;用量与快照遍历仍有总条目/深度上限。此限制不是文件系统硬配额。

用户软配额覆盖工作区与实例目录,已接入上传、Profile增长、恢复/升级快照的写前检查及写入串行化,并每5分钟巡检记录超额/恢复审计;覆盖范围见 ACCEPTANCE.md。它不能阻止DSH直接写盘或插件安装增长。监控数据目录和Docker存储空间,快照也消耗容量。硬quota需宿主文件系统和管理员配置,是可选增强,不是默认路线必做项。

每个实例配置独立bridge、非root、只读根文件系统和资源上限,但并非完整网络安全边界:未限制访问宿主、局域网或互联网。公网不可信租户需另外设计独立origin、可信TLS入口与出站策略,并按威胁模型评估硬配额。不要给runtime发布端口;server-held DSH cookie不下发浏览器,不能代替面板归属鉴权。

验收

按版本分层记录的验收结果见 ACCEPTANCE.md。以下命令是检查入口;历史通过记录不能替代当前版本回归,自动化测试不能替代实际公网域名与浏览器验收。

bash scripts/check-trial.sh

该脚本执行本地自动化测试、race、静态检查及前后端构建,不启动容器、不安装依赖、不部署。需提前准备 Go/Node/npm 和前端依赖。可通过 TEST_TMPDIR 指定已存在的临时目录。镜像构建单测已隔离真实磁盘空闲量;生产磁盘检查仍保留。

scripts/test-panel.mjs 必须指向独立测试部署,通过 TEST_PANEL_URL、TEST_USERNAME、TEST_PASSWORD 指定访问参数;TEST_UPGRADE=1 包含同镜像替换升级。它会创建及删除测试实例、留下保留策略要求的数据,并可能构建或复用本地 runtime 镜像。不要对生产账号运行。