mcpField
W
WRM PRO

WRM PRO

远程服务
github.com云与基础设施2今天更新

关于 WRM PRO

WRM PRO 是可自托管的远程服务器管理工具,可通过浏览器访问并提供 AI 功能。它整合服务器管理、文件与桌面访问、监控,以及带审批和审计记录的 AI 操作。

主要功能

  1. 01管理 SSH、SFTP/FTP/FTPS、RDP 和 VNC 访问
  2. 02检查日志与服务并运行获准命令
  3. 03审批 AI 提议的文件更改
  4. 04配置 MCP Agent 连接和服务器权限
  5. 05记录审计日志与会话

适用场景

  1. 01检查服务器日志并诊断服务问题
  2. 02在服务器间传输文件或编辑远程文件
  3. 03允许 AI 应用执行获批的服务器操作
  4. 04将支持 MCP 的 AI 应用连接到选定服务器

MCP 相关

WRM PRO 提供 MCP 配置向导,为 AI 应用生成连接命令或配置,并可选择可访问的服务器及权限。AI 工具可检查服务器数据并执行获准操作,具体受配置的审批模式控制。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://{wrm_host}/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

全部服务地址
Streamable HTTPhttps://{wrm_host}/mcp需要授权

工具

详细介绍

WRM PRO — Web Remote Manager

Web Remote Manager PRO(WRM)

**可在任何网页浏览器中运行的远程服务管理器,配备 AI 助手和面向 AI Agent 的引导式设置。**添加您自己的 AI 提供商或本地模型:WRM 提供模型建议、Ollama 设置向导和 MCP Agent 连接预设,帮助您快速开始在服务器上开展实际工作。

**可选的 Ollama 自动安装:**管理员可以通过 WRM 在 WRM 主机上安装 Ollama 服务,启动后台服务并下载所选模型。在 Admin → AI 中启用 ai_ollama_manage,然后在提供商向导中确认每项操作。选择推荐的本地模型或其他受支持的模型;安装和设置操作都会被记录并审计。通过 MCP 向导连接 Codex CLI、Claude Code、Gemini CLI、OpenCode、Cursor / VS Code、Claude 或 ChatGPT;向导会提供连接命令或配置,并允许您选择服务器和权限。

管理 SSH 终端、SFTP / FTP / FTPS 文件和 RDP / VNC 桌面、Git 服务比较与部署、跳板机、代理、隧道、BMC 和串行控制台、密钥和凭据、资产清单导入、服务器间传输、通知以及语音协作。AI 工具可以检查日志和服务、诊断问题、运行获准的命令,并在只读、审批或有限自动模式下提出文件更改建议。WRM 还提供共享角色、2FA、审计日志和会话录制。可将 WRM 作为一个可自托管的二进制文件、Docker 容器或 Linux AppImage 运行。

当前版本:v13.13.0 · 下载 · 发行说明 · 变更日志 · 安全 · 架构

v13.13.0 有哪些新内容

**只需选择一次,即可从 Claude 应用安装 WRM PRO 插件;一个脚本即可连接所有 AI 应用。**插件不再需要任何设置:它内置 WRM 桥接程序,首次运行 /wrm-pro:wrm 时会询问 WRM 地址,并在浏览器中打开 WRM,供您登录并批准;令牌会直接发送到您的计算机,绝不会进入聊天内容。随后,/wrm-pro:wrm 会列出您的服务器以及 WRM 能执行的所有操作。此前,插件依赖 Claude 应用无法询问的设置,而且其 HTTP 连接器会从云端发起连接,无法访问您自己网络中的 WRM。Settings → AI connections → 🧰 All AI apps at once 会下载一个脚本(适用于 Windows 或 Linux/macOS),该脚本只需登录一次,即可将 WRM 添加到 Claude Code、Claude 应用、Codex、Gemini CLI、VS Code、Cursor、Windsurf 和 OpenCode。发行包中包含 claude-plugin-wrm-pro.zip,可用于 Customize → Plugins → Upload plugin。请参阅 AI 桌面应用(MCP)。

v13.12.0 新增内容

用于编写插件的工具,也适用于 AI。 wrm -addon-lint ./my-addon 会在安装前检查插件:清单是否符合其架构、每个文件,以及代码中沙盒会拒绝的内容(远程脚本、内联处理程序、eval、fetch、localStorage、ZIP 中的令牌、未列入 http.origins 的站点,以及从未显示 ready 的面板)。每项发现都包含代码、文件、行号和提示,因此 AI 可以修复自己的插件;-addon-lint-json 会以 JSON 格式输出相同内容,而在 Settings → Addons 中安装失败时,报告会自动打开。wrm -addon-new grafana-panel ./my-addon 会从四种模板之一(blank、fetch-and-render、grafana-panel、wasm-hook)开始创建,这些模板附带用于桥接的轻量辅助工具 wrm-bridge.js。wrm -addon-dev ./my-addon 会在你的电脑上使用真实的沙盒和 CSP 打开面板,并提供 WRM 替身(设置、Web 请求、环境变量中的密钥),且会在文件发生变化时重新加载。WRM 还提供清单架构和供 AI 助手使用的 llms.txt 指南。请参阅 插件 和插件开发指南。

v13.11.0 新增内容

插件可以通过 WRM 访问网站,但仅限管理员批准的网站。 插件现在会在 addon.json 中列出所需的网站(例如 https://grafana.example.com,以及它使用的方法和路径)。WRM 会代替面板发出请求,因此面板本身仍然无法访问网络:任何未列出的网站都会被拒绝;每个域名都由 WRM 解析,并会阻止访问私有或本地地址,除非管理员为该网站勾选了 private network;重定向也会再次检查。此类网站的 API 密钥和密码属于密钥,需要由你在 WRM 中输入(实例中的 🔑 Secrets):每个实例各自独立;如果你需要在共享实例中使用密钥,可以填入自己的值。密钥会加密存储,由 WRM 添加到请求中,且绝不会显示给面板。个人插件所需的网站须等待管理员批准。窗口的诊断信息中会列出最近的请求。请参阅 插件 和插件开发指南。

v13.10.0 新增内容

按需查看已保存的登录信息、使用主机名作为名称,以及更简洁的顶部栏。 Edit connection 中新增了 👁 Show saved login:使用 WRM 密码(或域密码)确认后,WRM 会显示该连接使用的登录信息。右键点击连接,可选择 Copy username、Copy password(需进行相同的确认)和 Copy IP address。新建连接时,可以使用服务器的主机名作为名称。标签页只显示连接名称,徽标旁的版本号会保持可见,用户名不再每 5 秒跳动一次,Git 工作区服务器筛选器也不再包含空白项。请参阅连接和文件夹。

v13.9.0 新增内容

插件平台 v2:创建自己的插件、为每个插件打开多个窗口,以及持久保存设置。 现在,每位用户都可以安装只有自己可见的个人插件(管理员通过 addon_personal 决定谁可以安装,也可以关闭任意个人插件)。带面板的插件会以实例形式打开,每个实例都有自己的设置和窗口,例如可以并排打开两个仪表板;管理员可以为所有人设置共享实例。设置会保存在 WRM 服务端,并支持导出和导入;重新加载或换用其他设备后,窗口会恢复到原来的位置。用户可在 Settings → Appearance 中选择插件的主题。启用插件前,WRM 会根据 addon.json 生成并显示一份权限清单;更新若申请更多权限,则必须再次获得批准。apiVersion 2 面板无法自行访问网络,每个文件都通过 SHA-256 固定校验;如果面板卡住,监视程序会提供 Reload 选项。请参阅 插件 和插件开发指南。

v13.8.0 新增内容

AI 会话、自定义 AI 设置,以及言出必行的审批。 全新的 🧠 AI 会话面板会列出你的所有 AI 会话,包括来自助手、日志和文件助手、OpenCode Agent,以及通过 MCP 使用的 AI 应用的会话;支持搜索(也可在对话中搜索)、筛选、查看记录、继续(也支持 MCP 会话,其步骤会成为更早的上下文)、保存(不会受记录保留期限影响),以及导出为 Markdown 或 JSON。每个人只能查看自己的会话。助手中的 ⚙ 我的 AI 设置 可让你设置自己的默认提供方(使用你自己的密钥,例如 OpenAI 或 Anthropic 账户)、模型、模式、引擎,以及是否查看模型的思考过程。通过 MCP,如果 AI 应用已停止等待,而你随后在 WRM 中批准请求,现在会立即执行调用(ai_mcp_later_approval);在 AI 应用中选择拒绝后,决定即为最终决定;当你在 WRM 中作出决定时,应用中尚未结束的问题会关闭;如果请求已不再处于等待状态,决定界面会显示由谁以及在哪里作出了决定。工作日志现在会保留完整的思考文本,而不是只保留最后几行。请参阅AI 会话和 AI 桌面应用(MCP)。

v13.7.0 新增内容

主题、无障碍功能,以及可靠的屏幕锁定。 设置 → 外观提供 11 种主题(深色、OLED 黑色、Fjord、Solar、Forest、Ember、浅色 Daylight、Paper、浅色 Solar,以及两种高对比度主题);你可以选择跟随系统的浅色/深色设置,还可以更改所有颜色、字体、界面大小、圆角和间距,保存自己的主题,导出和导入主题,以及添加自己的 CSS。插件中的主题可按用户单独选择,不再强制应用于所有人。针对色觉缺陷(绿色盲、红色盲、蓝黄色盲、全色盲),WRM 会将状态颜色、差异和可选的终端调色板切换为更容易区分的颜色;你还可以添加 ✓ ✕ ! 符号和形状,避免仅依赖颜色传达信息;此外还提供增强对比度、终端最低对比度、减少动态效果和透明度,以及醒目的焦点轮廓。设置 → 安全 → 屏幕锁定可设置 WRM 的锁定时机(无操作并显示警告、窗口隐藏、计算机锁定或休眠、每次启动时、使用键盘快捷键),以及锁屏的外观;立即锁定会立即锁定,而终端、传输、隧道、AI 和 MCP 会继续运行。现在,锁定状态由服务端保存:重新加载页面或打开新标签页后仍会保持锁定;目录(LDAP)账户可以解锁;也可以使用个人 PIN 码代替密码解锁。请参阅外观、主题和无障碍功能和屏幕锁定。

v13.6.0 新增内容

日志文件夹、文件夹树,以及更智能的运维人员识别。 监控 → 日志可以将日志显示为文件夹树,并按主文件夹分类(/var/log、/home/scripts …);还提供文件夹筛选器,可筛选指定文件夹及其所有子文件夹;日志设置可配置你自己的主文件夹。系统会根据文件夹和服务名称中重复出现的词识别运维人员(nova、NOVA2、novatv → 同一运维人员组),并为每条日志标明其位于日志文件夹还是应用文件夹。名称相同(大小写不同)的日志文件夹和脚本文件夹不再互相隐藏日志。请参阅日志:查看器、搜索和日志设置。

v13.5.0 有哪些新内容

专业的日志查看器、智能编辑器,以及能展示工作过程的 AI。 监控 → 日志 会在约 1 秒内列出服务器上的所有日志(只读 SSH 命令),可按操作员和服务排序、筛选,并且绝不会列出 .py 等脚本。日志会在标签页中打开,支持级别颜色、智能高亮、查找、级别筛选和 跟踪;搜索 标签页会在服务器上对所有选中的日志按起止时间范围进行 grep,日期格式采用欧盟格式,并按时间线排序结果。日志设置 现已与 Zabbix 分开。文件管理器的编辑器支持语法高亮、查找和替换、在保存前查看更改,并会在服务器上的文件发生变化时发出警告;它还有一个 AI 助手,可在获得你的批准后检查并编辑当前打开的文件。日志查看器提供 AI 日志助手(search_logs)。AI 工作日志会显示助手的思考过程和每个步骤;聊天会显示简短标题和日期、时间,已结束的聊天也可以继续。请参阅日志:查看器、搜索和日志设置、文本编辑器和AI 助手。

v13.0.0 至 v13.4.4(日志引擎、插件、屏幕锁定、OpenCode Go、Claude 快速入门、Claude Desktop 和 Claude Code 设置)的说明请见更新日志。

v12.9.1 有哪些新内容

Medium 无需原始工具即可运行。 WRM 引擎现已成为未选择引擎的项目的默认引擎,其卡片会优先显示在 Medium 页面上;原始部署工具及其 Docker 运行时则折叠为可选项。已升级且正在使用原始工具的安装会继续将其设为默认引擎,直到管理员将 Medium: default engine 切换为 native。部署配置编辑器现在可以从其 Git 仓库拉取配置、显示本地更改,并通过 WRM Git 源 提交并推送,但会先检查整个配置能否加载。WRM 主机上的构建可使用非特权账户(medium_build_user)并在干净的环境中运行。

v12.9.0 有哪些新内容

Medium 会显示每个文件的更改内容,并允许编辑 deploy-config。 在 WRM 引擎的计划中,详细信息会逐行对比服务器版本的已更改文件与分支版本。仅 CRLF/LF 不同的文件会标记为仅换行符不同,并单独计数,与原始工具的行为一致。编辑 deploy-config 可在 WRM 中编辑 servers.yaml、environments.yaml 和项目文件:只有整个配置仍能成功加载时,文件才会保存;注释、布局和换行符都会保持原样。

v12.8.1 有哪些新内容

安全更新,无需更改数据库。 构建工具链现已使用 Go 1.27.3,修复了 GO-2026-6809 / CVE-2026-111943:crypto/x509 现在会拒绝已知的受损中间证书,即使较旧的系统信任存储中仍可能包含这些证书。我们已审查并接受 OpenCode Docker 沙箱中的 gosec G702 检测结果,判定其为误报:Docker 路径由操作员配置,容器名称由 WRM 生成,二者都作为单独参数传入,不经过 shell。有关这两项检测结果的来源,请参阅发行说明。

v12.8.0 新增内容

文件夹现在可像真正的远程管理器一样工作。 删除文件夹时,一步即可移除其子文件夹和其中的所有连接,无需先将内容移到根目录。可以通过上下文菜单移动文件夹和连接,也可以拖动;还可以一次移动多个选中的连接,并且新位置会被保存。共享树和协作树会保留嵌套的文件夹结构;连接名称按不区分大小写的方式排序,而文件夹则保留手动排序。

报告的每项细节都已完善。 设置窗口会以与管理窗口相同的尺寸打开,宽标签栏带有滚动箭头。终端窗口的标题栏中有 编辑 和 隧道 按钮。文件管理器可以更改权限(包括递归更改,并可选用 sudo 密码),传输目标位置也可以新建文件夹。上传任务运行期间可以继续排队其他上传。隧道可按端口、描述或主机筛选,并可切换为仅显示活动隧道;可从 工具 和隧道面板访问代理设置。保存按钮会显示进度并阻止重复点击;在文件夹中点击 + 连接 时,会自动填入该文件夹及其默认值。

v12.7.4 新增内容

无需手动准备 guacd,RDP 即可在 Windows 上运行。 如果 guacd 无响应且其地址为本地地址(127.0.0.1:4822),WRM 会在 Docker Desktop 中启动官方 guacamole/guacd:1.5.5 容器,仅在回环地址上发布,并通过 Docker 使其持续运行(wrm-guacd、unless-stopped)。首次建立 RDP/VNC/Telnet 连接时可以启动它;之后由 WRM 启动。管理 → 概览 会显示状态并提供 启动 guacd 按钮,命令行中的 -setup-guacd 也有相同作用;如果缺少或已停止 Docker Desktop,桌面窗口会说明情况。不会触碰其他机器上的自定义 guacd。Linux 仍使用系统 guacd 或 docker-compose.yml 服务。

所有文本文件都能保留格式预览。 预览现在会根据文件内容检测文本,因此 Shell/Python 脚本、XML/SMIL、JSON、YAML、配置文件和无扩展名文件都会以文本形式打开,而不会被拒绝。内置的离线 PrismJS 高亮器会为其支持的格式着色;二进制文件仍会明确提示需要下载。256 KiB 的预览上限和转义文本安全策略保持不变。

v12.7.3 新增内容

Medium 构建,任你选择。 有构建步骤的项目现在可以使用 WRM 原生引擎部署。每个项目都可以选择构建运行的位置:WRM 主机、通过 SSH 连接的指定 Linux 构建服务器,或完全不构建。执行前,计划会显示构建位置及其平台和架构;如果目标位置的平台或架构不同,系统会拒绝执行并说明原因。构建服务器只会收到准备好的源代码,且存放在临时目录中(不包含 Git 元数据和 SSH 密钥);完成后会删除该目录。

监控 → 日志可查找所有服务。 现在会在 /home/<operator>/<operator>/<service>/log 和 /logs 下查找服务日志,并显示正确的服务和操作员标签。列表会显示未压缩的服务日志,包括 FTP .txt 文件;虚拟环境、构建/归档目录和旧备份则会被跳过。查找和列表显示的时间预算有所增加,因此大型主机不再会显示不完整的结果。

v12.7.2 的新功能

版本号从代码中读取。 Git 工作区不再依赖 VERSION.md 来判断已部署的版本,而是将服务器上的每个受跟踪文件与目标版本及更早标签对应的仓库树进行比较:如果所有文件都匹配同一版本,就显示该版本;如果文件一致地匹配较早版本,就准确显示其提交树对应的版本;如果文件版本混杂或经过手动编辑,就显示 混合 / 已修改,并列出每个文件的详细信息。立即检查旁边新增了一个复选框(默认关闭),启用后还会检查 VERSION.md,并在其内容不一致时发出警告。请参阅 Git 工作区:逐个文件检查与部分检查。

v12.7.1 的新功能

Medium:按环境设置服务列表。 environments.yaml 现在接受原始部署工具的 servers: [name, ...] 键,因此可以限制某个环境可使用的服务。该环境中的项目目标不能部署到其他服务;如果列表未知、重复或为空,系统会拒绝配置,并指出对应的文件和键。没有此键的现有配置仍可使用所有服务。请参阅 Medium 原生引擎。

v12.7.0 的新功能

Medium 原生部署。 将 Medium 项目切换到 WRM 原生引擎后,WRM 会自行部署项目:通过已保存的 WRM 连接,将项目从 WRM Git 源部署到环境中的每个服务,无需 Docker,也无需原始工具。每个服务都会获得一个锁,并对所有更改内容进行备份、对每个上传文件进行 SHA-256 校验、运行 post_deploy,并添加历史记录;所有格式均与原始工具一致,因此两个引擎可以轮流在同一组服务上部署,也可以回滚对方的部署。试运行会在锁定后再次进行比较,但不会更改任何内容;可以在部署中排除更改;历史记录和回滚可显示各项操作的运行位置、回滚最近一次部署,并释放他人遗留的锁。v12.7.3 为带有构建步骤的项目新增了原生构建功能。请参阅 Medium 原生引擎。

v12.6.26 的新功能

SIEM 导出、安全警报与锁定模式。 WRM 会将每条审计记录发送到你的 SIEM:支持通过 TLS 传输 syslog(RFC 5424)、JSON Lines 文件、Splunk HEC、Elastic、Microsoft Sentinel 或任意 HTTPS 收集器,并包含用户、角色、目录身份、源地址和审计哈希链;服务中断后还会补发记录。管理员可以查看每个目标是否正在接收数据以及有哪些记录等待发送。安全警报会通知管理员多次登录失败、紧急访问登录、新增管理员、机密信息被查看、AI 完全访问权限获批,以及审计功能被关闭等情况。停止用户可以一键结束某个账户开启的所有内容;锁定模式则会将紧急访问管理员以外的所有人拒之门外、关闭 AI 并暂停共享,可通过界面、wrm -lockdown 或 WRM_LOCKDOWN=1 启用。请参阅 SIEM 导出、警报与锁定模式。

v12.6.25 的新功能

Active Directory、LDAP 和 SCIM。 用户可以在常规登录页面使用 Active Directory 或 LDAP 用户名和密码登录;WRM 通过 LDAPS 或 StartTLS 向目录验证密码,且不会存储密码。规则可将目录组(包括嵌套的 AD 组)映射为 WRM 角色和团队;WRM 还会定期检查每个已关联账户:如果某人被删除、停用、锁定或移出 WRM 组,其访问权限会立即被撤销。SCIM 2.0 支持 Microsoft Entra ID 或 Okta 即时创建、更改和停用 WRM 账户及组。无论通过哪种方式停用账户,WRM 都会结束该账户的会话、终端、隧道、房间、AI 会话和 AI 连接。请参阅 LDAP / Active Directory 和 SCIM。

v12.6.24 中的新功能

使用组织账号登录。 WRM 现在支持通过 Microsoft Entra ID、ADFS、Okta、Keycloak、Google Workspace 或任何 OpenID Connect 提供商登录(使用带 PKCE 的授权码)。在 管理面板 → 目录登录 中添加提供商,逐步测试连接,并编写规则:Entra 应用角色或组 ID会分配 WRM 角色和团队。只有符合规则的人员才会在首次登录时创建账号;其他人都会被拒绝,并看到说明原因的消息。系统通过不可变的目录 ID 识别用户,而非姓名,因此更名或重复使用的姓名无法接管账号。提供商可以要求 令牌证明用户已通过 MFA。WRM 会定期向提供商核实每位已登录用户是否仍有权限登录:账号被禁用或从 WRM 组中移除后,其会话和终端都会失效。密码登录可以限制为仅供紧急访问管理员使用(启用目录登录后,Enterprise 级别要求必须这样设置)。测试登录会显示提供商发送的内容以及 WRM 将采取的操作,但不会创建任何内容。请参阅目录登录(OIDC)。

v12.6.23 中的新功能

角色、团队,以及对风险操作的二次确认。 每个账号现在都有一个角色:管理员、安全审计员(可查看审计日志、终端会话、录制内容、文件传输和安全态势,但不能更改任何内容)、操作员或用户。管理员可在 管理面板 → 团队 中创建团队;共享可以包含整个团队并为其分配一个角色;用于指定谁可以使用某项功能的策略,除了 off / admins / all,现在还接受 operators 和 teams:<names>。启用二次验证后(Business 级别及以上必须启用),更改策略、角色或安全级别,删除或禁用用户,重置密码或 2FA,以及显示已存储的机密信息时,都需要重新输入密码(和 2FA 验证码)。紧急访问管理员账号必须使用 2FA,可限制其仅能从指定网络登录,且每次登录都会记入审计日志并通知其他管理员。删除用户时,其连接、文件夹、凭据、密钥、共享和代理可以转交给团队负责人或其他账号,而不是被删除。请参阅角色、团队、二次验证和紧急访问。

v12.6.22 中的新功能

安全级别:Home、Business、Enterprise。 可在首次运行屏幕上、安装时(通过 -security-level、WRM_INITIAL_SECURITY_LEVEL 设置,并可用 WRM_SECURITY_LEVEL 强制指定)或之后在管理面板 → 安全中选择 WRM 的安全严格程度。每个级别都会设定 HTTPS、双因素身份验证、密码、会话、注册、主机密钥、机密信息导出、访客链接、AI 完全访问、审计和会话录制的最低要求。切换前,预览会显示所有变更、阻止切换的原因及受影响的人员;低于该级别要求的设置属于例外项,必须填写理由并留档、接受审计。安全态势页面会逐项评估安装情况并提供确切的修复方法,还可导出供审计员使用的报告(JSON 或 PDF)。请参阅安全级别和安全态势。

v12.6.21 中的新功能

已签名的发行版。 从现在起,每个发行版都附带其 SHA256SUMS.txt 的 ed25519 签名、软件物料清单(CycloneDX)和 GitHub 构建来源证明。项目的公钥内置后,一键更新会拒绝签名缺失或错误的发行版,因此无法安装发行页面上被篡改的文件。wrm -release-verify SHA256SUMS.txt 可手动验证下载内容。每晚都会运行模糊测试,向导入解析器(mRemoteNG、SSH config、CSV/XLSX、PuTTY、WinSCP、配置文件、deploy-config YAML)输入随机数据;同时,OWASP ZAP 会扫描正在运行的 WRM,分别以未登录用户和管理员身份进行测试。模糊测试已经发现并修复了 PuTTY 导入中的一个崩溃问题。

v12.6.20 有哪些新内容

每次变更都会进行安全检查。 WRM 现已使用受支持的 Go 版本(1.27)和最新的库构建,每次推送和拉取请求都会运行自动安全检查:检查 Go 和 WRM 所用库中的已知漏洞(govulncheck)、针对服务器和 Web UI 的 GitHub CodeQL、gosec 和 staticcheck、机密扫描(gitleaks)、构建工作流本身的检查、依赖项审查、Docker 镜像漏洞扫描,以及 OpenSSF Scorecard。Dependabot 每周都会提出库更新建议,Claude 也可以审查拉取请求中的安全问题。Medium 代理使用 Go 更安全的 Rewrite 钩子。用户无需进行任何更改;请参阅持续安全检查和安全路线图(签名发布、家庭版、商业版和企业版的安全级别、角色与团队、使用 Microsoft Entra ID / AD、LDAP 和 SCIM 登录、SIEM 导出)。

v12.6.11 有哪些新内容

在 WRM 中使用 OpenCode。 添加 OpenCode Zen 提供商,无需账户即可在 AI 助手中使用 OpenCode 的免费模型,也可以粘贴 OpenCode 账户的 Zen 密钥来使用其所有模型。Go 订阅有自己的 OpenCode Go 提供商,因此 Go 密钥会发送到 Go 的端点,而不是 Zen。选择 OpenCode agent 作为助手的引擎(Agent 会构建和规划):管理员只需点击一次,WRM 就会下载 OpenCode 本身(并校验 sha512),然后在 WRM 主机上运行;其自带的 shell、文件和 Web 工具均已关闭,因此只能通过 WRM 在你的服务器上使用,每条命令仍需等待你的批准。助手还可以将文本任务交给辅助模型,并根据任务类型自动选择(优先选择免费模型);每个模型都会标注其处理数据的方式。可能会使用提示词进行训练的模型默认处于关闭状态,需由你手动启用。请参阅 OpenCode Zen、Go、Agent 和辅助模型。

v12.6.10 有哪些新内容

一个画布,随心排布。 窗口区域现在是一个画布:终端、文件管理器、桌面、Workboard 插件和面板都可以放在其中。插件是可移动、可调整大小、可贴靠、可固定或可停靠的窗口;面板可以放在画布的任意位置,而不仅限于边缘。▤ Workboard 菜单可添加插件,并提供画布工具:网格、平铺和层叠、锁定、已保存的布局(可选包含终端),以及导出 / 导入。新增插件:链接、已保存的会话和计时器。顶部栏更加简洁:广播位于 🧰 工具中,共享改为图标,设置 · 面板 · Workboard并排显示。已关闭终端的横幅上有一个 ✕ 关闭窗口按钮。请参阅 Workboard:共享画布和插件。

v12.6.9 有哪些新内容

Workboard:一眼掌握重要信息。 点击顶部栏中的 ▤ Workboard,即可打开由你从插件目录中自行组合的磁贴页面;在添加之前,页面不会显示任何内容。可添加服务器状态、所选服务器的 CPU / RAM / 磁盘条形图(来自 Monitoring,或通过 SSH 读取)、WRM 内部的 WRM 通知、各时区时钟、Git 服务的最新提交、运行中的隧道、快速连接按钮和便笺。任何磁贴都可以拖出成为面板,并像其他面板一样停靠、堆叠或浮动。请参阅 Workboard 和插件。

v12.6.8 有哪些新内容

面板放在你想要的位置。 连接、会话、片段、剪贴板和 AI 实时视图都是带有可拖动标签的面板:拖到另一个面板的标签栏上,可将其堆叠为标签页;拖到面板的上半部或下半部,可拆分列;拖到边缘条上,可将其停靠在左侧、右侧或窗口下方;拖到其他位置,则可使其浮动。顶部栏中的面板(▦)可显示和隐藏面板,锁定布局可将所有内容固定在原位。布局会存储在服务器上的账户中,因此你在任何浏览器中都能使用相同布局。请参阅面板布局。

v12.6.7 版本更新

适配各种宽度的顶部栏,以及可停靠的 AI 面板。 顶部栏现在在任意宽度和浏览器缩放比例下都能完整显示:先隐藏标签,再将不常用的按钮移入 ⋯ 菜单,不会再出现重叠。AI 实时视图(显示 AI 应用在你的服务器上运行的内容,包括审批和输出)不再遮挡窗口:你可以将它设为 Sessions 和 Snippets 旁边的 🤖 AI 标签页、窗口下方的停靠面板、浮动窗口,或将其隐藏;通过标题栏按钮或将其拖至边缘即可选择,并且会按用户记住设置。审批卡片仍会始终弹出。请参阅 AI 桌面应用(MCP)。页面上的所有文本现在都可以再次选中和复制;Medium 的 Docker 运行时会信任你计算机上的证书,因此可在代理和会检查 HTTPS 的杀毒软件环境下工作(请参阅 Medium 的 Docker(由 WRM 安装))。

v12.6.6 版本更新

随处可用的 Docker,由 WRM 安装。 原始部署工具现在可在 Linux、macOS 和 Windows 上的 WRM 托管 Docker 运行时中运行;如果缺少 Docker,WRM 也会自行安装:管理员只需在 Medium 第 2 步中按一次 Install Docker(在 Windows 和 macOS 上接受 Docker Desktop 许可协议),WRM 就会从 Linux 发行版的软件包安装 Docker Engine,或从 docker.com 安装 Docker Desktop(并检查签名),然后启动并等待 Docker 就绪,再准备运行时。每一步的输出都会显示在活动日志中。之后,导入工具 ZIP 就会自动完成所有这些操作。如果 WRM 没有管理员权限,它会显示需要运行的一条命令:sudo wrm -setup-docker。请参阅 Medium 的 Docker(由 WRM 安装)。

v12.6.5 版本更新

Medium 会告诉你它正在做什么。 Medium 视图现在为原始部署工具提供编号的逐步指南(1 导入工具 ZIP,2 准备运行时,3 设置你的 deploy-config,4 设置你的 SSH 配置文件,5 启动/停止);每一步都会说明等待什么,以及失败时该怎么做。运行期间,你可以看到运行的内容、启动者、运行时长,以及每一步及其耗时,并查看 Docker、pip 和原始工具的输出(已隐藏机密信息)。WRM 会立即检查 deploy-config ZIP,并在运行时仍在准备期间保存它以供下次启动使用,因此你不必再等待上传。新增的活动日志会列出每项 Medium 操作及其结果、耗时、步骤和输出;WRM 的控制台也会记录每一步。只读的 WRM 预览位于单独的面板中,并有清晰标注。请参阅 Medium 分步状态和活动日志。

v12.6.4 版本更新

被阻止的命令,由你决定。 开启完全访问权限后,管理员现在可以决定自己的被阻止命令列表(ai_blocked_commands)是否像其他命令一样需要审批(默认设置),或是在完全访问权限开启时仍保持阻止(ai_full_access_blocked,管理面板 → AI 连接)。请参阅 AI 桌面应用(MCP)。

v12.6.3 版本更新

一个开关,即可启用完全访问权限。 管理员现在可以选择完全访问权限的适用方式(ai_full_access_mode):默认情况下,只需打开 Full access for the AI 开关,即可为所有 AI 会话启用完全访问权限;也可以将其限制为具有 ⚠ Full access 范围的 AI 连接,或仅适用于在 设置 → AI 连接 中自行开启此功能的用户。对于 WRM 原本会拒绝的操作,Claude 仍会先询问。请参阅 AI 桌面应用(MCP)。

v12.6.2 版本更新

启用完全访问权限,但 Claude 仍会询问。 管理员允许后(ai_full_access),AI 连接可以获得 ⚠ Full access 范围。此时 WRM 不会直接拒绝任何操作:破坏性命令、被阻止的命令、拒绝列表、关机操作和机密文件都会以标记为 FULL ACCESS 的审批请求发送给你,每次都需要审批,绝不会自动执行。只读连接仍保持只读。请参阅 AI 桌面应用(MCP)。

v12.6.1 新增内容

“全部允许”现在意味着真正的全部允许。 在 AI 连接的自动模式下,全部允许会为命令填入 *,为文件填入 /**;不限制时间或操作次数则会让连接在有效期内始终保持自动模式。允许 * 后,包含 &&、变量和重定向的命令链不会再因等待批准而中断;被阻止的命令、你的拒绝列表和敏感文件仍然会受到限制。如果 WRM 发出询问后无人及时答复(或应用拒绝了询问),请求会留在 WRM 中,供你稍后批准;你批准后,AI 会重新执行该请求。可能包含机密的文件会在你批准后读取,并对机密内容进行脱敏。参见 AI 桌面应用(MCP)。

v12.6.0 新增内容

Medium 原生引擎,迈出第一步。 Medium 视图中新增了只读的 原生引擎 面板:WRM 会按原样读取你的 deploy-config,将其中的服务与已保存的 WRM 连接进行匹配,从 WRM Git 源准备所选分支或标签,并显示部署会对各服务造成哪些更改,全程无需 Docker,也不会写入任何内容。与原始工具比较会在旁边运行原始比较,并显示两者结果是否一致。原生部署和回滚功能随后在 v12.7.0 中推出。参见 Medium 原生引擎。

v12.5.1 新增内容

一步完成 Claude Desktop 和 Claude Code 的配置。 Settings → AI connections → Claude Desktop 现在会下载一款WRM PRO 扩展(wrm-pro.mcpb),其中已填入你的 WRM 地址和令牌:打开扩展,点击安装即可。它可通过你自己的网络连接 WRM,也支持普通 HTTP,因为 Claude Desktop 是从你的电脑与 WRM 通信(claude.ai 自定义连接器则从 Anthropic 的云端连接,因此需要公开的 HTTPS 地址)。Claude Code 也提供了 WRM PRO 插件:claude plugin install wrm-pro --marketplace vedranius/web-browser-RDM-public --config wrm_url=… --config wrm_token=…。令牌有效期以小时或天为单位输入,默认值为 7 天(最长 30 天),因此你不必每天都重新批准。在 AI 应用处理服务器任务时,WRM 中的实时面板会显示每条命令、批准按钮和输出;拒绝后,AI 会询问你接下来该怎么做。参见 AI 桌面应用(MCP)。

v12.5.0 新增内容

按实际情况盖章:盖章对话框会显示哪些文件存在差异,以及安装无法盖章的原因。勾选同时为未保持最新状态的安装盖章,即可写入 VERSION.md,其中会记录每个文件的实际版本,并注明该安装并不完整。

对话框也能返回:从另一个对话框打开的对话框(例如“详情 → 更新 → 确认”)现在提供← 返回(Alt+←),并会保留你勾选或输入的内容。对 v12.4.x 功能进行代码审查时,修复了生产环境确认、Medium 启动/停止/设置和导入、包含非 UTF-8 字节及特殊字符的日志搜索,以及客户端 GitLab 缓存问题。后续版本将使用 WRM 自身的引擎运行 Medium,而不依赖 Docker(路线图)。

v12.4.5 新增内容

**Medium:**选择可信的工具/配置 ZIP 文件,然后点击 Prepare and run。WRM 会保留导入内容、启动 Docker、准备原始依赖项、验证配置、同步私有配置文件,并打开未经修改的原始工具。首次在 Windows 上设置时,可以调用官方签名 Docker 安装程序;操作系统/供应商提示和所需重启仍会显示。现有自定义配置 Git 设置会被明确上传的本地配置 ZIP 替换。

**Monitoring → Logs:**自动开始发现,并按服务流式显示结果。服务日志文件夹和 Supervisor 路径会补充手动指定的根目录。可按服务/操作员/服务和事件时间筛选,然后在所有匹配文件中从头搜索关键词。结果会显示文件修改时间、匹配事件范围、高亮摘录,以及打开/跟踪操作。进度、权限错误和部分搜索结果仍会显示;必要时可继续执行有界扫描。主机指标、服务检查和 SSH 日志各自有不同的设置要求。

Overview/Installations 在滚动时会将筛选器、检查控件和操作保持在一起。Environments 新增组合搜索/服务/环境/服务筛选器。

操作与限制 · 验证。

v12.4.4 新增内容

监控新增 Zabbix 指标/历史记录和服务 Functionality、多窗口日志、客户端 GitLab 令牌访问及持久快照、更轻松的 MCP 设置和可编辑授权、结构化配置清单、终端选择内容发送给 AI/在此打开终端、可视化文件夹/连接标签、更长的提供商超时、固定筛选器,以及回放/导入修复。

操作与限制 · 发布验证 · 原始 Medium 工具对等情况。常规配置导入现已支持识别 mRemoteNG XML 和 PuTTY 注册表文件(#5)。

📜 许可证:可免费用于个人用途及公司工作工具

WRM 提供源代码。您可以根据 PolyForm Noncommercial License 1.0.0 或 PolyForm Internal Use License 1.0.0 使用,以适合您的许可证为准。

✅ 个人及非商业用途免费个人用途、家庭实验室、学习、业余项目、非营利组织、学校和大学、公共研究、政府。您可以使用、分叉、修改和分享,包括修改后的版本。请保留 LICENSE 及其中的 Required Notice: 行。
✅ 公司可免费用作工作工具任何规模的公司都可以在自己的服务器上运行 WRM 并将其用于工作,包括为客户提供有偿工作(例如管理客户的服务器),也可以为内部用途修改 WRM。
💼 需要商业许可证将 WRM 作为托管服务/SaaS 提供给他人、向任何人收取访问或使用 WRM 的费用、转售、出租或贴牌、将其捆绑到产品或设备中,或在您向他人提供的产品中使用其代码。请先联系所有者。参见 COMMERCIAL-LICENSE.md。
🤝 欢迎贡献欢迎提交创意、错误报告、翻译和拉取请求。参见 CONTRIBUTING.md。

版权所有 © 2026 vedranius。第三方库保留其各自的许可证。

☕ 支持项目

WRM 是我利用业余时间开发的。如果它为您节省了时间,欢迎请我喝杯咖啡:

在 Ko-fi 上支持我

**https://ko-fi.com/vedranius**。谢谢!❤️


目录

  1. WRM 是什么
  2. 快速开始
  3. 从 v13.12.0 升级 · 从 v13.11.0 升级 · 从 v13.10.0 升级 · 从 v13.9.0 升级 · 从 v13.8.0 升级 · 从 v13.7.0 升级 · 从 v13.6.0 升级 · 从 v13.5.0 升级 · 从 v13.4.4 升级 · 从 v12.9.0 升级 · 从 v12.8.1 升级 · 从 v12.7.1 升级 · 从 v12.7.0 升级 · 从 v12.6.26 升级 · 从 v12.6.25 升级 · 从 v12.6.24 升级 · 从 v12.6.23 升级 · 从 v12.6.22 升级 · 从 v12.6.21 升级 · 从 v12.6.20 升级 · 从 v12.6.19 升级 · 从 v12.6.11 升级 · 从 v12.6.10 升级 · 从 v12.6.9 升级 · 从 v12.6.8 升级 · 从 v12.6.7 升级 · 从 v12.6.6 升级 · 从 v12.6.5 升级 · 从 v12.6.4 升级 · 从 v12.6.3 升级 · 从 v12.6.2 升级 · 从 v12.6.1 升级 · 从 v12.6.0 升级 · 从 v12.5.1 升级 · 从 v12.5.0 升级 · 从 v12.4.5 升级 · 从 v12.4.4 升级 · 从 v12.4.3b 升级 · 从 v12.4.3 升级 · 从 v12.4.0 升级 · 从 v12.3.6 升级 · 从 v12.2.8 升级 · 从 v12.2.7 升级 · 从 v12.2.6 升级 · 从 v12.2.5 升级 · 从 v12.2.4 升级 · 从 v12.2.3 升级 · 从 v12.2.2 升级 · 从 v12.2.1 升级 · 从 v12.2.0 升级 · 从 v12.1.0 升级 · 从 v12.0.0 升级 · 从 v11.7.0 升级 · 从 v11.6.1 升级 · 从 v11.6.0 升级 · 从 v11.5.0 升级 · 从 v11.4.1 升级 · 从 v11.4.0 升级 · 从 v11.3.0 升级 · 从 v11.2.0 升级 · 从 v11.1.0 升级 · 从 v11.0.0 升级 · 从 v10.10.0 升级 · 从 v10.9.1 升级 · 从 v10.9.0 升级 · 从 v10.8.1 升级 · 从 v10.8.0 升级 · 从 v10.7 升级 · 从 v10.6 升级 · 从 v10.5 升级 · 从 v10.4 升级 · 从 v10.3 升级 · 从 v10.2 升级 · 从 v10.1 升级 · 从 v10.0 升级 · 从 v9 升级
  4. 工作原理
  5. 功能详解
  6. 键盘快捷键
  7. 配置
  8. Docker、服务、反向代理与防火墙
  9. 安全模型
  10. 限制
  11. API 参考
  12. 从源代码构建与发布
  13. 故障排除
  14. 参与贡献

WRM 是什么

WRM 是一个单一可执行文件,内置 Web 服务器和 Web 应用。你可以在任何设备上启动它:PC、Raspberry Pi、VPS 或公司服务器。然后在浏览器中打开它,并从那里管理你的远程服务:

  • 浏览器中的 SSH 终端(xterm.js、256 色、nano、vim、htop、mc 等全屏应用),支持 命令片段(带变量的已保存命令,可单击运行或按 Ctrl+Shift+Space)、连接时运行(sudo -i、cd /srv/app……)和 广播输入(同时向多个终端输入,并对危险命令进行安全检查)。
  • 侧边栏中显示每个已保存连接的 实时在线/离线状态,并提供延迟、服务端标语,以及服务器宕机通知。
  • 快速连接 — 输入 [email protected]:22(或 rdp://…、vnc://…)即可连接,无需保存;每个连接都可添加 备注和运行手册(操作流程、联系人、链接);网络工具 — 从 WRM 服务或 任意一台服务器检查端口、执行 ping、traceroute、DNS 和 HTTP/TLS 检查(“app-01 能连接到 5432 端口的数据库吗?”)。
  • 带外管理 — 通过服务器的 BMC(iDRAC、iLO、XClarity、Supermicro、OpenBMC,使用 Redfish 或 IPMI)开机、关机、重启,并查看健康状况和资产清单;在终端窗口中打开其 串行控制台(BMC SSH 或 IPMI Serial-over-LAN);通过 WRM 机器的 串行端口连接交换机和路由器控制台。
  • 远程桌面 — 在浏览器窗口中使用 RDP(Windows)、VNC 和 Telnet,也支持通过跳板主机连接;提供剪贴板、Ctrl+Alt+Del、录制和回放功能(通过 Apache Guacamole 代理 guacd)。
  • SFTP(通过 SSH)、FTP 和 FTPS 的文件管理器:浏览、上传、下载、重命名、删除、编辑和搜索。
  • SSH 密钥和凭据库:生成 SSH 密钥,一次将密钥部署到多台服务器(类似 ssh-copy-id),查看谁有权访问服务器;多个连接可共用一个登录账号,例如 root@dc1,与同事共享而不泄露凭据,并在其所有服务器上轮换密码。
  • 跳板主机(类似 ssh -J):访问堡垒机后面的服务器,也支持链式跳转,适用于终端、文件、传输和隧道。代理(SOCKS5/4、HTTP CONNECT)可像在 PuTTY 中一样设为连接选项,也可与跳板主机组合使用;还可为文件夹内的所有连接设置跳板主机和代理的文件夹默认值。
  • 书签(类似 WinSCP),用于快速访问深层目录:可按服务器、文件夹或标签设置,也可全局设置;支持 {name} 等变量 — 单击即可在文件管理器中打开目录,或在终端中执行 cd 进入该目录。
  • 当服务器宕机或恢复、密码到期需轮换或有新服务版本可用时发送通知:通过 WRM、浏览器、电子邮件、Telegram、Slack / Mattermost、Microsoft Teams、Discord、ntfy、Gotify、Pushover 或签名 Webhook 通知。
  • SSH 隧道(类似 ssh -L / -R / -D、PuTTY、mRemoteNG):访问交换机、iDRAC/iLO 或服务器后面的数据库的 Web 界面;通过 SOCKS 代理接入整个管理网络。通过 Web 界面连接,双击即可打开此类页面。
  • 从 CSV / Excel 文件和 NetBox 导入服务器资产清单(支持环境、站点和机架标签及同步);从 mRemoteNG(包括密码、文件夹和 SSH 隧道)、PuTTY(包括代理)和 OpenSSH ~/.ssh/config 导入连接。使用标签筛选侧边栏,并标记生产服务器。
  • Git 工作区:查看各项服务的不同版本分别运行在哪些位置 — 将服务器上的安装逐文件与 GitLab / GitHub 或离线包进行比较,通过差异和通知查看哪些内容已过时、缺失或被手动更改 — 并通过 SSH 更新、升级或回滚这些服务(包括备份、原子写入、检查、自动回滚、可选重启和维护时段);将服务部署到按顺序排列的服务器环境,使用经过审核的一次性计划、试运行、服务端锁、历史记录和逐次部署回滚;或在新服务器上安装服务,并在服务器之间传输服务及其按主机配置;还提供 .gitignore 辅助工具和可选的 CI 集成(GitLab / GitHub / Jenkins Webhook、来自 CI 构建产物的包、通过流水线部署)。
  • **AI 桌面应用(MCP):**将 Claude(桌面版或 claude.ai)、ChatGPT 或其他 MCP 客户端连接到 WRM — 可通过 OAuth、个人访问令牌,或 WRM 二进制文件中的轻量 stdio 桥接程序连接。应用将根据你选择的模式和范围,在限时内访问服务器;每次调用都经过相同的权限引擎,所有更改都需等待你批准(在 WRM 或应用中批准);AI 已连接指示器会显示会话状态,单击即可撤销访问。
  • 与终端和文件管理器并排的 AI 助手:询问服务器相关问题,助手便会通过 WRM 自带的工具读取日志、服务、软件包和文件。可选择 只读、每次更改前询问(显示确切命令或差异,由你批准、编辑或拒绝),或 在限制范围内自动操作(使用你选择启用的允许列表、时间和操作次数限制)。始终拒绝破坏性命令;管理员可决定每个连接、文件夹或标签允许使用哪些模式、提供商和模型,并审计和记录每项请求、工具调用和批准操作。支持 Anthropic API、OpenAI、Azure OpenAI、AWS Bedrock、Google Vertex AI 和兼容 OpenAI 的本地模型,可使用组织的密钥或你自己的密钥。
  • 在两台 SSH 服务器之间进行服务器到服务器的复制,无需先下载到你的计算机。
  • 工作区:并排打开多个终端和文件窗口,使用标签页、窗口吸附功能和已保存的会话。可在桌面、平板电脑和手机上安装为应用(PWA)。
  • 按角色共享:授予同事或访客对部分连接的访问权限,可设为观察者、查看者、操作员或版主,且始终不会泄露密码。
  • 实时协作:带历史记录的聊天、文件交换、语音通话(类似 Discord/Jitsi)、带快照的终端共享、经请求后远程控制键盘、举手和管理功能。
  • 企业级安全性:双重身份验证、关闭注册、由管理员管理账号、密码和会话策略、账号锁定、审计日志(支持 CSV 导出和兼容 SIEM 的日志行)、SSH 主机密钥验证、加密机密信息、CSRF 防护和严格的安全标头。 所有数据都存储在一个本地 SQLite 文件中。无需外部数据库,也不要求使用 Docker;没有 CDN,也不需要云账户:该二进制文件还会提供所有脚本和字体,因此 WRM 可在封闭网络中运行。

支持的平台(预编译二进制文件): Linux(x86-64、arm64、ARMv7/Raspberry Pi、ARMv6、32 位)、Windows(x86-64、arm64)、macOS(Intel、Apple Silicon、Universal)、Android arm64(Termux)、FreeBSD(x86-64、arm64)、OpenBSD(x86-64)。


快速开始

  1. 从 Releases 下载适用于你系统的二进制文件,并可选择验证文件:将 SHA256SUMS.txt 和 SHA256SUMS.txt.sig 放在其旁边,然后运行 wrm-pro-… -release-verify SHA256SUMS.txt(验证签名和 SHA-256),也可以自行比较 SHA-256 值。gh attestation verify <file> --repo vedranius/web-browser-RDM-public 可显示用于构建该文件的工作流和提交。

  2. 运行:

    Linux / macOS / FreeBSD / OpenBSD

    chmod +x wrm-pro-v13.13.0-linux-amd64
    ./wrm-pro-v13.13.0-linux-amd64
    

    在 macOS 上,如果 Gatekeeper 阻止了该文件:xattr -d com.apple.quarantine wrm-pro-*-darwin-*。

    Windows(PowerShell),或直接双击 .exe:

    .\wrm-pro-v13.13.0-windows-amd64.exe
    

    Linux AppImage(x86_64 / ARM64)

    chmod +x wrm-pro-v13.13.0-linux-amd64.AppImage
    ./wrm-pro-v13.13.0-linux-amd64.AppImage
    # On ARM64 use wrm-pro-v13.13.0-linux-arm64.AppImage instead.
    

    打开 **http://localhost:8080**。AppImage 会在终端中运行,默认绑定到 localhost;使用 PORT 或 LISTEN_ADDR 更改此设置。按 Ctrl+C 停止。如果无法使用 FUSE,请使用 --appimage-extract-and-run 运行。

    数据存储在 ${XDG_DATA_HOME:-$HOME/.local/share}/wrm-pro/,或你显式指定的 DB_PATH 中。替换 AppImage 即可升级;数据和加密密钥会保留。若要将其用作启动服务,请使用独立的 Linux 二进制文件并添加 -install-service。

    Android(Termux)

    pkg install wget
    wget https://github.com/vedranius/web-browser-RDM-public/releases/download/v13.13.0/wrm-pro-v13.13.0-android-arm64
    chmod +x wrm-pro-v13.13.0-android-arm64 && ./wrm-pro-v13.13.0-android-arm64
    

    Docker

    git clone https://github.com/vedranius/web-browser-RDM-public.git && cd web-browser-RDM-public
    docker compose up -d          # https://<host>:8080 (self-signed certificate)
    

    详情请参阅 Docker。

  3. 打开 **http://localhost:8080**(或 http://<server-ip>:8080)。若要从其他计算机进行语音通话,请使用 HTTPS——最快的方式是设置 HTTPS_SELF_SIGNED=1(参见配置)。

  4. 创建管理员账户(第一个账户)。之后将关闭自行注册:管理员可在 Admin panel → Users 中创建账户(或在 Security policies 中开放注册)。

  5. 点击 + Connection,输入主机、用户和密码或密钥,然后双击连接以打开它。

首次启动时,WRM 会在数据库旁创建以下文件:

文件用途
remote_manager.dbSQLite 数据库(用户、连接、共享、审计日志)。权限模式为 0600。
remote_manager.db.key用于加密存储的密码、私钥和 2FA 密钥的随机 256 位密钥。权限模式为 0600。请单独备份此文件——没有它就无法解密已存储的机密信息。也可使用 ENCRYPTION_KEY / ENCRYPTION_KEY_FILE 设置自己的密钥。
recordings/终端会话录制文件(YYYY/MM/<id>.cast.gz,权限模式为 0600),在录制第一个会话时创建。位置:WRM_RECORDINGS_DIR。

无法登录?./wrm-pro-… -reset-password admin 会打印一个新的临时密码(添加 -reset-2fa 还会关闭双重身份验证)。


从 v13.12.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库无需更改;先前版本仍可使用该数据库启动。新增端点 POST /api/mcp/setup-all(审计事件为 mcp.setup_script)。WRM PRO Claude 插件 1.2.0 不再使用 wrm_url 和 wrm_token 设置:更新插件后,运行一次 /wrm-pro:wrm(或 /wrm-pro:connect),并在浏览器中批准登录;从安装该插件的脚本中移除 --config。从此版本下载的 Claude Desktop 扩展在令牌被拒绝时仍会继续运行,并提供 wrm_connect。

从 v13.11.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库无需更改;旧版本仍可在该数据库上启动。新增命令行选项 -addon-lint、-addon-lint-json、-addon-new、-addon-id、-addon-dev、-addon-dev-port 和 -addon-dev-private,以及 /api/addons/dev/ 下的新端点。dev、install、drafts、community 和 users 现为保留的 addon ID;已安装的同 ID addon 仍可正常使用,但不能再以该 ID 安装。

从 v13.10.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。增量迁移:新增表 addon_http_grants、addon_secrets 和 addon_http_log;旧版本仍可在该数据库上启动(它会忽略这些表,而且含有 http 块的 addon 无法在旧版本中安装)。新增策略 addon_http(all):控制谁可以使用访问网站的 addon(off、admins、all)。现有 addon 不受影响;只有在 addon 更新中声明 http 并获得新的批准后,才会获得网络访问权限。

从 v13.9.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库无需更改;旧版本仍可在该数据库上启动。连接已删除的 Git 工作区安装不再显示;删除连接时也会删除其安装项。显示已保存的登录信息和复制密码遵循现有的允许导出密码和密钥策略(allow_secret_export,默认开启;管理员始终可以使用),以及增强验证策略。

从 v13.8.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。增量迁移:新增表 addons_personal、addon_instances、addon_store 和 addon_windows,并在 addons 中新增列 files、approved 和 pending;旧版本仍可在该数据库上启动(它会忽略个人 addon、实例和已存储的值)。已安装的 addon 仍可正常使用;下次安装时,其文件会通过 SHA-256 固定。新增策略 addon_personal(all):如果用户不得安装自己的 addon,请将其设为 admins 或 off。

从 v13.7.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。增量迁移:在 ai_sessions 中新增列 saved 和一个索引;旧版本仍可在该数据库上启动。新增设置 ai_mcp_later_approval(run:如果 AI 应用停止等待后,用户在 WRM 中批准,则立即执行调用;repeat 保持原有行为,要求 AI 重新发起调用)和 ai_keep_saved_sessions(1)。AI 应用的批准问题中选择拒绝,现在会导致最终拒绝;未作答就关闭问题,仍会将请求保留在 WRM 中。新增端点:GET /api/ai/sessions?view=all、POST /api/ai/sessions/{id}/save、GET /api/ai/sessions/{id}/export,以及 /api/me/ui/{key} 的 ai 键。对于已不再等待的请求作出决定时,会以 decided 返回 409。

从 v13.6.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。增量迁移:在 auth_sessions 中新增列 locked_at 和 lock_failures,在 users 中新增列 lock_pin_hash;旧版本仍可使用该数据库启动。新增设置 screen_lock_mode(server)、screen_lock_max_minutes(0)、screen_lock_pin(1)、screen_lock_max_failures(0)、appearance_default_theme(graphite)和 appearance_custom_css(1);Business 和 Enterprise 安全级别要求 screen_lock_mode=server,且空闲锁定时间最多为 30/15 分钟;Enterprise 会关闭 PIN。**两项行为变更:**浏览器会话锁定后,在解锁前将无法访问 API(如需采用较宽松的行为,请将 screen_lock_mode 设置为 remember 或 browser);插件提供的配色主题不再应用于所有用户:每位用户可在 设置 → 外观 中选择,管理员也可将其设为默认值(appearance_default_theme=addon:<addon>:theme)。v13.7 之前在 设置 → 常规 中选择的强调色会一次性沿用到主题中。

从 v13.5.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。无需迁移:日志设置会在现有的每服务器 JSON 中新增 main_folders(空)和 guess_operators(开启);旧版本会忽略这些设置。位于已配置主文件夹下的日志,其标签会优先从主文件夹获取,而非使用默认模式。

从 v13.4.4 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。增量迁移:新增表 log_settings(按连接配置、加密存储),并在 ai_sessions 中新增列 title、purpose、resumed_from 和 file_path;旧版本仍可使用该数据库启动。在 Zabbix 对话框中配置的日志文件夹和日志单元会读入新的 日志设置,直到你在那里保存设置。新增设置 ai_show_thinking 和 ai_auto_titles(均为 1)。默认以欧盟格式显示日期;可在 设置 → 日期和时间格式 中选择其他格式(按浏览器设置)。

从 v12.9.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库无变更。新增策略:medium_default_engine(native)和 medium_build_user(空)。如果原始部署工具已导入,WRM 会在首次启动时将 medium_default_engine=original 设置一次并记录日志,因此项目会保留其引擎;在 管理 → 策略 中将其设为 native,即可默认使用 WRM 部署。显式选择了引擎的项目会保留该引擎。从 Git 拉取 deploy-config 需要在 Medium 设置中配置 DEPLOY_CONFIG_REPO,并为该仓库配置一个 WRM Git 源(提交和推送时需要写入令牌)。

从 v12.8.1 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库无变更。在 WRM 中编辑 deploy-config 会使用现有的 medium_native 策略(默认值为 admins);没有该策略的用户只能只读查看文件。

从 v12.7.1 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库无变更。Git 检查默认从代码中读取版本;只有启用新的复选框时,才会比较 VERSION.md。部署和更新仍会写入 VERSION.md。升级后的首次检查可能需要刷新目标,以加载较旧的版本树;在此之前会使用单文件历史记录。

从 v12.7.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库无变更。现有 deploy-config 文件仍可正常使用;环境现在可以添加 servers: [name, ...],将其项目限制为指定的服务器。导入配置 ZIP 仍会替换配置目录并删除其 Git 历史记录,因此该目录成为克隆仓库后,请使用 Git 进行更改。

从 v12.6.26 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库会新增表 medium_project_engine;之前的版本仍可在该数据库上启动(切换到原生引擎的项目随后会再次由原工具部署,原工具读取的是相同的服务器状态)。每个项目都会继续使用 Docker 运行时,直到新策略 medium_native(默认为 admins)允许的人员将其切换为 WRM 原生。新增设置 medium_command_timeout(300)和 medium_transfer_timeout(3600)。启用逐步验证后,原生部署、回滚和锁定释放都需要确认(medium.deploy、medium.rollback、medium.lock_release)。

从 v12.6.25 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库会新增表 siem_destinations;之前的版本仍可在该数据库上启动(它不会强制执行锁定,因此返回旧版本前请先结束锁定)。在管理员添加 SIEM 目标之前,不会导出任何内容。新增设置 alert_failed_signins(10)、alert_failed_signins_minutes(10)、alert_break_glass、alert_new_admin、alert_secret_reveal、alert_ai_full_access 和 alert_audit_off(均为开启);新增通知事件 security.alert;新增命令行标志 -lockdown / -lockdown-reason 和环境变量 WRM_LOCKDOWN。即使 audit_enabled 关闭,现在也会记录安全事件(security.*)。

从 v12.6.24 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库会新增表 ldap_directories、ldap_identities、scim_clients、scim_users、scim_groups 和 scim_group_members;之前的版本仍可在该数据库上启动(使用目录密码登录的账户届时将无法登录,因为 WRM 不会为其保留密码)。在管理员添加 LDAP 目录或 SCIM 客户端之前,不会有任何变化。新增设置 ldap_sync_minutes(15)。更改 OIDC 提供方的颁发者时,现在会再次要求输入其客户端密钥。

从 v12.6.23 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库会新增表 oidc_providers 和 user_identities,以及列 users.sso_only、auth_sessions.identity_id 和 team_members.source;之前的版本仍可在该数据库上启动(目录账户届时将无法登录,因为它们没有密码)。在管理员添加身份提供方之前,不会有任何变化。新增设置 local_login(all)、oidc_revalidate_minutes(60)和 oidc_unverified_hours(12)。Enterprise 级别现在要求 local_login = break_glass;此设置仅在启用了目录登录时生效,因此没有目录登录的安装不会导致任何人被锁在外面。从此版本开始,版本合并时会自动签名并发布发行版。

从 v12.6.22 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库会新增表 teams、team_members 和 share_teams,以及列 users.role、users.break_glass 和 auth_sessions.step_up_at;之前的版本仍可在该数据库上启动(它会像之前一样将管理员识别为管理员,并将审计员和操作员识别为普通用户)。现有账户保留其权限:管理员仍为管理员,其他所有人均为 用户。新增设置 require_step_up(关闭;Business 和 Enterprise 级别要求启用此设置,因此这些级别的安装会在安全态势中显示此项,直到将其开启)、step_up_minutes 和 break_glass_ips。启用逐步验证后,调用 PUT /api/admin/settings、更改角色或删除用户的脚本会收到 403 {"step_up": true},除非会话已通过 POST /api/auth/step-up 确认(登录视为一次确认,有效期为 step_up_minutes)。除非指定 ?transfer_to=<user id>,否则 DELETE /api/admin/users/{id} 仍会删除该用户拥有的所有内容。

从 v12.6.21 升级

替换可执行文件、AppImage 或容器,并保留数据库和加密密钥。数据库会新增一张表 security_deviations;旧版本仍可在该数据库上启动。现有安装会保持在 Home 级别,且在管理员于 Admin panel → Security 中选择其他级别(或设置 WRM_INITIAL_SECURITY_LEVEL / WRM_SECURITY_LEVEL)之前,不会更改任何设置。新增设置 security_level、require_https 和 link_share_max_days;新增端点 GET /api/admin/security 和 POST /api/admin/security/level。现在,将策略放宽到所选级别以下时需要填写原因(PUT /api/admin/settings 中的 _deviation_notes);在 Home 级别设置选项的脚本不受影响。

从 v12.6.20 升级

替换可执行文件、AppImage 或容器,并保留数据库和加密密钥。数据库无变化。新增设置 update_signing_keys(为空时仅使用内置密钥)。此版本尚无内置发布密钥,因此自动更新仍只验证 SHA-256,更新对话框会显示 Signature: not checked;加入密钥的版本会启用签名检查。新增命令行选项 -release-keygen、-release-sign、-release-verify。

从 v12.6.19 升级

替换可执行文件、AppImage 或容器,并保留数据库和加密密钥。数据库和设置均无变化。从源代码构建现在需要 Go 1.26 或更高版本(go.mod 指定 Go 1.27.2 工具链;在 GOTOOLCHAIN 允许时,go 会自行下载该工具链)。

从 v12.6.11 升级

替换可执行文件、AppImage 或容器,并保留数据库和加密密钥。数据库无变化。在管理员设置 ai_opencode_sandbox(admins 或 all),并再次点击 Admin panel → AI assistant → OpenCode agents 中的 Download and install 之前,不会有任何变化;该操作会准备 Docker 沙箱。新增设置 ai_opencode_sandbox 和 ai_opencode_sandbox_image;POST /api/ai/sessions 接受 sandbox: true。

从 v12.6.10 升级

替换可执行文件、AppImage 或容器,并保留数据库和加密密钥。数据库会新增一列 users.ai_delegate_training(用于记录用户是否允许使用可能会基于提示词进行训练的辅助模型);旧版本仍可在该数据库上启动。在管理员添加 OpenCode Zen 提供商、启用委派(ai_delegate)或在 Admin panel → AI assistant → OpenCode agents 中安装 OpenCode 之前,不会有任何变化。ai_provider_kinds 现在包含 opencode;如果自行设置该项,请添加 opencode 以允许使用新提供商。新增设置 ai_delegate* 和 ai_opencode*;新增端点 /api/ai/delegate 和 /api/admin/opencode。OpenCode 本身存储在数据库旁边的 <DB>.opencode/ 中。

从 v12.6.9 升级

替换可执行文件、AppImage 或容器,并保留数据库和加密密钥。数据库无变化。Workboard 现在就是画布本身:首次打开时,v12.6.9 中的磁贴会作为附加窗口显示在终端旁边(从右上角打开);拖入面板的磁贴会保留原位。Broadcast 已从顶栏移至 🧰 Tools。/api/me/ui/{key} 现在接受最大 256 KiB 的值。

从 v12.6.8 升级

替换可执行文件、AppImage 或容器,并保留数据库和加密密钥。数据库会新增一张表 user_events(每位用户最新的 200 条应用内通知);旧版本仍可在该数据库上启动,并会忽略这张表。打开 ▤ Workboard 并添加附加组件之前,页面不会有任何变化。新增策略 workboard_ssh_metrics(默认开启):如果 Server load 附加组件不得通过 SSH 登录服务器,请将其关闭;启用了 Monitoring 的服务器仍会显示其数值。新增端点 /api/me/events 和 /api/workboard/metrics。

从 v12.6.7 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库会新增一张表 user_ui(用于保存你的面板布局);旧版本仍可启动,并会忽略这张表。不会迁移任何内容:你的初始布局会根据浏览器在 v12.6.7 中记住的设置构建(右侧面板的标签页和宽度、AI 实时视图的停靠位置,以及它是浮动还是隐藏)。新增端点 /api/me/ui/{key}。

从 v12.6.6 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库或 API 没有变化。AI 实时视图现在会作为 🤖 AI 标签页在右侧面板中打开,而不是显示在左下方的框中;如需恢复旧行为,可在标题栏(或 🤖 菜单)中选择 Floating。Medium 的 Docker 运行时现在会信任 WRM 主机的根证书(策略 medium_host_ca,默认开启);如果运行时准备失败并显示 certificate verify failed,请再次按下 Prepare runtime。

从 v12.6.5 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库没有变化。Medium 现在在 Linux 和 macOS 上也默认使用受管理的 Docker 运行时。如果主机运行时(Python 虚拟环境)已准备就绪,则会继续使用;设置 WRM_MEDIUM_RUNTIME=docker 可切换到 Docker,设置为 native 则可始终使用主机运行时。管理员按下 Medium 第 2 步中的 Install Docker 之前,不会安装任何内容;新的策略 medium_docker_install(默认开启)可关闭该按钮和自动安装。

从 v12.6.4 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库只会新增一张表(medium_activity);旧版本仍可在该数据库上启动。POST /api/git/medium/start 现在会返回 202 并在后台启动(轮询 GET /api/git/medium);在 Medium 忙碌或尚未准备就绪时上传的 deploy-config 或 SSH ZIP 会被保留,并在下次启动时应用(202,pending)。命令输出会显示在运行该命令的用户的 Medium 活动日志中;对于共享运行时,也会显示给所有 Medium 用户;设置 medium_log_output 为 admins 或 none 可限制输出。

从 v12.6.3 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库没有变化。在管理员将 ai_full_access_blocked 设置为 deny 之前,受阻止的命令在完全访问权限下仍会持续询问(Admin panel → AI connections → Blocked commands with full access)。

从 v12.6.2 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库只会新增一列(users.ai_full_access);旧版本仍可在该数据库上启动。如果此前已启用 ai_full_access,现在它会应用于每个 AI 会话(ai_full_access_mode = all,默认值);如需保持 v12.6.2 的行为,可在 Admin panel → AI connections 中将模式设为 AI connections with the Full access scope(connection),或设为 Users who turn it on themselves(user)。

从 v12.6.1 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库没有变化。在管理员启用 ai_full_access(Admin panel → AI connections)之前,完全访问权限会保持关闭;启用后,编辑 AI 连接并勾选 ⚠ Full access。该连接的已打开会话会结束,应用会按照新规则重新打开这些会话。

从 v12.6.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。数据库没有变化。现有 AI 连接会保留其限制。要让应用不受限制地运行,请在 Settings → AI connections 中编辑其 AI 连接,按下 Allow everything(这也会勾选 No time or action limit),确认并保存;已打开的会话会结束,应用会按照新规则重新打开这些会话。管理员可通过关闭 ai_auto_until_grant,禁止不受限制的连接。

从 v12.5.1 升级

替换可执行文件/AppImage/容器,并保留数据库、加密密钥和 Medium 目录。启动时会创建一个附加表(medium_server_links);旧版本二进制仍可基于该数据库启动。原生预览会使用现有的 WRM Git 源和 SSH 连接,且不会向服务器写入任何内容。Medium 部署会继续通过原始工具运行。

从 v12.5.0 升级

替换可执行文件/AppImage/容器,并保留数据库和加密密钥。无需更改数据库。AI 连接(MCP)默认仍处于关闭状态;管理员启用后(管理面板 → AI 连接),Claude Desktop 用户可在 设置 → AI 连接 中选择 Claude Desktop,下载扩展并安装。旧版 claude_desktop_config.json 中的 stdio 桥接配置仍可继续使用。现在可以按小时或天设置令牌有效期。默认值从 8 小时(最多 24 小时)变为 7 天(最多 30 天):ai_mcp_token_hours 为 168,ai_mcp_max_token_hours 为 720。管理员明确保存的值仍会生效;如果策略要求较短的有效期,可在 管理面板 → AI 连接 中重新调低。

从 v12.4.5 升级

替换可执行文件/AppImage/容器,并保留数据库、加密密钥和私有 Medium 目录/卷。无需迁移数据库。现在,Medium 中保存的空设置表示“原始默认值”,不会再传递给工具;被替换的 SSH 配置文件的早期 .previous 副本会在下次启动 Medium 时删除。Stamp 不会再静默拒绝:选择同时为未更新的安装实例盖章,即可按安装实例当前状态盖章。

在 Monitoring 中选择日志和一台服务器。发现过程使用相同的 SSH 帐户,且不使用 sudo;它会查找已知服务的 log/logs 目录、受限的已配置服务根目录以及 Supervisor 日志目录。仍可通过日志工具栏编辑手动设置的根目录。日期/时区筛选和关键字搜索会读取匹配日志中的历史片段,而不只是最近的日志尾部。进度和范围仍会显示。主机指标需要 Zabbix,而 SSH 日志不需要。

Windows 初次设置可能需要接受 Docker/WSL 许可、操作系统权限、虚拟化设置,或在 WRM 主机上重启。Windows 服务无法显示桌面安装程序:请先为该帐户安装一次 Docker,然后继续操作。不会自动切换 Windows 中的 Docker 容器模式,因为其他容器可能正在使用该模式。请参阅指南。

从 v12.4.3b 升级

将可执行文件/容器替换为 v12.4.4,并保留数据库、加密密钥和私有运行时目录/卷。迁移仅会添加内容。现有明确设置的策略值仍会生效;MCP 默认仍处于关闭状态。功能已移至监控 → 功能。请为每台服务器配置 Agent 传输方式/日志根目录;自动指标轮询需选择启用。

客户端 GitLab 缓存需要客户端令牌和浏览器 CORS 权限,或者需要安装在可访问 GitLab 的计算机上的伴随程序。原生 Medium 的 Git/构建子进程仍需要直接路由。v12.4.4 设置、限制和故障排除。

从 v12.4.3 升级

下载 v12.4.3b Windows 可执行文件,停止 WRM,并在保留其数据库和加密密钥的同时替换旧可执行文件。**v12.4.3 更新程序无法解析 b 后缀,因此需要手动下载此首个热修复版本。**v12.4.3b 增加了字母热修复版本支持,供后续检查和更新使用。

对于 Windows 10/11,请在运行 WRM 的账户下安装并启动使用 Linux 容器的 Docker Desktop。在 Git → Medium 中,导入原始工具 ZIP;如果已导入,则点击 Prepare runtime / retry。WRM 会拉取固定版本的 Linux 映像,并在 Linux 卷中安装原始锁定文件。导入部署配置和 SSH 配置文件,然后启动 Medium。标准的 ~/.ssh/key 引用可在其私有 Linux 主目录中使用。无需安装 Windows 版 Python/rsync。浏览器客户端无需部署工具。

Windows Server 不支持 Docker Desktop:请在受支持的 Linux 主机或 Linux VM/容器上运行 WRM/Medium,然后通过 Windows 浏览器访问。不支持通过此绑定挂载/localhost 桥接使用远程 Docker 守护进程。Docker 引擎的访问权限必须属于运行 WRM 的账户;为其他桌面账户安装 Docker,不会自动授予 Windows 服务访问权限。

请备份数据库/密钥和私有 .medium 源代码/配置/偏好设置,以及名为 wrm-medium-<instance>-runtime 和 wrm-medium-<instance>-u<user> 的 Docker 卷。备份用户卷前请停止 Medium。运行时源代码/venv 为只读;用户卷会在重启后保留原生编辑内容/历史记录。重新导入配置/SSH 会明确替换该配置文件,但不会删除部署历史记录。首次启动 Docker 时,现有原生 Linux 运行时数据会复制到新的用户卷中。源代码和 SSH 密钥仍为私有数据。

如果依赖项已就绪,Linux 会保留其原生运行时;使用 WRM_MEDIUM_RUNTIME=docker 选择托管运行时,或使用 native 明确选择原生运行时。Windows 始终选择 Docker。自定义 Docker 路径/映像使用 WRM_MEDIUM_DOCKER 和 WRM_MEDIUM_CONTAINER_IMAGE。无需刷新 PATH,系统也会在 Docker Desktop 的标准安装路径中查找 Windows CLI。其他构建工具链/用户可能需要可信的自定义 Linux 映像;固定版本映像使用非特权 wrm 账户进行构建。Unix 主机 Agent 转发仍是原生运行时选项;托管 Docker 使用私有 SSH 配置文件。

从 v12.4.0 升级

替换二进制文件/AppImage,或更新容器。增量迁移会创建 git_config_profiles 并添加 folders.sort_order。现有文件夹在重新排序前仍按字母顺序排列。请备份数据库、匹配的加密密钥以及相邻的 .medium / .bitwarden 目录;这些目录包含私有运行时/配置数据。旧版二进制文件会忽略新增字段,但无法使用新功能。

默认情况下,Medium 已为管理员启用。请由管理员导入一次原始部署工具 ZIP,然后每位操作员导入自己的部署配置和可选的 SSH 配置文件。Docker 映像包含 Python 3.12+、git、OpenSSH、rsync 和官方 Bitwarden CLI。独立二进制文件会将这些依赖项设为可选:启用相应功能前,请先在 WRM 主机上安装它们。Medium 使用原始引擎自身的计划、锁定文件、备份和历史记录;不会将这些内容导入 Simple/Advanced 运行中。

较早版本中的客户端 GitLab 中继/重放以及 AI/导航/颜色/图标请求已在 v12.4.4 中实现;请参阅操作指南。

从 v12.3.6 升级

替换二进制文件,或使用应用内更新器;按需更新 AppImage/容器。启动时会新增一个可空的文件夹父级字段和 git_server_health 缓存表。现有文件夹、目录和路由默认设置会保留;旧版二进制文件会忽略这些新字段。

新的 功能 视图可从 Git 简单模式和高级模式进入。运行 Git 检查以填充此视图,并可按需启用定期监控/通知订阅。运行时命令会使用 SSH 登录账号的权限读取服务状态;不会启动或重启任何服务。要查看 AI 是否可用,请打开 设置 → AI 助手;提供商连接状态和有效账号权限会分别显示。

从 v12.2.8 升级

替换二进制文件。系统会自动创建一个仅新增的表(git_hostnames);v12.2.8 仍可使用同一数据库启动。无需更改配置。

  • Git 简单模式会自动启用。 检查器在服务器上发现的服务和环境会以就绪卡片显示,无需为每项服务定义环境;保存检测到的环境会将其保存到目录中(并记录审计日志)。高级模式不变,且你自己的定义仍优先。
  • 服务器按主机名显示(通过现有 SSH 登录读取一次并缓存;读取失败时回退到连接主机),而不是按连接名称显示。

从 v12.2.7 升级

替换二进制文件。无需更改数据库或配置;v12.2.7 仍可使用同一数据库启动。

  • 现在,顶部栏中的版本标签(“WRM v12.2.8”)会打开 更新 对话框,因此即使没有已知更新且绿色徽章被隐藏,管理员也始终可以点击 立即检查。非管理员只能查看版本。

从 v12.2.6 升级

替换二进制文件。系统会自动创建一个仅新增的表(ai_ollama_runs);v12.2.6 仍可使用同一数据库启动。无需更改配置。

  • AI 提供商向导提供 xAI、DeepSeek、Together AI、Fireworks AI、Cerebras、Cohere 和 Perplexity 的预设,更新了模型建议,并新增 加载模型列表按钮(调用提供商的 /models)。也可以随时直接输入模型名称。
  • Ollama 分步操作:检测、状态、已安装模型,以及各操作系统对应的安装/后台服务/下载命令;还可选择通过 WRM 运行这些命令。此功能默认关闭:管理员需启用策略 ai_ollama_manage(WRM_AI_OLLAMA_MANAGE=1)。每次运行都需要确认,服务器会检查权限,并将操作写入审计日志(admin.ai_ollama_*)。请参阅下方的配置表和 API 参考。

从 v12.2.5 升级

替换二进制文件。无需更改数据库或配置;v12.2.5 仍可使用同一数据库启动。

  • 设置 → AI 连接现在提供分步向导,用于连接 Codex CLI、Claude Code、Gemini CLI、Cursor / VS Code、Claude 和 ChatGPT:向导会创建令牌、显示(并允许下载)可直接使用的命令或配置文件,并测试连接。AI 助手也有相应的提供商向导。请参阅下文的 连接 AI 应用。
  • MCP 服务会向其客户端说明“wrm”的含义;权限被拒绝时,现在会指出缺少哪个作用域以及如何解决。

从 v12.2.4 升级

替换二进制文件。无需更改数据库或配置;v12.2.4 仍可使用同一数据库启动。

  • 现在可以将终端窗口内的 AI 助手窗口停靠在左侧/右侧/顶部/底部,也可以浮动、移动、调整大小,并展开至整个终端窗口。请参阅下文的 AI 助手。

从 v12.2.3 升级

替换二进制文件。无需更改数据库或配置;v12.2.3 仍可使用同一数据库启动。

  • 现在可以调整会话录制回放窗口的大小(拖动右下角),并将其展开至全屏(点击 ⛶ 按钮;按 Esc 退出)。终端会缩放至窗口宽度,因此无需横向滚动。请参阅下文的 会话录制。

从 v12.2.2 升级

替换二进制文件。无需更改数据库或配置;v12.2.2 仍可在同一数据库上启动。

从 v12.2.1 升级

替换二进制文件。无需更改数据库或配置;v12.2.1 仍可在同一数据库上启动。

  • Git 工作区的标题栏中新增 简单 / 高级 切换开关。简单 模式会为每个服务环境显示一张引导卡片(说明服务器上运行的版本与分支上的最新版本、清晰的状态),并提供 安装 / 更新 / 再次部署 和 回滚到上一版本 操作。高级 模式与原有 Git 工作区相同,仍为默认模式。请参阅 Git 工作区:简单模式。

从 v12.2.0 升级

替换二进制文件。无需更改数据库或配置。

  • 新终端窗口会以最大化状态打开,且光标位于终端中;已保存会话的窗口会保留原有布局。
  • 现在,即使选中的文本超出屏幕范围,也会复制整个选区(松开鼠标时复制)。
  • 最大化窗口的标题栏不再支持单击或双击来缩小窗口;只有拖动标题栏才能还原窗口。

从 v12.1.0 升级

替换二进制文件。无需更改数据库;v12.1.0 仍可在同一数据库上启动。

  • Gemini 和其他兼容 OpenAI 的提供方现在可以使用工具:每次工具调用的提供方 extra_content(Gemini 的 thought_signature)都会存储在会话中,并原样发回,从而修复 HTTP 400: Function call is missing a thought_signature。
  • 临时提供方错误不再立即结束本轮对话:HTTP 408 / 429 / 5xx(例如 503 high demand)最多会经过三次退避重试;对于超出提供方限制的请求(HTTP 413,或 Groq 等提供方的令牌限制),系统会缩短对话中较长的命令输出并重试。对于这两种情况,助手都会显示简短提示。

从 v12.0.0 升级

替换二进制文件。数据库会新增表(mcp_tokens、mcp_clients)和列 ai_sessions.mcp_token_id;v12.0.0 仍可在该数据库上启动,并会忽略这些内容。

  • AI 桌面应用(MCP)默认关闭。管理员可在管理面板 → AI 连接中启用(ai_mcp_enabled);默认情况下,只有管理员可以创建 AI 连接(ai_mcp = admins),模式为 read_only,ask,auto(ai_mcp_modes),默认有效期为 8 小时(ai_mcp_token_hours),最长为 24 小时(ai_mcp_max_token_hours;从 v12.5.1 起,默认值为 7 天和 30 天)。之后,用户可在设置 → AI 连接中找到相关选项。请参阅 AI 桌面应用(MCP)。
  • MCP 客户端通过 https://<your WRM>/mcp 连接 WRM。托管连接器(claude.ai、ChatGPT)会从提供方的云端连接:它们需要 WRM 可通过 HTTPS 从互联网访问。如果使用反向代理,请设置 ai_mcp_public_url(应用使用的地址),并转发 /mcp、/oauth/ 和 /.well-known/。使用 stdio 桥接的桌面应用只需能从你的计算机访问 WRM。
  • AI 助手的紧急关闭开关(ai_kill_switch)也会停止所有 AI 连接。关闭内置助手(ai_assistant)不会关闭 MCP,反之亦然。
  • AI 应用连接时,顶部栏会显示 🤖 AI 已连接;在较窄的窗口宽度下,顶部栏标签会比以前更早隐藏,避免内容重叠。

从 v11.7.0 升级

替换二进制文件。数据库会新增表(ai_providers、ai_sessions、ai_messages)和列 users.ai_blocked;v11.7.0 仍可在此数据库上启动,并会忽略这些内容。

  • AI 助手(默认关闭)。管理员可在 管理面板 → AI 助手 中启用(ai_assistant = admins 或 all),并添加组织的服务提供商(Anthropic、OpenAI、Azure OpenAI、AWS Bedrock、Google Vertex AI 或兼容 OpenAI 的端点)。之后,用户可在 SSH 终端和文件管理器的标题栏中看到 AI 按钮。请参阅 AI 助手。
  • 新模式默认采用严格限制:ai_modes = read_only,ask(必须显式允许自动模式),个人 API 密钥默认关闭(ai_personal_keys),输出会在发送给服务提供商前进行脱敏(ai_redact_output)。
  • 消费者聊天订阅(Claude.ai、ChatGPT)不能由 WRM 或任何其他第三方应用使用:请使用 API 密钥、企业网关,或 v12.1.0 的 MCP 集成(AI 桌面应用)。
  • AI 会话会在 会话与录制 中显示 ✦ AI 标记(转录记录方式与终端相同),并在审计日志中记为 ai.* 事件。
  • 在约 1100 px 宽度时,顶部栏不再与 新建窗口 按钮重叠。

从 v11.6.1 升级

替换二进制文件(或从下一个版本开始使用新的单击更新功能);数据库不会更改。

  • **作为服务运行:**交互式启动时,WRM 会询问一次是否将自身安装为开机启动的服务(systemd、launchd、rc.d 或 Windows 服务;不再询问 的设置会记录在 <DB_PATH>.service.json 中)。脚本可使用 -install-service、-uninstall-service 和 -service-status;-no-service-prompt 可跳过询问。请参阅 服务。sudo wrm -setup-docker [-service-user ACCOUNT](Linux)会为 Medium 安装 Docker Engine,允许 WRM 账户使用它,并重启 WRM 服务。
  • **更新:**WRM 每天检查一次项目的 GitHub 版本发布(不会发送用户数据)。顶部栏中的版本会显示 ⬆ 更新 vX.Y.Z 及发行说明;管理员可单击一次完成更新(根据 SHA256SUMS.txt 校验 SHA-256,并保留上一个二进制文件以便回滚)。隔离网络安装:WRM_UPDATE_CHECK=off。Docker 不会自行替换。请参阅 更新与自我更新。
  • SSH 终端中的 📂 现在会显示菜单:在此处打开、打开 /、打开主目录。“此处”无需配置 OSC 7 即可使用。请参阅 窗口、标签页与贴靠。
  • 使用 ProtectSystem=strict 运行 WRM 的 systemd 单元,需要将二进制文件所在文件夹添加到 ReadWritePaths,以便使用单击更新(通过 -install-service 编写的单元已包含此设置)。

从 v11.6.0 升级

替换二进制文件;数据库不会更改。

  • SSH 终端标题栏中的 📂 会打开同一服务器的文件管理器;如果 shell 提供了终端当前目录(OSC 7),文件管理器会在该目录中打开(#24)。请参阅 窗口、标签页与贴靠。

从 v11.5.0 升级

替换二进制文件;数据库不会更改。

  • Git 工作区中的 Activity 选项卡提供三个视图——Git activity(从 Git 服务获取各分支和作者的推送与提交)、Deploy history(合并每个环境目标的 history.jsonl,以及没有环境的安装所对应的 WRM 运行记录)和 What is where(显示每个环境和服务器上的分支、提交、版本、负责人和时间、落后于分支头部的提交数,以及差异)。每个视图均提供所显示筛选结果的 CSV 导出。请参阅 Git 工作区:活动、部署历史和部署位置。
  • **Gitea 源:**Git 源现在可以是 Gitea 服务(API v1,Authorization: token …)。目标、比较、部署和活动功能与 GitHub 一致;Gitea 暂不支持 .gitignore 拉取请求(请下载该文件)。
  • 活动视图会使用源的只读令牌读取提供商 API;对于 GitHub 仓库活动(推送、强制推送),令牌需要有权读取仓库的元数据,否则只会显示提交。部署历史和矩阵会像 Environments 选项卡一样通过 SSH 读取目标,并且需要 git_checks 策略;没有该策略时,只会显示 WRM 自身的记录。
  • 没有新增设置或策略。

从 v11.4.1 升级

替换二进制文件。数据库会新增一个表(git_env_exclusions);旧版二进制仍可在此数据库上启动,并会忽略该表。没有环境的目录和安装与以前完全相同。

  • **环境(可选):**目录中的服务可以配置命名环境——由有序目标 server:/path 组成(其中服务器是 SSH 连接的名称),并带有以下规则:输入确认、allowed_refs、额外的忽略模式、可选的 post_deploy 命令,以及要保留的备份数量。可在新的 Environments 选项卡(✎)中添加,也可在目录 JSON(apps[].environments)中添加。请参阅 Git 工作区:环境、部署计划和安全部署。
  • **服务器端状态:**环境部署会将状态保存在安装目录旁,默认位于 <path>/.deploy-bak(现有备份目录):state.json、history.jsonl、deploys/<id>.json、backups/rollback-<id>/ 和锁文件 .lock/。备份仍沿用现有的 <id>-<YYYYMMDD-HHMMSS> 格式,VERSION.md / updates.jsonl 也会照常写入,因此基于文件的工具仍可继续使用。
  • **锚定模式:**以 / 开头的排除或忽略模式现在只匹配完整的相对路径(/lib/a.py 不会匹配 x/lib/a.py)。Exclude permanently 会写入此类模式;现有模式不会更改。
  • 策略保持不变:git_update(部署)、git_upgrade(部署其他引用)、git_rollback、git_restart。环境部署会立即运行(不安排计划);使用试运行进行预览。

从 v11.4.0 升级

替换二进制文件;数据库不会更改。

  • **按用户保存剪贴板历史:**现在,Clipboard 面板会按登录用户保存历史记录,退出登录时会从浏览器中删除这些记录(#30)。首次登录时会删除早期版本保存的全浏览器历史记录,因此面板会有一次以空白状态启动。

从 v11.3.0 升级

替换二进制文件。数据库中的 git_installs 表会新增两列(last_ok_at、last_ok_state);旧版二进制文件仍可在该数据库上启动,并会忽略这两列。

  • 升级到 v11.3.0 时丢失的 Git 源将恢复: 将数据库从 v11.2.0 或更早版本升级到 v11.3.0 时,git_sources 表会被移出并重命名为 git_sources_old_<time>。首次启动时,如果尚无任何源,v11.4.0 会恢复这些源(包括加密令牌),并将旧表重命名为 git_sources_restored_<time>。
  • 安装中的每个文件: 详情会列出服务端文件夹和代码仓库中的每个文件,并说明每种状态的原因;还会对代码仓库中的每个文件执行差异比较(也包括目录清单排除的文件)。请刷新一次目标,这样目标会保留完整提交信息,也会列出目录清单以外的代码仓库文件。参见 Git 工作区:每个文件和部分检查。
  • 部分检查: 选择安装、服务端或服务,只检查所选项(或仅检查过期项);结果会持续传入,也可以取消。新增两个设置:git_check_parallel(8)和 git_check_per_server(2)。

从 v11.2.0 升级

替换二进制文件。数据库会新增两张表(git_feeds、git_pipelines),并在 git_sources 中新增四列(write_token、hook_id、hook_secret、hook_at);旧版二进制文件仍可在该数据库上启动,并会忽略这些新增内容。

  • .gitignore 助手: Git 工作区新增一个 .gitignore 选项卡。输出内容可下载;要创建合并 / 拉取请求,需要为 Git 源设置可选的写入令牌,并启用新策略 git_gitignore_mr(默认仅限管理员)。参见 Git 工作区:.gitignore 助手。
  • 可选的 CI 集成: 每个 Git 源都可配置一个 Webhook,可从 CI 构件获取软件包,也可为每个服务选择部署方式 CI pipeline。完成设置前,这些功能均处于关闭状态;WRM 无需任何 CI 也能正常运行。参见 Git 工作区:CI 集成(可选)。
  • Webhook 会发送到 /api/hooks/git/<id>:如果 WRM 位于只转发部分路径的反向代理之后,也要转发此路径。
  • 检查现在也会记录仅在服务端找到的文件大小;安装会在下次检查后显示该信息。

从 v11.1.0 升级

替换二进制文件。数据库保持不变:安装和传输会作为运行记录存储在 git_runs 中;旧版二进制文件仍可在该数据库上启动。

  • 从 Git 工作区安装到新服务端: 在 Installations 选项卡中选择 Install…(使用向导:选择服务端、服务及其版本、目标目录、预检查、来自模板 / 副本 / 手动输入的主机专属文件,以及可选的 systemd 或 supervisor 单元,还可选择是否启动),或针对某个安装选择 Transfer…,将其连同主机专属配置复制到另一台服务端。参见 Git 工作区:新服务端(安装和传输)。
  • 新增策略 git_install 和 git_transfer——默认仅限管理员;可在 Admin panel → Policies 中更改。
  • 安装和传输会发送现有的运行通知(Git: … started / succeeded / failed),并记录为 git.install / git.transfer。

从 v11.0.0 升级

替换二进制文件。数据库会新增两个表(git_runs、git_pending_restarts);旧版二进制文件仍可在此数据库上启动,并会忽略这两个表。

  • 从 Git 工作区部署: 在 Installations 选项卡和安装详情中提供 Update、Upgrade…、Rollback…、Restart… 和 Stamp,新增 Runs 选项卡,并支持计划运行。请参阅 Git 工作区:更新、升级、回滚和重启。
  • 新增策略 git_update、git_upgrade、git_rollback、git_restart——默认仅限管理员使用;可在 Admin panel → Policies 中更改——以及 git_schedule_grace_minutes(30)。
  • 在 Settings → Notifications 中新增运行和重启相关的通知事件(Git:更新、升级或回滚已开始 / 已成功 / 已失败、服务重启已安排 / 已完成、计划运行即将开始)。
  • 只有在启动或安排运行时,才会在服务器上写入 WRM;检查操作仍为只读。

从 v10.10.0 升级

替换二进制文件。数据库会新增表(git_sources、git_trees、git_blobs、git_workspace、git_targets、git_installs);旧版二进制文件仍可在此数据库上启动,并会忽略这些表。

  • Git 工作区: 顶栏中的新 ⎇ Git 按钮可将服务器上安装的服务与 GitLab / GitHub 或离线包进行逐文件只读比较。请参阅 Git 工作区。
  • 所有人都可使用此功能。管理员可以隐藏它(关闭 git_enabled,或设置 WRM_GIT_ENABLED=0),也可以将检查权限限制为管理员(git_checks)。
  • 在 Settings → Notifications 中新增通知事件 Git:有新版本可用、Git:服务器上的文件被手动更改 和 Git:服务器无法进行检查。

从 v10.9.1 升级

替换二进制文件。数据库会新增表 bookmarks;旧版二进制文件仍可在此数据库上启动,并会忽略该表。

  • 文件夹书签: 文件管理器路径栏旁和终端标题栏中都有 ★。Bookmark this directory… 可为一个连接、一个文件夹、一个标签或所有连接保存当前文件夹;路径可使用 ~、$USER、{host} 和 {name}。书签可以作为连接的起始目录。请参阅 文件夹书签。
  • WinSCP 书签: 使用 ★ → Manage bookmarks… → Import WinSCP.ini,可将 WinSCP 配置中的远程目录书签添加为全局书签。
  • 书签包含在 Export / Import 中。

从 v10.9.0 升级

替换二进制文件。数据库会新增表 putty_sessions 和列 connections.putty_session;旧版二进制文件仍可在此数据库上启动,并会忽略它们。

  • 从 PuTTY 导入: Settings → Data → Import from PuTTY 会读取已保存 PuTTY 会话的 .reg 导出文件及其代理。请参阅 从 mRemoteNG、PuTTY 和 OpenSSH 导入。
  • 在 v10.9.1 之前导入的 mRemoteNG 连接不会记住其 PuttySession,再次导入文件时会因其已存在而跳过:请手动为它们指定代理(或通过其文件夹的默认代理指定)。

从 v10.8.1 升级

替换二进制文件。数据库会新增表(proxies、proxy_grants、notify_channels、notify_subscriptions、notify_prefs、notify_pending、notify_state)和列(connections.proxy_id、folders.jump_conn_id、folders.proxy_id);旧版二进制仍可在此数据库上启动,并会忽略这些内容(连接因此不会使用代理,文件夹默认设置也不会生效)。

  • 代理: 在 🔑 SSH keys & credentials → 🌐 Proxies 下定义 SOCKS5、SOCKS4/4a 或 HTTP CONNECT 代理(或连接的 SOCKS 隧道),并在连接中选择一个(Proxy,位于 Jump host 旁边)。参见 Proxies。
  • 文件夹默认设置: 右键单击文件夹 → Folder settings…,为其设置默认跳板主机和代理。文件夹中没有自己的跳板主机的连接会使用文件夹默认设置(包括现有的、没有跳板主机的连接)。如果某个连接必须保持直连,请选择 no jump host (not the folder's)。
  • 通知: 管理员在 Admin panel → Notifications 中添加渠道(电子邮件、Telegram、Slack / Mattermost / Rocket.Chat、Teams、Discord、ntfy、Gotify、Pushover、webhook);用户在 Settings → Notifications 中订阅。只有两者都完成后才会发送通知。参见 Notifications。
  • Docker: docker-compose.yml 现在会将 host.docker.internal 映射到 Docker 主机(extra_hosts),供在主机上运行的代理使用。
  • 删除跳板主机后,原先使用它的连接现在会回退到其文件夹的默认跳板主机(或改为直连)。

从 v10.8.0 升级

替换二进制文件。数据库不会发生变化。

  • 支持导入更大的文件: mRemoteNG、OpenSSH 配置和清单(CSV / Excel)文件现在可导入,最大为 20 MB(此前从约 1 MB 起就会因 Bad JSON 而失败)。文件过大时,浏览器会直接显示包含文件大小和限制的明确提示。
  • 安装为应用(Settings → General)现在会显示适用于你所用浏览器的步骤,或说明为何无法在此处安装(使用纯 http:// 访问非 localhost 地址、证书不受信任、桌面版 Firefox)。只有浏览器可以立即安装时,才会显示 Install 按钮。要快速启用 HTTPS,请参见 HTTPS with Caddy。
  • WRM 前方的反向代理必须允许至少 32 MB 的请求正文,以便导入(nginx 示例中的 client_max_body_size 0; 即可满足要求)。

从 v10.7 升级

替换二进制文件。数据库会新增两列(connections.notes、connections.temp_until);旧版二进制仍可在此数据库上启动(快速连接会显示为普通连接)。

  • 侧边栏顶部新增 ⚡ Quick connect 字段:输入 user@host:port 并按 Enter。
  • 连接对话框和右键菜单中新增 📝 Notes;连接旁的 📝 可用于打开备注。
  • 顶栏新增 🧰 Tools,右键菜单中新增 Network tools from this server… / Check ports of this host(策略 network_tools,默认对所有用户开放)。
  • 安装为应用:使用 Settings → General,或浏览器地址栏中的安装图标(需要使用受信任证书的 HTTPS,或 localhost)。

从 v10.6 升级

替换二进制文件。数据库会新增一列(connections.bmc);旧版二进制仍可在此数据库上启动。

  • 连接可设置 BMC(Edit → Out-of-band management);右键单击 → Power & status (BMC)… 和 Serial console。使用 IPMI 时,请在 WRM 服务或跳板主机上安装 ipmitool(apt install ipmitool)。
  • 新增 Serial port 协议,可用于连接 WRM 机器上的控制台线缆(默认仅限管理员,策略 serial_ports)。
  • 已保存的工作区会话现在会真正保留远程桌面窗口(以及控制台窗口)。

从 v10.5 升级

替换二进制文件。数据库会新增三列(connections.tags、ext_id、ext_tags)和一个表 inventory_sources;旧版二进制文件仍可在该数据库上启动(会忽略标签)。

  • 连接现在支持标签;侧边栏会显示标签筛选器和环境徽标(env:prod …)。请参阅标签与清单导入。
  • Settings → Data → Import inventory:支持导入 CSV / Excel 文件和 NetBox。

从 v10.4 升级

替换二进制文件。数据库会新增一些表(ssh_keys、ssh_key_deployments、credentials、credential_grants)和两列(connections.key_id、connections.credential_id);旧版二进制文件仍可在该数据库上启动(使用新登录类型的连接将无法登录)。

  • 新增 🔑 Keys 按钮:用于管理 SSH 密钥库和凭据保险库。请参阅 SSH 密钥与凭据保险库。
  • 连接可以使用密钥库中的 SSH 密钥或保险库中的凭据登录;远程桌面和 FTP 也可以使用保险库凭据。
  • 删除账户时,现在也会删除其片段、隧道、密钥和凭据。

从 v10.3 升级

替换二进制文件。数据库会新增一列(connections.options);旧版二进制文件仍可在该数据库上启动。

  • 远程桌面需要在 WRM 旁边运行 guacd:执行 apt install guacd(Debian/Ubuntu)、docker run -d --network host guacamole/guacd,或使用 docker-compose.yml 中现已包含的 guacd 服务。没有 guacd 时,其他功能仍可正常使用;打开 RDP/VNC/Telnet 连接时会说明缺少什么。请参阅远程桌面。
  • 从 mRemoteNG 导入时,现在也会导入 RDP、VNC 和 Telnet 连接(包括域、控制台、颜色和 RD Gateway)。
  • SQLite 现在会在每次连接时,最多等待 10 s,以等待繁忙的数据库(修复负载较高时偶尔出现的 database is locked 错误)。

从 v10.2 升级

替换二进制文件。数据库会新增一个表(snippets)和一列(connections.monitor);旧版二进制文件仍可在该数据库上启动。

  • 文件名不再带后缀:发行版本为 v10.3.0,二进制文件名为 wrm-pro-v10.3.0-linux-amd64 等。请更新使用该文件名的脚本和 systemd 单元。
  • 实时状态默认开启:WRM 每分钟会与每个已保存的主机和端口建立一次 TCP 连接(SSH 和 FTP:读取问候信息后礼貌地关闭连接,类似 Nagios 的 check_ssh)。服务器日志中会记录这些连接。可在 Admin panel → Security policies → Live status 中更改间隔或关闭此功能,也可在某个连接中取消勾选 Monitor up/down status。关于 fail2ban,请参阅实时在线/离线状态。
  • 广播输入对所有人开放;如果不需要,可通过 broadcast_enabled 将其关闭。每次启动和停止都会记录在审计日志中。

从 v10.1 升级

替换二进制文件。数据库会新增一个表(connection_tunnels)和 connections 表中的两列(jump_conn_id、web_path);其他内容不变。若要回退,请在同一数据库上运行 v10.1 二进制文件;它不支持这些功能(跳板主机后的连接会尝试直接连接,无法打开 Web 界面连接,隧道也不会运行)。

  • 新功能:跳板主机、SSH 隧道、Web 界面连接,以及从 mRemoteNG / OpenSSH 导入。
  • 所有用户默认启用隧道,且仅监听 WRM 机器上的 127.0.0.1。远程转发(-R)和监听网络地址仅限管理员使用。请检查 Admin panel → Security policies → SSH tunnels;例如,如果 WRM 运行在共享服务器上,可关闭隧道(WRM_TUNNELS_ENABLED=0)或将其限制为仅管理员使用。
  • 跳板主机上需要设置 AllowTcpForwarding yes(OpenSSH 默认值),与 ssh -J 完全相同。

从 v10.0 升级

替换二进制文件。数据库会自动扩展(仅添加新表、列和触发器,不会更改或删除任何内容;旧版二进制文件仍可在升级后的数据库上运行)。

  • 默认开始记录终端会话(session_recording)。用户会看到 “此会话正在录制”,终端上也会显示 ● REC 标记。请告知用户(许多国家和地区对此有要求),或在 管理面板 → 安全策略 → 会话录制 中关闭此功能。除非启用 记录按键输入,否则不会记录按键输入。
  • 录制文件会占用数据库旁边的磁盘空间(recordings/,每个会话通常为几 KB 到几 MB;每个会话的上限为 recording_max_mb,保留时间 recording_retention_days = 90 天)。请按需备份或排除此文件夹。
  • 审计日志现在为仅追加且采用哈希链。管理面板 → 审计日志 → 验证完整性 可对其进行检查。升级前写入的条目没有哈希,检查时会跳过。
  • 每次上传、下载(包括在编辑器中打开的文件和 ZIP 下载中的文件)以及服务器间复制,都会记录在 管理面板 → 文件传输 中,并包含大小和 SHA-256。
  • 新增:供负载均衡器和监控使用的 /healthz、用于容器健康检查的 wrm -healthcheck、Dockerfile 和 docker-compose.yml。

从 v9 升级

替换二进制文件,并使用相同的数据库和相同的 ENCRYPTION_KEY(如果设置过)启动。所有内容都会自动迁移。请注意:

  • 已存储的机密会重新加密。 未设置 ENCRYPTION_KEY 时,v9 使用公开的默认密钥。v10 会生成一个随机密钥文件(remote_manager.db.key),并在首次启动时用它重新加密所有机密。请备份该文件。(如果设置过 ENCRYPTION_KEY,则不会有任何变化。)
  • 默认关闭自主注册。 现有账户仍可正常使用。如果需要,可在 管理面板 → 安全策略 中重新开启。
  • 密码和密钥不再发送到浏览器。 编辑连接 对话框会显示“已保存并加密——留空以保留”。导出 不包含机密;导出(包含密码和密钥) 会要求输入密码。
  • 会验证 SSH 主机密钥(首次使用时信任)。首次连接到每台服务器时,系统会记住其密钥;如果密钥发生更改,系统会拒绝连接,直到你接受该密钥。
  • **密钥文件 / Auto(~/.ssh)**身份验证(密钥存储在 WRM 服务器上)仅限管理员使用,除非启用了 允许所有用户使用服务器密钥文件 策略。
  • 现有共享保持原有行为(任何持有链接的人都可以访问,角色为 Operator)。请编辑共享,以使用新的访问模式和角色。
  • **位于反向代理之后时:**状态更改类 API 调用现在要求 Origin 与 Host 匹配(WebSocket 此前已要求匹配)。请传递 Host 标头,或设置 WRM_ALLOWED_ORIGINS。请设置 WRM_TRUST_PROXY=1,以便速率限制和审计日志获取真实客户端 IP。
  • 每个 IP 的登录限制现在为 10 分钟内失败 20 次;此外,账户在输错密码 10 次后会锁定 15 分钟(策略)。
  • 如果数据库来自更早的版本,且其中已有与新的 v10 表同名(如 audit_log、collab_messages 等)但布局不同的表,WRM 会将它们保留为 <table>_old_<time>,并创建新表(记录为 Upgraded table …)。不会删除任何内容。
  • 应用现在通过 / 提供服务。指向 /static/ 的旧书签会重定向到此处。

工作原理

 Browser (any device)                      WRM server (one binary)                     Your servers
┌──────────────────────┐   HTTPS/HTTP   ┌──────────────────────────────┐   SSH / SFTP   ┌───────────┐
│ Web UI (embedded     │ ─────────────▶ │ REST API  (/api/...)         │ ─────────────▶ │ Linux/BSD │
│ single-page app,     │                │ WebSockets:                  │   FTP / FTPS   │ servers,  │
│ xterm.js terminal)   │ ◀───────────── │  /ws/ssh     terminal        │ ─────────────▶ │ NAS, ...  │
│                      │   WebSockets   │  /ws/share/  collaboration   │                └───────────┘
└──────────┬───────────┘                │  /ws/events  live updates    │
           │  voice (WebRTC, DTLS-SRTP) │ TURN relay  UDP/TCP 3478     │
           └────────────────────────────┤ SQLite: users, connections,  │
             peer-to-peer or via relay  │ shares, audit log, settings  │
                                        └──────────────────────────────┘
  • WRM 服务负责建立连接。 你的浏览器只与 WRM 通信,WRM 则通过 SSH(golang.org/x/crypto/ssh)、SFTP(pkg/sftp)和 FTP(jlaffaye/ftp)与你的服务通信。你的服务只需能够从 WRM 所在机器访问。
  • 终端: 每个终端窗口都是一个 WebSocket(/ws/ssh),绑定到一个带有 PTY 的 SSH 会话。按键和输出以二进制帧传输,因此大体量输出和多字节 UTF-8 内容不会损坏。PTY 大小会随窗口调整。
  • 流量控制: 当命令输出速度快于浏览器的绘制速度时,浏览器会要求服务暂停并恢复传输。不会丢失任何内容。
  • 文件操作使用每个已保存连接对应的少量SFTP 连接池(连接会复用 5 分钟并进行健康检查)。上传采用流式传输;下载和 ZIP 压缩包会流式传输到浏览器。
  • 静态密钥(连接密码、私钥、双重身份验证密钥)使用 AES-256-GCM 加密。会话令牌仅以 SHA-256 哈希形式存储。
  • 协作: /ws/share/{token} 是共享房间。服务端负责确定身份和角色,并转发聊天、文件、终端数据流(仅发送给正在观看终端的用户)、远程控制按键(仅发送给授予控制权的用户)以及语音信令。
  • 跳板机和隧道: WRM 登录跳板机,通过它打开 SSH direct-tcpip 通道,并在其中运行另一个独立加密的 SSH 会话(类似 ssh -J)。隧道会在WRM 所在机器(本地 / SOCKS)或 SSH 服务端(远程)监听,并通过 SSH 转发每个连接。隧道端口由 WRM 开放,而非浏览器。
  • 语音: 音频在浏览器之间直接传输(WebRTC,通过 DTLS-SRTP 进行端到端加密)。当浏览器无法互相访问时(NAT、防火墙),内置 TURN 中继会转发仍处于加密状态的音频。

功能详解

账户、登录和双重身份验证
  • 第一个账户将成为管理员。 之后会根据策略关闭自主注册;管理员负责创建账户,并可选择生成临时密码,用户必须在首次登录时更改该密码。
  • 密码以 bcrypt 哈希形式存储(成本为 12)。最小长度由策略设定(默认为 8)。
  • 使用任意身份验证器应用进行双重身份验证(TOTP)(Google/Microsoft Authenticator、1Password、Bitwarden、FreeOTP……):设置 → 安全 → 双重身份验证。页面会显示 QR 码,并生成 10 个一次性恢复码。恢复码不能重复使用。管理员可以要求管理员或所有用户启用 2FA;尚未启用的用户必须在下次登录时完成设置。
  • 暴力破解防护: 10 分钟内,同一 IP 登录失败 20 次后,该 IP 将被锁定 5 分钟;账户在密码错误 10 次后将被锁定 15 分钟(策略)。无论用户是否存在,登录失败所耗时间都相同。
  • 会话: 使用 HttpOnly、SameSite Cookie(HTTPS 下启用 Secure);数据库仅存储令牌的哈希。会话会在不活动后结束(默认为 7 天),也会在达到最长时长后结束(默认为 30 天)——这两项均由策略设定。设置 → 安全会列出你的已登录设备,并可将其中一台或所有其他设备登出。更改密码会将所有其他设备登出。
  • 如果你在终端或传输任务运行期间登录过期,WRM 会显示提示消息,而不是重新加载页面。
连接和文件夹

文件夹可以设置父文件夹(最多 32 层);右键单击文件夹即可创建子文件夹或编辑其父文件夹。侧边栏会显示层级结构,连接选择器会显示完整文件夹路径;标签页和窗口标题仅显示连接名称,文件夹路径则显示在工具提示中。连接标签页上方的行可按文件夹筛选已打开的标签页/窗口,并聚焦最近使用的窗口。配置导出/导入和新的 mRemoteNG 导入会保留嵌套结构。删除文件夹时,其子文件夹会移至原父文件夹,且其中的连接会保留。共享文件夹时会包含其所有后代;跳转/代理默认值仅适用于当前文件夹。

左侧边栏(“PRO MANAGER”):

  • + Connection 用于创建连接:
    • 协议:SSH(终端,以及通过 SFTP 传输文件)、SFTP(默认打开文件管理器)、🖥 RDP、🖥 VNC、Telnet(参见远程桌面)、WRM 服务的 🔌 串口(参见串口)、FTP、FTPS(使用显式 TLS 的 FTP;仅限文件管理器)、🌐 Web 界面 HTTPS / HTTP(参见 Web 界面)。
    • 主机:端口(SSH/SFTP 的默认端口为 22,FTP/FTPS 为 21,Web 界面为 443/80)、用户名、文件夹、标签(用逗号分隔,例如 env:prod, site:dc1, rack:a12, web;字段下方会显示最常用的标签)。
    • **跳转主机(连接方式):**通过另一个已保存的 SSH 连接进行连接(参见跳转主机(堡垒机))。
    • **代理:**为连接通过 TCP 执行的所有操作指定已保存的 SOCKS / HTTP 代理(参见代理(SOCKS / HTTP))。如果使用跳转主机,则通过它连接代理;对话框会显示连接路径,例如 ⤳ Route: bastion → socks5://10.1.1.1:1080 → app-01。
    • 如果文件夹设有默认值,两者都会显示 — 文件夹:…… —(见下文);无跳转主机 / 无代理(不使用文件夹默认值) 会覆盖该默认值。
    • **🔀 SSH 隧道:**此连接的端口转发(参见 SSH 隧道)。
    • **⚡ 带外管理:**服务器的 BMC(参见带外管理)。
    • **📝 备注与运行手册:**操作步骤、联系人、链接(参见备注)。
    • 身份验证:密码、私钥(粘贴)、密钥文件(WRM 服务上的路径)、自动(尝试使用 WRM 服务用户的 ~/.ssh/id_rsa、id_ed25519、id_ecdsa、id_dsa)、🔑 密钥库中的 SSH 密钥或🗝 凭据库中的凭据(参见 SSH 密钥与凭据库)。密钥文件和自动使用的是 WRM 服务本身的密钥,因此仅限管理员使用(策略限制)。密码身份验证也会响应 keyboard-interactive 提示。RDP、VNC、Telnet 和 FTP 使用密码或凭据库中的凭据登录。
    • **使用服务器主机名作为名称:**将名称留空;保存后,WRM 会登录一次并读取主机名(SSH、SFTP),或通过 DNS 查找地址(其他协议,或输入的主机名的第一个标签),并以此命名连接。在此之前,名称为地址。若主机密钥尚未记录,系统会先显示该密钥供批准。连接菜单中的重命名为服务器主机名可在之后执行相同操作。
    • 🔌 测试连接会登录一次并显示结果、延迟,以及新服务器的主机密钥指纹。
  • **除非所有者要求,否则机密信息会保留在服务器上。**表单中的密码和私钥为只写:编辑对话框会显示“已保存并加密——留空即可保留”,并提供移除已保存机密信息的选项。复制会在服务器上复制该连接。
  • 👁 显示已保存的登录信息(位于编辑连接中,或空密码字段中的 👁)会显示连接的登录凭据:密码或私钥、凭据库凭据的用户名和密码(仅限你拥有的凭据)、密钥库密钥或 Bitwarden SSH 密钥,或 WRM 服务上密钥文件的路径。你需要使用 WRM 密码进行确认;域(LDAP / Active Directory)账户使用其目录密码确认,而只能通过身份提供商登录的账户则需在身份提供商处确认(强化验证)。启用确认危险操作(强化验证)后,还需输入 2FA 验证码。每次查看都会记录在审计日志中(connection.secret_revealed,失败的尝试为 connection.secret_denied),在启用机密信息已显示警报时会触发该警报,计入登录速率限制,并遵循允许导出密码和密钥策略(allow_secret_export;管理员始终可以导出)。
  • **主机密钥验证:**首次连接服务器时,会记住其 SSH 主机密钥(对于 FTPS,如果证书未经公共 CA 签名,也会记住该证书)。更改后的密钥会被拒绝,并显示明确警告和两个指纹;连接所有者(或管理员)检查后可以接受新密钥。策略选项:首次使用时信任(默认)、严格(必须批准新主机)或关闭。
  • 双击连接即可打开:SSH 会打开终端;SFTP/FTP/FTPS 会打开文件管理器。在触控设备上,轻点一次即可打开。
  • 右键单击连接:以终端 / 文件管理器打开(在新窗口或现有窗口中)、隧道、启动 / 停止所有隧道、添加隧道……、从此服务器运行网络工具……、查看访问权限(authorized_keys)……、部署 SSH 密钥……、备注与运行手册、检查此主机的端口、编辑、复制、重命名为服务器主机名、共享、复制用户名、复制密码(需通过与显示已保存的登录信息相同的确认;通知中绝不会显示密码)、复制 IP 地址(或主机名)、删除。Web 界面连接还提供:打开 Web 界面。
  • 📁 文件夹用于创建文件夹。将连接拖放到文件夹中即可移动;拖放到 “↓ 放到此处” 则可移回根目录。右键单击文件夹可共享或删除(其中的连接会移至根目录),也可选择文件夹设置……来重命名,并为其设置默认跳转主机和默认代理:除非连接自行选择,否则该文件夹中的连接(包括新建的连接和移入的连接)都会使用这些默认设置(文件夹名称后会显示 ⤳)。导出和导入时会保留默认设置。
  • 搜索框可按名称、主机、用户名、协议或标签筛选;#tag 仅搜索标签,多个词必须全部匹配(#env:prod web)。列表上方的 🏷 标签栏可按一个或多个标签筛选(再次点击可移除)。使用 Ctrl/Cmd + 点击进行多选,然后可使用 🤝 共享、🔑 密钥(向所有所选连接部署 SSH 密钥)、🏷 标签(添加标签,或用 -tag 移除标签)或删除。
  • 连接前的圆点表示其实时状态:🟢 在线,🟡 在线但较慢(> 300 ms),🔴 离线;圆环表示通过跳转主机连接(颜色随跳转主机的状态变化)。名称后的蓝点表示其中一个终端已连接。**⤳**表示连接经过跳转主机(悬停可查看路径);🔀表示已配置隧道(隧道运行时会显示颜色;点击可打开);WEB表示 Web 界面。
  • 与我共享会列出你参与的共享(以及面向所有用户发布的共享),并显示你的角色;点击 ↗ 可打开协作空间。 文件夹也支持手动排序:使用文件夹菜单中的 上移 / 下移,或拖动到另一个文件夹顶部或底部的三分之一区域,将其放置在该文件夹之前或之后。放到中间可将其设为子文件夹,放到根目录区域则可将其移至根目录。所有权、层级深度和循环检查均适用。导出和导入会保留已保存的顺序。
快速连接与连接备注

⚡ 快速连接 — 侧边栏顶部的输入框(⚡ 快速连接:user@host:port)可让你无需填写连接对话框即可连接:

  • 输入地址并按 Enter:[email protected]、admin@sw1:2222、10.0.0.7,或添加协议前缀:ssh://、sftp://、rdp://[email protected]、vnc://10.0.0.30:5901、telnet://sw1:23、https://10.0.0.11/ui。未指定协议时,默认使用 SSH。
  • 一个小对话框会要求你输入 登录凭据 — 密码、保险库凭据或密钥库中的密钥 — 以及可选的跳板主机。按 Enter 即可连接:终端、文件管理器、远程桌面或 Web 界面会像已保存的连接一样打开(包括主机密钥检查、录制和审计;审计操作为 connection.quick)。
  • 连接会显示在侧边栏的 ⚡ 快速连接下:💾(或右键 → 另存为连接)会打开连接对话框,可为其命名、指定文件夹和标签并将其保存;✕ 可将其移除。快速连接会在最后一次使用后保留 24 小时(打开的终端会让其继续保留),每位用户最多 20 个,不受监控,也不会导出。

📝 备注与运行手册 — 每个连接都可以添加备注,记录该连接上的服务、重启方法、联系人以及 Wiki 或工单链接:

  • 编辑 → 📝 备注与运行手册,或右键 → 备注与运行手册。侧边栏名称后面的 📝,以及终端窗口栏中的 📝,都可以打开备注。
  • 支持基础 Markdown:# 标题、- 列表、**粗体**、`代码`、``` 代码块和链接(https://…)。其他内容均显示为文本(不支持 HTML)。
  • 备注归连接所有者所有:共享成员看不到这些备注。导出和导入连接时会一并包含备注,使用 复制 时也会复制备注。最多 20 000 个字符。
SSH 密钥与凭据保险库

顶部栏中的 🔑 密钥按钮会打开两个列表:SSH 密钥和凭据。

SSH 密钥(密钥库)

  • 生成密钥: ED25519(推荐)、RSA 2048/3072/4096 或 ECDSA 256/384/521,并为其设置名称和备注。密钥在 WRM 服务上创建,并像其他所有机密信息一样以加密形式存储。
  • 导入密钥:粘贴或选择 OpenSSH 或 PEM 私钥文件。带密码短语的密钥会提示输入一次,随后使用 WRM 的密钥加密存储。也可以导入仅含公钥的密钥(例如同事的 id_ed25519.pub):可以将其部署到服务器,但 WRM 无法用它登录。PuTTY .ppk 密钥:请先使用 PuTTYgen → Conversions → Export OpenSSH key 导出。
  • **使用密钥:**在连接中选择 Authentication → SSH key from the key store。密钥列表会显示哪些连接使用密钥登录、密钥部署到了哪里,以及最后一次使用时间。
  • **🚀 部署:将公钥安装到选定的 SSH 连接上,类似于 ssh-copy-id:WRM 使用每个连接当前的登录方式(密码、其他密钥或保险库凭据,也包括通过跳板主机)登录,必要时创建 ~/.ssh,并将密钥追加到 ~/.ssh/authorized_keys 中一次(已存在的密钥不会重复添加;其他行保持不变;会恢复 SELinux 上下文)。选择“从现在起使用此密钥登录”**后,WRM 会使用该密钥登录以进行测试,并将连接切换为使用该密钥。可以从密钥、连接(右键单击 → Deploy SSH key…)部署,也可以为多个选定连接部署(侧边栏中的 🔑 Key)。
  • **✂ 撤销:**从选定服务器的 authorized_keys 中移除密钥。无法选择使用该密钥登录的连接,否则 WRM 将无法登录。
  • 📋 复制公钥、⬇ 下载 .pub、重命名、删除(若有连接或凭据使用该密钥登录,则会拒绝删除——删除密钥后,服务器上的密钥仍会保留,直到你将其撤销)。
  • **🔓 导出私钥:**再次输入 WRM 密码后,可选择使用新的密码短语进行保护;此操作会记录在审计日志中。仅当启用 allow_secret_export 时才允许导出(管理员始终可以导出)。

谁有权访问(右键单击 SSH 连接 → Who has access (authorized_keys)…):WRM 会读取登录用户的 ~/.ssh/authorized_keys,并列出每个密钥的类型、大小、备注、指纹和选项(from=…、command=…)。密钥库中的密钥会显示名称,WRM 自己用于登录的密钥会标记出来(且无法移除),其他密钥均可一键移除。Add a key… 会在此处部署密钥。通过其他方式允许的密钥(AuthorizedKeysFile、AuthorizedKeysCommand、其他账户)不会显示。

凭据(保险库)

凭据是多个连接共用的登录信息:用户名和密码、密钥库中的 SSH 密钥,或两者兼有。常见示例:root@dc1、Windows 服务器的 Administrator、iDRAC/iLO 管理员。

  • 新建凭据:名称、用户名(可选——不填写时,每个连接都会使用自己的用户名)、密码(🎲 可生成强密码)、SSH 密钥、描述、以天为单位的轮换提醒,以及仅限以下主机:支持 * 和 ? 的主机名或 CIDR 范围(*.dc1.example.com, 10.1.0.0/16)。设置主机列表后,该凭据仅适用于匹配的主机。
  • **使用凭据:**在连接中选择 身份验证 → 凭据库中的凭据。SSH、SFTP、RDP、VNC、Telnet 和 FTP 连接均可使用。只需更改一次凭据,所有连接都会使用新密钥登录。
  • 与用户共享:添加同事(或由管理员添加所有用户)。他们会在自己的列表中看到该凭据,并可在自己的连接中使用,但始终无法查看或更改密钥。移除用户后,其连接将立即停止使用该凭据登录。由于登录时会向服务器发送密码,共享凭据应设置主机列表:这样凭据仅适用于列表中的主机;对于获共享权限的用户,也仅能通过同样匹配列表的跳板主机使用。若共享凭据未设置主机列表,WRM 会在保存前询问。
  • 👁 显示:凭据所有者再次输入 WRM 密码后即可查看已存储的密码(操作会记录在审计日志中;受 allow_secret_export 策略控制)。🔗 使用者:列出使用该凭据的连接(所有者可查看所有用户的连接)。

密码轮换(仅所有者可在凭据上使用 🔄 轮换…)会更改所有使用该凭据的 SSH 服务器上的密码:

  1. 检查登录——WRM 使用已存储的密码登录每台服务器(通过跳板主机,并行执行),不做任何更改。其他用户使用该凭据的连接也会纳入检查;相同的 user@host:port 只会更改一次。
  2. 立即轮换——首先执行相同的检查:如果有一台服务器不接受已存储的密码,则不会进行任何更改。随后,WRM 依次在每台服务器上通过 SSH 运行 passwd(在终端中回应其提示),使用新密码登录以验证,最后将新密码存入凭据库。新密码由系统生成(24 个字符,包含大小写字母、数字和符号),也可以由你输入。
  3. 全部成功或全部回滚:如果某台服务器失败(密码规则、禁止使用 passwd 等),则已更改密码的服务器会恢复为旧密码,凭据库中也会保留旧密码。如果恢复也失败(例如密码历史规则不允许使用旧密码),凭据库仍会保留旧密码,并将新密码记为待处理:该凭据会标记为轮换未完成,显示会同时显示两个密码,结果中会列出各服务器正在使用哪个密码。问题修复后,通过编辑设置正确的密码。

每台服务器的进度都会实时显示。轮换需要通过 SSH 连接到允许登录用户使用 passwd 修改自身密码的服务器(Linux、BSD、macOS)。其他类型的连接(RDP、VNC、FTP…)会阻止轮换——请自行更改这些密码,再通过编辑保存新密码(通过编辑设置新密码也视为已轮换)。轮换提醒到期时,🔑 按钮会显示徽标,管理面板 → 概览也会发出提醒。

所有操作都会记录在审计日志中:ssh_key.created、ssh_key.deployed、ssh_key.revoked、ssh_key.exported、ssh_key.deleted、credential.created、credential.updated、credential.granted、credential.grant_revoked、credential.revealed、credential.checked、credential.rotated、credential.rotation_failed、credential.rotation_incomplete(绝不记录密钥)。

Bitwarden SSH 密钥

打开 密钥和凭据 → Bitwarden,选择云端/EU/自托管 HTTPS 服务器,然后使用邮箱、主密码和受支持的两步验证码登录。如果邮箱登录需要机器人验证或其他 MFA 流程,也支持使用个人 API 凭据和主密码。解锁保管库;如有需要,先同步,然后在 SSH/SFTP 连接中选择 Bitwarden SSH 密钥,再选择原生 SSH 密钥项目。安全笔记附件和任意文本字段都不是 SSH 密钥项目。

在 WRM 服务器上安装官方 Bitwarden CLI(确保 bw 位于 PATH 中,或设置 WRM_BITWARDEN_CLI);Docker 内置 CLI 2026.9.1。每个 WRM 账户都有自己的 CLI 配置文件。连接中存储的是项目 ID;私钥在服务器端获取,用于身份验证,不会返回浏览器或复制到连接数据库中。主密码和解锁会话密钥不会持久化。CLI data.json 会在命令之间使用 WRM 加密密钥进行封存,并在调用中断后于启动时恢复。

默认的解锁闲置时长为 15 分钟;重启 WRM、退出 WRM、锁定或退出登录也会结束解锁状态。锁定会阻止获取新密钥;现有 SSH 会话会继续运行。刷新密钥和手动同步保管库会延长交互式闲置时长;后台 SSH 操作不会延长。云端登录要求 WRM 主机能够访问相应服务。错误信息会区分 CLI 缺失/保管库已锁定和登录失败,且不会暴露 CLI 输出。

跳转主机(堡垒机)

数据中心和客户网络中的服务器通常只能通过堡垒机(“跳转主机”)访问。WRM 会像 ssh -J/ProxyJump 和 mRemoteNG 的 SSH tunnel 设置一样,通过跳转主机连接:

  1. 将堡垒机创建为普通 SSH 连接,例如 bastion-dc1 → 203.0.113.10:22。
  2. 创建内部服务器,例如 app-01 → 10.0.0.21:22,并选择 跳转主机(连接经过)→ bastion-dc1。
  3. 双击 app-01。终端会显示 Connecting to 10.0.0.21:22 via bastion-dc1…。
 WRM ──SSH──► bastion-dc1 ──SSH inside the first connection──► app-01 (10.0.0.21)
  • **所有功能都能通过跳转主机使用:**终端、文件管理器(SFTP)、FTP/FTPS(FTP 连接从跳转主机发起)、搜索、编辑器、服务器间传输、测试连接、隧道和 Web 界面。
  • **链式连接:**跳转主机也可以设置自己的跳转主机,最多支持 5 跳,例如 vpn-gw → bastion-dc1 → app-01。保存时会拒绝循环连接。
  • 每一跳都使用各自的凭据登录(密码、密钥、密钥文件),且都会验证主机密钥(首次使用时信任/严格验证),与直接连接一样。WRM 不会在跳转主机上开放端口;它使用 direct-tcpip 通道,因此堡垒机只需启用 AllowTcpForwarding yes(OpenSSH 的默认设置)。
  • 路由会显示在侧边栏(⤳)、测试连接(… via bastion-dc1)、终端、会话和录制以及审计日志中。
  • 跳转主机是你自己保存的 SSH 连接。通过跳转主机连接的连接也可以共享,成员不会看到任一连接的凭据。
  • 删除跳转主机后,使用它的连接会恢复为直连(或使用其文件夹的默认跳转主机)。
  • 文件夹可为其中的连接设置默认跳转主机(文件夹设置…);如果跳转主机本身位于该文件夹中,则不会通过自身连接。
代理(SOCKS / HTTP)

有些服务器需要通过 SOCKS 或 HTTP 代理访问,而不是通过跳板机(或在跳板机之后访问),类似 PuTTY 的 Connection → Proxy。代理只需定义一次,并像保险库凭据一样按连接选择:

  • 🔑 SSH keys & credentials → 🌐 Proxies → New proxy(或在连接对话框的 Proxy 字段中选择 + New proxy…)。类型:
    • SOCKS5,可选用户名和密码(RFC 1929)——加密保存,或使用保险库凭据;
    • SOCKS4 / SOCKS4a(用户 ID,无密码);
    • 支持 Basic 身份验证的 HTTP CONNECT;
    • **连接的 WRM SOCKS 隧道:**某个 SSH 连接的动态隧道(-D)。当连接需要时,WRM 会启动它,并在 30 分钟无流量后停止。
  • 在代理处进行 DNS 解析(PuTTY:Do DNS name lookup at proxy end,默认开启):由代理解析主机名(SOCKS5 域名、SOCKS4a)。关闭:由 WRM 解析主机名并发送地址。
  • **连接通过 TCP 执行的所有操作都会经由代理:**SSH 终端、SFTP、搜索、传输、隧道、密钥部署和密码轮换、FTP/FTPS(包括数据连接)、RDP / VNC / Telnet(guacd 连接到 desktop_tunnel_bind 上的本地中继)、Web 界面(通过 127.0.0.1 上的本地中继打开)、Test connection、实时状态、服务器上的网络工具、Redfish(勾选 Through the jump host 时)。IPMI 和 Serial-over-LAN 使用 UDP,无法通过代理:WRM 会拒绝这种组合。
  • **代理和跳板机同时使用:**先通过跳板机连接代理,再连接目标:
 WRM ──SSH──► bastion ──direct-tcpip──► proxy 10.1.1.1:1080 ──SOCKS CONNECT──► app-01:22

路由会显示在侧边栏、对话框、终端、Sessions & recordings 和审计日志中:bastion → socks5://10.1.1.1:1080 → app-01。跳板机也可以有自己的代理。

  • 清晰的错误信息会区分代理和目标:
    • proxy socks5://10.1.1.1:1080: not reachable: connection refused — 代理本身不可用;
    • proxy socks5://…: authentication required / authentication failed: wrong user name or password(HTTP:407);
    • proxy socks5://… cannot reach 10.0.0.5:22: connection refused (SOCKS5 reply 5) — 代理正常,但目标无响应(HTTP:502 / 504)。
  • 实时状态仅当 WRM SOCKS tunnel 代理的隧道正在运行时才会通过该代理检查(检查不会启动隧道,也不会让隧道保持运行);否则状态为 unknown。
  • 如果 WRM 机器上的代理地址对应的是另一位用户运行的 SSH 隧道,则会被拒绝(this address is an SSH tunnel of another user on the WRM server):隧道监听端口没有自己的登录信息。
  • 共享:将代理共享给用户(或由管理员共享给所有人):他们可以使用代理,但看不到其登录信息。与他人共享含密码的代理时,不会通过被授权者自己的跳板机访问该代理(否则他们可能在那里读取明文代理登录信息)。WRM 隧道代理不能共享。
  • **文件夹默认值:**Folder settings… → Default proxy。
  • 策略 proxies(all / admins / off):规定谁可以定义代理。所有人都可以使用共享给自己的代理。
  • 导出和导入会按名称保留代理(导出内容会列出你的代理;只有包含机密信息的导出才会包含密码;导入时会创建缺失的代理);Duplicate 会保留代理。
  • **Docker:**在容器内,127.0.0.1 指向容器本身。docker-compose.yml 会将 host.docker.internal 映射到 Docker 主机(extra_hosts: ["host.docker.internal:host-gateway"]):对于 ssh -D 1080 或主机上的代理,请使用 host.docker.internal:1080,并让代理监听容器可访问的地址(不能只监听主机的 127.0.0.1)。如果 WRM 在容器中运行,而代理地址保存为 127.0.0.1,WRM 会发出警告。
SSH 隧道(端口转发)

类似于 ssh -L / -R / -D、PuTTY 的隧道和 mRemoteNG 的 SSH 隧道功能。在连接中配置隧道(✏ Edit → 🔀 SSH tunnels,或右键单击 → Add tunnel…),然后在顶部栏的 🔀 Tunnels 面板中启动和停止隧道。

类型功能示例
本地(-L)WRM 计算机上的端口通过 SSH 连接,指向从该服务端视角可访问的主机和端口。监听 127.0.0.1:2443 → 目标 10.0.0.5:443:打开 https://127.0.0.1:2443,即可访问服务端后方交换机的 Web 界面
SOCKS 代理(-D)WRM 计算机上的 SOCKS5 代理。所有目标地址都通过服务端访问。127.0.0.1:1080:在浏览器中设置(例如 FoxyProxy、SOCKS v5,代理 DNS),即可浏览整个管理网络;也可运行 curl --socks5-hostname 127.0.0.1:1080 http://10.0.0.5
远程(-R)SSH 服务端上的端口指向 WRM 可访问的主机和端口。服务端上的 127.0.0.1:9000 → 10.10.0.2:80:服务端从你这边的镜像下载内容

隧道字段

  • 监听:地址和端口。127.0.0.1(默认值)表示只有 WRM 计算机上的程序可以使用此隧道。端口留空时,会自动选择一个可用端口(运行时会显示)。本地和 SOCKS 端口必须在 1024–65535 之间。网络地址(0.0.0.0、LAN IP)会使任何能够连接该端口的人都能使用隧道,无需登录 WRM——除非策略允许,否则仅限管理员使用。
  • **目标:**主机和端口,从服务端(本地隧道)或 WRM(远程隧道)的视角指定。SOCKS 不使用此项。
  • 打开为 http/https + 路径:添加一个 🌐 打开按钮,在新的浏览器标签页中打开隧道。
  • **启动:**手动(在“隧道”面板中点击 ▶);随终端启动(连接的第一个终端启动时一并启动,最后一个终端关闭约 15 秒后停止);始终运行(随 WRM 启动并持续运行,重启后也会继续运行)。
  • **模板:**Web 界面(HTTPS 443 / HTTP 80)、连接内部主机的 SSH、RDP 和 VNC、PostgreSQL、MySQL/MariaDB、iDRAC / iLO / IPMI Web、SOCKS 代理。

每个隧道下方的提示会用通俗语言说明其功能,例如:WRM 计算机上发往 127.0.0.1:2443 的连接会经过 Site1 到达 10.0.0.5:443。

🔀 隧道面板按连接列出你的隧道:状态(🟢 运行中,🟡 正在重新连接,🔴 出错)、监听地址 → 目标地址、当前 / 总连接数、流量 ↑↓、运行时长和启动者,以及 🌐 打开、📋 复制地址(SOCKS 地址格式为 socks5h://…)、▶ 启动和 ■ 停止。按钮上的数字表示正在运行的隧道数量。管理员可以显示所有用户的隧道并停止它们(也可在 管理面板 → 概览 中操作)。

可靠性:每条运行中的隧道都有独立的 SSH 连接(经过跳板主机),每 30 秒检查一次,并会在端口保持打开时自动重新连接(间隔依次为 2、5、10、30、60 秒……)。更改连接会重启其运行中的隧道;删除连接会停止其隧道。每次启动、停止(含传输的字节数)和错误都会记录在审计日志中。

隧道端口在哪里?在运行 WRM 的计算机上:

  • WRM 运行在你自己的 PC 上(通常情况):在浏览器中打开 http://127.0.0.1:<port>,或让任意程序(DBeaver、RDP 客户端、psql、FileZilla……)连接 127.0.0.1:<port>。
  • WRM 运行在你通过网络访问的服务端上:127.0.0.1 隧道只能在该服务端上使用。管理员可以使用监听地址 0.0.0.0(或服务端的 LAN 地址),并在防火墙中开放该端口——这样任何能够连接该端口的人都可以使用隧道,因此建议使用受限网络。或者通过普通 SSH 将端口转发到你的 PC(ssh -L 2443:127.0.0.1:2443 wrm-server)。

示例——通过站点网关访问服务端的 Web 界面(PC → WRM → Site1 → Site1-Webserver:443):

  1. 连接 Site1(通过 SSH 连接到站点网关)。
  2. 编辑 Site1 → 🔀 SSH 隧道 → + 本地(-L):监听 127.0.0.1:2443,目标 10.1.0.20:443(从 Site1 视角可见的 Web 服务端),打开方式为 https。
  3. 🔀 隧道 → ▶ 启动 → 🌐 打开 → https://127.0.0.1:2443。

更简单的方法:将其另存为Web 界面连接,并将 Site1 设为跳板主机。

Web 界面(HTTP / HTTPS 连接)

将设备的 Web 界面(iDRAC / iLO / IPMI、交换机、防火墙、NAS、虚拟机管理程序、监控系统)保存为连接,协议选择 🌐 Web interface (HTTPS) 或 (HTTP):主机:端口、可选的 路径(例如 /login.html)和可选的 跳板机。

  • 双击(或右键单击 → 打开 Web 界面)即可在新的浏览器标签页中打开。
  • 不使用跳板机时,浏览器会直接打开该地址(https://10.0.0.200/login.html)。
  • 使用跳板机时,WRM 会在 WRM 机器上打开一个临时隧道(127.0.0.1:<free port> → 从最后一台跳板机看来可访问的主机:端口),并打开该地址。隧道会在你使用期间重复使用,无流量 30 分钟后停止;隧道面板会将其标记为临时。
  • 测试连接会检查端口是否有响应(通过跳板机)。
  • TLS 连接从浏览器端到设备端全程加密;如果设备使用自签名证书,浏览器会显示常见的警告。
  • 与所有隧道一样,临时隧道位于 WRM 机器上:当 WRM 在另一台计算机上运行时,WRM 会显示地址,而不会直接打开它(请参阅上文的隧道端口在哪里?)。
标签和清单导入(CSV、Excel、NetBox)

标签用于描述连接:自由词(web、db)和带键的标签——env:(环境)、site:(位置)、rack:、role:、tenant:、platform:、cluster:。标签全部使用小写,不含空格(Rack A 12 会变为 rack:a-12),每个连接最多 30 个标签。

  • 在连接对话框中设置标签,或一次为多个连接设置(多选后点击 🏷 标签;-tag 会移除一个标签)。
  • 连接上方的 🏷 标签栏会列出使用最多的标签及其数量;点击标签可仅显示包含所有这些标签的连接(其余标签以 +N 表示)。搜索框也可以查找标签(#rack:a12)。
  • 环境一目了然:env:prod(以及 production、prd、live)会显示红色 PROD 徽标和红色边框;staging/UAT 显示黄色徽标,test/QA 显示蓝色徽标,dev/lab 显示绿色徽标——这样就不会把生产服务器误认为测试服务器。
  • 导出 / 导入和复制操作都会保留标签。

导入清单(设置 → 数据 → 导入清单):

CSV / Excel

  • 选择一个 CSV 文件(逗号、分号、制表符或 | 分隔——自动检测;支持 UTF-8、UTF-16 或 Windows-1250,Excel 在克罗地亚语环境下会以此格式保存,因此 č ć š ž đ 均能正确显示),或选择一个带工作表选择器的 Excel 工作簿 (.xlsx)。旧版 .xls 文件请先另存为 .xlsx 或 CSV。
  • WRM 会将第一行读取为列名并猜测字段映射(英文和克罗地亚语名称:Name/Naziv/Hostname、IP/IP adresa/Address/URL、Port、Protocol/Protokol、User/Korisnik、Password/Lozinka、Folder/Mapa/Grupa、Tags/Oznake、Environment/Okruženje、Site/Location/Lokacija、Rack、Role/Uloga、Platform/OS、Jump host/Bastion、Path)。预览会显示前几行,并在每列下方提供字段选择器——你可以更改任意列的字段,或将其设为忽略。
  • 主机列支持 10.0.0.5、10.0.0.5:2222、[email protected]、10.0.0.5/24、IPv6 和 URL(https://idrac-01/ 会变为 Web 界面连接,ssh://admin@sw1:2222 会变为 SSH 连接)。Platform 包含 Windows 时会创建 RDP 连接。Environment、Site、Rack、Role 和 Platform 会变为标签;Jump host 列会按名称将连接关联到跳转主机。

NetBox

  • 输入 NetBox 地址和 API 令牌(只读权限即可),还可选择填写筛选条件(站点、角色、租户、NetBox 标签、状态)、选择使用主 IP还是名称(DNS)作为地址,以及环境所在自定义字段的名称。点击 从 NetBox 加载可读取设备和/或虚拟机(所有分页)并显示结果;没有地址的对象会被标记。
  • 站点、机架、角色、租户、平台、集群、环境和 NetBox 标签都会变为标签;Windows 平台会变为 RDP 连接。
  • 同步:导入的对象会记住其 NetBox ID。再次加载时,这些对象会标记为已导入;启用更新之前导入的对象后,其地址、NetBox 标签和文件夹会跟随 NetBox 更新(你自己的标签、名称和登录信息保持不变)。NetBox 中已消失的对象会列出来——WRM 绝不会自行删除连接。
  • 记住地址和令牌会为你的账户保存地址、筛选条件和令牌(加密保存);令牌不会再次显示。

*两种方式均适用:*为导入的连接选择登录方式——无(稍后设置)、保管库凭据(例如 root@dc1)或已存储的 SSH 密钥——并设置默认用户名和协议、文件夹(按列设置、每个站点 / 角色 / 租户一个文件夹、全部放入一个文件夹,或不设文件夹),以及应用于所有连接的额外标签。包含自身密码的行会保留该密码。现有连接(名称、主机和协议均相同)会被跳过,因此可以安全地重复导入。结果会列出已导入、已更新和已跳过的项目(以及相应原因)。

从 mRemoteNG、PuTTY 和 OpenSSH 导入

Settings → Data:

  • 从 mRemoteNG 导入 — confCons.xml 文件(%APPDATA%\mRemoteNG\confCons.xml,或在 mRemoteNG 中选择 File → Export):
    • 容器会转换为文件夹(DC1 / Rack A);SSH1/SSH2 连接会转换为 SSH 连接,RDP、VNC 和 Telnet 连接会转换为远程桌面(保留其选项),HTTP/HTTPS 连接会转换为 Web 界面连接(保留 URL 路径);
    • 密码会被解密(当前 AES-GCM 格式、较早的 AES-CBC 格式、FullFileEncryption),并以加密形式存储在 WRM 中。如果文件受主密码保护,WRM 会要求输入该密码;
    • 从父文件夹解析继承的设置(Inherit 用户名、密码、端口、域、SSH 隧道);
    • SSH 隧道设置(SSHTunnelConnectionName)会转换为跳板主机;
    • WRM 不支持打开的 ICA、rlogin 和其他协议会列为已跳过;已存在的连接(名称、主机和协议相同)也会跳过,因此可以安全地重复导入。
  • 导入 OpenSSH 配置 — ~/.ssh/config(文件夹 SSH config):
    • 包含 HostName、User、Port 的 Host 条目;Host * 和通配符模式中的默认值;
    • ProxyJump(也支持 user@host:port;如果跳板主机没有自己的 Host 条目,则会创建该条目)和 ProxyCommand ssh -W … 会转换为跳板主机;
    • LocalForward、RemoteForward、DynamicForward 会转换为随终端启动的隧道;
    • IdentityFile 会转换为 Key file 身份验证(仅当允许你使用 WRM 服务端上的密钥文件时;否则会提示你添加密钥或密码);
    • Match 块和仅包含通配符的主机会跳过。
  • 从 PuTTY 导入 — 已保存会话的注册表导出文件(文件夹 PuTTY)。在 regedit 中右键单击 HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions → Export,或运行 reg export HKCU\Software\SimonTatham\PuTTY\Sessions putty.reg。支持读取 UTF-16(regedit 默认格式)和 UTF-8 文件:
    • 会话名称会解码(My%20Server → My Server);导入 HostName(也支持 user@host)、PortNumber、UserName 和 Protocol。Default Settings 不会作为连接导入,但其中的值会作为其他会话的默认值;
    • SSH 和 Telnet 会话会转换为连接;raw、rlogin 和 serial 会话(Windows PC 的 COM 端口)会列为已跳过;
    • PublicKeyFile 会提示:使用 PuTTYgen 转换 .ppk(Conversions → Export OpenSSH key),并在 🔑 SSH keys 下添加;
    • 代理:SOCKS4、SOCKS5 和 HTTP 代理(ProxyMethod、ProxyHost、ProxyPort、ProxyUsername、ProxyPassword、ProxyDNS)会转换为已保存的代理,名称示例:PuTTY socks5 proxy.example.com:1080,并关联到连接。使用同一代理的会话会共用代理;如果你已有代理(类型、地址、登录信息和 DNS 设置相同),则会重复使用,因此重复导入不会创建新代理。PuTTY 的 SSH proxy 会按名称转换为跳板主机;Telnet 和本地命令代理会附带提示。需要策略 proxies 允许你定义代理;
    • **与 mRemoteNG 配合:**如果连接的 PuttySession 指定了已导入的 PuTTY 会话名称,该连接就会使用该会话的代理(除非连接已有代理)。导入顺序不限:第二次导入会为第一次导入创建的连接关联代理。

导入后,摘要会列出已导入的连接、文件夹、跳板主机关联和隧道、已跳过的内容,以及需要检查的项目(例如缺少用户名或密码的连接)。

**大小限制:**每个导入文件(WRM 导出文件、mRemoteNG、PuTTY、OpenSSH 配置、CSV / Excel 清单)最大为 20 MB。浏览器会在发送前检查文件大小;超过限制时会显示 The file is too large (… MB): the import limit is 20.0 MB(API 返回 HTTP 413)。

窗口、标签页与贴靠

每个打开的连接都是工作区内的一个窗口,标签栏中也会有对应的标签页。

  • + 新建窗口(或 Alt+N)会打开一个空窗口,其中包含连接和已保存会话的快捷按钮。
  • 标题栏:拖动即可移动,双击即可最大化或还原。按钮:贴靠布局、↻ 重新连接(SSH 窗口)、📂 文件(SSH 终端)、📡 共享终端(协作房间中)、最小化、最大化、关闭。
  • SSH 终端标题栏中的 📂▾ 文件是一个菜单,可打开同一服务器的文件管理器(#24);如果该连接的文件管理器已经打开,则会将其置于前台并切换到所选目录:
    • **在此处打开:**打开终端的当前目录。当远程 shell 通过 OSC 7 报告当前目录时,WRM 会立即使用它(bash:在 ~/.bashrc 中设置 PROMPT_COMMAND='printf "\033]7;file://%s%s\033\\" "$HOSTNAME" "$PWD"')。否则,WRM 会通过同一连接的独立 SSH 通道向服务器查询:它会在服务器的进程中(Linux 和 BSD 上的 /proc 或 ps)查找终端的 shell,优先选择终端的前台程序,并读取其工作目录(/proc/<pid>/cwd、pwdx、procstat 或 lsof)。无需进行任何配置。如果无法找到目录(没有 /proc 或 ps、通过 sudo -i 切换到其他用户的进程,或服务器不是 OpenSSH),WRM 会说明原因,并提供主目录或 / 作为选项。
    • 打开 / 和 打开主目录。
  • 贴靠:左侧、右侧、上半部分和下半部分、四个象限,以及最大化。可使用标题栏中的按钮、窄窗口中的精简贴靠布局菜单,或标签页的右键菜单。
  • **拖动到边缘贴靠:**用指针将窗口拖到工作区的边缘(半屏)或角落(四分之一屏)。蓝色预览会显示窗口将要放置的位置。
  • **窗口不会离开工作区:**移动和调整大小时都会限制在四条边缘内。浏览器调整大小或缩放,或面板大小发生变化时,窗口会移动并缩小,以保持可见。已贴靠和最大化的窗口会保留原有位置。
  • 可从任意边缘或角落调整大小。拖动已贴靠的窗口会恢复其先前的大小。
  • **标签页:**单击即可聚焦或还原,拖动即可重新排序,单击鼠标中键即可关闭,单击鼠标右键可打开重新连接、复制窗口、贴靠布局和关闭选项。SSH 标签页会显示连接状态(🟡 正在连接,🟢 已连接,🔴 已断开)。
  • 关闭确认可设为始终、从不或仅在已连接时(设置)。
  • 终端仍处于连接状态或正在进行传输时,离开页面前浏览器会发出警告。
外观、主题与无障碍

设置 → 外观(static/appearance.js)可更改 WRM 的显示效果;所选设置会保存在服务器上(/api/me/ui/appearance),并同步到你使用的每个浏览器。

  • 主题: Graphite(默认)、Midnight(OLED 黑色)、Fjord、Solar dark、Forest、Ember、Daylight、Paper、Solar light、High contrast dark 和 High contrast light。跟随系统的浅色/深色设置会在你选择的深色和浅色主题之间切换。每种主题还会设置终端颜色。
  • 自定义颜色: 每个颜色令牌(背景、文本、边框、强调色、状态颜色及其文本变体、终端背景色、前景色和 ANSI 颜色)都有颜色选择器和 CSS 字段;更改会叠加在主题之上,可逐项重置,也可一次全部重置。保存为我的主题可保留设置(最多 30 个),导出/导入可通过 JSON({"wrm_theme": 1, "name", "mode", "tokens", "term"})迁移主题。
  • 字体和大小: 界面字体(包括已安装时可选的易读字体,如 Atkinson Hyperlegible、Lexend 和 OpenDyslexic)、终端、编辑器和日志的等宽字体、界面大小 70–160 %、间距(紧凑、正常、宽松,点击目标更大)、圆角、行距和字距、加粗文本。
  • 色觉: 变更红绿色盲、红色盲、蓝黄色盲和全色盲设置后,OK/警告/错误/信息颜色及差异会改用基于 Okabe–Ito 的调色板,也可选择在终端中应用。不要只依赖颜色会在状态徽标和提示消息中添加 ✓ ✕ ! 标记,为连接状态圆点使用不同形状(● 已连接、◆ 较慢、■ 已断开),并为链接添加下划线。
  • 其他选项: 对比度(正常、较高、最高)、终端中的最低对比度(WCAG 4.5:1 或 7:1)、动画(系统、减少、完整)、减少透明效果和模糊、醒目的键盘焦点轮廓、为链接添加下划线。
  • 自定义 CSS 仅适用于你自己的界面(appearance_custom_css,默认开启)。
  • 来自扩展的主题: 已启用的扩展可在此提供主题(addon.json 中的 ui.themes,包含 id、name、name_hr、mode、tokens 和/或 css;旧版的单个 ui.theme 样式表会作为一个主题显示)。未选择该主题的用户不会应用这些设置。管理员可通过 设为所有人的默认主题 或 appearance_default_theme 将任何主题设为默认主题。
屏幕锁定

锁定会遮住 WRM 并要求输入账户密码;终端、文件传输、隧道、AI 和 MCP 会话会继续运行。Settings → Security → Screen lock(按用户设置,/api/me/ui/lock):

  • 立即锁定(也可点击顶部栏中的 🔒,或使用键盘快捷键,默认为 Ctrl+Alt+L)。
  • **触发条件:**闲置后(关闭、1 分钟至 4 小时或自定义时长,可选择提前 10/30/60 秒警告;任意 WRM 标签页中的活动都会计入,也可选择将鼠标移动计入),WRM 不可见时(立即或 1/5/15 分钟后,除非另一个 WRM 标签页可见),电脑锁定时(浏览器闲置检测,适用于 Chrome/Edge,仅请求一次权限),电脑休眠后,以及每次启动或重新加载时。
  • **锁屏界面:**模糊、暗淡或纯色背景,时钟、你的姓名、仍在运行的窗口数、自定义消息,以及中性标签页标题。锁定期间会暂存通知,并在解锁后显示;桌面通知不会显示其文本。
  • **解锁:**账户密码(本地账户或目录/LDAP),或个人 4–12 位数字 PIN(screen_lock_pin)。仅通过身份提供方登录的账户,可在登录后立即设置 PIN,或从锁屏界面退出登录。每次锁定、解锁和失败尝试都会记录审计日志;每分钟最多尝试五次,screen_lock_max_failures 会在错误尝试达到设定次数后让浏览器会话退出登录。
  • 严格程度(screen_lock_mode):server(默认)会按登录会话记住锁定状态,并在解锁前对该会话的请求返回 423 Locked,因此重新加载、新建标签页或打开浏览器开发者工具都无法绕过锁定;remember 会在重新加载后保持锁定,但允许页面在后台刷新;browser 是早期版本中仅限页面的锁定方式。浏览器中的所有 WRM 标签页会同时锁定和解锁。
  • 管理员限制:screen_lock_max_minutes 是用户可选择的最长闲置时间(0 = 无限制);用户不能将闲置锁定的时间设得低于此值。
面板布局:停靠、堆叠、浮动和锁定

侧边面板可以由你自行排列(v12.6.8)。Connections、Sessions、Snippets、Clipboard 和 AI 实时视图(AI 应用在服务器上运行时)都是面板,每个面板都有一个标签页。面板共享组中的标签栏;组位于停靠区域(左侧、右侧或窗口下方的底部),也可以位于画布上,在窗口之间的任意位置(v12.6.10)。

  • 拖动面板标签页(蓝色边框会显示放置位置):
    • 拖到另一个标签栏上:面板会作为标签页共享该标签栏(放在两个标签页之间时,会插入两者之间);
    • 拖到面板顶部或底部 30 % 的区域:该列会被拆分,拖动的面板会放在上方或下方(位于底部区域时,则放在左侧或右侧);
    • 拖到工作区边缘的左侧、右侧或底部条带:面板会停靠在那里,成为一个新组;
    • 拖到画布上的其他位置:面板会放在该处的窗口之间。它与这些窗口共用堆叠顺序(点击面板即可将其置于最前方),浏览器或侧边面板尺寸变化时,面板仍会留在画布内;启用对齐到网格时,面板会对齐到网格。
  • **调整大小:**拖动两个组之间的分隔线、左右区域的内侧边缘或底部区域的上边缘。画布上的面板可通过标签栏的空白部分移动,并通过右下角调整大小。
  • **每个组的 ⋯ 菜单:**停靠到左侧、停靠到右侧、停靠到底部(作为该区域第一个组的标签页)、放到画布上(任意位置)、隐藏、锁定布局、面板…、重置布局。
  • 面板(顶部栏中的 ▦,或栏宽度较窄时位于其 ⋯ 菜单中)会列出所有面板及其位置(左侧、右侧、底部、画布上、已隐藏)。勾选面板即可在原位置重新显示,取消勾选即可隐藏。列表中会显示 AI 实时视图,但只有 AI 应用在服务器上运行时才会出现。
  • 锁定布局(位于面板、▤ Workboard 菜单或任意 ⋯ 菜单中):无法拖动、拆分、调整大小或移动面板和窗口(对齐和最大化按钮仍可使用),且 ▦ 按钮会显示 🔒。切换标签页、折叠侧边面板以及显示或隐藏面板仍可使用。锁定时拖动标签页会提示如何解锁。
  • 重置布局会还原所有面板的位置:Connections 在左侧;Sessions、Snippets 和 AI 实时视图作为标签页位于右侧,Clipboard 在它们下方。
  • 按用户保存在服务器上(/api/me/ui/layout),因此布局会在你使用的每个浏览器中保持一致;浏览器中也会保存一份副本,以便立即启动。没有面板的区域会消失。AI 实时视图显示在侧边区域时,该区域会保持自身宽度(最多为窗口宽度的一半)。
  • 手机(屏幕宽度低于 760 px)使用固定布局:连接列表和 Sessions/Snippets/Clipboard 抽屉;AI 实时视图则以底部弹出层显示。
  • 停靠为面板的 Workboard 插件也属于面板;面板会在 Workboard 插件下列出它们,隐藏插件会将其放回画布,作为一个窗口(参见画布)。
Workboard:共享画布和插件

窗口区域是一块画布(v12.6.10):终端、文件管理器、桌面、Workboard 插件以及你放到画布上的面板共用这块画布,你可以按自己的喜好排列。▤ Workboard(位于顶部栏的 Settings · Panels · Workboard 组中,或栏宽度较窄时位于其 ⋯ 菜单中)会打开画布菜单。插件初始为空:你可以从目录中只添加所需内容(+ Add addon,空画布上也有此按钮),最多可添加 24 个;同一插件也可以添加多次(例如,为两组服务器添加两个 Server load 插件)。

  • 插件是窗口: 拖动标题栏可移动窗口,从任意边缘或角落可调整大小;拖到边缘或使用吸附按钮可吸附;双击可最大化;使用标签页切换。标题栏按钮:↻ 刷新(用于获取数据的插件;将鼠标悬停在标题上可查看数据的时效),⚙ 设置,⇥ 停靠为面板,以及常见的最小化、最大化和 ✕ 移除(如果会丢失设置或笔记,会先询问)。无论选择哪个连接文件夹标签页,插件都会保持可见。新插件会在窗口旁找到空位。
  • 窗口菜单(右键单击标题栏或标签页),适用于每个窗口:吸附布局、📌 固定位置(取消固定前无法移动或调整大小;标题栏会显示 📌)和总在最前;插件还提供设置、立即刷新和停靠到右侧 / 左侧 / 底部。
  • 停靠为面板后,插件会成为面板布局中的一个面板:与 Sessions 堆叠、拆分列、移动到另一条边或画布上的任意位置。面板栏保留 ↻、⚙ 和 ⧉ 作为窗口放回画布,可将插件窗口恢复到上次的位置。
  • ▤ 工作区菜单:
    • 添加插件…
    • 画布: 吸附到网格(移动窗口和面板时会落在网格线上,调整大小时移动的边缘也会对齐网格线)、网格大小 10 / 20 / 40 px、画布背景(仅网格模式会在吸附开启时显示点;也可始终显示点、线条或纯色背景)。
    • 平铺窗口(将所有显示且未固定的窗口排列成网格)、层叠窗口、最小化所有窗口、显示所有已最小化窗口、最小化 / 显示插件、锁定布局。
    • 已保存的布局: 保存此布局… 会按名称保存插件及其位置和设置、面板布局以及画布设置(最多 10 个);勾选同时保存打开的终端、文件管理器和桌面,也可保留这些窗口(类似工作区会话)。选择已保存的布局会替换当前插件和面板布局;如果布局中包含窗口,WRM 会询问是替换还是添加到已打开的窗口。管理已保存的布局… 可应用或删除布局。
    • *导出布局(JSON)*会将插件、画布设置、面板布局和已保存的布局下载为 wrm-workboard-<date>.json;*导入布局…*会读取此类文件(最大 512 KiB,读取时会检查所有内容),替换当前插件和面板布局,并将文件中的已保存布局添加到现有布局中。导出的文件包含插件设置和笔记,但不含机密信息。
    • *面板…*和简短的帮助文本。
  • **每个插件的设置:**自定义标题、颜色(标题栏上的彩色边框)、文字大小(从小到特大)、插件自身的选项,以及移除。
  • 按用户保存在服务器上(/api/me/ui/workboard,并在浏览器中保存一份副本),因此画布会随你切换到任何浏览器。位置以画布比例保存,因此可适配其他屏幕尺寸。
  • 插件仅在可见时加载和刷新:未最小化,且未被其他窗口完全遮挡(倒计时仍会按时结束)。
  • 手机(宽度低于 760 px):所有窗口(包括插件)都会全屏显示,并通过标签页切换;此时插件不会停靠为面板。 | 插件 | 显示内容 | 设置 | |---|---|---| | 🟢 服务状态 | 来自实时状态的连接状态:中断、缓慢(超过 300 ms)、未知和正常;问题优先显示,并显示延迟或持续时间;点击可打开连接 | 连接(未选择:显示所有有状态的连接),仅显示问题 | | 📈 服务负载 | 每台服务:CPU、RAM(含总量)、每 CPU 负载、运行时间和磁盘(按使用率从高到低排列;悬停可查看更多)。负载条达到 75 % 时变黄,达到 90 % 时变红。每台服务都会标明数据来源:Monitoring(Zabbix agent)或通过 SSH 读取,以及数据的时间;错误(SSH 拒绝、非 Linux 系统……)也会显示 | 最多 8 个 SSH/SFTP 连接 | | 🔔 通知 | WRM 通知过你的所有内容,按时间从新到旧排列,未读项会标记;全部标为已读、清除;▤ 工作板按钮会显示未读数量 | — | | 🕒 时钟 | 本地时间和日期,以及其他时区 | IANA 时区(UTC、Europe/London……),秒数 | | ⎇ 最近提交 | Git 服务的最近提交和推送(作者、分支、短 SHA、时间、Git 服务上的提交链接),每 5 分钟刷新一次 | Git 目录中的服务、分支(留空:该服务跟踪的分支)、5 / 10 / 20 | | 🔀 运行中的隧道 | 显示运行中的隧道及其本地地址;*隧道…*会打开隧道面板 | — | | ⚡ 快速连接 | 带状态指示灯的按钮,点击可打开连接 | 最多 12 个连接 | | 📝 便笺 | 写给自己的便笺(最多 2000 个字符),由插件保存 | — | | 🗂 已保存的会话 | 显示已保存的会话及其窗口数量;点击可打开会话 | — | | 🔗 链接 | 指向网页的链接(仪表板、Wiki、工单),在新标签页中打开 | 最多 30 行,格式为 Name \| https://address(仅限 http 和 https) | | ⏱ 计时器 | 倒计时(带进度条,时间结束时闪烁并发出通知〔提示和允许时的浏览器通知〕),或秒表;开始 / 暂停 / 重置;重新加载后仍会继续运行 | 倒计时或秒表,分钟数(1–1440) |

**服务负载的数据来源:**如果服务已启用 Monitoring(顶栏中的 📊,Zabbix agent),且最近一次采样距今不到 5 分钟,WRM 会使用该采样数据,不会登录。否则,WRM 会使用连接本身的凭据通过 SSH 登录,并运行一条只读命令(uname -s、/proc/loadavg、间隔一秒读取两次的 /proc/stat、/proc/meminfo 中的 MemTotal/MemAvailable、排除 tmpfs/overlay 挂载的 df -P -k、/proc/uptime、nproc):插件可见时,每台服务最多每分钟执行一次;每台服务同一时间只登录一次;结果缓存 25 s。通过 SSH 读取仅适用于 Linux,管理员可将其关闭(workboard_ssh_metrics);关闭后,只有启用了 Monitoring 的服务才会显示数据。只能选择你自己的 SSH/SFTP 连接。

**WRM 中的通知:**WRM 向你发送的每条通知也会保存在应用内列表中(最新 200 条),不受你在设置 → 通知中选择的渠道或事件影响;即使管理员关闭了通知发送(notifications_enabled)也一样。重复提醒(密钥和凭据即将过期、新版本、即将运行的 Git 任务)每天只保留一次。

远程桌面:RDP、VNC、Telnet

Windows 服务(RDP)、Linux 桌面和 KVM/IPMI 控制台(VNC),以及旧式网络设备(Telnet),都会在 WRM 窗口中打开,显示在 SSH 终端旁边——无需 RDP 客户端或插件。

 browser ──WebSocket── WRM ──guacd protocol── guacd ──RDP / VNC / Telnet── server

**一次性设置:**WRM 使用 guacd(Apache Guacamole 的代理守护进程)来实现这些协议。请在与 WRM 相同的机器上运行它:

WRM 运行位置安装 guacd
Debian / Ubuntusudo apt install guacd(监听 127.0.0.1:4822)
Dockerdocker compose up -d — docker-compose.yml 包含一个与 WRM 共用网络的 guacd 服务
任何安装了 Docker 的 Linuxdocker run -d --name guacd --network host --restart unless-stopped guacamole/guacd
Windows / macOS**无需手动操作:**当 guacd_address 为本地地址(127.0.0.1:4822)时,WRM 会在 Docker Desktop 中启动官方 guacd 容器。Docker Desktop 必须使用 Linux 容器。安装并启动 Docker Desktop;否则,请在 Linux 机器上运行 guacd 并设置 guacd_address。

管理面板 → 概览 会显示 guacd 是否响应(以及其版本);RDP/VNC 连接上的测试连接会检查服务器端口和 guacd。

**连接:**选择协议 RDP、VNC 或 Telnet,填写主机(默认端口分别为 3389、5900、23)、用户名、密码,也可以选择跳转主机。🖥 远程桌面选项:

  • **RDP:**域、安全模式(自动、NLA、TLS、RDP、Hyper-V 控制台)、服务器键盘布局、调整窗口大小时的处理方式(调整桌面大小、自适应,重新连接,或保持桌面大小并缩放)、颜色、启动程序、接受服务器证书、控制台(管理员)会话、声音、剪贴板、壁纸、RD 网关(主机、端口、用户、域)。
  • **VNC:**颜色、本地或远程鼠标指针、仅查看、剪贴板。
  • **Telnet:**字体大小、颜色、登录和密码提示模式(用于自动登录)。

在桌面窗口中操作:

  • 双击连接(或右键单击 → 打开远程桌面)。窗口会显示远程屏幕,并缩放以适应窗口;⤢ 适应窗口会切换到 1:1 显示并启用滚动条,**⛶**会切换到全屏。使用 RDP 时,远程桌面会适应窗口大小。
  • 当窗口处于焦点状态时(单击窗口),键盘和鼠标输入会发送到远程计算机。Ctrl+Alt+Del有专用按钮。
  • 剪贴板:在远程计算机上复制的文本会显示在 WRM 的剪贴板面板中,也会出现在你的剪贴板中;📋 剪贴板会将文本发送到远程剪贴板。⌨ 输入会将文本作为按键输入——适用于登录界面、BIOS/iDRAC 控制台以及其他无法使用剪贴板的场景。
  • RDP 的声音会在浏览器中播放。
  • 如果服务器要求提供尚未保存的凭据(例如空密码),WRM 会向你询问。
  • **↻**会重新连接;标签页和窗口会显示连接状态。
  • 通过跳转主机连接时,WRM 会在会话期间通过跳转主机建立临时隧道(在“隧道”面板中列为远程桌面(临时)),并在会话结束时关闭隧道。
  • 恢复已保存的工作区会话时,也会恢复桌面窗口。

审计和录制:每个桌面会话都会显示在会话与录制和审计日志中(desktop.open、desktop.close、desktop.error)。开启会话录制后,WRM 会录制屏幕流(不录制密码:密码会在握手期间发送到 guacd,且不会出现在屏幕上);▶ 回放会在浏览器中播放录制内容,并支持播放/暂停和拖动进度;⬇ .guac会下载录制文件(可使用 Guacamole 的工具播放)。

**安全性:**浏览器不会选择目标主机:WRM 会使用已保存的主机、用户、密码和选项执行握手,之后只会转发允许列表中的显示数据和输入指令。访问权限遵循与终端相同的规则(所有者;具有操作员角色或更高角色的共享成员)。策略:desktop_enabled(REMOTE_DESKTOP_ENABLED)、guacd_address(GUACD_ADDRESS,默认值为 127.0.0.1:4822)、guacd_auto(Windows/macOS:在 Docker Desktop 中启动本地 guacd 容器;默认开启)、desktop_tunnel_bind(guacd 的跳转主机隧道地址,默认值为 127.0.0.1)。

带外管理、控制台和串口

服务器的 BMC(iDRAC、iLO、XClarity、Supermicro、OpenBMC,或任何 IPMI 控制器)在连接中配置:编辑 → ⚡ 带外管理:

  • 类型: Redfish(当前 BMC 的 HTTPS API)或 IPMI(通过 ipmitool 使用 LAN 上的 IPMI)。
  • BMC 地址(10.0.100.11 或 host:port)、登录信息:用户名和密码(加密存储),或凭据库凭据(例如,所有服务器共用一个 idrac-root)。
  • **通过跳板主机:**如果管理网络只能从堡垒机访问,WRM 会通过连接的跳板主机访问 BMC:通过最后一跳的 SSH 通道使用 Redfish,ipmitool 则在最后一跳上运行(IPMI 使用 UDP)。
  • BMC 的串口控制台命令(由 BMC 厂商建议,例如 iDRAC 使用 console com2、iLO 使用 vsp、XClarity 使用 console 1),以及其 SSH 端口。

⚡ 电源和状态(右键单击 → 电源和状态(BMC)…):

  • 电源状态、健康状况(通过 IPMI 获取故障消息)、厂商、型号、序列号、BIOS、CPU 和内存、BMC 型号和固件、功耗和进气温度(以 BMC 提供的信息为限)。
  • 开机、关机(正常)、重启(正常)、强制关机、强制重启、电源循环、NMI——仅限 BMC 支持的操作。除开机外,所有操作都会先询问并说明后果;每项操作都会记入审计日志(bmc.power、bmc.power_failed)。
  • Redfish 证书大多是自签名的:WRM 会像处理 SSH 主机密钥一样,在首次使用时固定证书,并拒绝已更改的证书(检查后再接受,方式与主机密钥相同)。

📟 串口控制台(右键单击 → 串口控制台,或点击电源和状态中的按钮)会打开一个终端窗口,显示机器的控制台——BIOS/UEFI 设置、引导加载程序、内核消息,以及网络中断时的登录提示:

  • **Redfish BMC:**WRM 使用 BMC 登录信息通过 SSH 登录 BMC,并输入控制台命令(iDRAC 使用 console com2,iLO 使用 vsp 等)。
  • **IPMI:**串口 LAN(Serial-over-LAN,ipmitool sol activate,会先停用旧会话),在跳板主机或 WRM 服务器(Linux)上运行。输入 ~. 可结束会话。
  • 控制台与其他终端会话一样:会经过审计并记录(协议为 console / sol),管理员可以查看——但只有连接所有者可以打开(共享成员不能打开)。保存的工作区会话会恢复控制台窗口。

🔌 WRM 机器的串口(USB 控制台线缆,ttyS0):协议为 Serial port,将设备名称(ttyUSB0、ttyACM0、ttyS0)设为主机,并配置线路参数——波特率(默认 9600;115200 也很常见)、数据位、奇偶校验、停止位、流控制(无、RTS/CTS、XON/XOFF)。点击测试连接会打开端口;双击会在终端中打开端口(原始模式,且会记录)。串口与密钥文件一样,属于 WRM 服务器:默认情况下,只有管理员可以添加串口(策略 serial_ports:off / admins / all);WRM 必须在 Linux 上以有权打开设备的用户身份运行(属于 dialout 组)。

策略:bmc_enabled(BMC_ENABLED)、serial_ports。

片段和连接时运行

片段是已保存的命令。可在右侧面板的 ⚡ Snippets 选项卡中打开,或在终端中按 Ctrl+Shift+Space(也可点击标题栏中的 ⚡)快速选择。

  • 点击片段:将其输入当前聚焦的终端并运行。Shift+点击(或 ⎘)会输入片段但不按 Enter,方便你先进行编辑。**右键点击:**运行、插入、复制、编辑、复制一份或删除。
  • **快速选择器:**输入文字进行筛选,按 ↑ ↓ 选择,按 Enter 运行,按 Shift+Enter 插入,按 Esc 关闭;点击 + New snippet 可将所选终端文本保存为片段。
  • 分组(Diagnostics、Services 等)、描述和适用范围:所有连接、某个文件夹中的连接或某个连接。选择器只会显示适用于当前终端连接的片段。
  • **多行片段:**每一行都是一条命令。
  • 变量会针对每个终端填入对应值:{{host}}、{{port}}、{{user}}、{{name}}(连接)、{{folder}}、{{wrm_user}}、{{date}}、{{time}}。运行片段前会询问你填写提示项,并显示实时预览:{{?Service}} 或带默认值的 {{?Service=nginx}}。示例:journalctl -u {{?Service=nginx}} --since "{{?Since=1 hour ago}}" --no-pager。
  • **连接时运行:**勾选 Run on connect,当匹配连接的终端连上时(重新连接后也一样),WRM 就会立即在 shell 中输入该片段 — sudo -i、cd /srv/app、tmux attach || tmux new、export KUBECONFIG=…。右键点击连接或文件夹 → ⚡ Run on connect… 可创建此类片段。运行顺序:所有连接片段,然后是文件夹片段,最后是连接片段。消息会列出已运行的片段;审计日志会记录此次操作(terminal.auto_run)。
  • **共享片段:**管理员可以将片段共享给所有用户(用户只能读取,适用于所有连接,且绝不会自动运行)— 可在终端中使用的团队运行手册。
  • ✨ Add example snippets 会创建一组入门片段(磁盘、内存、占用资源最多的进程、失败的服务、日志错误、监听端口、大文件、服务状态/重启等)。
  • 片段会包含在 Export / Import 中,通过 Duplicate 复制,并在其所属连接或文件夹删除时一并移除。
  • 看起来有危险的命令(见下文)运行前会要求确认。
文件夹书签

命名的远程目录,类似 WinSCP 中的书签:在每台服务器上,常用的深层目录(/opt/app/servers/<server>/downloads)都可一键打开。

  • 文件管理器中的 ★(位于路径栏旁):☆ 将此目录加入书签…、此连接的书签,以及 ⚙ 管理书签…。选择书签即可打开对应目录。如果此服务器上不存在该目录,系统会提示你,当前文件夹仍保持打开状态。
  • **终端标题栏中的 ★**和 Ctrl+Shift+Space 选择器(位于代码片段之后):选择书签会在终端中输入 cd -- '<path>'(使用 shell 引号;开头的 ~/ 会保留在引号外,以便 shell 展开)。在广播中,书签旁的 📣 会将 cd 发送到组内的每个终端,并使用各自连接的变量。
  • 作用范围: 一个连接、某个文件夹中的连接、带有某个标签的连接,或 所有 SSH / SFTP / FTP 连接(全局)。
  • 变量由服务器为每个连接填入:~(主目录)、$USER / ${USER} / {user}(连接的用户名)、{host}(不含端口)、{name}(连接名称)。示例:/opt/app/servers/{name}/downloads。
  • **起始目录:**勾选 起始目录,匹配的连接所对应的文件管理器便会在该目录打开;终端在连接时(包括重新连接后)会输入 cd,并且在连接时运行代码片段之前执行。优先使用作用范围最具体的起始目录:连接,然后是标签、文件夹,最后是全局。右键单击连接或文件夹 → **★ 起始目录…**即可创建。
  • 名称、颜色和备注;管理书签可重命名、重新排序(↑ ↓)、在不同作用范围之间移动书签,以及删除书签。
  • **共享:**标记为 与共享成员共享 的全局书签会以只读方式提供给通过共享使用你连接的人员。
  • **从 WinSCP 导入:**选择 管理书签 → 导入 WinSCP.ini,即可读取 WinSCP 配置文件中的远程目录书签([Configuration\Bookmarks\Remote\…]),并将其添加为全局书签,同时在备注中记录 WinSCP 站点。已存在的书签(名称和路径相同)会被跳过。
  • 书签会包含在 导出 / 导入中,会随 复制 操作一同复制,并会在删除其所属连接或文件夹时一并移除。
广播输入

同时向多台服务输入相同的命令——类似于 MultiSSH、cssh 或 mRemoteNG 的多 SSH。

  1. 打开终端(例如,集群中的所有 Web 服务)。
  2. 顶栏 → 🧰 Tools → 📣 Broadcast… → 选择终端 → Start broadcast(只需确认一次)。
  3. 现在,在其中一个终端中输入的所有内容都会发送到所有终端。橙色栏会显示接收内容的终端数量;已纳入广播的窗口会显示橙色边框。窗口标题栏中的 📣 可添加或移除该终端;■ Stop 可结束广播。

安全性:

  • 危险命令会先询问: 发送看起来有危险的命令行之前按 Enter 时——例如 rm -r/-f、shutdown/reboot/halt、init 0/6、systemctl stop/restart/disable…、mkfs、dd … of=、fdisk/parted、wipefs、写入 /dev/sd* 或 /etc/…、kill -9、pkill、chmod 777、chown -R、iptables -F、ufw disable、DROP/TRUNCATE TABLE、DELETE FROM、crontab -r、卸载软件包、docker rm、kubectl delete、terraform destroy、fork bomb 等——WRM 会显示命令和终端数量;Cancel 是默认按钮。
  • 向广播中粘贴多行内容也会要求确认。
  • 代码片段会在广播中的每个终端上运行,各自使用自己的 {{host}}/{{user}},并且只需确认一次。
  • 检查只针对你在此次广播中输入的内容(不检查通过 ↑ 从 shell 历史记录中调出的命令)。
  • 每个终端都会记录加入和离开广播的时间(terminal.broadcast,并包含终端数量);而且一如既往,会话录制会显示每台服务上发生的情况。管理员可以关闭此功能(broadcast_enabled)。
实时运行状态

WRM 会在后台检查每个已保存的连接,并在侧边栏中显示结果:

  • 🟢 正常(悬停可查看延迟、持续时间、SSH 服务版本),🟡 较慢(超过 300 ms),🔴 离线(闪烁;悬停可查看持续时间和原因——连接被拒绝、超时、找不到主机名……);位于跳转主机后方的连接会显示一个圆环。
  • 文件夹会显示其中有多少个连接处于离线状态(2↓)。有连接离线时,连接树上方会显示红色栏,点击一次即可仅显示离线连接。
  • 通知: 服务离线或恢复时会显示消息;WRM 在后台运行时会发送桌面通知(Settings → General → Notify when a server goes down)。在浏览器之外,可通过通知发送电子邮件、聊天消息或推送通知。
  • 通过代理: 使用代理的连接会经由代理进行检查(启用 Check through jump hosts 时,也会经过跳转主机)。
  • 🔄 立即检查状态(右键点击连接或文件夹)会立即进行检查——也会经过跳转主机——并显示每个连接的结果。
  • 检查方式: 与连接的端口建立 TCP 连接(SSH 22、FTP 21、Web 80/443 或你设置的端口)。SSH 检查会读取服务横幅,并在关闭连接前发送 SSH-2.0-WRM_status_check;FTP 检查会读取 220 问候消息并发送 QUIT——与 Nagios 的 check_ssh/check_ftp 相同。不会登录。检查失败后会再重试一次,之后才将服务计为离线。每轮中,每个不同的主机:端口只检查一次,无论有多少连接和用户指向该地址。
  • **位于跳转主机后方时,**连接会显示其跳转主机的状态(跳转主机离线时显示红色圆环)。启用策略 Check through jump hosts 后,WRM 每轮会登录跳转主机一次,并通过该 SSH 连接检查其后方的端口。
  • 取消勾选连接中的 Monitor up/down status,即可将其排除在检查之外(例如,有些服务经常会按计划关闭)。
  • 策略:status_enabled(开启)、status_interval_seconds(60,范围 15–3600)、status_jump_checks(关闭)。

fail2ban / IDS: 此检查是普通连接,不会登录。默认的 fail2ban sshd 筛选器不会将其计入,但 aggressive / ddos 模式可能会。可将 WRM 服务添加到 ignoreip、延长检查间隔,或取消勾选此类主机的监控。

日志:查看器、搜索和日志设置

监控 → 日志,选择一个服务。

  • 发现通过连接的 SSH 账号运行,不使用 sudo:一条只读命令读取 systemd 单元、Supervisor 程序和 Docker 容器;另一条命令在扫描路径上运行 find,并设有时间预算。没有 shell 的账号(仅支持 SFTP)会改用 SFTP 遍历。脚本和代码(.py、.sh、.js 等)不会列为日志,即使它们位于日志文件夹中也一样。
  • 文件列表:按最新、最旧、名称、大小、服务、操作人员或路径排序;按操作人员、服务、文件夹和名称筛选;勾选文件后即可只搜索这些文件。每个文件都会显示其操作人员和服务标签、所在位置属于日志文件夹(/var/log、log、logs 等)还是应用文件夹(脚本、应用程序),以及文件夹、大小和修改时间。服务比较时不区分大小写,因此日志文件夹 /var/log/VideoX_NOVA 和脚本文件夹 /home/scripts/Videox_NOVA 会被视为同一服务的两个文件夹。
  • 文件夹树(视图:文件夹树):日志按其主文件夹(扫描路径、Git 工作区服务根目录,以及 日志设置中的主文件夹)及其子文件夹分组。点击文件夹即可展开或收起;勾选文件夹会选中其中显示的所有日志。文件夹筛选器显示相同的树,并会在任一视图中保留一个文件夹及其下的所有内容。
  • **操作人员:**路径模式和固定文件夹中的标签优先显示。开启 猜测操作人员(默认开启)后,服务名称和文件夹名称中重复出现的词会被视为操作人员,除非该词是产品名称(多个名称中的首个词)或环境词(qa、test、dev、prod、bkp 等):VideoX_NOVA、VideoX_NOVA2、novatv 和 INGEST_SFTP_novatv 会得出操作人员 nova 和 novatv。一个操作人员名称以另一个名称开头(且至少有四个字母)时,会组成一组;操作人员筛选器会提供该分组(nova (5) · nova, novatv)以及每个成员。猜测出的操作人员会以 ≈ 标记。
  • 日志标签页:行号、级别颜色(堆栈跟踪沿用其所在行的级别)、高亮显示时间、IP、URL、HTTP 状态码、UUID 和键值对,在日志中查找(正则表达式、大小写、↑ ↓、仅匹配行),级别筛选标签(错误、警告、信息、调试、其他)、跟随(每 2.5 s 获取新行;对于日志记录器,按游标获取)、加载更早的行、跳转到行、自动换行、行号、复制、下载和在此处打开终端。快捷键:/ 查找,n / N 下一个和上一个匹配项,g 跳转到行,f 跟随,w 自动换行。
  • 搜索标签页:搜索在服务端运行(grep),因此可以快速搜索大型和较旧的日志:按字面内容或正则表达式搜索、大小写、整词匹配、上下文行、按你的日期格式设置 起始时间 / 结束时间并使用快捷范围(15 分钟至 30 天)、日志时区,以及选定文件或显示的文件。匹配项按时间排序(可选择顺序),并提供级别筛选标签、按文件筛选和可缩放的时间轴。点击即可在对应行打开文件。
  • ⚙ 日志设置(按服务配置,仅其所有者可以更改):扫描路径、用于文件夹树的主文件夹、猜测操作人员、排除名称、用于标注操作人员和服务的路径模式(默认 /home/*/{operator}/{service}/{logdir}/**、/srv/{operator}/{service}/{logdir}/** 等)、额外的日志名称模式、深度、最大文件数和文件年龄、时间预算、轮转和压缩文件、空文件、systemd 日志记录器、systemd/Supervisor/Docker 元数据、指定文件夹和日志记录器单元,以及方法(auto、ssh、sftp)。Zabbix 设置仍在 Zabbix 对话框中。
  • **🤖 AI 日志助手:**位于日志旁边的聊天面板,可通过 search_logs 搜索所有已发现的日志,读取匹配项附近的内容,并说明故障内容、开始时间、发生频率以及受影响的服务。它始终为只读。其聊天记录与终端聊天记录分开列出,并显示标题、日期和时间。
  • **日期和时间格式:**默认使用欧盟格式(dd.mm.yyyy hh:mm);可在 设置 → 日期和时间格式中选择 ISO、美国格式或浏览器区域设置(按浏览器保存)。
通知(电子邮件、聊天、推送、Webhook)

WRM 也会告知你浏览器之外发生的事件。管理员设置通知渠道(管理面板 → 通知),用户选择接收哪些通知以及接收位置(设置 → 通知)。应用内消息和浏览器通知保持不变。

  • 渠道:
类型所需信息
电子邮件(SMTP)服务器、端口、安全方式(STARTTLS / TLS / 无)、可选登录信息、发件人、收件人。登录信息仅会通过 TLS 发送,或发送到 WRM 所在机器上的服务器
Telegram机器人令牌(@BotFather)、聊天 ID;可选本地 Bot API 服务器地址
Slack / Mattermost / Rocket.Chat传入 Webhook URL(Slack 格式)
Microsoft TeamsWorkflows Webhook URL(收到 Webhook 请求时发布到频道);以 Adaptive Card 形式发送
DiscordWebhook URL
ntfy服务器(ntfy.sh 或自有服务器)、主题、可选访问令牌
Gotify服务器、应用令牌
Pushover应用令牌、用户或群组密钥
WebhookURL;WRM 会 POST JSON(title、text、events)。设置签名密钥后,接收方可通过标头 X-WRM-Signature: sha256=<HMAC-SHA256 of the body> 验证请求
  • 密钥(密码、令牌、Webhook URL)会经过加密,且不会再次显示;留空字段即可保留原值。📨 发送测试会立即发送测试消息并显示服务的响应(HTTP 400 chat not found、SMTP login: …)。每个渠道都会列出最近一次投递结果和最近一次错误。
  • 用户可以填写自己的收件地址(电子邮件、Telegram、ntfy、Pushover):每位用户都可以填写自己的地址、聊天 ID、主题或用户密钥(电子邮件:仅限纯文本地址);否则使用渠道默认值。没有默认收件人的渠道需要用户填写自己的收件信息。通过连接名称无法在 Slack 格式和 Discord 消息中提及 @channel / @everyone。
  • **事件:**服务器宕机、服务器恢复运行(仅限所有者自己的受监控连接;关闭监控的连接不计入)、凭据轮换到期(到期期间每 7 天再次通知)、凭据轮换未完成(每天再次通知)。
  • 每轮发送一条消息:一个状态轮次(或几秒内)发生的事件会合并为每位用户、每个渠道的一条摘要;每个渠道向同一收件人发送消息的间隔至少为 notify_min_interval_seconds(60);期间发生的事件会纳入下一条消息。
  • 免打扰时段(按用户浏览器的时区):消息会暂存,并在免打扰时段结束时一并发送。
  • 消息使用用户的语言(English / Hrvatski)。等待发送的消息会在重启后保留;发送失败的渠道会逐渐延长重试间隔,最多重试 6 次后放弃。
  • 策略 notifications_enabled(开启)和 notify_min_interval_seconds。渠道变更和测试会记录审计日志(admin.notify_channel_*),订阅变更也会记录(notify.settings_changed)。
Git 工作区:比较服务

顶部栏中的 ⎇ Git 会打开全屏工作区(其代码 static/git.js 仅在此时加载)。它可以回答哪些服务的哪个版本运行在哪里,以及手动更改了哪些内容——适用于你连接的任何 GitLab 或 GitHub(云端或可自托管)。WRM 不附带任何服务或组织专属配置。服务器无需安装 git、Python,也无需访问互联网:WRM 会直接读取 Git 提供商的 API,并通过现有 SSH 连接在服务器上运行,因此跳板机、代理和密钥库都适用。检查只会读取信息;只有执行下一节所述的运行操作时才会更改服务器。

  • 源(Settings):GitLab(API v4)、GitHub(REST;github.com 或 Enterprise <url>/api/v3)或 Gitea(API v1,<url>/api/v1),需使用只读令牌(加密保存,绝不会发送回浏览器)。Test 会列出目录中各组/组织的项目(包括子组)。自签名 Git 服务器会在首次使用时固定其证书。
  • **减少 API 调用:**每个版本仅需递归列出一次目录树(永久缓存,提交永不更改),即可获取每个文件的 blob ID;只有当 WRM 尚未见过某个 blob 时,才会下载该文件的内容,并按 blob ID 缓存——同一个文件出现在 20 个版本中也只会获取一次。
  • 离线包(Settings → Offline bundles):当 WRM 无法连接 Git 服务器时,可导入在其他位置构建的 .tar.gz——包含一个顶层目录,其中有 bundle.json(按服务记录目标 ref,以及每个文件的哈希和历史)和 payload/<service>/<path>;deploytool.py 和 README.txt 会被忽略,payload 中的受保护文件绝不会被使用。列表会显示离线包的创建时间、作者和来源。Services → Export bundle 会以相同格式导出离线包,供只能通过基于文件的部署工具访问的服务器使用。Targets from:自动(Git API,否则使用最新离线包)、Git API 或离线包。
  • 服务目录(Services):名称、项目、ref(tag:latest、tag:v2 = 最新的 v2.x,或分支)、标签对应的分支、标签筛选器(正则表达式)、作为安装根目录的仓库子目录、包含/排除 glob 模式、每台主机的受保护文件(config*、*.ini、.env;按 Python 的 fnmatch 对路径和文件名进行匹配),此类文件绝不会被覆盖,且只会显示;用于识别安装的指纹文件、安装提示(目录名称)和类型(应用、库、工具)。Suggest from repository 会根据仓库目录树填充条目。Import catalog(合并或替换)和 Export catalog 使用目录 JSON(gitlab.url / groups、fallback_branches、server_roots、apps、ignore_dirs)。导入的离线包中的服务即使没有目录条目也可使用。
  • **Refs:**只有提交位于所选分支上的标签才会计入(branch-aware);版本按数字排序(v1.10 排在 v1.9 后);tag:latest 没有匹配的标签时会使用分支头,而分支不存在时会回退到 fallback_branches 或默认分支——两种情况都会显示警告。总览中的 Ref:与目录中的设置一致、所有项目使用同一个分支,或每个项目使用其默认分支。
  • 发现(Installations → Discover,以及每次检查时):每台服务器执行一次 SSH 调用,遍历服务器根目录(/opt、/srv 等),深度为 3,并通过指纹文件查找安装。看起来像副本或备份的路径会被跳过(包含 bkp、backup、bak、old、orig、prev、copy、kopija、stari、recyclebin、trash、snapshot 的路径段、策略 git_backup_words,以及目录中的 ignore_dirs)。环境根据路径推断:/srv/scripts/test/App → test,/opt/App_prod → prod。也可以手动添加安装。
  • 比较:服务器使用 tr -d '\r' < f | sha256sum(或 shasum / openssl)计算文件哈希;WRM 会将其与目标文件(SHA-256,CRLF 转为 LF)以及每个文件的较早版本(该分支的较早标签,使用 Settings 中的 History depth)比较。文件状态为正常、较旧(落后 n 个版本,并显示匹配的标签)、已修改、缺失、额外(仅在服务器上)或受保护;文件已修改时,安装状态为需审核;文件较旧或缺失时,状态为需要更新;否则为已是最新。部署工具的 VERSION.md 和 updates.jsonl、.deploy-bak、.git、__pycache__ 均不纳入比较。
  • 从代码推断版本:根据比较的文件推断已部署版本,而不是从 VERSION.md 读取。当所有受跟踪文件都与某个已知版本匹配时,会准确显示该版本;较旧且一致的版本会在其 Git 提交目录树中查找;文件混杂或有手动编辑的文件时,会显示混合/已修改及各文件状态,绝不会猜测为某个版本。Check now 旁边的复选框(默认关闭)也会比较 VERSION.md,并在不一致时发出警告;为保持兼容,部署和更新仍会写入该文件。
  • 详情:检测到的版本、提交和日期、可选的 VERSION.md 版本(启用复选框时)、单位文件中提及该目录的 systemd / supervisor 单元、文件状态,以及文件的彩色差异(服务器 → 目标)。
  • 总览:每项服务的目标(版本、最新标签、来源、警告),以及服务器 × 服务矩阵,显示每项安装的状态、环境、检测到的版本和落后 n 个版本的信息,并可按状态、环境、文件夹、标签和文本筛选。
  • 定期检查(Settings → Periodic checks):WRM 运行期间,每隔 git_check_interval_minutes(60)分钟检查所选服务器。检查绝不会更改任何内容。检查会通知用户(每轮发送一条摘要):服务有新版本、出现偏差(安装状态变为需审核)以及无法连接的服务器——请在 Settings → Notifications 中订阅 Git 事件。
  • 所有内容均按用户隔离(源、目录、安装)。策略 git_enabled(隐藏工作区)、git_checks(有权运行检查的用户:所有人)、git_check_interval_minutes、git_backup_words。检查、离线包导入/导出、源和目录的更改以及查看差异均会被审计(git.*)。
Git 工作区:服务功能和配置

打开 监控 → 功能,或在 Git Simple 模式下点击 功能 按钮。此功能使用现有的服务目录和安装信息,包括 GitLab 源。手动和定期 Git 检查会检查每台所选服务器上的所有 Supervisor 工作进程、失败的 systemd 服务、安装占用的磁盘空间以及 Linux 内存使用情况(达到 90% 时发出警告)。每项安装都会检查发现的或已配置的单元,并报告健康、警告、失败或未验证状态,同时显示时间戳和有大小限制的错误日志。某个 Supervisor 工作进程正在运行,不会掩盖其他失败的同级进程。缺少的安装仍会显示。读取权限失败、缺少工具、未进行运行时检查以及扫描不完整,均不能报告为健康。

编辑服务以设置可选的运行时单元、HTTP 健康检查 URL 或 TCP host:port。HTTP 检查接受 2xx 状态码、不跟随重定向并验证 TLS;探测通过 SSH 从所选服务器发起。单元命令使用 SSH 账户,不会自动使用 sudo 或重启。命令受 30 秒运行步骤限制(可用时,单条命令的超时时间为 6 秒);端点的超时时间为 6 秒。服务器清单最多检查 256 个工作进程和 64 个失败的 systemd 单元;如果检查不完整,会明确发出警告。每次检查的日志上限为 16 KiB,并会在存储前进行脱敏。

配置会按需读取配置文件,并显示节、变量/函数、已配置的值和注释说明。显式指定的相对路径 config_files 优先;否则 WRM 会发现 .ini、.conf、.cfg、.env* 以及 config/settings 文件。JSON 会被展平为设置路径;INI 和赋值格式的设置会被解析,但不会执行源代码。无法识别的行会计数。敏感名称对应的值、凭据 URL 和已知令牌格式会被遮盖;配置内容不会存储在数据库中。每次最多检查 20 个文件,每个文件不超过 256 KiB,每个文件最多检查 2,000 个条目。符号链接越界、文件不可读或缺失以及超出限制的情况都会报告。

可选目录字段(现有目录仍然有效):

"functionality": {
  "units": [{"kind": "systemd", "name": "demo-api.service"}, {"kind": "supervisor", "name": "demo-workers"}],
  "http": "http://127.0.0.1:8080/health",
  "tcp": "127.0.0.1:8080",
  "config_files": ["config.ini", ".env"]
}

在 设置 → 通知 中订阅 git.functionality_problem、git.functionality_recovered、git.server_problem 和 git.server_recovered。服务器事件会包含未关联目录的工作进程。通知会报告状态转换或警告变化,不会在每次检查时重复发送相同结果。

功能配置档案

在 监控 → 功能 → 配置档案 中,上传 storage_backend.ini 或 config.py 等参考文件,选择目录服务、每项安装内的相对路径和可选的操作员标签。针对该服务的所有安装运行档案检查(也可通过 API 指定安装 ID)。矩阵会显示主机名、连接、服务、环境、操作员、路径、时间戳、节/键/函数以及参考值/实际值。搜索可匹配服务器、操作员和设置。值会标记为匹配、不同、额外、缺失或已遮盖。

档案使用现有的静态解析器:Python 表达式会作为源文本显示,绝不会求值。解析缺漏、文件缺失、不安全的符号链接和检查不完整都会明确标示。每个账户最多支持 50 个档案、256 KiB 的参考文件、每次检查 50 个安装以及 4 个并发读取。结构化参考值会在 SQLite 中脱敏并加密;实时远程值则按需读取。这些档案检查的是 WRM 目录中的安装;Medium 使用自己的原生配置,不会自动将其私有项目注册到该目录中。

Git 工作区:Medium 原始部署工具

选择 Medium(位于 Simple 和 Advanced 旁边)。使用组合 ZIP 字段和 Prepare and run trusted ZIPs 来保留依赖项设置并自动启动;请参阅设置指南。Advanced 的单项导入控件仍可使用。原始工具必须以私有 ZIP 的形式提供,本公开仓库不包含该工具。管理员导入获批的工具 ZIP;WRM 会创建其 Python 虚拟环境,并安装归档中固定版本的 requirements.lock。设置可能需要几分钟,并会报告状态。每位用户导入自己的部署配置 ZIP(servers.yaml、environments.yaml、projects/*.yaml)以及可选的 SSH ZIP(config、密钥和 known_hosts)。在 UI 中确认可执行代码/配置导入。替换配置文件/配置档/设置前,请先停止运行时;比较或后台部署正在进行时,不允许停止。

原始工具在 WRM 经过身份验证的 /medium/ 桥接层后运行,可嵌入工作区或在完整窗口中打开。它自身的项目编辑器、服务器/标签/分支选择、比较、排除项、本地构建、试运行、确认、部署、各服务器进度、备份、回滚、历史记录和配置 Git 控件均可继续使用。请参阅兼容性记录。关闭 Git 窗口不会停止进程;重启 WRM 会停止进程。运行时数据会保留在磁盘上。

使用 Runtime settings 配置原始工具的 DEPLOY_CONFIG_REPO、拉取/检查频率、用户电子邮件/主机名、SSH 选项、构建用户和超时。偏好设置会加密;读取时,已存储的命令/凭据值会被隐藏。配置 Git 克隆与导入的扁平配置分开存放。要使用原生 Git 推送,必须配置 Git 身份、密钥、已知主机验证和仓库写入权限。上传的 SSH 文件使用用户的私有运行时主目录;管理员可为获准使用服务器端密钥的用户提供 WRM_MEDIUM_SSH_AUTH_SOCK。

Medium 在 Linux、macOS 和 Windows 上的受管 Docker 运行时中运行原始工具(v12.6.6);其 Linux 镜像自带 Python、git、SSH 和 rsync,WRM 会自行安装 Docker(见下文)。主机运行时(WRM_MEDIUM_RUNTIME=native,以及 FreeBSD 等无 Docker 系统上的默认运行时)要求 WRM 主机上安装 Python 3.12+、git、OpenSSH 和 rsync(可通过 WRM_MEDIUM_PYTHON 选择 Python)。构建需要原始工具链及操作系统用户权限。运行时必须能够访问 Git 和目标主机。**仅向可信操作人员授予 Medium 权限:**可编辑的配置/构建/部署命令会以 WRM 操作系统账户身份执行。每位用户的目录/进程并非操作系统沙箱。WRM 会检查身份验证、git_medium、Git 检查和操作策略,并记录操作边界;原始工具则提供其原生的审查/锁定/历史记录功能。Simple 和 Advanced 仍使用 WRM 现有的引擎和目录。

由 WRM 安装的 Medium Docker

Medium 在所有操作系统上使用同一个 Docker 运行时(v12.6.6)。如果缺少 Docker,步骤 2 会说明 WRM 将安装哪种 Docker 以及安装方式,管理员按一次 Install Docker 即可。该授权会记录管理员姓名和时间,并纳入审计(git.medium_docker_consent);此后,导入工具 ZIP 或选择 Prepare runtime / retry 时,系统会自动安装、启动并准备所有内容,无需再次点击。每个步骤(Installing Docker、Downloading Docker Desktop、Checking the installer's signature、Starting Docker、Waiting for the Docker engine)都会显示时间、输出和失败时的处理方法,并保留在活动日志中。

WRM 主机WRM 的操作
Linux,WRM 以 root 身份运行从发行版的软件包安装 Docker Engine(apt-get install docker.io、Fedora 的 moby-engine、Amazon Linux 的 docker、RHEL/CentOS/Rocky/Alma 上 Docker 的 docker-ce 软件源,以及 zypper/pacman/apk 的 docker),并启动其服务(systemctl enable --now docker、OpenRC 或 service)。在 WRM 自身受沙盒保护的 systemd 服务(ProtectSystem=strict)中,命令通过 systemd-run 作为单独的单元运行。WRM 的代理变量(HTTPS_PROXY、NO_PROXY 等)会一并传递。安装有独立的 45 分钟时限,因此绝不会中途停止软件包管理器。
Linux,WRM 以普通账户运行如果有免密码 sudo,则通过 sudo -n 执行相同操作,然后将 WRM 的账户加入 docker 组(重启一次 WRM)。否则,步骤 2 会显示一条由 root 运行的命令:sudo wrm -setup-docker -service-user <account>。该命令会安装并启动 Docker Engine,将账户加入 docker 组,并重启 WRM 服务。
Linux,WRM 在容器中运行无需操作:将主机的 Docker 套接字和 CLI 挂载到 WRM 的容器中。
macOS从 docker.com 下载 Docker.dmg,检查其是否由 Docker Inc. 签名(团队 9BNSXJN65R),并为 Mac 上已登录的用户安装已接受许可的版本(以 root 身份或使用免密码 sudo;Docker Desktop 随后会在该用户的会话中运行,因此必须有人登录);如果没有管理员权限,则将 Docker Desktop 复制到 ~/Applications 并启动,其首次启动窗口需要在 Mac 上确认一次。
Windows从 docker.com 下载 Docker Desktop 安装程序,检查其 Authenticode 签名(Docker Inc.),并为已登录的用户静默安装(install --user --quiet --accept-license --backend=wsl-2)。首次运行时,Windows 可能会要求启用 WSL(需要管理员确认)并重启。WRM 作为 Windows 服务运行时无法运行 Docker Desktop:请为已登录的用户安装,或以该用户身份运行 WRM。

Docker Desktop(Windows、macOS)可免费用于个人用途、教育用途、非商业开源项目和小型企业(员工少于 250 人且年收入低于 1,000 万美元);规模更大的组织需要付费订阅。WRM 会显示此信息和 Docker Subscription Service Agreement,并仅在管理员接受协议后安装 Docker Desktop。Linux 上的 Docker Engine 是开源的,无需接受许可。策略 medium_docker_install 可关闭自动安装;管理员可以通过 POST /api/git/medium/docker {"accept": false} 撤回同意。如果 Docker 已运行但拒绝 WRM 账户的访问(permission denied),系统会显示相同的 -setup-docker 命令。

代理和会检查 HTTPS 的防病毒软件。 Medium 的 Docker 运行时除信任镜像自身的根证书外,还会信任 WRM 主机信任的根证书:Windows 证书存储(用户、计算机、组策略、企业)、macOS 钥匙串或 Linux/BSD CA 证书包。WRM 会将证书(仅公共证书)写入 <database>.medium/host-ca.pem,并以只读方式挂载到每个 Medium 容器中,pip、Python、git 和 curl 会使用合并后的证书包。如果没有此设置,在代理或防病毒软件会检查 HTTPS 的网络中,Docker 内的 pip 会因 self-signed certificate in certificate chain 而失败。使用策略 medium_host_ca 可关闭此功能;如果代理的根证书不在主机的存储中,请将其导出为 PEM,并在 medium_ca_file 中设置其路径。

Medium 分步操作、状态和活动日志

Medium 视图(v12.6.5)将其分为两部分:原始部署工具(用于部署和回滚)和 WRM 预览(只读,见下文)。原始工具的卡片会显示状态(关闭、运行中、已运行、需要处理)和编号指南:

  1. 部署工具 ZIP(管理员,一次):导入已批准的工具,并自动开始第 2 步。
  2. 准备运行环境(管理员):Docker(经管理员一次性同意后由 WRM 安装,并在需要时启动)、Docker 镜像和 Python 环境,然后是工具的 Python 包;或者在 WRM 主机上使用 Python、虚拟环境和包。首次执行时会下载镜像和包,可能需要几分钟;准备运行环境 / 重试会重新执行此步骤。
  3. 你的部署配置 ZIP:WRM 会立即使用自己的读取器(规则与原始工具相同)检查它,并指出错误所在的文件和键。如果运行环境尚未就绪,或正在执行其他 Medium 操作,ZIP 会保留,并由原始工具检查,在你下次启动时应用;WRM 预览会立即使用它。如果原始工具拒绝某个部署配置,该配置会被丢弃,并继续使用之前的配置;如果无法执行检查(例如 Docker 未运行),ZIP 会保留。
  4. 你的 SSH 配置文件 ZIP(可选):以相同方式保留。
  5. 启动 / 停止:启动会运行原始工具的配置检查,将你的文件复制到运行环境中,启动进程并等待其响应;只有此时才会显示为已运行,并在下方打开其标签页。停止只会结束你的进程,即使它仍在启动也一样。

暂时无法执行的步骤会说明原因(例如运行环境仍在准备中),其按钮会被禁用,并在工具提示中显示原因。操作运行期间,所有人都能看到操作内容、发起者和开始时间;发起者可以查看每个步骤及其开始时间和持续时间,也可以查看实时输出。操作失败时,会保留显示失败步骤、错误和处理方法,以及输出的最后几行。操作运行期间再次点击会被拒绝,并返回 409,指出操作、用户和开始时间。一键完成仍会保留合并后的准备并运行表单。

下方的活动日志会列出每项 Medium 操作(导入、准备、启动、停止、设置、WRM 预览运行、对原始工具的请求),并显示时间、用户、结果和持续时间;点击某一行可查看其步骤和输出。用户可查看自己的记录及共享运行环境的记录;管理员可查看所有记录。每项操作的命令输出(Docker、pip、配置检查、原始工具的进程)都会保留(最多 200 行),机密信息会被隐藏,并加密存储在数据库中(medium_activity,每位用户和共享运行环境最多保留最新的 1000 条记录)。medium_log_output 用于决定谁能查看输出:all(默认值:执行操作的用户、管理员,以及共享运行环境的所有人)、admins 或 none。WRM 的控制台会按 Medium (user): … 的格式记录每项操作和步骤。

Medium 原生引擎

Medium 视图中有一个 WRM 引擎面板。它会将一个分支或标签与某个环境的所有服务进行比较;对于使用原生引擎的项目,无需 Docker 和原始工具即可部署和回滚(路线图)。将原生引擎设为默认值(medium_default_engine=native)后,该面板会置于首位并默认展开,原始工具卡片则会折叠为可选项;也可以从 WRM 引擎面板导入部署配置 ZIP。

  • **配置:**导入的 deploy-config(servers.yaml、environments.yaml、projects/*.yaml)会由 Go 读取器按原样读取,并应用原工具的验证规则:未知键和重复键、YAML 1.1 布尔值和 << 合并、名称、主机、端口、allowed_refs、每个环境的 servers 列表、忽略规则、绝对路径、source_dir、状态位置(.deploy/<app> 或 state_dir),以及相互重叠或嵌套的目标。错误会指出文件和键。
  • **环境服务器限制:**环境的 servers: [name, ...] 会像原工具一样,将该环境中每个项目目标限制为指定服务器。列出的服务器必须存在于 servers.yaml 中;未知、重复和空列表都会被拒绝。省略此键即可允许使用所有服务器。
  • **服务器和 WRM 连接:**每台服务器会自动匹配地址和用户名相同的已保存 SSH 连接(Automatic),也可以关联到选定的连接。关联按用户保存,并会记录审计日志(git.medium_server_linked)。密钥保留在 WRM 中。
  • **源:**项目仓库由同一主机上的 WRM Git 源(GitLab、GitHub 或 Gitea API)提供。分支、标签、完整引用和提交会在此解析;source_dir 下的文件通过 Blob 缓存获取,符号链接保留其目标;绝对路径或包含 . 或 .. 组件的路径会中止比较。
  • **计划:**对于环境中的每个目标,WRM 会通过 SFTP 遍历应用程序目录,并计算执行带有项目排除项的 rsync -rlc --delete 会产生的结果:新增、变更(SHA-256;如有 sha256sum,则在服务器上计算)、删除、类型变更、保留含有排除项的目录,以及“cannot make way”错误。它会以原格式显示服务器状态(current.json、最近的 history.jsonl 条目、锁的所有者)、allowed_refs 和确认规则,以及 post_deploy 命令。勾选变更项并选择 Compare again without the ticked ones,即可在本次部署中排除这些项目。
  • **与原工具比较:**Medium 运行时,原始比较流程(获取、导出、构建、rsync --dry-run)会通过经过身份验证的桥接运行,并对同一份已准备好的源计算原生计划。每台服务器都会显示 Same result as the original tool,或显示仅由其中一个引擎发现的变更。WRM Git 源也会与原始导出进行检查。
  • **每个项目的引擎:**可选 Original tool (Docker) 或 WRM native。未选择引擎的项目使用 medium_default_engine(获准使用 medium_native 的用户使用 native,其他用户使用原工具)。切换需要 medium_native 策略(默认值为 admins),并会记录审计日志(git.medium_engine_set)。两种引擎使用相同的服务器状态,因此可以随时将项目切换回来。
  • **试运行和部署:**部署使用你已审核的比较结果(及其修订版本);如果比较结果已更改、环境的 allowed_refs 不允许该引用,或环境启用了 confirm 但未输入其名称,则会拒绝部署。按配置顺序逐个处理目标:加锁(lock/ 和 lock/owner.json)、在锁定状态下重新比较(结果不同则不写入任何内容)、创建备份清单、将删除项移入 backups/<deploy_id>/、创建新目录、将文件上传到目标旁的临时文件并检查 SHA-256、替换文件(先将旧版本放入备份)、通过账户的登录 Shell 在应用程序目录中运行 post_deploy(medium_command_timeout)、最终检查、更新 current.json 和 history.jsonl、清理旧备份(保留本次部署和最近五次已应用的部署),然后释放锁。试运行会在第二次比较后停止。开始变更后失败的目标会写入部分历史记录,可供回滚;后续目标会跳过。
  • **历史记录和回滚:**每台服务器会显示当前版本、锁(所有者和已持有时长)、包含计数的近期历史记录,以及回滚将撤销的部署和将恢复的内容(从历史记录中选择,方式与原工具一致)。Dry rollback 会显示将要执行的操作;Roll back 会从备份中恢复文件、链接和目录及其模式,并记录 ROLLBACK 条目(rollback-<id>/ 会保留被替换的内容)。如果锁的持有时间超过部署可能持续的最长时间(根据 medium_command_timeout 和 medium_transfer_timeout 计算,至少为 30 分钟),且锁的所有者未变,则可通过 Release lock 释放锁。
  • **进度:**每位用户可在后台运行一次部署或回滚,并查看实时日志(命令及其输出)、各目标的结果,还可选择 Cancel;此操作会在下一个目标开始变更前停止运行。每次运行都会作为一行记录在 Medium 活动日志中。停止用户或启用 lockdown 会取消其运行任务。
  • 部署、回滚和释放锁需要 medium_native 策略;启用 step-up 时,还需要重新确认;所有这些操作都会记录审计日志(git.medium_native_deploy、git.medium_native_rollback、git.medium_native_lock_released、git.medium_native_cancelled,以及包含各目标结果的 git.medium_native_<kind>_done)。比较和试运行与 Medium 的其他功能一样需要 git_medium,并会记录审计日志(git.medium_native_preview)。
  • **文件详情:**计划中的每个变更文件都有 Details:以逐行方式比较服务器上的版本与分支版本,方式与 Git 工作区相同(每侧最多 512 KiB;对于新建和已删除文件、链接、目录及二进制文件,则会改为说明相关情况)。打开详情会记录审计日志(git.medium_native_diff)。
  • **行尾:**如果变更文件去掉 \r 后的内容与分支版本相同,则会标记为 line endings only(eol_only),并单独计数;对于不超过 8 MiB 的文件,每台服务器最多处理 2000 个文件时,会通过 tr -d '\r' | sha256sum 计算哈希(缺少 sha256sum 时通过 SFTP 计算)。计划不会因此改变:部署仍会发送这些文件,历史记录条目的 counts.eol 会记录其数量。
  • **deploy-config 编辑器:**选择 Edit deploy-config 会以文本形式打开 servers.yaml、environments.yaml 和 projects/*.yaml。Check 会加载包含你所做编辑的完整配置;只有文件成功加载且自打开后未发生更改时,Save 才会写入文件(否则需 reload)。注释、布局和 CRLF 行尾都会保留;可以创建和删除项目文件(不能创建或删除 servers.yaml 或 environments.yaml)。需要 medium_native 策略;操作会记录审计日志(git.medium_config_edit),并列入 Medium 活动日志。
  • **构建位置:**对于包含构建步骤的项目,请在预览前选择构建位置:WRM 主机、通过 SSH 连接的指定 Linux 构建服务器,或不构建(none)。此选择按用户和项目保存,并记录审计日志(git.medium_build_set)。系统会准备完整提交,在仓库根目录运行配置的 build 命令,并从结果中读取 source_dir。构建服务器会获得一个仅包含源代码的临时目录(不含 Git 元数据或 SSH 密钥),之后该目录会被删除;构建通过账户的登录 Shell 运行。计划会显示构建位置、平台、架构和最近一次构建输出;如果目标的平台或架构不匹配,则会显示原因并拒绝操作。WRM 主机构建需要配备工具链的 POSIX 主机,因此在 Windows 上请使用 Linux 构建服务器或选择 none。
  • **构建用户:**设置 medium_build_user(例如 wrm-build)后,WRM 主机构建会以该账户运行:在 Linux 或其他 Unix 系统上,WRM 必须以 root 身份运行;root 账户、属于 root 组的账户,以及可以读取 WRM 数据库、其密钥或 <DB>.medium 的账户都会被拒绝,并显示原因。构建目录会移交给该账户;构建进程只能获取 PATH、HOME、USER、LOGNAME、LANG 和 TMPDIR(不含 WRM 变量),计划会显示 as wrm-build。完成后,WRM 会在读取结果前收回该目录,并拒绝指向该账户不拥有的文件的硬链接。
  • **来自 Git 的 deploy-config:**如果 Medium 设置中配置了 DEPLOY_CONFIG_REPO,且有 WRM Git 源提供该仓库,编辑器的 Git 部分会显示仓库、分支、已拉取的提交、Git 是否有更新的提交,以及本地变更。选择 Pull from Git and use it 后,WRM 的副本(<DB>.medium/users/<id>/native-config)将成为当前使用的配置;导入的 deploy-config 不会被修改。仅当没有本地变更时,Pull 才会用分支头提交替换该副本(也可选择 Discard changes and pull);如果配置无法加载,则不会应用该提交。Commit and push 会验证完整配置;如果自上次拉取后 Git 上的某个已变更文件发生过变动,则会拒绝操作;然后通过源的写入令牌创建一个提交(GitLab commits API、GitHub Git data API,并以非强制方式更新引用;Gitea contents API;如果设置了 DEPLOY_USER_EMAIL,则使用该值作为作者),并拉取提交结果。Stop using the Git copy 会删除该副本,并改回使用导入的 deploy-config。需要 medium_native;操作会记录审计日志(git.medium_config_pull、git.medium_config_push、git.medium_config_git_stop),并列入 Medium 活动日志。
Git 工作区:所有文件与部分检查

安装的每个文件。 安装详情(在概览中点击安装项,或点击 Details)会读取一次服务文件夹,并列出每个文件——不仅是目录跟踪的文件——以及目标 ref 下、位于服务子目录中的仓库所有文件:

  • 列:路径、大小、修改时间、状态和原因:已跟踪、被目录排除(附带模式,例如 setup.py 或 tests)、不在包含列表中、受保护(附带模式)、不在 Git 中(仅在服务端)、由部署工具写入(VERSION.md、updates.jsonl)、已编译文件、在 Git 中但未跟踪。
  • **状态:**已跟踪文件的状态与检查中的相同(正常、旧、已修改、缺失);目录未跟踪的文件则为相同、不同或未比较;额外(仅在服务端)、缺失(仅在 Git 中)、符号链接(显示目标,绝不跟随符号链接,并标记指向安装目录之外的链接)、无法读取(权限被拒,包括目录)。
  • 目录的 ignore_dirs、看起来像备份的路径以及 .git、.deploy-bak、node_modules、__pycache__ 和虚拟环境不会列出;最多列出 10 000 个条目(文件夹中条目更多时会显示提示)。
  • **筛选:**全部、有差异、仅已跟踪、未跟踪,以及搜索。
  • 打开可显示任意文件(只读,最多约 1.9 MB;二进制文件显示其大小和哈希),文件可来自服务端或 Git。Diff 可比较仓库中的任意文件的服务端 ↔ Git 版本——也包括目录排除的文件,并标记为仅供参考,不会更新——支持统一或并排视图;与哈希计算一样,会忽略换行符格式。二进制文件和大文件通过哈希进行比较。
  • 目录未跟踪的文件仅供参考:它们不会改变安装状态(需检查/需要更新/已是最新仍只根据已跟踪文件确定)。
  • **落后提交数:**详情使用检测到的提交;启用 VERSION.md 复选框后,则改用 VERSION.md 中的提交(或版本)。详情会显示目标领先多少个提交并列出这些提交(通过 GitLab / GitHub compare API 获取)。当代码处于混合或已修改状态时,无法确定单个提交,因此不会显示列表。
  • 通过 SSH 读取服务端文件,路径会加引号,且仅使用 POSIX 工具;WRM 绝不会缓存这些文件。打开文件的操作会记录审计日志(git.file_viewed)。其他仓库文件来自目标提交的缓存树;其内容会像目标文件一样获取和缓存(每次列表最多获取 200 个未知文件)。

部分检查与增量检查。 在概览和 Installations 标签页中:

  • 筛选条件包括服务、服务端、状态(包括未检查)、环境、文件夹、标签,以及也会匹配主机名的搜索。
  • **选择:**每个安装项、每行服务端以及每列服务都有一个复选框(另有所有可见项)。可选择检查所选项、检查可见项(筛选结果中的项目)、↻ 检查此单元格、仅检查过期项(从未检查过,或检查时间早于 1 小时/24 小时/7 天)。标题栏中的 Check now 仍会检查所有内容(在 Settings 中配置的服务端上执行发现,并使用最新目标)。
  • **流式处理:**检查会作为后台作业运行;每个安装项一经比较便立即保存,在排队或检查过程中显示旋转指示器。点击 Cancel 会跳过排队中的项目,并丢弃正在运行的扫描。
  • 限制:git_check_per_server(每个服务端 2 个安装项)和 git_check_parallel(同时总计 8 个安装项)。
  • 未参与检查的安装项会保留原有结果,并显示 checked X ago。检查失败时会保留上次成功结果中的文件和计数,并在错误旁显示该结果。
Git 工作区:更新、升级、回滚与重启

仅在启动或安排运行时才会更改服务。在 Installations 选项卡中选择安装项(或打开一个安装项)并选择操作;一次运行会依次处理各安装项,并在首次失败时停止(滚动式)。所有操作都通过 SSH 和 POSIX 工具(sh、cp、mv、find、awk、tr、sha256sum)完成。

  • Update — 安装项所跟踪引用的最新版本。Upgrade… — 其他分支或标签(main、tag:v2、tag:latest),并显示警告和每个安装项的摘要:要更改的文件、新文件、本地已更改的文件,以及新版本中已不存在的文件(这些文件会保留在服务端)。Follow this ref from now on 会设置服务的引用覆盖值,因此之后的比较会使用该引用。Rollback… — 从 .deploy-bak/ 恢复备份。Stamp — 在已是最新版本且没有 VERSION.md 的安装项中写入 VERSION.md(Overwrite an existing VERSION.md 会强制覆盖)。对话框会列出有差异的文件;Also stamp installations that are not up to date 会将其写入其他安装项,并记录每个文件的实际版本(较旧文件记录其匹配的版本,手动更改的文件记录为 (local)),同时添加一行 Napomena,说明该安装项并非完整版本。从其他对话框打开的对话框会显示 ← Back(Alt+←)。
  • **选择文件:**默认勾选旧文件和缺失文件。只有在勾选后,手动更改的文件才会被写入,并会显示警告(其内容会保留在备份中)。受保护的文件绝不会被写入。Show all files 会同时列出当前文件。
  • 确认:显示摘要;对于生产环境安装项——标签为 env:prod(或 prod、production、prd、live),或环境目录名称为上述名称之一——需要输入服务名称。服务端会再次检查。
  • 每个安装项的步骤,会实时显示在运行详情中:
    1. 再次比较(重新扫描):自上次检查后有文件发生更改时,运行会停止,除非该文件已作为更改文件勾选。
    2. **悬空的 Python 导入:**写入 .py 文件时,如果该安装项中的其他文件有 from mod import name,而新的 mod.py 不再定义 name(扫描顶层的 def、class、赋值和导入;会解析相对导入和包),则运行会在写入任何内容之前停止。Skip the check for dangling Python imports 会在一次运行中关闭此检查。
    3. 备份将被替换的文件(以及 VERSION.md),保存到 <install>/.deploy-bak/<id>-<YYYYMMDD-HHMMSS>/<path>;对于来自 bundle 的目标,<id> 是 bundle ID,否则为运行 ID wrm-<YYYYMMDD-HHMM>。
    4. 原子写入:每个文件都会先写入同一目录中的临时文件(先从旧文件复制,因此权限和所有者保持不变),并通过哈希验证,然后全部重命名到位。换行符格式保持不变:CRLF 文件仍使用 CRLF;新文件采用该安装项中最常见的换行符格式;新文件的权限为 644(有 #! 行时为 755),所有者与安装项相同。
    5. 检查:对 .py 文件运行 python3 -m py_compile(存在 python3 时;其 .pyc 文件会写入临时目录),对 .js 文件运行 node --check,对 .sh 文件运行 sh -n(bash 脚本运行 bash -n),并可按服务运行可选的自定义命令(在安装目录中运行,退出代码为 0 表示正常;下次运行时会记住该命令)。
    6. **失败时自动回滚:**从备份中恢复被替换的文件(原子操作),移除新文件和新目录,并删除备份。在写入前失败的运行不会更改任何内容。
    7. 写入 VERSION.md 和 updates.jsonl 中的一行,然后再次比较该安装项。
    8. 可选地重启(见下文)。
  • 与基于文件的部署工具兼容——WRM 会写入这些工具使用的格式,因此两者可以并行使用:
    • 安装根目录中的 VERSION.md,采用安装项的换行符格式(绝不会参与比较):

      # demo-api - v1.10
      - **服务**:      demo-api
      - **版本**:     v1.10
      - **分支/ref**:   main (tag)
      - **Commit**:      0123456789 (2026-09-10)
      - **更新时间**:   2026-10-09 21:05:07
      - **主机**:        app-01
      - **用户**:    deploy
      - **Bundle**:      wrm-20261009-2105
      
      ## 服务(3 个)
      
      | 文件        | 版本       | 日期       |
      | ----------- | ---------- | ---------- |
      | config.ini  | (per-host) | -          |
      | lib/util.py | v1.10      | 2026-09-10 |
      | run.py      | v1.10      | 2026-09-10 |
      

      行按路径排序;列宽补齐至最长值。版本 是文件最新历史记录的标签,否则为其 commit;未更新的旧文件显示其匹配的版本,手动修改的文件显示 (local)。

    • updates.jsonl:每次安装和运行占一行(键已排序),写入 /var/log/deploytool/updates.jsonl、<install>/.deploy-bak/updates.jsonl 和 /tmp/deploytool-updates.jsonl 中第一个可写入的文件:

      {"app": "demo-api", "backup": "/opt/demo-api/.deploy-bak/wrm-20261009-2105-20261009-210507", "branch": "main", "bundle": "wrm-20261009-2105", "env": "prod", "files": ["lib/util.py", "run.py"], "from_version": "v1.9", "host": "app-01", "install": "/opt/demo-api", "services": ["systemctl demo-api"], "time": "2026-10-09T21:05:07", "to_version": "0123456789 (2026-09-10)", "user": "deploy"}
      
    • 回滚会列出安装的备份及其时间、VERSION.md 和日志行。备份中的文件来自 WRM 的运行历史或 updates.jsonl 行;恢复时会删除之前不存在的文件。对于没有此类记录的备份,只会恢复其中的文件。当前文件会先备份,因此回滚操作本身也可以回滚。

  • 重启服务(可选,默认关闭)。 服务单元是检查时找到的 systemd / supervisor 单元(其单元文件中提及了安装目录)。每次运行可选择:不重启(安装显示 ↻ restart pending)、成功更新后立即重启(按滚动顺序)、在指定时间重启或延迟重启。警告会列出单元和服务器。每次重启后都会进行健康检查(systemctl is-active 必须返回 active,supervisorctl status 必须显示 RUNNING);单元不健康时会停止运行。当 SSH 用户不是 root,但可以免密码使用 sudo 时,会使用 sudo -n。重启… 也会重启未更新的安装。
  • 计划任务(维护时段): When → At a chosen time。计划运行和重启会存储在数据库中,WRM 重启后仍会保留,并且可以取消(Runs)。如果更新失败,等待更新完成后执行的重启会被跳过。如果 WRM 在计划时间未运行,且超出 git_schedule_grace_minutes(30)分钟,则会跳过运行。通知:开始前 15 分钟(a scheduled run starts soon)、开始时和结束时。
  • Runs 标签页: 历史记录(每位用户最近 500 次运行)和计划运行,显示安装、版本、状态和每个步骤;可对正在运行的任务选择 Stop after the current server。
  • 策略: git_update(更新并标记)、git_upgrade、git_rollback、git_restart —— 默认对 admins 开放,也可设为 all 或 off。每个安装的运行都会记录审计日志(git.update、git.upgrade、git.rollback、git.restart、git.stamp,包含结果、文件、备份和版本),计划、取消和跳过的运行也会记录。
Git 工作区:标签页说明

高级 Git 工作区的每个标签页(概览、服务、安装、环境、运行、活动、.gitignore、设置)都会在标题下方显示一段简短的通俗说明,标签页按钮上也会显示相同文本作为工具提示。设置窗口和管理面板也会在标签栏下方显示说明(设置:常规、终端、安全、通知、语音和音频、会话历史、AI 连接、数据;管理:概览……文件传输)。这些文本提供英语和克罗地亚语版本(gtd_*、stin_*、adin_* 键)。其他行为和布局均不变;简易模式保留自己的简介。

Git 工作区:简易模式

Git 工作区标题中有一个 简易 | 高级 切换开关。此选择会按用户保存在此浏览器的 localStorage 中;默认模式为 高级,其内容与其他 Git 部分所述的工作区完全相同。

简易模式是一个单一视图,适合只想了解当前部署情况并更新服务的用户。它会为每项服务的每个环境显示一张卡片。**无需手动设置:**连接 Git 源并且检查器在服务器上找到服务后,环境就会自动出现(参见下文的自动环境);在高级 → 环境中定义的环境仍会像以前一样显示,并优先于检测到的环境:

  • 服务器上的版本:每台目标服务器上检测到的版本和提交、可选的 VERSION.md(以及 立即检查 旁边的复选框)和部署者(如果尚未安装,则显示 尚未在此处安装)。
  • 分支上的最新版本:服务目标的版本、分支、提交和日期。
  • 一种状态:已是最新、有可用更新、未安装、不一致/已修改、无法比较或有问题。
  • 服务、主机名、环境和状态的组合筛选器,以及按分支、版本或提交进行搜索;每张卡片都会显示服务器状态的比较时间。
  • 大型操作按钮:安装(尚未安装)、更新(存在较新版本)、再次部署(已是最新)和回滚到上一版本。

安装、更新和部署操作会打开一个通俗易懂的确认页面:显示版本变更、每台服务器新增或更改的文件数量,以及可展开的文件列表,其中列出每个文件在各目标服务器上的状态。确认前,你可以选择比较成功的服务器并排除文件。不能提交空选择。简易模式会保留已从仓库移除的文件;高级模式允许在备份后删除这些文件。还可使用可选的 post_deploy 和 restart 复选框(在允许的情况下)、可选的不同版本(标签或分支),以及在受保护的环境中输入环境名称。回滚时,你可以选择要还原的服务器,并查看每台服务器当前的版本以及回滚后的版本。

自动环境。简易模式会从概览请求检测到的环境(?auto=1)。对于目录中的每项服务,检查器找到的安装(git_installs)会按环境标签分组(标签或文件夹名称提示;如果没有则使用 default),形成虚拟环境;如果标签表示生产环境,则仍会像以前一样要求输入环境名称。这些环境只是派生出来的:在你启动安装、更新或回滚之前,不会保存任何内容,也不会部署任何内容;启动操作后,会使用相同的计划、锁、备份、权限检查和审计流程。名称相同的已保存环境,或已列出相同服务器和文件夹的环境,会优先使用;存在冲突或无效的派生环境会被排除。提示会显示检测到的环境数量;对于获准执行 git_update 的用户,保存检测到的环境会将它们存入目录(POST /api/git/env/adopt,审计事件为 git.env_adopted;不会更改现有定义)。空的简易模式会提供在我的服务器上查找服务(执行常规检查)。高级标签页仅显示已保存的环境。 服务器按主机名显示。 无论 Git 工作区在哪个位置列出服务器(简单卡片和对话框、环境、活动、安装和运行),标签都显示服务器的真实主机名,而不是你选择的连接名称。WRM 会在检查和部署计划期间通过现有 SSH 登录获取 hostname,并将其缓存(git_hostnames,6 h);在获取到之前,则回退为连接的主机地址。筛选条件和请求仍使用连接名称。

简单模式会新增一个端点(POST /api/git/env/adopt),其他方面则使用高级部署中的环境概览、单元格、计划、历史记录和运行端点,因此权限(deploy 更新/回滚/重启)、锁、备份、记住的排除项、审计跟踪和运行历史记录都相同。设置、源、目录、活动、.gitignore、CI、计划任务和其他高级控制仍保留在高级模式中。

Git 工作区:环境、部署计划和安全部署

环境是可选的。没有环境的服务仍像以前一样,按安装项使用更新、升级和回滚。环境是同一服务的一组具名、有序目标,各自有规则;部署会先审核为计划,应用一次,在服务器上锁定,并在那里记录。

定义环境(环境标签页 → ✎,或目录 JSON):

"environments": [{
  "name": "prod",
  "destinations": [{"server": "app-01", "path": "/opt/demo-api"}, {"server": "app-02", "path": "/opt/demo-api"}],
  "confirm": true,
  "allowed_refs": ["refs/tags/v*"],
  "ignore": ["/data", "*.local"],
  "post_deploy": "./bin/migrate --yes",
  "keep_backups": 5,
  "state_dir": ""
}]
  • server 是 SSH 连接的名称(跳板主机、保险库凭据和代理的用法与其他地方相同);路径是服务目录的绝对路径,不是系统目录。
  • confirm 要求在部署或回滚前输入环境名称(对于名为 prod、production、prd 或 live 的环境始终如此)。allowed_refs 限制可部署的内容(refs/heads/main、refs/tags/v*;不带 refs/ 的模式会匹配简短的分支名或标签名)。ignore 会将模式添加到该环境的目录排除项中。post_deploy 会在文件部署完成后于应用目录中运行——仅当部署或回滚时勾选此项。每个目标会保留 keep_backups 个部署备份(1–50,默认为 5)。
  • state_dir(可选)会将服务器端状态移至 <state_dir>/<service>/<path with / as _>;默认位置为 <path>/.deploy-bak。
  • **验证:**同一服务器上的两个目标中,如果一个应用路径位于另一个之内,则会被拒绝,除非外层服务的排除项(或环境忽略项)涵盖内层路径;如果 state_dir 位于任何应用路径之内,也会被拒绝。

概览(环境标签页)是一个服务 × 环境表格。每个单元格都以延迟方式读取,每个单元格发起一个请求:每个目标已部署的版本和提交、部署者及部署时间(来自 state.json,否则来自 VERSION.md)、与服务目标相比落后的提交数量,以及是否存在锁。若某个环境中的服务器不一致,单元格会发出警告。

部署: ▶ 部署会将每个目标与目标版本(或其他引用,如 tag:v2、某个分支)进行比较,并显示每台服务器的计划:

  • 状态: new、changed(匹配不到仓库中的任何版本时标记为 changed by hand,或显示落后多少个版本)、same (CRLF/LF) — 仅行尾符不同:单独计数且仍会发送,因此部署会将行尾符规范化为仓库中的格式 —、removed from Git(在已部署的提交中存在于仓库,但现在已不在仓库中)、only on the server、protected、ignored(附带匹配模式)、same(Show all files)。
  • 排除文件:取消勾选某个文件,即可将其排除在本次运行之外;此选择会在下次比较时记住(并显示排除者和时间,使用 Clear remembered exclusions 清除)。⊘ service / ⊘ environment 会永久排除某个文件:系统会将带锚点且已转义 glob 字符的模式(/lib/a[[]1].py)写入服务的排除列表或环境的忽略列表,除非已有模式覆盖该文件;然后会重新比较计划。
  • **选项:**删除仓库中已移除的文件(选择启用)、运行 post_deploy(选择启用,会显示命令)、每个目标部署完成后重启单元(选择启用)、自定义检查命令。
  • **计划错误和警告:**如果某个分支将目录改为文件或反之,排除(或不删除)相关内容会导致错误;替换服务端符号链接、手动更改的文件、缺失路径(首次部署会创建该路径及其父目录)和锁会产生警告。
  • 每个目标的计划都有一个指纹,记录比较内容(服务端文件及其哈希值、当前部署、目标提交)。计划只能应用一次;新的部署需要重新比较。
  • 试运行使用与实际部署完全相同的选项,不获取锁、不写入任何内容,也不需要输入确认文字;运行日志会列出将要添加、更改、删除和运行的内容。Back to the plan 会返回同一计划。

每个目标按顺序执行(运行日志约每秒刷新一次):

  1. 锁:通过原子操作执行 mkdir <state>/.lock,并写入所有者文件——部署 id、WRM 用户、WRM 主机和服务端时间。由其他人持有的锁会阻止部署;部署只会释放自己的锁(所有者文件必须记录其部署 id)。
  2. **在锁定状态下再次检查计划:**如果指纹不同,部署会在写入任何内容之前停止(compare again)。
  3. 传输:将文件(和 VERSION.md)作为单个 tar 流传输到 <path>/.wrm-incoming-<id>(超时至少为 1 小时),并通过哈希值验证。传输中断会记录为部分传输,并记录实际到达的内容(随后再次移除);安装内容不会发生变化,也不会写入新的当前状态。
  4. 将被替换或删除的内容备份到 <state>/<id>/(使用现有备份布局),然后执行删除和重命名(被替换文件的模式和所有者保持不变;删除操作留下的空目录会被移除,并记录其模式和所有者),运行检查(py_compile、node --check、sh -n、自定义命令),失败时自动还原。
  5. **状态:**写入 deploys/<id>.json(清单:添加、更改和删除的文件、已移除的目录、之前的状态)、state.json(current 和 previous)、updates.jsonl 中的一行;如已选择则运行 post_deploy;随后在 history.jsonl 中写入 DEPLOY 条目,其中包含之前的状态以及新增、更改和删除文件列表(每类最多记录 500 个名称,同时记录实际数量)。超出 keep_backups 数量的最早备份会被删除。
  6. 发生故障时,运行会停止:不会启动剩余目标。post_deploy 失败会附带备注记录——文件已在服务端,且新状态已成为当前状态。

历史记录(🕘 History)会合并每个目标的 history.jsonl(每个目标一行),并在可展开列中显示文件列表。回滚按所选目标中的部署 id 执行(默认:所有最新部署对应的目标),按目标顺序逆序执行:

  • 在锁定状态下,它会检查此次部署是否仍是目标服务器上的最新部署,并确认其备份存在。
  • 部署新增的文件会被移动到 <state>/backups/rollback-<id>/(绝不删除);已更改文件的当前版本也会保存在那里,然后原子地恢复备份版本;已删除的文件会被恢复;已移除的目录会连同其权限模式和所有者一起重新创建。
  • 在服务器上,任何操作都不会通过符号链接进行:此类项目会被跳过,回滚会被标记为未完成(状态不会改变;修复服务器后再次回滚)。
  • 随后会运行 post_deploy(如果已勾选),已存储的先前状态会恢复为当前状态,并写入一条包含 rolled_back=<id> 的 ROLLBACK 记录。最近 5 个回滚备份会保留。试运行会显示回滚将执行的操作。

过期锁: 根据服务器时钟计算,超过最长 30 分钟或传输超时时间(取两者较大值)的锁即为过期。计划会在确认后提供移除过期锁选项;一条服务器命令会在移除前再次检查该锁是否为同一把锁(所有者 ID)且仍已过期(记录为 git.lock_removed)。

🩺 Doctor 会检查每个目标:SSH 登录、干净的非交互式 shell(命令运行前没有横幅或 rc 输出)、SSH 用户(使用 root 时会发出警告)、应用目录(可写;如果最近的现存父目录可写,则应用目录不存在也没问题)、状态目录、不可读的子目录、其他部署方式的迹象(.git、.svn、.hg、releases / current、通过符号链接指向的应用路径)、看起来像公共 Web 根目录的路径、sha256sum、rsync 和 tar 及其版本,以及锁。

环境部署和回滚都是普通运行:它们会显示在 Runs 选项卡中,可在当前目标完成后停止,会发送运行通知(试运行除外),并按目标记录审计日志(git.update / git.upgrade / git.rollback,包含 env、deploy_id、dry_run、partial、post_deploy)。

Git 工作区:活动、部署历史和部署位置

活动选项卡回答了谁在什么分支上做了哪些更改、谁把什么部署到了哪里,以及现在什么运行在哪里。它有三个视图,每个视图都有自己的筛选条件,并可**⬇ CSV**导出筛选结果的全部内容(使用带字节顺序标记的 UTF-8,便于电子表格处理;可能被电子表格执行为公式的值会加上前缀 ')。

Git 活动(按服务显示,数据来自其目标的 Git 源):

  • **GitLab:**项目中 action=pushed 的事件(所有分支和标签:推送者、提交数、起始位置 → 目标位置)以及所列分支的提交。**GitHub:**所列分支的提交,以及令牌权限允许时的仓库活动(推送、强制推送、创建和删除分支、合并)。**Gitea:**所列分支的提交。
  • **分支:**未选择分支时,会列出服务分支、目标分支、默认分支、目录的 fallback_branches 以及各环境 allowed_refs 中的分支上的提交(最多 6 个)。可在筛选器中选择项目的任意分支。同一提交若出现在多个所列分支中,只显示一次,并列出所属分支。
  • 筛选条件:分支、作者(姓名、用户名或电子邮件中的部分内容)和日期(默认:最近 30 天,最多 366 天)。筛选结果下方会显示按作者(提交、推送、分支、最近活动)和按分支(提交、推送、作者、最近活动、分支提交链接)的摘要;点击行即可按该项筛选。每条提交都链接到其提交页面,每次推送都链接到其范围的比较页面。
  • **API 限制:**每个列表会按提供方的后续链接最多请求 10 页;当提供方报告剩余调用次数不超过 5 次时,会提前停止。若列表不完整,会显示提示(如果提供方告知何时可以再次调用,也会显示时间)。遭遇速率限制的请求(HTTP 429,或剩余调用次数为 0 时的 403)会显示为提示,而非错误。结果会按用户、服务、分支和日期缓存 3 分钟(↻ 刷新会重新读取);作者筛选作用于缓存的列表。

**部署历史:**从每个环境的每个目标读取其 history.jsonl(部署和回滚,每个目标一行;通过 SSH 读取,与环境单元格相同,每个服务和环境请求一次,同时最多三个请求),并合并没有环境的安装记录中的 WRM 运行记录(更新、升级、回滚、安装、传输)——环境运行记录不纳入其中,因为其目标会保留历史记录。筛选条件:服务、环境、服务器、操作(部署 / 回滚 / 更新 / 升级 / 安装 / 传输)、操作者、分支、版本或提交、日期。每行显示结果、之前的版本、提交(带链接)以及可展开列中的逐文件列表(新增、更改、删除、排除、恢复、移至一旁等)。

部署位置:按服务、环境和服务器显示正在运行的分支、提交(带链接)和版本、部署者及部署时间(来自 state.json,否则来自 VERSION.md),以及落后于其分支头部的提交数,并链接到这些提交的比较页面。标签部署或不带分支的 VERSION.md 会按服务分支计算落后提交数。同一环境中提交和版本与其他服务器不同的服务器会高亮显示(存在差异)。没有环境的安装会根据最近一次检查列出(不使用 SSH)。单元格像环境选项卡一样按需加载;头部和比较结果会缓存 2 分钟。

策略:活动视图只需要 Git 工作区(git_enabled);服务器上的部署历史和矩阵需要 git_checks(即使没有该项,也会显示 WRM 自身的记录)。令牌不会传到浏览器。

Git 工作区:新增服务器(安装和传输)

两个向导可在服务尚未运行的服务器上设置该服务。两者都是运行任务(会在运行选项卡中显示每个步骤),启动后立即执行,并通过 SSH 使用 POSIX 工具和 tar。

  • 安装……(安装选项卡):
    1. **目标服务器:**任意 SSH 连接。
    2. 服务及其版本:目标版本(与目录中的相同)、其他分支或标签(main、tag:v2;需要 GitLab / GitHub 来源),或包含该服务的已导入离线包。
    3. 每个服务的目标目录,根据服务器根目录提供建议值(/opt/<service>),以及环境标签。系统目录(/etc、/usr、/opt 本身等)不允许使用。
    4. 目标上的预检查:可用磁盘空间(文件大小加 10 %)、可写目录(或最近的现有父目录)、tar,以及文件中含有 .py / .js 文件时的 python3 / node 版本(缺少工具时会发出警告并跳过相关检查),还有现有安装(目录中的文件)——除非勾选替换它,否则不允许继续;替换的文件和 VERSION.md 会先备份到 .deploy-bak/。
    5. 每台主机的文件。 WRM 会写入该版本的文件,不包括受保护文件,并提供每个受保护文件供填写:
      • 使用仓库中的模板:<name>.example、.sample、.template、.tmpl、.tpl、.dist、.default(也包括 settings.example.py → settings.py、.env.example → .env),或者使用仓库中存在的受保护文件本身。模板中的占位符({{ name }}、${NAME} / ${NAME:-default}、__NAME__、@NAME@、<NAME>)和**key = value / key: value 行**(INI 键采用 section.key 格式,保留引号)会变成表单字段,并使用模板中的默认值;看起来像密钥的名称会显示为密码字段。字段可以使用凭据库中的凭据(其密码或用户名;仅限主机列表允许目标服务器的凭据)。留空的占位符会保留在文件中(运行记录会注明)。
      • 从同一服务的另一个安装中复制(任意服务器),或手动输入,或留空。
      • 填写的文件权限会设为 640。输入的值和内容不会随运行记录保存;凭据库中的值只会在服务器端读取。
    6. 可选的自定义检查命令(与更新时相同)。
    7. 可选的服务单元(需主动选择,并会显示警告):systemd 单元(/etc/systemd/system/<name>.service:User=、WorkingDirectory=、ExecStart=、Restart=on-failure、daemon-reload,以及可选的 enable),或 supervisor 程序(/etc/supervisor/conf.d/<name>.conf 或 /etc/supervisord.d/<name>.ini,然后运行 supervisorctl reread)。将以 root 身份或通过 sudo -n 写入,绝不会覆盖现有文件。WRM 不会测试该命令。
    8. 可选的安装后启动(策略 git_restart):重启并进行健康检查那些包含该目录的单元,与更新后的处理相同。否则,安装会显示*↻ 等待重启*。
  • 运行内容:内容(来自 Git API 或离线包,以及填写的每台主机文件)会以单个 tar 流传输到目标中的暂存目录(.wrm-incoming-<run>),经哈希验证后再通过重命名移至目标位置;随后运行语言检查和自定义检查;任何失败都会回滚(从备份恢复被替换的文件,并移除新文件和目录)。接着写入 VERSION.md(写入方式与更新相同)和 updates.jsonl 行,注册该安装(如同手动添加,以便发现功能保留该安装)并进行比对,然后创建单元。
  • 传输……(安装项,位于安装选项卡或其详情页):将安装复制到另一台服务器或目录,同时保留其每台主机的配置,但不包括日志(log/、logs/、*.log、*.log.N、updates.jsonl)、.deploy-bak、缓存(__pycache__、*.pyc、.pytest_cache)、目录中的 ignore_dirs、看起来像备份的路径(目录名中含备份词,或文件名第一部分之后含备份词:data_BKP/、run.py.bak、config_old.ini),以及通常会排除的项目(.git、node_modules、venv、.venv——请在目标上重新创建)。向导会列出哪些内容会被保留,以及源服务器上的单元(不会复制;请在向导中创建单元)。文件会从服务器 A 经 WRM 直接流向服务器 B(tar -c → tar -x,WRM 磁盘上不会保留任何内容),并执行相同的预检查、覆盖确认、备份、验证、检查和回滚;VERSION.md 会写入新的主机和用户。
  • 确认:显示摘要;对于生产目标(标签 env:prod,或生产环境标签)和覆盖操作,必须输入服务器名称。
  • 策略:git_install 和 git_transfer——默认仅限 admins,也可设为 all 或 off。按安装项审计 git.install / git.transfer(结果、文件、备份、版本、来源、新安装)。通知方式与其他运行相同(已启动、成功、失败)。
Git 工作区:.gitignore 助手

Git 工作区的 .gitignore 选项卡会根据检查结果,为服务的仓库生成 .gitignore。选择服务后,WRM 会通过 API 读取其分支头部(与其他内容一样,树和文件都会缓存),并显示:

  • 仅存在于服务器上的文件——服务每个安装最近一次检查中状态为 extra 的文件,以及它们的大小和发现这些文件的服务器,还有建议的模式:已知目录(logs/、tmp/、cache/、venv/ 等)、已知扩展名(*.log、*.pyc、*.bak、*.sqlite 等)或文件本身(/local.txt)。
  • 各技术栈的标准模式——Python、Node、Go、Java、Docker 和 IDE 文件。仓库树中检测到的技术栈(requirements.txt、*.py、package.json、go.mod、pom.xml、Dockerfile 等)会预先选中。
  • 服务的受保护 glob 模式(每台主机的文件),会预先选中;另有一个用于添加更多模式的输入框。
  • 关于已提交文件的警告:这些文件看起来像机密(.env、*.pem、*.key、*credentials*、*secret*、id_rsa* 等),或匹配受保护的 glob 模式(每台主机的配置,例如 config.ini)。建议改为提交模板(config.example.ini、.env.example——安装向导会填充这些模板),将文件添加到 .gitignore,并使用 git rm --cached 移除文件。
  • 目录中的服务排除列表/受保护列表,可在同一屏幕上编辑。
  • 服务子目录中的当前 .gitignore(例如 linux/.gitignore)。

预览会显示与当前文件相比的差异:仅追加当前文件中尚不存在的模式,并置于带日期的注释下方,同时保留文件的行尾格式。默认情况下,输出为下载文件。创建合并请求……(GitLab)/创建拉取请求……(GitHub)是单独的显式选项:它需要 Git 源中配置写入令牌(可选、加密保存,且不会用于其他用途——读取令牌仍为只读),并且策略 git_gitignore_mr 默认仅限 admins。确认时会显示仓库名称,且必须手动输入该名称。随后,WRM 会从读取的分支头部创建分支 wrm/gitignore-<service>-<time>,提交文件,并针对服务分支创建请求。审计记录 git.gitignore_mr(仓库、分支、模式数量、链接或错误)。WRM 绝不会自行写入 Git 服务。

Git 工作区:CI 集成(可选)

WRM 不需要 Jenkins 或 GitLab CI;这两者都是可选项。

  • 每个 Git 源的传入 Webhook(Settings → Git sources → Webhook…):启用后会显示 URL(https://<wrm>/api/hooks/git/<id>)和一次性显示的密钥(加密存储;New secret 会替换它)。收到投递后,会立即检查受影响的服务——刷新其目标,并比较其安装情况——而不是等待检查间隔,并会发送常规通知。
    • GitLab 推送、标签推送和发布事件:将密钥用作 Secret token(X-Gitlab-Token)。
    • GitHub 推送和发布事件:密钥用于签署请求正文(X-Hub-Signature-256,HMAC-SHA256);ping 会收到响应。
    • 通用 POST(Jenkins、任何 CI):使用请求头 X-WRM-Token: <secret>,或使用签名 X-WRM-Signature: sha256=<HMAC of "<timestamp>.<body>"> 并提供 X-WRM-Timestamp(Unix 秒,时间偏差不超过 5 分钟)。请求正文可以包含 {"project": "group/name"} 或 {"services": ["name"]};若都未提供,则检查所有服务。
    • 要检查的服务是其目录项目与事件项目匹配的服务。投递会受到速率限制(每个 Hook 和客户端地址每分钟 30 次)、记录审计日志(git.webhook、git.webhook_rejected,附带原因),并且如果提供方发送了投递 ID(X-GitHub-Delivery、X-Gitlab-Event-UUID、X-WRM-Delivery 或通用签名),则会拒绝重放请求。在检查期间收到的投递会合并到下一次检查中。源的所有者需要拥有 git_checks 策略。
  • 来自 CI 制品的捆绑包(Settings → Bundles from CI artifacts):提供捆绑包 .tar.gz 的 URL——GitLab 作业制品 API(…/api/v4/projects/<id>/jobs/artifacts/<ref>/raw/bundle.tar.gz?job=<job>,使用 PRIVATE-TOKEN)、Jenkins 制品 URL(…/lastSuccessfulBuild/artifact/bundle.tar.gz,使用 Authorization: Basic user:token,由 WRM 编码)或任何 HTTPS URL——并可选提供授权请求头(加密保存,之后不会再次显示);可手动获取(Fetch now),或设置为每 N 分钟获取一次。文件发生变化时,会作为离线捆绑包导入(信息流仅保留最新版本);未变化时则跳过。审计事件为 git.bundle_fetched / git.bundle_fetch_failed。
  • 每个服务的部署方式“CI pipeline”(服务的 Edit 对话框,策略 git_update):适用于在其他位置构建和部署的服务。
    • **Jenkins 作业:**作业 URL、用户和 API 令牌(或无需用户、使用作业的 trigger builds remotely 令牌)。Update / Upgrade 会使用 server(连接的主机)、install_path 和 version(目标版本)调用 buildWithParameters,然后跟踪队列项和构建,直到其结束(SUCCESS 表示成功;FAILURE、UNSTABLE、ABORTED 会使运行失败)。
    • GitLab pipeline:GitLab 地址(默认使用 Git 源)、项目(默认使用服务的项目)、分支(默认使用目标分支)和pipeline 触发令牌;变量为 server、install_path 和 version。状态会通过同一主机上的 GitLab 源读取令牌获取。
    • 此运行遵循与常规更新相同的计划、确认(生产环境:需输入服务器名称)、策略和审计流程(git.update / git.upgrade,包含 via: ci、链接和结果)。不会写入任何文件;运行历史会显示 CI 状态和链接。之后,只要 WRM 能登录,就会再次比较安装情况。Stop 会停止等待(CI 中的作业仍会继续运行)。
AI 助手

使用顶部的 AI 按钮,或选择 Settings → AI assistant,查看生效的账户权限、提供方可用情况和配置障碍。SSH 和基于 SSH 的 SFTP 窗口都带有 AI 按钮;如果访问被禁用,点击后会打开诊断视图。启用或禁用策略后,已打开的浏览器会刷新,包括事件总线重新连接后。提供方测试成功表示连接正常;配置结果会单独显示账户是否可以使用助手。终端 AI 不依赖 MCP 设置。

面板中的 AI 助手位于终端旁边(也可从文件管理器打开)。在 SSH 终端或文件管理器窗口的标题栏中点击 AI,选择提供方、模型和模式,然后用自然语言提问:为什么 nginx 无法运行?、腾出一些磁盘空间、提高工作进程数量。助手会解释每一步,并且只通过 WRM 工作:

位置和大小(桌面端):使用 ◧ ⬒ ⬓ ◨ 按钮将面板停靠在左侧、右侧、顶部或底部;使用 ❐ 将其显示为浮动窗口;使用 ⛶ 将其展开至整个终端窗口(也可双击标题栏;再次按下即可还原);拖动面板内缘(浮动时拖动角落)可调整大小。拖动标题栏可移动面板;停靠的面板随后会变为浮动状态。终端会在停靠面板旁边缩小,并重新调整布局。停靠状态、大小和浮动位置会按用户保存在浏览器中(localStorage 键 wrm_ai_win_<user id>)。在紧凑窗口(宽度不超过 760 px,例如手机)中,面板会保持全窗口布局,并隐藏这些按钮。

  • 模型无法获得 shell。它只能调用 WRM 的工具:system_info、read_file(有大小限制)、list_directory、tail_log、find_logs、read_log、search_logs(对所有已发现的日志运行 grep)、journal(journalctl)、service_status、list_packages、processes、disk_usage、network_status、run_command、write_file 和 edit_file。每次调用都会经过服务器上的权限引擎,由其作出决定;WRM 通过自身与该服务器的 SSH 连接运行结果(与终端一样支持跳转主机、代理和密码库登录)。
  • 每个会话有三种模式(面板会显示当前模式;由 WRM 端的策略决定):
模式行为
只读可使用只读工具,以及通过只读分类器判定的命令(systemctl status、journalctl -u …、df、ss -tulpn、dpkg -l、grep … /var/log/…、此类命令的管道等)。任何无法明确判定为只读的操作——未知命令、重定向、$( … )、sed -i、find -delete、systemctl restart——都会被拒绝。模型甚至不会收到文件编辑选项。
每次变更前询问读取操作直接执行。每条会产生变更的命令和每次文件编辑都会在面板中创建一个待批准项:显示确切命令(批准前可以编辑)或统一差异(可以编辑新内容)。可批准或拒绝,并附上可选备注;如果在时限内未响应(ai_approval_timeout_seconds),则会拒绝。只有自生成差异后文件未发生变化时,才会写入文件。
限制范围内自动执行只有在明确选择为本次会话启用后才生效:设置命令模式(systemctl restart nginx、apt-get install -y *)和文件路径(/etc/nginx/**)的允许列表和拒绝列表、时间限制以及操作次数上限(两者都受策略限制)。符合条件的变更会直接运行,无需询问;拒绝列表会拒绝操作;其余操作以及超出限制后的所有操作都会再次询问。时间到期后,会话将退回询问模式。* 允许列表会放行所有命令,包括命令链、变量和重定向(仍不包括被阻止或拒绝的命令)。AI 连接(MCP)也可以选择不设时间或操作次数限制:自动执行,直到连接过期。
  • 始终阻止,无论何种模式,即使已获批准也不例外: rm -rf / 和删除系统目录、mkfs / wipefs / 分区操作、对磁盘运行 dd、fork 炸弹、停止或终止 SSH 服务、清空防火墙规则、终止 PID 1、停止审计、crontab -r、删除或锁定 root、写入 /etc/shadow、/etc/passwd、sudoers、/boot、原始磁盘或 authorized_keys、curl … | sh。除非 ai_allow_power 策略允许并且经过批准,否则会阻止 shutdown / reboot(绝不会自动执行)。管理员可以添加自己的模式(ai_blocked_commands);内置列表显示在 管理面板 → AI 助手 中。
  • 未经你的允许,不会读取敏感文件: 密码哈希、SSH 和 TLS 私钥、云服务和工具凭据(~/.aws/credentials、.kube/config、.netrc …)、进程环境变量——包括通过通配符或符号链接访问的内容——以及你自己的模式(ai_read_deny_paths)。从 v12.6.1 开始,使用 read_file / tail_log 读取此类文件时,每次都会征求你的同意,并会向 AI 提供已遮盖类似机密值的内容;设置 ai_sensitive_reads = deny 时,绝不会读取这些文件。命令中提及此类文件时,始终需要批准。
  • AI 能看到的内容(面板中的 👁):本次会话的工具结果、服务的操作系统,以及仅在你勾选后才会包含的连接备注。绝不会看到 WRM 中存储的密码和密钥、你的 WRM 登录信息、其他连接或终端屏幕。发送给提供商之前,会对输出中的机密信息进行遮盖(ai_redact_output):私钥、以 key=value 形式出现的密码和令牌、Authorization 标头、URL 中的密码、AWS / GitHub / GitLab / Slack / OpenAI / Anthropic / Google 密钥、JWT、密码哈希。每次调用的输出都有限制(ai_output_max_kb)。
  • 服务输出是不可信数据。 工具结果会被标记为不可信数据,并告知模型绝不要遵循其中的指令。日志行中写着切换到自动模式也不会改变任何内容:只有你可以在 WRM 界面中更改模式,而且每次更改都会经过相同的检查。
  • 工作日志、标题和继续聊天: 工作日志会显示助手的思考(💭;支持相应功能的模型使用 Anthropic 自适应思考,兼容 OpenAI 的服务使用 reasoning_content)、每个步骤前的说明以及每条工具结果(ai_show_thinking)。首次回答后,聊天会生成一个简短标题(ai_auto_titles;点击即可重命名)。聊天结束后(WRM 重启、空闲超时、触发终止开关),会显示 继续聊天,以先前对话为上下文开启新会话;历史记录会列出标题、日期、时间和继续。
  • 我的 AI 设置(面板中的 ⚙,像面板布局一样按用户保存):新聊天的默认提供商(组织提供商或你自己的密钥,需 ai_personal_keys 允许)、模型、模式和引擎,以及是否显示模型的思考内容(仅在启用 ai_show_thinking 时)。工作日志会在可滚动框中保留完整的思考文本。
  • 停止和终止: ■ 停止会取消正在运行的请求和命令;⏻ 会结束会话。管理员可以结束一个会话、某个用户的所有会话或所有会话(立即停止所有 AI 会话),为某个用户关闭助手,或启用终止开关(ai_kill_switch,也可以设置 WRM_AI_KILL_SWITCH=1),结束所有会话并阻止新会话。窗口上的 ✦ AI 徽标表示当前有会话处于活动状态。
  • 提供商: Anthropic API(最新的 Claude 模型,例如 claude-opus-5-5、claude-sonnet-5-5、claude-haiku-5-5;可选网关基础 URL)、OpenAI API、Azure OpenAI(部署 + api-version,或 v1 API)、AWS Bedrock(使用 SigV4 访问密钥或 Bedrock API 密钥的 Converse API,或使用 API 密钥的 Messages API 端点;模型 ID 示例:anthropic.claude-opus-5-5)、Google Vertex AI(通过 rawPredict 使用 Claude,或使用兼容 OpenAI 的端点,并提供服务账号密钥)、OpenCode Zen(按量付费:无需密钥即可使用免费模型,使用 OpenCode 账号密钥即可使用所有模型)、OpenCode Go(Go 订阅密钥;参见 OpenCode Zen、Go、Agent 和辅助模型),以及任意兼容 OpenAI 的基础 URL(Ollama、vLLM、LM Studio …)。响应会以流式方式传输;按请求统计令牌数和预估费用(Anthropic 模型使用内置价格表,其他模型使用你设置的价格);请求会在超时后结束,也可以通过停止取消。
  • 密钥: 组织的提供商由管理员管理(管理面板 → AI 助手 → 组织提供商);仅当 ai_personal_keys 允许时,才可使用个人密钥(面板中的 🔑 我的 API 密钥)。密钥在静态存储时会加密,绝不会发送到浏览器;测试会发送一个极小的请求。
  • 此处无法使用消费者订阅: Claude.ai 和 ChatGPT 聊天订阅不能作为 API 用于第三方应用。请为此面板使用 API 密钥(或你公司的网关)——也可以让聊天应用本身通过 MCP 连接 WRM:参见 AI 桌面应用(MCP)。
  • 共享连接: 具有终端和文件更改权限的已登录用户(Operator 及以上)可以在共享连接上使用助手;他们的备注不会共享。 管理员策略(管理面板 → AI 助手):谁可以使用它(ai_assistant)、允许的模式(ai_modes),以及每个标签、文件夹、连接或主机的模式规则——匹配的规则中以限制最严格者为准,例如 [{"match":"tag","value":"prod","modes":["read_only"]}, {"match":"folder","value":"Staging","modes":["read_only","ask"]}]——默认模式、提供方和模型(ai_provider_kinds、ai_models)、个人密钥、脱敏、共享备注、审批超时、自动模式的最长运行时间和操作、强力命令、额外禁止的命令和不可读取的文件、命令时间限制、输出限制、每个请求的步骤数、空闲超时,以及对话记录保留期限(ai_transcript_retention_days)。运行中的会话会在下一次工具调用时遵循策略变更。

审计和对话记录:每个 AI 请求(提供方、模型、令牌、费用)、每次工具调用及其输入和(已脱敏的)输出、每次审批和拒绝及其人员和时间、模式变更、停止和强制终止,都会作为审计事件(ai.*)关联到连接。会话对话记录(已脱敏)会保留 ai_transcript_retention_days 天,并向会话用户(面板中的 🕘)和管理员(管理面板 → AI 助手 → 对话记录)显示;它也会像终端会话一样录制(会话和录制,标记为 ✦ AI,并支持回放)。

OpenCode Zen、Go、Agent 和辅助模型

OpenCode 是一款开源编码 Agent(MIT 许可),提供两个模型网关:OpenCode Zen(按量付费)和 OpenCode Go(月度订阅)。WRM 在彼此独立的部分中使用这两者。所有信息都清晰可见:运行的内容、各模型收到的内容、令牌和费用。

**1. 将 OpenCode Zen 用作提供方。**在管理面板 → AI 助手 → 组织提供方中添加(供所有人使用),或在 ai_personal_keys 允许时,将其作为个人密钥添加到🔑 我的 API 密钥中;提供方向导包含 OpenCode Zen 预设。

  • 不使用密钥时,WRM 仅提供免费模型(它会发送 OpenCode 的公钥,与 OpenCode 自己的客户端相同)。无需进行其他设置。
  • 使用密钥时,从你的 OpenCode 账户(opencode.ai/auth → API 密钥)获取的密钥可使用账户中的所有模型,费用由 OpenCode 收取。
  • 模型列表来自 OpenCode 的公开目录(models.dev):名称、价格、上下文大小,以及各模型支持的 API。仅支持 OpenAI Responses API 或 Google API 的模型会被拒绝,并显示明确提示;请选择其他模型。

**OpenCode Go。**Go 是包含每月用量的订阅,并非 Console 余额。Go 密钥仅适用于 Go 端点,因此将其用作 OpenCode Zen 提供方时,Console 会返回 insufficient funds。请添加单独的 **OpenCode Go(订阅密钥)**提供方,并使用从 opencode.ai/console/go 获取的密钥:

  • WRM 会将密钥发送到 https://opencode.ai/inference/go/...,并根据模型选择 Chat Completions 或 Anthropic Messages(即使 Zen 目录标注为 chat,Qwen 和 MiniMax M3 在 Go 上也使用 Messages),且每段对话都会使用稳定的 x-opencode-session。
  • 加载模型会向 Go 请求当前模型列表;如果无法访问该列表,则会提供文档中列出的模型。仅支持 OpenAI Responses 或 Google Gemini 的模型不会列出。
  • OpenCode Agent 引擎接受相同的提供方,并运行 opencode-go/<model>;不涉及 Zen 余额。 2. 辅助模型(委派)。 启用 ai_delegate 后,助手可以将独立的文本任务交给辅助模型处理:总结长日志、分类、解释错误、起草代码片段或代码。辅助模型只会收到助手传递的文本,其中的机密信息会被隐藏,文本大小最多为 ai_delegate_max_kb;它没有工具,也无法接触任何服务。
  • 自动选择: 当 ai_delegate_models 为空时,WRM 会使用 ai_delegate_provider 中提供商的完整模型目录,并根据任务选择模型:优先选择免费模型,然后为代码和草稿选择编码和推理模型,为解释选择推理模型,为摘要选择大上下文和快速模型。如果模型失败,WRM 会尝试下一个模型(最多三个)。指定模型列表可缩小选择范围。
  • 每个模型都会显示数据使用标签,包括管理列表、助手设置和每张委派卡片:🛡 零留存、⚠ 可能会将提示词用于训练、❔ 条款未知(按 ⚠ 处理)、💳 付费、🔑 你自己的提供商。这些标签遵循 OpenCode 发布的免费模型条款。
  • 默认关闭训练。 仅在获准时才会使用标记为 ⚠ 或 ❔ 的模型:ai_delegate_training = user(默认值)允许每位用户在助手设置中为自己启用所有此类模型(辅助模型 → 也使用可能会将我的提示词用于训练的免费模型),all 允许所有人使用,off 则始终禁用。
  • 每次委派都会在聊天中显示为一张卡片(任务、模型、标签、大小、令牌、费用),并纳入对话记录和审计日志(ai.delegated、ai.delegate_result、ai.delegate_denied;用户的训练选择为 ai.delegate_training)。 3. OpenCode Agent。 在助手设置中选择 Engine → OpenCode agent 和一个 Agent:build 负责执行工作,plan 负责查看并制定计划。WRM 模式(只读、询问、自动)与 WRM 助手的模式相同,并在会话期间固定不变。
  • 由 WRM 安装,一次即可。 管理面板 → AI 助手 → OpenCode agents 会显示状态。点击 Download and install 后需要确认,随后会从 npm registry 为 WRM 主机下载官方软件包(ai_opencode_registry,也可使用 HTTPS 镜像),根据 registry 中的信息校验其 sha512,仅将 opencode 二进制文件解压到 <DB>.opencode/bin/<version>/,并运行 --version。日志会实时显示;安装者和安装的版本会被记录并审计(opencode.install_started、opencode.installed)。或者,将 ai_opencode_path 指向你自行安装的 OpenCode 二进制文件。
  • 运行方式: 每个会话会在 127.0.0.1 上运行一个 opencode serve 进程,并使用 <DB>.opencode/run/ 下的独立文件夹,以及由 WRM 写入的配置:一个提供方(OpenCode Zen、Anthropic、OpenAI 或 WRM 支持的 OpenAI 兼容提供方;密钥通过进程环境传递,绝不会写入磁盘)、关闭 OpenCode 自带的所有工具(shell、文件读取和编辑、网页抓取和搜索、LSP、提问),并且仅使用 WRM 作为工具服务(MCP 通过仅限回环地址的监听器提供)。进程获得的环境变量经过精简,不包含 WRM 的变量。
  • 所有操作都通过 WRM 执行。 Agent 会在为其开启的 WRM 会话中使用 WRM 的服务工具,因此每条命令和文件编辑都会经过 WRM 的权限引擎,并以相同的审批卡片显示在聊天中;除非启用了完全访问权限,否则未经你批准,服务器上的任何内容都不会更改。OpenCode 自身的步骤也会显示。如果 OpenCode 请求权限或提问,WRM 会拒绝并审计 ai.opencode_refused。
  • 选项:在 Docker 沙盒中使用 OpenCode 自带的工具(ai_opencode_sandbox = admins 或 all;默认值为 off)。此时,设置流程会提供 🐳 OpenCode 自带工具,运行于 Docker 沙盒中。Agent 会在 WRM 主机上的容器中运行,并可在那里使用 shell、文件和网页工具执行临时工作,例如运行脚本、解析通过 WRM 获取的输出或下载内容;访问服务器仍只能通过 WRM 的工具进行。
    • 每次使用都需要审批: OpenCode 的 bash、文件更改和 webfetch 均设为 ask;每项请求都会生成一张 WRM 审批卡片,其中包含确切的命令、差异(已遮盖机密)或 URL。审批选项不可修改:批准一次或拒绝,并可选择添加备注。任何模式(包括完全访问权限)都不会自动批准。读取沙盒文件夹内的文件无需审批;其他任何权限请求都会被拒绝。
    • 容器: 使用镜像 ai_opencode_sandbox_image(默认值为 debian:stable-slim;任何带 shell 的镜像均可),使用 WRM 自身的用户 ID,不授予任何 capabilities,启用 no-new-privileges,根文件系统设为只读,/tmp 使用 tmpfs,内存限制为 2 GB、CPU 限制为 2 个,进程数限制为 512。只挂载会话文件夹(/work,工作文件夹为 /work/work)和只读的 OpenCode 二进制文件;OpenCode 端口仅发布到 127.0.0.1。容器会标记所属的 WRM 安装,并在会话结束、WRM 停止或崩溃后下次启动时移除。
    • 设置: WRM 主机上必须安装 Docker(Linux 引擎,或使用 Linux 容器的 Docker Desktop),且 WRM 本身不能运行在容器中。Medium 的第 2 步可以安装 Docker。点击 Download and install 后,还会为 Docker 服务端下载 OpenCode 的 Linux 版本(经 sha512 校验)、拉取镜像并在其中运行一次 OpenCode;管理页面会显示 Docker sandbox ready 或指出缺少的内容。
    • 网络: 容器可以正常访问外部网络(网页抓取仍需审批)。容器通过 host.docker.internal 连接 WRM 的 MCP 监听器(在 Linux 上,WRM 会监听 Docker 网桥网关地址,并使用令牌保护);WRM 主机回环地址上的 AI 提供方会转发到该容器。已在 Linux 上使用 Docker Engine 测试;Windows 和 macOS 上的 Docker Desktop 使用其自身的 host.docker.internal。
  • 生命周期: 会话的 AI 连接(类型为 opencode)仅可通过 127.0.0.1 访问,且仅在 Agent 运行期间有效;结束会话、终止进程、触发终止开关、达到空闲超时或停止 WRM 时,都会停止进程并移除其文件夹。最多可同时运行 ai_opencode_max_sessions 个 Agent;ai_opencode 决定谁可以使用(off、admins、all)。 在自己的电脑上使用 OpenCode 时,也可以将 WRM 用作 MCP 服务:Settings → AI connections → Connect an AI app → OpenCode 会提供 opencode.json 片段(令牌位于 WRM_MCP_TOKEN 中),或使用 OAuth 登录(opencode mcp auth wrm)。
AI 会话

🧠 AI 会话(一个面板;位于 Panels 菜单中)会按时间倒序列出你自己的所有 AI 会话,无论会话由什么启动:终端中的助手、日志和文件助手、OpenCode Agent,以及通过 MCP 连接的 AI 应用。不会列出其他人的会话,管理员也不例外(管理员可通过 Admin panel → AI assistant → Transcript 查看)。

  • **搜索和筛选:**搜索范围包括标题、服务、模型、提供方和对话内容;可按类型(assistant、logs、file、OpenCode、AI app)、Live 和 Saved 筛选。
  • **打开:**查看会话记录(按存储内容脱敏),包括思考过程、步骤、审批和结果;打开实时 MCP 会话时会显示其实时视图,打开实时聊天时会跳转到对应窗口。
  • **继续:**在同一服务上启动新的助手聊天,并将先前会话作为上下文。MCP 或 OpenCode 会话也可以继续:其工具调用和结果会成为先前上下文。
  • 保存:☆ 可在 ai_keep_saved_sessions 启用时,让会话超出 ai_transcript_retention_days 的保留期限。还可重命名和导出(Markdown 或 JSON;审计事件为 ai.session_export)。
AI 桌面应用(MCP)

WRM 是一个MCP 服务(Model Context Protocol)。支持 MCP 的 AI 应用——Claude(桌面应用和 claude.ai)、ChatGPT(连接器/开发者模式)、Claude Code 和其他 MCP 客户端——可以打开与所选服务的 WRM 会话,并遵循与内置助手相同的规则进行操作。模型在应用中运行,使用你在该应用上的账户;WRM 永远看不到你的聊天,也不需要提供方密钥。

快速开始:一次配置所有 AI 应用(v13.13.0)。 Settings → AI connections → 🧰 All AI apps at once 会为运行 AI 应用的电脑下载一个脚本(Windows 使用 wrm-setup-all.ps1,Linux 和 macOS 使用 wrm-setup-all.sh)。在该电脑上运行脚本:

# Windows (in the folder with the file)
powershell -ExecutionPolicy Bypass -File .\wrm-setup-all.ps1
# Linux / macOS
sh wrm-setup-all.sh

脚本会在浏览器中打开 WRM,你可以登录并选择服务、模式、权限范围和有效期(标准 OAuth 授权确认对话框),然后将连接一次性保存到 ~/.wrm/mcp.json,并将 WRM 添加到所有检测到的 AI 应用中:Claude Code(作为 WRM PRO 插件)、Claude 应用(claude_desktop_config.json,聊天和 Cowork)、Codex CLI、Gemini CLI、VS Code、Cursor、Windsurf 和 OpenCode。修改文件前会先复制到 <file>.wrm-backup-<time>;未检测到的应用会列为跳过。所有应用都会使用已保存的连接启动同一个轻量桥接程序(~/.wrm/wrm-mcp.js),因此访问权限过期时,在其中任一应用中运行 wrm_connect 都会重新登录,并使所有应用恢复连接。该脚本包含此 WRM 的地址和桥接程序,但不包含令牌;设置 WRM_MCP_TOKEN 后,脚本会使用该令牌,而不通过浏览器登录。需要 Node.js 18 或更高版本。POST /api/mcp/setup-all 用于生成脚本;下载操作会被审计(mcp.setup_script)。

快速开始:使用 WRM PRO 插件配置 Claude 应用和 Claude Code。 此仓库是一个插件市场。该插件无需设置:

  • Claude 应用(桌面应用或 claude.ai):Customize → Plugins → Add → Add marketplace → vedranius/web-browser-RDM-public → WRM PRO → Install。如果添加市场失败,可从最新发布版本获取 claude-plugin-wrm-pro.zip,通过 Add → Upload plugin 安装相同的插件。
  • Claude Code:运行 claude plugin install wrm-pro --marketplace vedranius/web-browser-RDM-public,或在 Claude Code 中运行 /plugin marketplace add vedranius/web-browser-RDM-public 和 /plugin install wrm-pro@wrm-pro。 然后输入 /wrm-pro:wrm(输入 /wrm 即可找到它)。首次使用时,Claude 会询问 WRM 地址(即你在浏览器中打开的地址,例如 http://192.168.1.10:8780),并调用 wrm_connect,在浏览器中打开 WRM 以便登录和批准;令牌会直接保存到你电脑上的 ~/.wrm/mcp.json,绝不会进入聊天内容。之后,/wrm-pro:wrm 会列出你的服务器以及 WRM 能执行的所有操作。该插件的 MCP 服务与 Claude Desktop 扩展使用的是同一个桥接程序,它打包为 MCP bundle(packaging/claude-plugin/wrm-pro/server/wrm.mcpb),应用会使用内置的 Node.js 在你的电脑上运行它,因此它可以连接到你自己网络中的 WRM,并通过普通 HTTP 连接。在 Claude 应用中,打包的服务会在 Cowork 中运行;桌面应用中的聊天则使用扩展或上述设置脚本(聊天不会使用插件的本地服务)。

不使用插件的纯 MCP(适用于任意版本的 Claude Code;使用向导生成的令牌):

claude mcp add --transport http --scope user wrm "https://wrm.example.com/mcp" \
  --header "Authorization: Bearer wrm_pat_…"

本地 WRM(http://localhost:8080/mcp)只有使用令牌请求头时才能通过此命令使用:Claude Code 仅会通过 HTTPS 打开登录页面。向导创建配置后,Settings → AI connections 会显示包含你的地址和令牌的命令,并提供 Copy 按钮。

**通过 WRM 使用 Claude 或 ChatGPT 订阅:**消费者聊天订阅不能作为 API 供其他应用使用(因此内置助手需要 API 密钥)。通过 WRM 使用你的 Claude 或 ChatGPT 账户的受支持方式是反向连接:聊天应用通过 MCP 连接到 WRM,具体说明见此处。

连接 AI 应用(向导)

打开 Settings → AI connections 后,会显示分步向导:1. 选择应用(Codex CLI、Claude Desktop、Claude Code、Gemini CLI、Cursor / VS Code / 其他,或通过登录连接 claude.ai / ChatGPT);2. 选择服务器、令牌有效时长,以及应用可以执行的操作(仅查看,或在策略允许 ask 时查看并在你批准后更改);3. 复制或下载准备就绪的命令或配置文件;4. 按下 Test,使用新令牌向 MCP 地址运行 initialize 和 tools/list。令牌通过经过审计的 POST /api/mcp/grants 创建,并且只显示一次;旧表单位于 Advanced 下。对于 Codex CLI:codex mcp add wrm --url <address> --bearer-token-env-var WRM_MCP_TOKEN;对于 Claude Code:claude mcp add --transport http wrm <address> --header "Authorization: Bearer …";对于 Gemini CLI:gemini mcp add --transport http wrm <address> -H "Authorization: Bearer …"。

向导还会提供一段 AGENTS.md / CLAUDE.md / GEMINI.md 文本,向 Agent 说明 “wrm” 是 WRM PRO MCP 服务;服务也会在 initialize 期间通过 instructions 发送相同说明,因此客户端不再会询问 wrm 是什么。

**权限消息。**如果某个工具被拒绝,WRM 会回复 Denied by WRM: this AI connection's scopes (…) do not allow <tool>; it needs one of: …。这是 AI 连接(作用域或模式)的限制,不是服务器或服务器账户的限制:创建一个包含该作用域的新 AI 连接(Settings → AI connections),然后重新连接。open_session 的结果会列出 not_allowed 和 how_to_allow。

工作原理

  • 一个AI 连接会绑定你、你选择的服务器(你自己的 SSH 连接)、一种模式(只读、每次更改前询问,或在限制范围内自动执行)、作用域以及以小时或天为单位的有效期(默认 7 天,最长不超过策略允许的时长,默认最多 30 天)。它可以是你在 Settings → AI connections 中创建的个人访问令牌,也可以是应用连接时由你授予的 OAuth 批准。令牌只显示一次,并且仅以哈希形式存储;你可以随时撤销。
  • 应用可以看到这些工具:list_connections(AI 连接包含的服务器,以及 WRM 在这些服务器上应用的模式)、open_session / close_session,以及作用域允许的 WRM 工具;每个工具都包含已打开会话的 session_id: | 范围 | 工具 | WRM 的作用 | |---|---|---| | read_logs | system_info、read_file、list_directory、tail_log、journal、service_status、list_packages、processes、disk_usage、network_status | 读取信息;拒绝访问敏感文件(密码哈希、私钥、凭据) | | run_readonly | run_command | 仅接受只读分类器认可的命令 | | run_with_approval | run_command | 也接受会造成更改的命令:每条命令都需要等待你的批准(或自动模式的允许列表) | | edit_file_with_approval | write_file、edit_file | 将文件更改显示为统一差异,供你批准 | | transfer | transfer_file | 获得你的批准后,通过 SFTP 将文件从 AI 连接中的一台服务复制到另一台;记录在文件传输中,并包含大小和 SHA-256 |
  • 每次调用都会经过 v12.0.0 权限引擎:只读分类器、始终拦截的破坏性模式、审批、自动模式限制(按会话计算)、按标签/文件夹/连接/主机应用的模式规则(采用限制最严格的规则——即使 AI 连接允许询问,生产服务器对应用也可以是只读的)、输出中的机密信息脱敏,以及审计。
  • 审批会在 WRM 中显示为卡片,带有批准、拒绝和编辑(可编辑确切命令或差异),并显示在你打开的每个 WRM 标签页中;如果应用支持 MCP elicitation,还会在应用中显示为问题(策略 ai_mcp_elicitation)。谁先作出答复,就以谁的答复为准;未答复的审批会在 ai_approval_timeout_seconds 后被拒绝。
  • 服务输出不可信。 工具结果会被标记为不可信数据;其中的任何内容,以及应用提出的任何要求,都不能更改模式或作用域:没有这样的工具,只有你能在 WRM 中更改它们(通过创建新的 AI 连接)。
  • 实时视图:应用开启会话时,WRM 会打开一个跟踪该会话的面板:显示每次工具调用及其命令或文件、WRM 的决定(运行、需要你批准、WRM 已拒绝)、待处理审批的批准/拒绝按钮、结果、退出代码和输出。在 🤖 菜单中选择实时监控可重新打开面板;该处的复选框可关闭此浏览器中的自动打开功能。关闭会话框不会停止应用。
  • **实时视图的位置:**这是面板布局中的一个面板(v12.6.8):将 🤖 AI 标签拖到任意位置,或使用标题栏中的按钮(▕ 右侧、▁ 底部、⧉ 浮动、– 隐藏),也可以使用 🤖 菜单中的布局。
    • 右侧(默认):在 Sessions 和 Snippets 旁边显示一个 🤖 AI 标签。该标签显示打开的 AI 会话数量;有审批等待你处理时会变黄;显示实时视图时,该区域会保持自身宽度(拖动其左边缘可调整)。
    • 底部:位于各窗口下方;拖动其上边缘可调整大小。多个会话会并排显示。
    • 浮动:拖动标签栏的空白处可移动;拖动角落可调整大小。
    • 隐藏:左下角的显示 AI 面板提示条可重新打开面板;有审批等待时会闪烁。
    • 布局会保存到你的账户中。无论布局如何,审批卡片始终会在右下角弹出。在手机上,实时视图会以底部弹出层的形式显示。
  • 拒绝后(在 WRM 或应用中拒绝,或在 ai_approval_timeout_seconds 内未答复),工具结果会告诉 AI 请求在哪里被拒绝、WRM 因哪条规则要求审批(时间或操作限制、不在允许列表中的命令、询问模式、电源命令),以及你可以在 WRM 中更改什么,并要求它询问你是要继续、更改命令还是停止,而不是自行重试变体。
  • 完全访问(v12.6.2,模式 v12.6.3):管理员的 ai_full_access 开关根据 ai_full_access_mode 应用于每个 AI 会话(all,默认值:WRM AI 面板和每个 AI 连接)、仅应用于具有 full_access 作用域的 AI 连接(connection;仅在此模式下提供该作用域),或应用于在 Settings → AI connections 中开启为我的 AI 会话启用完全访问的用户(user)。此时不会直接拒绝任何请求:破坏性列表或 ai_blocked_commands 中的命令、连接的拒绝列表、电源命令、受保护路径和机密文件(ai_sensitive_reads = deny 时也包括这些文件)都会变为标记为 FULL ACCESS 的审批,每次都需要审批且永不自动执行,即使启用了“允许所有内容”也一样。只读连接仍保持只读,其他作用域仍然适用。当 ai_full_access_blocked = deny(v12.6.4)时,即使启用了完全访问,管理员的 ai_blocked_commands 仍会被拒绝。关闭该策略后,下一次调用就会恢复拒绝规则。
  • **稍后批准:**如果审批在 ai_approval_timeout_seconds 内无人答复、应用自行拒绝,或应用不再等待,该审批不会消失:它会在 WRM 中保留一小时(卡片、实时面板、🤖 计数器)。自 v13.8.0 起,在 WRM 中批准后,会立即运行该调用(ai_mcp_later_approval = run,默认值):输出会显示在实时视图中;当 AI 重复相同调用时,会收到该输出(标记为在你批准后运行),而不是再次运行。设为 repeat 时,审批仅允许 AI 重复相同调用时运行一次,且无需再次询问。即使 AI 应用已关闭会话,此功能也可用(v12.6.5):该审批会在你下次通过该连接启动会话时,对同一调用生效一次。在 WRM 中拒绝仍然是拒绝,应用问题中的拒绝也是如此(v13.8.0);只有关闭问题而不作答,才会保留请求供稍后处理。你在 WRM 中作出决定时,应用中打开的问题会关闭。如果决定的请求已不再等待,系统会告知你由谁、在哪里(WRM 或 AI 应用)作出了决定,或者 AI 已不再等待。无法通过审批更改的拒绝(破坏性模式、拒绝列表、只读会话、作用域)会明确说明原因。
  • **允许所有内容:**在自动模式下,AI 连接可以允许所有命令(*)和文件(/**),不设时间或操作限制:之后它会一直保持自动模式,直到 AI 连接过期或你撤销它。使用 * 时,命令链、变量、分组和重定向也会运行。仍会拒绝或要求审批的内容:内置破坏性模式和 ai_blocked_commands、你的拒绝列表、敏感文件、WRM 无法解析的命令、电源命令,以及连接未包含的服务。策略 ai_auto_until_grant(默认开启)决定用户能否选择不设限制;浏览器内置助手始终保留其限制。
  • 顶栏中的 🤖 AI 已连接会在应用存在打开的会话时显示(并显示待处理审批数量);点击它可查看应用,并一键撤销其中一个或全部连接。撤销会立即结束会话;过期、紧急停止开关和策略也会结束会话。
  • 每个会话都是传输方式为 mcp 的 AI 会话:会记录在审计日志中(连接、令牌和 OAuth 对应 mcp.*;每次工具调用、审批和拒绝对应 ai.*)、会话记录以及 Sessions & recordings(✦ AI)中,与内置助手相同。 设置应用 — 设置 → AI 连接 显示地址(https://<your WRM>/mcp),并在创建令牌后提供可直接复制的代码片段:
  1. Claude Desktop — 一键扩展(推荐用于 Claude Desktop)。 在向导中选择 Claude Desktop,选择服务并按 Create token,然后选择 Download Claude Desktop extension。打开下载的 wrm-pro.mcpb(或选择 Claude → Settings → Extensions → Advanced settings → Install extension…),然后按 Install:WRM 地址和令牌已预先填好。该扩展是一个 MCP bundle,内含一个小型 Node.js 桥接程序(remote-manager/mcpb/server/index.js,无依赖项),Claude Desktop 会使用其内置的 Node.js 运行该程序;它会在 Claude 与 WRM 的 /mcp 之间传递 MCP 消息,包括审批问题。它在你的电脑上运行,因此可以访问你自己网络中的 WRM,也可以通过普通 HTTP 访问;如果使用自签名 HTTPS 证书,请在扩展设置中选择 CA 文件。Claude Desktop 会将令牌保存在操作系统的安全存储中;下载的文件包含令牌,因此安装后请将其删除。令牌过期或被撤销时,扩展会继续运行,并提供 wrm_connect 及相应原因(自 v13.13.0 起):让 Claude 重新连接 WRM,并在浏览器中批准登录,或者使用新令牌重新下载扩展。POST /api/mcp/claude-desktop 会构建该 bundle;下载操作会记录审计日志(mcp.desktop_extension)。
  2. Claude 应用和 Claude Code — WRM PRO 插件(无需设置,参见上方快速入门)。该插件(packaging/claude-plugin/wrm-pro,版本 1.2.0)包含一个作为 MCP bundle 的桥接程序、技能 wrm(/wrm-pro:wrm)、wrm-safe-operator 和 linux-incident-triage,以及命令 /wrm-pro:connect。即使没有已保存的连接,桥接程序也会启动,并提供一个工具 wrm_connect;如果令牌错误、过期或被撤销,或者无法访问 WRM,桥接程序也会继续运行,并通过该工具说明原因。wrm_connect 会向 WRM 注册自身(动态客户端注册,使用 http://127.0.0.1:<port>/callback 重定向,默认的 ai_mcp_redirect_uris 允许该重定向),在浏览器中打开 WRM 的授权对话框,使用 PKCE 交换授权码,并将令牌保存在 ~/.wrm/mcp.json 中(通过 WRM_MCP_CONFIG 更改路径;权限模式为 0600)。应用会收到工具列表已更改的通知,随后 WRM 工具便会显示出来。使用另一个地址调用 wrm_connect 可切换到另一个 WRM。需要启用 OAuth 的 AI 连接(ai_mcp_oauth,默认开启)。一键安装需要 Claude Code 2.1.275 或更高版本。
  3. claude.ai — 使用 OAuth 的自定义连接器。 选择 Settings → Connectors → Add custom connector,输入 https://<your WRM>/mcp。Claude 会注册自身(动态客户端注册),在浏览器中打开 WRM;你登录(使用 2FA)并选择服务、模式、作用域和有效期;随后 Claude 会获得与这些设置完全对应的令牌。claude.ai 从 Anthropic 的云端连接,因此 WRM 必须可通过 HTTPS 从互联网访问(将其置于具有有效证书的反向代理后,并遵循 SECURITY.md 中的其他安全加固措施)。
  4. ChatGPT — 连接器。 选择 Settings → Apps & Connectors → Advanced settings → Developer mode,然后选择 Create(Add custom connector):MCP 服务 URL 为 https://<your WRM>/mcp,身份验证选择 OAuth。ChatGPT 会像上文所述那样打开 WRM 供你批准。ChatGPT 同样从其云端连接:WRM 必须可通过 HTTPS 访问。
  5. 任何 stdio 客户端 — WRM 二进制文件中的桥接程序(无需允许来自互联网的入站访问;Claude Desktop 用户建议使用上方的扩展)。将适用于你电脑系统的 WRM 二进制文件(与服务端使用同一发布文件)复制到电脑上,创建令牌,并添加到 claude_desktop_config.json(选择 Claude → Settings → Developer → Edit config):
    {
      "mcpServers": {
        "wrm": {
          "command": "/path/to/wrm-pro",
          "args": ["-mcp-stdio", "-url", "https://wrm.example.com/mcp"],
          "env": { "WRM_MCP_TOKEN": "wrm_pat_…" }
        }
      }
    }
    
    桥接程序(wrm -mcp-stdio -url … -token …,或使用 WRM_MCP_TOKEN / -token-file 提供令牌)会在 stdin/stdout 与 WRM 的 /mcp 之间传递 MCP 消息,包括审批问题;-ca-file 可信任私有 CA 或自签名 WRM 证书。适用于任何只能启动本地(stdio)服务的客户端。
  6. 其他 MCP 客户端(Claude Code、IDE Agent、自有脚本),使用流式 HTTP 和请求头:
    { "mcpServers": { "wrm": { "type": "http", "url": "https://wrm.example.com/mcp", "headers": { "Authorization": "Bearer wrm_pat_…" } } } }
    
    例如:claude mcp add --transport http wrm https://wrm.example.com/mcp --header "Authorization: Bearer wrm_pat_…"。支持 OAuth 发现(WWW-Authenticate 响应中包含 resource_metadata)的客户端可以使用 OAuth 代替令牌。 管理(管理面板 → AI 连接):查看所有活跃的 AI 连接(用户、应用、服务、模式、范围、到期时间、上次使用时间和地址),并可选择 撤销 和 全部撤销;查看已注册的 OAuth 应用(移除某个应用会撤销其连接);以及管理策略:启用/关闭 MCP(ai_mcp_enabled,默认关闭)、允许哪些人使用 AI 连接(ai_mcp:关闭 / 管理员 / 所有人,默认管理员)、允许的范围(ai_mcp_scopes)和模式(ai_mcp_modes)、默认和最长有效期(ai_mcp_token_hours、ai_mcp_max_token_hours)、启用/关闭 OAuth(ai_mcp_oauth)、重定向 URI 允许列表(ai_mcp_redirect_uris:默认包含 claude.ai / claude.com 和 ChatGPT 的回调地址,以及桌面客户端使用的 http://localhost:*)、允许调用 /mcp 的浏览器来源(ai_mcp_allowed_origins,CORS)、公开地址(ai_mcp_public_url)、应用内审批(ai_mcp_elicitation)和传输大小限制(ai_mcp_transfer_max_mb)。AI 助手的紧急停止开关、模式规则、屏蔽命令、不可读路径、审批超时、脱敏和限制也同样适用于 MCP 会话。
网络工具

顶部栏中的 🧰 工具(或右键单击某个连接 → 此服务的网络工具… / 检查此主机的端口)——无需打开终端,即可执行常见的初步检查,排查无响应的情况:

工具功能
🔍 端口检查尝试连接最多 100 个端口的 TCP 连接(22, 80, 443,以及 8000-8010 这样的范围):开放(显示耗时)、关闭(拒绝连接)或无响应(被防火墙过滤)
📶 Ping执行 4 次 Ping,显示 ping 的输出
🛤 Traceroute执行 traceroute(或 tracepath;Windows 上使用 tracert),最多跟踪 20 跳
🌍 DNS查询地址、CNAME、MX、TXT 记录,以及 IP 地址对应的名称(PTR)
🔒 HTTP / TLS向 URL 发送一次请求(显示但不跟随重定向):状态、耗时、服务信息;对于 HTTPS,还会显示 TLS 版本、证书名称、颁发者、有效期(剩余天数)、名称,以及证书是否可信

使用来源选择检查的执行位置:WRM 服务或你的一个 SSH 连接(通过其跳板主机)。这可以回答“app-01 能否连接到 5432 端口上的数据库?”或“dmz-web 和 API 之间的防火墙是否允许 443 端口通过?”。在服务上运行时,端口和 HTTP 检查通过 SSH 通道进行(无需在服务上安装任何内容);Ping、Traceroute 和 DNS 则运行服务上的命令(ping、traceroute/tracepath、getent/dig/nslookup)。

只能使用你自己的连接作为来源;每位用户一次只能运行一项检查;目标只能是主机名或地址(不能包含选项或 shell 字符);所有检查都会记录审计日志(nettool.run)。network_tools 策略可设置为:所有用户(默认)、仅管理员或关闭。

扩展

扩展可从 WRM 内部扩展其功能:提供面板(窗口)、配色主题,以及组织扩展专用的 WebAssembly 服务端代码。扩展是一个包含 addon.json 的 ZIP 文件,可在设置 → 扩展中安装。安装时不会运行任何内容,每个文件都会通过 SHA-256 固定校验,新扩展安装后默认为关闭。

  • 安装者:管理员可以为所有人安装(为所有人安装),或仅为自己安装(仅我)。其他用户安装的是个人扩展,只有自己能看到;如果策略 addon_personal 允许(默认:所有人),即可安装。个人扩展不能携带服务端代码。管理员可在其他用户的个人扩展下找到所有用户的个人扩展,并进行禁用和移除。
  • 启用:会显示权限清单:WRM 根据 addon.json 列出扩展可以执行的操作(无网络的窗口、n 个主题、每个实例 x KB 的设置、通知、服务端代码)。如果更新请求更多权限,扩展会保持关闭,并显示新增权限行及等待审批;你再次启用后才会生效。权限较少的更新会保持启用状态。安装旧版本时会先询问。
  • 实例:点击打开面板可打开你的实例(首次创建的实例名为默认)。扩展卡片中的实例可用于创建更多实例(管理员可以与所有人共享一个实例)、打开实例、重命名、导出和导入设置,以及移除实例。每个实例都有自己的设置和窗口。
  • 窗口是普通的 WRM 窗口(可移动、调整大小、贴靠、最小化和使用标签页)。窗口位置和大小会按用户保存在服务端,因此重新加载后或在其他设备上打开时,扩展窗口会恢复原状。↻会重新加载面板;⚠ n会列出面板报告的错误。如果面板在 5 秒内未启动,或 45 秒内停止响应,就会显示横幅,其中包含重新加载、诊断、禁用扩展和关闭选项。
  • 已启用扩展的主题会显示在设置 → 外观中;只有用户主动选择后才会应用。
  • 网站(v13.11):具有 http 能力的扩展会在 addon.json 中列出其网站(http.origins)、方法、路径和密钥。面板向 WRM 发起请求,由 WRM 发送请求:请求只能发送到已列出的网站、路径和方法;且网站须经管理员批准(启用组织扩展即表示批准其网站;个人扩展会显示网站等待管理员审批,管理员可点击批准)。网站名称由 WRM 解析;除非管理员为该网站勾选专用网络,否则会拒绝环回、专用、链路本地和 CGNAT 地址(普通 http:// 也需要勾选)。重定向(最多 3 次)会再次检查,且不会将密钥发送到其他网站。限制:请求最大 256 KB、响应最大 8 MB、超时 10 秒、每分钟 120 个请求、每个实例最多同时处理 20 个请求;2 秒内相同的 GET 请求会共用同一响应。点击撤销可移除审批。窗口的 ⚠ 诊断中会列出近期请求。
  • 密钥(v13.11):实例上的🔑 密钥可用于存储网站的 API 密钥或密码,并在服务端加密。共享实例使用管理员设置的值,私人实例使用所有者设置的值;也可设置你自己的值,在你使用时替代默认值。WRM 会将密钥添加到请求中(Authorization: Bearer、Basic 或指定名称的标头);面板只能获知密钥是否已设置。设置和清除密钥都会记录审计日志,但不记录密钥值。
  • 面板可以执行的操作:面板在沙盒框架中运行,无法访问 WRM、其 Cookie 或其他窗口;对于 apiVersion 2,面板本身无法联网。面板会收到显示名称、语言、主题、实例及已存储设置;可以存储设置、显示简短通知(每分钟 5 条)并请求调整窗口大小。扩展仅在窗口打开时运行:WRM 不会为其运行后台任务,因此 7×24 小时警报应由受监控的系统负责。
  • **编写扩展:**请参阅扩展开发者指南(清单、桥接、存储、主题、错误代码),或在同一窗格中选择AI 扩展,获取可直接使用的提示词。WRM 助手可以编写草稿,供你审阅(差异)并安装。
  • 开发者工具(v13.12):同一窗格中的🛠 开发者工具(适用于管理员及可安装个人扩展的用户)提供检查 ZIP,可在不安装扩展的情况下进行检查;还提供模板,其中包含 4 个 ZIP 格式的起始模板、清单架构和 llms.txt。安装失败时会自动打开检查报告;点击复制报告可将报告复制给 AI。命令行用法:
    • wrm -addon-new TEMPLATE [-addon-id ID] DIR 会将模板(blank、fetch-and-render、grafana-panel、wasm-hook)写入空文件夹;面板模板包含 wrm-bridge.js,WebAssembly 模板包含 TinyGo 源文件和占位模块。
    • wrm -addon-lint DIR|ZIP(JSON 格式使用 -addon-lint-json)会按 level file:line: message [code] 的格式打印错误、警告和提示,并附带说明,随后打印权限摘要;存在错误时返回代码 1。不会运行扩展中的任何内容。
    • wrm -addon-dev DIR 会在 http://127.0.0.1:8790 提供面板服务(使用 -addon-dev-port 指定端口),并提供真实的 CSP、语言、主题、可见性开关、内存存储、对已列出网站的请求(密钥来自 WRM_ADDON_SECRET_<NAME>;专用网络和普通 HTTP 网站仅在使用 -addon-dev-private 时可用)、检查结果和桥接日志;文件更改时会自动重新加载。选项必须放在文件夹路径之前。
SSH 终端
  • 完整的 xterm-256color 终端(xterm.js 5,由 WRM 自行提供服务,不使用 CDN),采用 JetBrains Mono 字体。支持 nano、vim、less、htop、mc、tmux、颜色、鼠标报告和 UTF-8(č、ć、ž、š、đ、emoji 等)。
  • **任何情况下都能正确调整大小:**连接、最大化、贴靠、调整大小、切换侧边栏、更改字体和浏览器缩放时,PTY 大小都会随窗口变化。
  • **安全处理大量输出:**使用二进制 WebSocket 帧和流量控制,因此大量 cat/tail/journalctl 输出不会导致连接断开。
  • 重新连接:
    • 点击标题栏中的 ↻ 按钮(已连接时也可使用,例如会话卡住时)、按 Ctrl+Shift+R,或使用标签页菜单。
    • 终端关闭时,横幅会显示 ↻ 重新连接(或按 Enter)和红色 ✕ 关闭窗口;– 可隐藏横幅并停止自动重新连接。
    • SSH 连接或与 Web 服务的连接断开时会自动重新连接(间隔从 1 秒递增至 30 秒,最多尝试 10 次),网络恢复时会立即重新连接。可在设置中关闭此功能。如果 shell 只是退出(exit),则不会自动重新连接。
  • **保活:**WRM 每 25 秒向浏览器发送一次 ping,每 30 秒向 SSH 服务发送一次 ping,并检测失效连接。
  • **选中即复制:**选中文本会将其复制到剪贴板,并添加到剪贴板面板。按 Ctrl+Shift+C 也可复制,按 Ctrl+Shift+V 或使用常规粘贴操作即可粘贴。
  • **搜索回滚内容:**按 Ctrl+Shift+F(Enter = 下一个,Shift+Enter = 上一个)。
  • 输出中的可点击 URL。
  • **终端处于焦点时会拦截浏览器快捷键:**按 Ctrl+W 会发送到终端(在 nano 中执行“Where Is”,在 bash 中执行“删除单词”),而不会关闭浏览器标签页。Ctrl+T、Ctrl+N 和 Ctrl+Q 也会被拦截。
  • 可配置字体大小(11–18 px)和回滚行数(5k–50k 行)。
  • 在文件管理器中选择**“在此处打开终端”**,即可打开新终端并 cd 到该文件夹。
文件管理器(SFTP / FTP / FTPS)

预览文件上下文菜单中的此选项可在 WRM 中打开视频/音频、图片、PDF 或文本。大型视频/音频文件可通过 SFTP/FTP 流式播放,并支持字节范围定位;浏览器的编解码器支持仍然适用。系统会根据内容而不仅仅是扩展名来识别文本:XML/SMIL/SVG、JSON、YAML、TOML、INI、shell、Python、JavaScript/TypeScript、Go、SQL、CSS/SCSS/LESS、Markdown、PowerShell、batch、Dockerfile、Makefile、C/C++/C#/Java/Rust/Ruby/PHP 等文件会由内置的 PrismJS 进行语法高亮;其他文本文件会以纯文本打开。UTF-8、UTF-16(带 BOM 或可检测字节序)和单字节文本均可解码;二进制文件无法预览,可选择下载。文本预览最多显示 256 KiB,并会显示截断提示和下载选项。HTML/SVG/源代码文件会以转义后的文本形式呈现。关闭查看器会停止播放。每次元数据/范围/内容请求都会检查与下载相同的文件读取/共享权限;FTP 必须支持 SIZE 和 REST,才能进行可定位的播放。

在终端中,用指针选中单个文件路径并右键单击,选择预览所选路径或下载所选路径。相对路径以终端的当前目录为基准;~/ 会解析为 SSH 文件账户的主目录。路径会被视为文件名,绝不会作为 shell 命令执行。

  • 面包屑路径栏:单击任意部分即可跳转到相应位置,也可单击空白处输入路径(按 Enter)。↑ 向上和**⟳ 刷新**(F5)。
  • **列:**名称(带文件类型图标和符号链接标记)、修改时间、大小(B … TB)、类型。单击列标题可排序(文件夹始终排在前面,使用自然排序)。
  • 选择:
    • 单击以选择,Ctrl/Cmd + 单击以切换选择,Shift + 单击以选择范围,复选框、全选、Ctrl+A
    • 键盘操作:方向键、Home/End、Enter(打开)、Backspace(向上)、Delete、F2(重命名)、F5、Ctrl+F(搜索)、Esc
  • **双击:**打开文件夹;在编辑器中打开文本文件;下载其他文件。
  • 上传:
    • ⬆ 上传(一次上传多个文件)、🗂 文件夹(上传整个文件夹及其子文件夹),或将电脑中的文件或文件夹拖放到列表中
    • 显示带速度的进度条,并提供取消按钮
    • 系统会检测已存在的文件,并询问是否要覆盖
    • 可选的单文件大小限制(在设置中配置;管理员可在服务器上强制实施限制)
  • 下载:单个文件,或将文件夹下载为 ZIP(SFTP)。⬇ 下载会下载所有已选项目。
  • 📁 新建文件夹、✏️ 重命名(F2)、🗑 删除(已选文件和文件夹;递归删除文件夹,并需确认)。
  • ⚡ 传输会将所选项目发送到另一台服务器(参见服务器间传输)。
  • ⌨ 终端会在当前文件夹中打开终端(仅限 SSH/SFTP)。
  • **右键菜单:**打开、编辑、下载 / 下载为 ZIP、传输到服务器、在此处打开终端、复制路径、重命名、删除。可对多个已选项目使用。
  • **状态栏:**文件夹和文件数量、所选项目数量及大小、连接名称。
  • 窗口较窄时,工具栏会切换为仅显示图标。
在文件中搜索

每个文件管理器顶部的搜索框:

  • 输入内容即可即时筛选当前文件夹。 支持通配符:*.log、nginx*.conf、?。
  • 按 Enter(或 ⌕)即可在服务器上搜索当前文件夹的所有子文件夹。结果会实时显示,并附带进度指示(已扫描的文件夹、当前文件夹),随时可以停止搜索。
  • 搜索选项(▾):
    • 文件名(默认):通过 SFTP/FTP 遍历目录树。适用于所有服务器,包括 Windows SFTP 和 FTP。
    • 文件内容:通过 SSH 在服务器上运行 grep:不区分大小写、固定字符串搜索,仅搜索文本文件。需要 POSIX shell 和 grep(Linux/BSD/macOS 服务器)。FTP 不支持此功能。
    • 包含/跳过隐藏文件;结果上限(200 / 500 / 2000 / 5000)。
  • 从 / 开始搜索时,会跳过虚拟文件系统 /proc、/sys、/dev、/run 和 /snap。搜索在 3 分钟或扫描 1,000,000 个条目后停止,并会告知结果是否被截断。
  • 结果显示文件、所在文件夹、大小和日期。双击结果即可打开其所在文件夹,并突出显示该文件。可选择结果、打开上下文菜单、下载和删除。
文本编辑器
  • 在浏览器中打开不超过 5 MB 的文本和配置文件(双击,或右键 → Edit)。二进制文件会先显示警告。只读共享会以只读模式打开。
  • 支持约 40 种语言的语法高亮(shell、YAML、JSON、INI 和 systemd 单元文件、nginx、Apache、Dockerfile、Python、Go、JavaScript、SQL 等);根据文件名选择,也可在工具栏中更改;文件超过 300 KB 时关闭。显示行号、当前行和列,并支持自动换行。
  • 查找和替换(Ctrl+F、Ctrl+H):支持字面文本或正则表达式、大小写设置,并标记所有匹配项;可使用 Replace 和 Replace all。跳转到行(Ctrl+G)。Tab / Shift+Tab 可缩进和取消缩进所选行,按 Enter 会保留缩进。
  • **JSON:**使用 Check JSON 检查 JSON(显示错误的行和列),使用 Format JSON 格式化 JSON;保存无效 JSON 时会先询问。
  • 保存(Ctrl+S):默认启用的 Review before saving 会先显示更改差异。写入前,WRM 会重新读取文件:如果其他人、服务或 AI 助手在你打开文件后修改了它,你可以选择覆盖或查看差异。随时点击 ± Changes 查看更改,点击 ⟲ Reload 重新读取文件。保留行尾格式(LF 或 CRLF)和 UTF-8 编码。
  • **🤖 AI 助手:**文件旁边的面板可检查文件(查找 bug、安全问题、错误配置)、解释文件并提出修改建议。每项修改都会以差异形式呈现,等待你批准;批准后,编辑器会重新加载文件,或者在你有未保存的更改时发出警告。Ask AI about the selection 会发送所选行。对话按文件保存,并记录标题、日期和时间,之后可以继续。
服务器间传输

直接在一台 SSH/SFTP 服务器与另一台之间复制文件和文件夹。数据经过 WRM 服务器传输,而非浏览器。

  • 在文件管理器中点击 ⚡ Transfer 或从上下文菜单打开。双面板对话框左侧显示源(含所选内容),右侧显示目标连接和文件夹。
  • 如果文件已存在: Ask each time(先检查冲突,然后统一询问)、Overwrite all、Skip existing、Overwrite if newer。
  • 文件夹会连同目录结构递归复制。保留文件修改时间。最多可并行复制 4 个文件。
  • 实时进度:单个文件进度、总字节数、速度(滑动窗口)、预计剩余时间、含错误信息的结果列表。
  • 将对话框最小化为小型浮动进度条(可拖动,始终保持在屏幕内),即可继续工作。点击取消也会在服务器上停止传输。
  • 传输完成时会播放提示音(成功或出错)。
  • 不支持使用 FTP 连接作为源或目标。
工作区会话

会话面板(默认位于右侧;请参阅面板布局):

  • + 保存会话会保存所有已打开的窗口:连接、终端或文件管理器、当前文件夹、吸附槽或位置(相对于工作区大小保存,因此可以适配其他屏幕)、最小化和聚焦状态。建议名称根据连接生成。
  • 点击已保存的会话即可打开。 如果已有窗口打开,可选择替换(关闭现有窗口)或添加(在现有窗口旁打开)。每个空白的新建窗口中也会显示已保存的会话。
  • 右键点击会话:打开(替换)、打开(添加)、将当前窗口保存到此处(更新)、重命名、锁定/解锁(锁定的会话无法覆盖,删除时需要确认)、删除。
  • 会话属于你的账户并存储在服务器上,因此可在每个浏览器中使用。
剪贴板面板

剪贴板面板(默认位于右侧):显示你从终端复制的最近 20 条文本(以及复制的路径)。

  • 点击条目即可再次复制。粘贴会将其发送到当前聚焦的终端。
  • 历史记录按工作区会话和用户分别保存在浏览器中(本地存储),而非服务器上。其他账户在同一浏览器中登录时看不到这些记录,退出登录时会将其删除。使用清除可清空记录。
共享:成员、角色和链接

与其他 WRM 用户或没有账户的人共享连接(或整个文件夹)——接收者可以使用这些连接,但不会看到你保存的凭据。

右键点击连接 → 🤝 共享,右键点击文件夹 → 共享文件夹,选择多个连接并使用🤝 共享,或选择共享 → + 新建共享。共享对话框包含:

  • **此共享中的连接:**勾选连接和/或整个文件夹(文件夹也会包含之后添加到其中的连接)。即使没有连接,共享仍可用于聊天、语音和终端共享。

  • 谁可以打开链接:

    模式对象
    👥 仅限成员(默认)仅限你添加为成员的用户。他们使用自己的账户登录。
    🏢 所有已登录用户任何拥有链接的 WRM 服务器用户。
    🌐 任何拥有链接的人也包括没有账户的人(访客)。管理员可以禁用此模式。
  • 成员各自拥有单独的角色;其他所有人的角色(其他两种模式中的非成员);可选的密码(成员无需输入);可选的对所有用户显示在“与我共享”中的条目;有效期(1 h … 30 天或自定义日期)。

  • 角色:

    观察者查看者操作者管理员所有者
    聊天和语音通话✔✔✔✔✔
    查看共享终端✔✔✔✔✔
    浏览和下载文件—✔✔✔✔
    打开终端——✔✔✔
    上传、编辑、重命名、删除、传输——✔✔✔
    共享自己的终端、接收键盘控制——✔✔✔
    更改角色、静音、移除、封禁他人———✔✔
    共享设置和成员————✔

    角色会由服务器针对每个请求强制执行;界面只会隐藏本就会被拒绝的操作。

  • 顶栏中的🤝 共享会列出你的共享及其模式、成员、有效期和在线人数。可执行的操作:打开房间、复制链接、编辑(以上所有设置)、人员(查看所有曾打开此共享的人及其最后上线时间和 IP——更改某人的角色或将其封禁)、新建链接(旧链接会立即失效)、暂停/恢复、删除。

  • **撤销会立即生效:**删除、暂停或轮换共享,移除成员、降低角色、封禁人员或禁用用户,都会立即关闭受影响的终端和房间连接。

实时协作

所有打开同一个分享链接的人(包括作为所有者的你)都会加入该链接的实时房间。协作栏会显示分享内容、你的角色、在线用户的头像(绿色圆环表示正在说话的人)以及各种控件。

  • 身份由服务器确定:已登录用户显示其账户名称;访客首次访问时选择名称,并标记为访客(他们不能冒充注册用户)。
  • 👥 人员面板:显示语音通话中的人员和在线人员,以及他们的角色、静音/禁听状态、共享的终端、举手状态、连接质量(P2P/中继、延迟)和每个人的音量滑块。版主会看到一个**⋯**菜单:更改角色、为所有人静音、停止其终端共享、放下手、将其移出房间、禁止其访问分享。
  • 💬 聊天,包含历史记录(保留最近的消息,后来加入的人也能看到)、时间戳、可点击链接、未读徽标和通知。📎 文件交换,文件大小不超过策略限制(图片可预览;其他文件始终会下载,不会在页面中打开)。
  • ✋ 举手。
  • 📡 终端共享:在 SSH 窗口的标题栏中点击 📡。可以同时共享多个终端。其他人点击👁 观看:观看者会先收到当前屏幕的快照(保留颜色),随后接收实时输出,显示尺寸与共享者完全相同。终端数据只会发送给正在观看该终端的人。
  • 🎮 远程键盘控制:观看者点击请求控制;共享者会看到允许 / 拒绝选项。共享者也可以直接在“人员”面板中授予控制权,并随时撤销。按键输入只会发送到获准控制的终端,且仅在该终端处于共享状态时发送。只有角色为操作员或更高权限的用户才能接收控制权。
  • 网络中断后,房间会自动重新连接,并恢复观看、共享和语音通话。
语音通话

在协作栏中点击🎙 加入语音即可加入通话。其使用方式类似 Discord 或 Jitsi:

  • 静音(🎤,Ctrl+Shift+M)、禁听(🎧,Ctrl+Shift+D)、离开(📞)。版主可以为所有人将某人静音。
  • 使用自选按键(例如 F8)按键通话,或使用语音活动检测。
  • 麦克风和扬声器选择、实时输入电平表、测试声音、噪声抑制、回声消除和自动增益控制(设置 → 语音与音频,或通话中的 ⚙)。
  • 说话指示器、每人音量调节、加入/离开提示音,以及每个人的连接质量(良好/一般/较差、P2P 或中继、往返时间)。
  • **仅听模式:**没有麦克风(或没有麦克风权限)也可以加入并收听。
  • **可靠的网络连接:**采用点对点 WebRTC,网络变化时会自动重启 ICE,重新连接后会自动重新加入,并内置 TURN 中继(UDP 和 TCP),适用于直连受阻的网络。也可以在管理 → 语音与网络中添加外部 STUN/TURN 服务(例如在限制严格的网络中使用 443/TLS 端口上的 coturn)。
  • **隐私保护:**音频采用端到端加密(DTLS-SRTP);中继无法解密音频。
  • 浏览器仅允许在 HTTPS 页面(或 localhost)中使用麦克风。每次通话约 12 人时效果良好(网状连接);人数上限由策略规定。
审计日志、会话录制和文件传输

WRM 会完整、可靠地记录谁在何处、何时做了什么,且记录可检测篡改:

  • 审计日志(管理面板 → 审计日志):登录(包括失败的登录)、账户和策略变更、连接、共享、加入房间和管理操作、终端会话、文件传输和变更、主机密钥、导出、查看录制内容。条目会关联到连接和终端会话(点击 ▶ #id 打开会话)。可按文本、事件类型、用户和日期范围筛选;支持 CSV 导出和验证完整性。
  • **只追加且可检测篡改:**数据库拒绝更改审计条目、文件传输记录和录制内容,也拒绝删除未满 7 天的内容。旧条目只会由保留策略作业(audit_retention_days、recording_retention_days)删除。每个条目都包含前一个条目的 SHA-256(哈希链),因此更改或删除条目会被验证完整性检测到。每个条目也会作为一条 AUDIT … 日志写入服务日志(journald/syslog → SIEM)。
  • 终端会话(管理面板 → 会话和录制;每位用户都可在设置 → 会话历史中查看自己的会话):用户、来源 IP、服务器和远程用户、时间、时长,以及会话结束方式(关闭、连接丢失、管理员结束、服务器重启导致中断)。
  • 会话录制:每个 SSH 终端的输出都会以开放的 asciinema 格式(asciicast v2)录制并压缩,其 SHA-256 会存储在数据库中。可在浏览器中点击 ▶ 回放——播放/暂停、跳转、调整速度(0.5–16×)、跳过空闲时间;可调整回放窗口大小(拖动右下角)或切换到全屏(⛶,按 Esc 退出),终端会按宽度缩放,无需横向滚动;也可点击 ⬇ 下载 .cast 文件并使用 asciinema play 播放。用户会看到*“此会话正在录制”*提示和 ● REC 标记。
    • **录制内容不包含密码:**服务器不会回显密码,因此密码不会出现在输出中。只有管理员开启录制按键输入后才会录制按键;在密码、口令和 PIN 提示处输入的内容会被屏蔽。
    • 录制不会拖慢终端(在后台写入);达到每个会话的大小上限时会停止录制,不会停止终端。
    • 谁可以查看录制内容:所有管理员都可以查看;用户可以查看自己的会话,以及其他人在自己的连接上的会话(例如共享的访客会话)。查看或下载录制内容本身也会记录在审计日志中。
  • 文件传输(管理面板 → 文件传输):记录每次上传、下载(包括在编辑器中打开的文件以及 ZIP 下载中的每个文件)和服务器间复制,并包含来源、目标、大小、SHA-256 和状态;支持 CSV 导出。
设置

顶部栏中的 ⚙ 设置包含以下选项卡:

选项卡包含内容
常规语言(English / Hrvatski)、安装为应用、主题色、关闭窗口确认、服务宕机时通知、浏览器端上传限制
通知可在浏览器外接收的事件 × 渠道、渠道支持时设置自定义收件人、免打扰时段、发送测试通知
终端字体大小、回滚缓冲区、自动重新连接
安全更改密码、双重身份验证(启用/停用、新恢复码)、已登录的设备
语音和音频麦克风、扬声器、音量电平表、降噪、回声消除、增益控制、输入模式 / 按键通话键、通话提示音
会话历史你的终端和远程桌面会话,以及连接上的会话,支持回放和下载
AI 连接MCP 地址、你的 AI 连接(撤销)、包含服务、模式、作用域和有效期的新令牌,以及 Claude Desktop、Claude 和 ChatGPT 连接器及其他 MCP 客户端的设置片段(启用 MCP 时)
数据导出连接(不含密钥)、导出包含密码和密钥的数据(需要输入密码;受策略限制)、导入(也包括跳板机和隧道)、从 mRemoteNG、PuTTY 和 OpenSSH config 导入

个人偏好按浏览器保存;所有与安全相关的数据均存储在服务器上。

管理面板

设置 → 🛡 管理面板(仅限管理员):

  • **概览:**版本、运行时间、用户(管理员、2FA)、HTTPS、语音中继状态、加密密钥来源、安全警告(未启用 HTTPS、开放注册、管理员未启用 2FA、关闭主机密钥……)、打开的终端(用户、服务器、IP 地址,以及 结束 操作)、活动 SSH 隧道(所有者、连接和路由、监听 → 目标、流量,以及 停止 操作)、实时房间(参与者、语音、共享终端)。
  • **用户:**创建用户并分配角色(如果密码留空,则生成临时密码)、设置显示名称、更改角色(管理员、安全审计员、操作员、用户)、为管理员启用/关闭 紧急访问、重置密码、重置 2FA、在所有位置退出登录、解锁、禁用/启用、删除(连同该用户拥有的所有内容,或将其移交给其他账户)。无法移除最后一位活动管理员。
  • **团队:**创建团队、添加成员并指定团队负责人;查看哪些策略和共享使用了某个团队。
  • **共享:**服务器上的所有共享——暂停/恢复或删除。
  • **安全:**安全级别(家庭版 / 商业版 / 企业版)、其预览、偏差和安全状况报告(参见安全级别和状况)。
  • **安全策略:**注册、是否必须启用 2FA、密码长度、锁定、会话空闲/最长时间、主机密钥策略、服务器密钥文件、服务器端上传限制、密钥导出、访客链接、聊天文件大小、审计日志启用/关闭及保留时间、会话录制(启用/关闭、按键记录、保留时间、大小限制)、广播输入、实时状态(启用/关闭、间隔、通过跳板机进行检查)、SSH 隧道(启用/关闭、允许使用者、监听网络地址、远程转发、空闲时停止)、代理(允许定义代理的用户)。
  • **通知:**通知渠道(电子邮件、Telegram、Slack / Mattermost / Rocket.Chat、Teams、Discord、ntfy、Gotify、Pushover、webhook),提供 发送测试、上次投递和错误信息;通知启用/关闭及最小间隔。
  • **语音和网络:**语音启用/关闭、每次通话的参与者人数、内置 TURN 中继(端口、公网 IP、主机名、中继端口、私有网络)、其他 STUN/TURN 服务器。
  • **主机密钥:**已记住的 SSH 主机密钥和 FTPS 证书;服务器重新安装后可忘记相应条目。
  • 审计日志:可搜索和筛选(事件类型、用户、日期范围),链接到会话,支持 CSV 导出和验证完整性(哈希链)。
  • **AI 助手:**组织级提供商、含转录记录的 AI 会话、回放和 终止、按用户统计用量(可为某个用户关闭助手)、终止开关和 AI 策略。
  • **AI 连接:**通过 MCP 连接的 AI 应用(可撤销单个或全部连接)、已注册的 OAuth 应用和 MCP 策略。
  • **会话和录制:**所有终端会话,支持回放和下载 .cast。
  • **文件传输:**所有已传输文件及其大小和 SHA-256,支持 CSV 导出。

任何策略也可以通过环境变量强制设置(WRM_<KEY>),例如用于配置管理;此时该策略会在管理面板中显示为锁定。

安全级别与安全态势

安全级别为重要设置设定最低要求。可在首次运行界面(首位管理员)选择;安装时使用 wrm -security-level home|business|enterprise(通过 -install-service 保留),或使用 WRM_INITIAL_SECURITY_LEVEL(尚未选择级别时应用一次);使用 WRM_SECURITY_LEVEL 强制指定;也可稍后在 管理面板 → 安全 中更改。

设置HomeBusinessEnterprise
require_https(仅允许通过 HTTPS 或从 localhost 登录)–开启开启
require_2fa(建议:管理员)所有人所有人
password_min_length–1214
session_idle_hours / session_max_days–12 / 78 / 1
login_max_failures–55
registration(建议:关闭)关闭关闭
host_key_policy(建议:tofu)tofustrict
allow_server_keys、allow_secret_export、ai_full_access–关闭关闭
allow_link_shares––关闭
link_share_max_days–307
audit_enabled / audit_retention_days(建议:开启)开启 / 365开启 / 730
session_recording / recording_retention_days–开启 / –开启 / 365
  • Home 是 WRM 之前的行为;现有安装会以此级别启动,且不会更改任何设置。
  • 更高级别会提高较弱的设置,并保留较强设置不变。应用前,预览会列出所有更改、受环境变量保持不变的设置、阻碍更改的因素(例如此浏览器使用纯 HTTP 时启用 HTTPS),以及受影响的对象:下次登录时必须设置 2FA 的用户、即将结束的会话、过期时间过长或遭封锁的访客链接,以及将在下次更改时检查的密码。应用还可以将所有其他会话注销。
  • **偏离项:**只有在提供书面理由后,设置才能低于该级别(在预览中提供,或更改策略时提供)。安全选项卡会列出每项偏离及其记录者和记录时间;偏离会写入审计日志(security.deviation、security.deviation_removed),并在设置再次达到该级别时移除。在首次运行界面通过纯 HTTP 选择级别时,系统会自动记录 HTTPS 偏离,因此之后可以启用 HTTPS。
  • **安全态势:**同一选项卡会逐项评估安装情况(✅ / ⚠ / ⛔):此浏览器是否使用 HTTPS、级别的每条规则、未启用 2FA 的管理员和用户、加密密钥的存放位置(数据库旁或单独存放)、WRM_ALLOW_ANY_ORIGIN、未设置过期时间的访客链接、已签名的更新、当前版本以及审计哈希链。每项都会说明其重要性及修复方法。导出 JSON 和 打印 / PDF 可生成供审计人员使用的报告。
角色、团队、升级验证和紧急访问

角色。 每个账户有一个角色,在创建时或之后通过 管理面板 → 用户 → ⋯ 设置:

角色权限
管理员拥有所有权限,与之前相同。
安全审计员可在管理面板中查看审计日志、终端会话和录制内容、文件传输以及安全状况。无法更改任何内容、打开连接、使用 AI 助手或 AI 连接。将某人改为审计员会结束其终端和 AI 会话。
操作员除了通过设置为 operators 的策略(例如仅供运维人员使用的隧道或 Git 更新)之外,与普通用户相同。
用户与之前相同。

团队。 管理面板 → 团队 可创建包含成员和可选负责人(★)的团队。团队用于以下三个方面:

  • **共享:**在共享对话框的(仅限成员)模式下,可为团队添加角色;每位成员都会获得该角色,之后加入团队的人也会获得该角色。从团队中移除某人会立即关闭其通过共享打开的内容。某人属于多个团队时,采用其获得的最高角色;如果直接成员角色更高,则采用直接成员角色。
  • **策略:**每项允许哪些人使用策略(隧道、远程转发、串行端口、网络工具、代理、Git 检查/更新/升级/回滚/重启/安装/Medium/传输/合并请求、Bitwarden、AI 助手、个人 AI 密钥、OpenCode、OpenCode 沙盒和 AI 连接)除 off、admins 和 all 外,还接受 operators(管理员和操作员)以及 teams:<name>,<name>(管理员和这些团队的成员)。在 策略 中选择 选择团队…。策略中指定的团队在策略更改前无法删除或重命名。
  • **交接:**离职用户所属团队的负责人会被建议为新的所有者(见下文)。

升级验证。 启用 require_step_up 后(Business 和 Enterprise 级别要求启用),以下操作会要求输入密码;如果账户启用了 2FA,还需提供 2FA 验证或恢复码:更改策略、更改安全级别、创建管理员或审计员、更改角色、停用或删除用户,或为用户启用紧急访问,重置密码或 2FA、查看已存储的凭据密码、导出私钥以及导出包含密钥的连接。验证在该浏览器会话中有效 step_up_minutes(默认值为 10 分钟);登录也算一次验证。错误密码会计入登录速率限制,每次验证都会记录在审计日志中(auth.step_up、auth.step_up_failed)。

紧急访问管理员。 将本地管理员账户标记为紧急访问账户(管理面板 → 用户 → ⋯),以便在紧急情况下使用,例如较新版本的目录登录不可用时。该账户必须使用 2FA(在设置 2FA 前,其会话会结束),还可通过 break_glass_ips 限制其访问范围(IP 地址或网络,例如 10.0.0.0/24)。每次登录都会记录在审计日志中(auth.break_glass_login),并向所有其他管理员发送通知。

删除用户时的交接。 点击 删除 会显示该用户拥有的内容(连接、文件夹、凭据、SSH 密钥、共享和代理),并询问如何处理:随账户一并删除,或移交给另一个有效账户(会推荐团队负责人,并列出管理员)。接收人会成为所有者;共享会保留其成员和团队,因此所有人仍可访问。如果接收人已有同名文件夹,则会在旧所有者的名称后追加该文件夹名称。交接会记录在审计日志中(admin.user_handover),并包含数量统计。

目录登录(OIDC)

公司可使用目录登录,而非 WRM 密码。管理面板 → 目录登录:

  1. 添加提供方:选择类型(Microsoft Entra ID、ADFS、Okta、Keycloak、Google Workspace 或其他 OpenID Connect 提供方);编辑器会显示如何在该提供方创建客户端。在提供方注册所示的重定向地址(https://<WRM address>/api/auth/oidc/callback;如果使用反向代理,请在提供方中设置该地址,或设置 ai_mcp_public_url)。输入颁发者(Entra:https://login.microsoftonline.com/<tenant ID>/v2.0,使用你自己的租户,不要使用 common)、客户端 ID和客户端密钥(加密存储,之后不会再次显示)。
  2. 测试连接会逐步检查:颁发者地址、发现文档、端点、签名密钥、PKCE,以及 WRM 之后能否检查用户(offline_access)。检查失败时会说明需要修复的内容。
  3. 规则决定谁可以登录:每条规则指定一个声明(Entra 应用角色使用 roles、组 ID 使用 groups、Google Workspace 域使用 hd,也可以使用任何其他声明)、一个值、一个 WRM 角色和可选的团队。匹配到的最高角色优先(管理员 > 安全审计员 > 操作员 > 用户);所有匹配规则中的团队都会添加。比较值时不区分大小写。如果没有规则,只有手动关联的 WRM 账户可以登录。
  4. 首次登录时创建账户(默认开启)会为匹配规则的用户创建账户。用户名取自 preferred_username(或你选择的声明);如果用户名已被占用,则会在末尾添加数字。此类账户没有密码(只能通过目录登录)。
  5. 测试登录会在新窗口中打开提供方,并显示其发送的内容(声明)、将使用或创建的账户、角色和团队、是否已验证 MFA,以及是否返回了刷新令牌。不会创建任何内容。
  6. 启用提供方后,登录页面会显示 使用 登录。 其工作方式:
  • 身份标识: 人员的身份标识是目录中不可变的 ID:Entra 的租户 ID 和对象 ID(tid + oid),否则为颁发者 + 主体(iss + sub)。绝不会使用电子邮件地址和姓名查找账户,因此重命名某人或在目录中重复使用某个姓名,不会让任何人获得他人的账户。
  • 每次登录都遵循目录设置: 角色以及规则添加的团队(team_members.source = 'oidc')都会更新;管理员手动添加的团队会保留。如果某人不再匹配任何规则,系统会拒绝其登录并结束其现有会话。登录不会降级最后一位活跃管理员(审计记录 oidc.role_kept)。紧急备用账户保持为本地账户,不能关联。
  • MFA: 启用 Require MFA proven by the provider 后,ID 令牌必须显示第二因素(amr,例如 mfa、otp、hwk),或者 acr 中列出的值之一,或 Entra 的 acrs 中列出的值之一(通过 claims 参数请求的身份验证上下文;对于其他提供商,则通过 acr_values 请求)。Microsoft Entra v2 令牌不包含 amr:应通过 Conditional Access 和身份验证上下文(例如 c1)在此处强制执行 MFA。能够证明 MFA 的提供商可满足 require_2fa;否则,使用 WRM 自带 2FA 的账户需要在目录登录后输入验证码,而 require_2fa 会要求其他账户进行设置。
  • 定期检查: 每隔 oidc_revalidate_minutes,WRM 会使用刷新令牌向提供商确认每位已登录人员是否仍可登录。如果刷新请求被拒绝(账户已禁用或删除、密码已重置、授权已撤销),或者刷新的令牌不再匹配任何规则,则会结束该人员的会话、终端、隧道、房间和 AI 会话(审计记录 oidc.access_ended)。如果没有刷新令牌,或无法联系提供商,目录会话将在 oidc_unverified_hours 后结束,除非期间成功完成检查。已关联账户列表会显示上次检查时间及其错误。
  • 提升验证级别: 没有密码的账户通过提供商确认危险操作(系统会要求提供商再次验证该人员的身份);有密码的账户则两种方式均可使用。
  • 关联现有账户: 已登录用户可在 Settings → Security → Organisation accounts 中关联其目录账户(提供商窗口必须确认是同一人);之后,他们可以通过任一方式登录。管理员可以在列表中取消关联;取消关联会结束目录会话。
  • 仅在紧急情况下使用密码登录: local_login = break_glass 会将密码表单仅保留给紧急备用管理员(折叠在 Emergency sign-in with a local account 下),并关闭自行注册。此设置仅在启用了提供商时生效。Enterprise 级别要求启用此设置。
  • 审计记录:oidc.provider_saved、oidc.provider_deleted、oidc.account_created、oidc.identity_linked、oidc.identity_unlinked、oidc.role_synced、oidc.access_ended、oidc.test_sign_in、auth.oidc_refused(包含原因)以及带有 method: oidc 的 auth.login。
LDAP / Active Directory 和 SCIM

LDAP / Active Directory 登录。 Admin panel → Directory sign-in → LDAP / Active Directory → Add directory:

  1. 类型: Active Directory 或 其他 LDAP(OpenLDAP、389 Directory Server、FreeIPA 等)。类型会自动填入用户筛选条件、登录属性(sAMAccountName / uid)和 ID 属性(objectGUID / entryUUID);如果你的目录不同,可在 高级 中修改。
  2. 服务器: ldaps://dc1.example.com(端口 636)或 ldap://dc1.example.com(端口 389,此时必须使用 StartTLS)。不支持不使用 TLS 的纯 LDAP。如果目录证书来自 WRM 主机不信任的内部 CA,请粘贴该 CA 证书(PEM)。
  3. **服务账户:**可读取用户和组的账户 DN(例如 CN=svc-wrm,OU=Service,DC=example,DC=com)及其密码。密码会加密存储,之后不会再次显示;更改服务器地址时,系统会要求重新输入密码。
  4. 基础 DN:搜索用户的位置,例如 DC=example,DC=com。
  5. 测试连接会逐步检查:地址、连接、TLS 和证书、服务账户、基础 DN、是否找到用户,以及测试名称对应的账户、不可变 ID 和所属组。某一步失败时,系统会说明需要修复什么。
  6. 规则决定谁可以登录:group 用于匹配组名或 DN(包括嵌套组),其他任何声明都用于匹配用户属性(例如 department)。匹配到的最高角色优先;所有匹配规则中的团队都会添加。
  7. 首次登录时创建账户会为匹配规则的人员创建账户,账户名采用目录中的登录名。测试登录会检查名称和密码,并显示账户、组、属性以及 WRM 将执行的操作,但不会创建任何内容。
  8. 启用该目录。只有服务账户可正常使用时才能启用。

运行方式:

  • **登录:**在常规登录页面输入 name、DOMAIN\name 或 name@domain 以及目录密码。WRM 使用服务账户查找用户,并通过以该用户身份绑定来验证密码;密码不会被存储,空密码会被拒绝(服务器会将其视为匿名绑定)。目录登录失败也会计入与本地登录相同的锁定次数。
  • **身份:**用户身份由目录中的不可变 ID(objectGUID 或所选 ID 属性)标识,而不是名称。
  • **拒绝登录的账户:**已禁用(userAccountControl)、已锁定、已过期(accountExpires)的账户,以及其他 LDAP 服务器上的 nsAccountLock、loginDisabled 或 pwdAccountLockedTime 账户,均无法登录。
  • **定期检查:**每隔 ldap_sync_minutes(默认 15 分钟),WRM 会使用服务账户查询每个已关联账户。账户被删除、禁用、锁定或过期,或者不再匹配任何规则时,其会话、终端、隧道、房间、AI 会话和 AI 连接会立即失效(审计事件 ldap.access_ended);角色和团队变更也会同步应用(team_members.source = 'ldap')。立即检查可按需运行检查。目录卡片会显示上次检查时间,检查失败时会显示 ⚠。
  • **关联现有账户:**已登录用户可在 设置 → 安全 → 组织账户 中使用名称和密码关联其目录账户(WRM 会先要求重新确认身份)。此后,该账户将使用目录密码登录;WRM 不再为其保留本地密码。管理员可在列表中取消关联;之后,用户需要重置密码才能在本地登录。
  • **WRM 中的目录密码:**这类账户无法在 WRM 中更改密码;更改需要提升认证级别的操作和 2FA 设置时,需使用目录密码确认。
  • 启用目录时,local_login = break_glass 仍然适用:只有紧急管理员保留本地密码。
  • 审计事件:ldap.directory_created、ldap.directory_updated、ldap.directory_deleted、ldap.account_created、ldap.identity_linked、ldap.identity_unlinked、ldap.synced、ldap.access_ended、ldap.test_sign_in,以及带有 method: ldap 的 auth.login / auth.login_failed(拒绝登录时会记录原因)。 **SCIM 配置。**借助 SCIM 2.0,身份提供商(Microsoft Entra ID、Okta 等)可以批量创建、修改、停用和删除 WRM 账户与群组。管理面板 → 目录登录 → SCIM 配置 → 添加配置客户端:
  1. 为客户端命名,并可选择添加将群组名称转换为角色的规则(group = WRM Admins → Administrator)。
  2. 复制 token(wrm_scim_…);它只显示一次,且仅以哈希形式存储。新建 token 会替换现有 token,撤销 会停用客户端。
  3. 在身份提供商中,将 租户 URL 设为显示的端点(https://<WRM address>/scim/v2),并将 密钥 token 设为复制的 token。在 Entra ID 中:企业应用程序 → 配置 → 自动。将 externalId 映射到 objectId,这样用户首次通过目录登录(OIDC)登录时会使用已配置的账户。

工作方式:

  • 客户端只能看到自己创建的账户和群组;它看不到本地账户和其他客户端的账户,且名称永远不会用于关联账户。
  • 已配置的账户没有密码;用户通过目录登录。首次 OIDC 登录时,如果账户的 externalId 与 token 的 oid(Entra)或 sub 相同,且账户尚未关联目录,则会关联该账户。
  • active: false 或删除用户会停用账户并结束其会话、终端、隧道、房间、AI 会话和 AI 连接;WRM 会保留该账户,以便管理员移交其工作。最后一位启用的管理员不会被停用或降级(scim.disable_refused)。
  • 群组会成为名称为 <group> (SCIM) 的 WRM 团队;成员关系随群组同步。手动创建的团队绝不会被接管。
  • 对其配置的账户,身份提供商是事实来源:即使管理员在 WRM 中停用了账户,active: true 仍会重新启用该账户。如需阻止某人访问,请在身份提供商中停用该用户或取消其分配。
  • 支持:Users 和 Groups(创建、读取、替换、PATCH、删除)、filter=userName eq "…"、externalId eq "…" 或 id eq "…"(群组:displayName、externalId、id)、startIndex / count、ServiceProviderConfig、ResourceTypes、Schemas。限制:每个地址每分钟 600 个请求,每个请求 1 MB。
  • 审计事件:scim.client_created、scim.client_updated、scim.token_rotated、scim.client_revoked、scim.user_created、scim.user_updated、scim.user_disabled、scim.user_deleted、scim.group_created、scim.group_renamed、scim.group_deleted、scim.team_created。

**结束访问。**所有停用账户的途径(管理员停用、OIDC 重新验证、LDAP 检查、SCIM)都会结束相同内容:登录会话、终端、隧道、协作房间、AI 会话和 AI 连接(MCP tokens)。

SIEM 导出、警报和锁定

自 v12.6.26 起(remote-manager/siem.go、alerts.go、lockdown.go),位于管理面板 → 安全中。

**SIEM 导出。**选择 SIEM 导出 → 添加目标,选择类型,填写字段并保存(需要二次验证)。测试会发送一个 siem.test 事件并显示响应。

类型地址密钥说明
Syslog(通过 TLS 的 RFC 5424)host:port(通常为 6514)客户端证书的私钥(可选)RFC 5425 八位组计数;包含主要字段的结构化数据 wrm@32473,完整事件以 JSON 格式放在消息中;除非另行设置,否则使用设施 authpriv(10);严重级别为 notice,失败时为 warning,security.alert 为 critical
JSON 行文件WRM 主机上的绝对路径,以 .jsonl、.json 或 .log 结尾–每行一个事件,权限模式为 0600,达到 100 MB 时轮换并保留 .1–.3;文件夹必须存在,且文件不能是符号链接
Splunk HECHEC 地址(https://splunk.example.com:8088)或完整的 …/services/collector/eventHEC 令牌sourcetype(默认为 wrm:audit)和 index 均可选
ElasticElasticsearch / OpenSearch 地址API 密钥(可选)使用 _bulk 写入索引(默认为 wrm-audit);条目错误会被视为投递失败
Microsoft Sentinel数据收集终结点(https://<dce>.<region>.ingest.monitor.azure.com)Entra 应用的客户端密钥租户 ID、应用程序(客户端)ID、数据收集规则的不可变 ID 和流(默认为 Custom-WRMAudit_CL);该应用需要在规则上拥有 Monitoring Metrics Publisher 角色
通用 HTTPS任意 HTTPS URL令牌(可选)以 POST 方式发送事件 JSON 数组;提供令牌时,WRM 会发送 Authorization: Bearer <token> 和 X-WRM-Signature: sha256=<HMAC-SHA256 of the body with the token>

HTTPS 地址必须使用 HTTPS(仅回环地址可使用普通 HTTP);可为内部收集器添加额外的 CA 证书(PEM)。不会跟随重定向。

工作方式:

  • 每个事件按顺序至少投递一次。 每个目标都会单独记录其在审计日志中的位置,每次最多发送 200 个事件。投递失败后会在 5 秒、10 秒、20 秒……后重试,间隔最长为 5 分钟;只要 WRM 保留着审计日志(audit_retention_days),就不会丢失任何内容。新目标会从新事件开始,或按需从保留的完整审计日志开始。仅发送这些操作会将目标限制为指定的操作前缀(例如 auth., admin., security.)。
  • 事件字段:@timestamp、event(id、action、category、outcome、kind)、observer(产品、版本、主机名)、hash(prev、this:审计链,用于让 SIEM 证明没有内容被删除)、user(id、name、roles、email、directory,其中目录账户包含提供方和不可变 ID)、source.ip、target、details、connection_id、session_id。
  • **状态:**每个目标会显示 Delivering、Behind(有超过 1000 个事件等待发送)、Failing(附带上次错误、错误时间和下次重试时间)或 Off,并显示已发送和等待中的数量以及上次投递时间。
  • 密钥在静态存储时会加密,绝不会发送到浏览器。更改目标地址或类型时需要重新输入密钥,因此已存储的密钥绝不会发送到其他服务。
  • 审计事件:siem.destination_created、siem.destination_updated、siem.destination_deleted、siem.tested、siem.test_failed。

安全警报。 规则会监控审计日志。匹配规则时会写入一条 security.alert 记录(包含规则、摘要、触发警报的操作、用户和地址),将其发送到 SIEM,并通过 Workboard 收件箱和 security.alert 通知告知所有活跃管理员。Admin panel → Security 会列出近期警报;Policies → Security alerts 可管理规则:

规则设置触发条件
登录失败alert_failed_signins(10,0 = 关闭)、alert_failed_signins_minutes(10)在时间窗口内,来自同一地址或针对同一用户名的登录失败次数达到设定值(密码、2FA、step-up、AI 令牌);每个窗口和键仅触发一次
紧急登录alert_break_glass紧急管理员登录(仅 SIEM:管理员已通过 security.break_glass_login 收到通知)
新建管理员alert_new_admin某个账户被创建为管理员、被更改为管理员,或从目录同步为管理员
查看机密alert_secret_reveal显示了已存储的密码,或导出了私有 SSH 密钥或包含机密信息的连接
AI 完全访问权限alert_ai_full_access有人批准了 WRM 在未获得完全访问权限时会拒绝的 AI 命令
审计关闭alert_audit_offaudit_enabled 被关闭,或 SIEM 目标被关闭或删除

即使 audit_enabled 处于关闭状态,也会记录安全事件(security.*)。

停止用户。 在 管理面板 → 用户 → ⋯ → 停止用户(step-up):该账户会被禁用,其登录会话、终端、共享会话、隧道、AI 会话和 AI 连接会立即结束;随后 WRM 会显示每种会话或连接结束的数量。确认安全后可重新启用该账户。无法停止自己的账户或最后一位管理员。审计记录 admin.user_stopped 以及已结束的内容。

锁定。 发生安全事件时,仅紧急管理员可以登录或保持会话。

  • 启用锁定: 在 管理面板 → 安全 → 锁定 → 锁定 WRM 中填写所有人都能看到的原因(始终会要求再次确认)。如果没有紧急管理员,则拒绝启用锁定,因为届时无人可以登录。在 WRM 主机上运行:wrm -lockdown on -lockdown-reason "incident 42"(也可使用 off 和 status);正在运行的 WRM 会在五秒内应用设置。WRM_LOCKDOWN=1 会在启动时强制启用锁定,且无法通过界面解除。
  • 锁定期间的操作: 除紧急管理员外,所有人都会被注销,其终端、共享会话和隧道都会结束;所有 AI 会话和 AI 连接都会结束,并像启用 AI 紧急停止开关时一样拒绝 AI;共享也会被拒绝。响应中会列出已结束的内容。非紧急管理员也会被注销。
  • 锁定期间,登录页面会显示锁定状态及原因,且只有紧急管理员可以登录(使用密码和 2FA;拒绝目录登录)。
  • 解除锁定: 紧急管理员点击 解除锁定,或在主机上运行 wrm -lockdown off。账户、共享和 AI 设置会恢复原样;用户需要重新登录。
  • 审计记录:security.lockdown_on、security.lockdown_off、security.lockdown_enforced(启动时或通过命令行应用),以及因 lockdown 原因被拒绝的登录。
更新与自我更新
  • 检查更新: 每天一次(以及点击 立即检查 时),WRM 会向 update_repo(默认为本项目)的 GitHub 发布版本 API 查询最新版本。只会发送仓库路径和固定的 User-Agent:不发送任何用户数据或安装 ID。代理取自 update_proxy 或 HTTPS_PROXY / HTTP_PROXY。无网络隔离环境中的安装可通过 update_check(WRM_UPDATE_CHECK=off)关闭此功能。
  • 版本徽章: 有较新版本时,顶部栏会显示 ⬆ 更新 vX.Y.Z(窄屏上仅显示 ⬆),登录页面会显示 有可用更新 vX.Y.Z。徽章会打开发布说明和发布页面。
  • 一键更新(管理员,策略 self_update):
    1. 将该版本的 wrm-pro-vX.Y.Z-<os>-<arch>[.exe] 下载到二进制文件旁边(显示进度);
    2. 使用内置于 WRM 的发布密钥(以及 update_signing_keys,例如你自己的分支所用的密钥)验证发布版本的 SHA256SUMS.txt 的签名 SHA256SUMS.txt.sig(ed25519),然后核对文件的 SHA-256 是否与 SHA256SUMS.txt 一致。如果签名缺失或错误(已知密钥时),或校验和文件、其条目或哈希值不匹配,则拒绝更新。如果没有任何已知密钥,弹窗会显示 未检查签名,且只验证 SHA-256;
    3. 使用 -version 运行新文件;它必须返回该发布版本的版本号;
    4. 原子替换二进制文件:重命名并覆盖旧文件(Linux、macOS、BSD),或在 Windows 上将正在运行的 .exe 重命名为 .exe.old,再将新文件移至原位置(下次启动时,.old 文件会成为回滚副本);
    5. 重启:服务通过其服务管理器重启(退出代码 75:systemd、launchd、FreeBSD daemon(8)、Windows 恢复机制);否则由 WRM 原地重新启动自身。页面会等待并自动重新连接。
    • 之前的二进制文件会保留为 <binary>.previous:↩ 回滚到 vX.Y.Z 会将其换回并重启。
    • 每个步骤都会记录审计日志:system.update_check、system.update_started、system.update_downloaded、system.update_verified、system.update_installed、system.update_failed、system.update_restart、system.update_rollback。
    • 更新本身绝不会修改数据库;新版本会照常运行增量迁移,因此旧二进制仍可在该数据库上启动。
    • WRM 必须能写入二进制文件所在文件夹,否则弹窗会说明这一点。
  • 文件夹中的最新二进制文件: 将较新的 wrm-pro-v<semver>-<os>-<arch>[.exe] 复制到正在运行的二进制文件旁边。服务启动时会切换到最新的有效文件(该文件必须通过 -version 返回其文件名中的版本号;其他平台、较旧版本以及没有响应的文件都会被忽略)。更新弹窗会为其提供 ↻ 重启并切换到 vX.Y.Z。
  • Docker: 容器不会自我替换。页面会显示徽章和发布说明;弹窗会列出 docker pull ghcr.io/<owner>/wrm-pro:vX.Y.Z 和 compose 命令。
移动设备、自适应 UI 和可安装应用
  • 顶部栏和协作栏会根据可用宽度进行调整(标签会逐步折叠为图标)。
  • 可安装应用(PWA): Settings → General → Install as an app(或地址栏中的安装图标;在 iPhone/iPad 上:Share → Add to Home Screen)会在独立窗口中打开 WRM,可从程序坞、开始菜单或主屏幕启动。应用只会缓存自身的脚本和字体(按版本缓存);连接和数据始终实时来自服务器,服务器不可用时则会显示离线页面。浏览器仅允许通过使用可信证书的 HTTPS(或 localhost)进行安装。Install as an app 一栏会显示当前浏览器的安装步骤,或说明无法安装的原因(普通的 http://、不受信任的证书、桌面版 Firefox);只有浏览器可以立即安装时才会显示 Install 按钮。
  • 在手机上(< 760 px):连接列表和 Sessions/Snippets/Clipboard 面板会变为滑入式抽屉(在固定的启动布局中,无论你在较大屏幕上如何排列)(☰ 和 🗂 按钮);窗口会全屏打开,轻点即可打开连接。Chat 和 People 会以全宽面板打开。

键盘快捷键

位置快捷键操作
任意位置Alt+N新建窗口
任意位置Esc关闭菜单 / 对话框 / 面板
语音通话Ctrl+Shift+M / Ctrl+Shift+D静音 / 禁用麦克风(即使终端处于焦点也有效)
语音通话你的按键通话键(例如 F8)按住说话
终端Ctrl+Shift+F搜索终端输出
终端Ctrl+Shift+Space打开代码片段选择器(Enter 执行,Shift+Enter 插入)
代码片段面板单击 / Shift+单击在焦点所在的终端中执行 / 不按 Enter 插入
终端Ctrl+Shift+C / 选择文本复制
终端Ctrl+Shift+R重新连接 SSH
终端Enter(关闭时)重新连接
终端Ctrl+W发送到终端(不会关闭浏览器标签页)
文件管理器Enter / Backspace打开 / 上移
文件管理器↑ ↓ Home End、Shift移动 / 扩展选择
文件管理器Ctrl+A、Delete、F2、F5全选、删除、重命名、刷新
文件管理器Ctrl+F、在搜索框中按 Enter筛选、搜索子文件夹
编辑器Ctrl+S、Tab保存、插入制表符
窗口标题双击最大化 / 还原
标签页中键单击、右键单击关闭、打开标签页菜单

配置

中级运行时设置(v12.4.3b 中引入):

设置项 / 环境变量覆盖项默认值用途
git_medium / WRM_GIT_MEDIUMadminsoff、admins、all;可信原始工具操作员。导入工具代码始终需要管理员权限。
medium_host_ca / WRM_MEDIUM_HOST_CA1Medium 的 Docker 运行时也信任 WRM 主机信任的根证书(在经过代理或会检查 HTTPS 的防病毒软件的环境中需要)。
medium_ca_file / WRM_MEDIUM_CA_FILE–包含额外根证书的 PEM 文件路径,供 Medium 的 Docker 运行时使用,例如代理的根 CA。
medium_docker_install / WRM_MEDIUM_DOCKER_INSTALL1管理员在 Medium 第 2 步中允许一次后,WRM 可在自己的主机上为 Medium 安装并启动 Docker(在 Windows 和 macOS 上需接受 Docker Desktop 许可)。0 会隐藏 Install Docker 并停止自动安装。
medium_native / WRM_MEDIUM_NATIVEadmins谁可以将 Medium 项目切换到 WRM 原生引擎,并使用该引擎进行部署、回滚和释放锁(off、admins、operators、teams:<names>、all)。比较和试运行只需要 git_medium。
medium_default_engine / WRM_MEDIUM_DEFAULT_ENGINEnative尚未选择引擎的 Medium 项目所用的引擎:native(WRM 为获准使用 medium_native 的用户部署项目;原始工具为可选项)或 original。已导入原始工具的升级安装会以 original 启动。
medium_build_user / WRM_MEDIUM_BUILD_USER–在 WRM 主机上运行 Medium 构建的非特权 OS 账户(在 Linux/Unix 上,WRM 必须以 root 身份运行)。为空:构建将使用 WRM 账户运行。
medium_command_timeout / WRM_MEDIUM_COMMAND_TIMEOUT300原生部署中的一条命令可在服务器上运行的秒数,例如 post_deploy(30–86400)。
medium_transfer_timeout / WRM_MEDIUM_TRANSFER_TIMEOUT3600一个目标位置的文件传输可用的秒数(600–86400)。该值与命令超时共同决定何时可以手动释放遗留的锁。
medium_log_output / WRM_MEDIUM_LOG_OUTPUTall谁可以在 Medium 活动日志中查看命令输出:all(运行命令的用户、管理员、共享运行时的所有人)、admins、none。步骤、结果和错误始终会显示。
bitwarden / WRM_BITWARDENalloff、admins、all;访问每位用户自己的保管库。
bitwarden_idle_minutes / WRM_BITWARDEN_IDLE_MINUTES15解锁后的闲置时长,1–240 分钟。
WRM_BITWARDEN_CLIPATH 上的 bw官方 CLI 可执行文件覆盖项。
WRM_MEDIUM_RUNTIMEautoauto 在 Linux、macOS 和 Windows 上使用 Docker(已提前准备好的主机运行时会一直保留,直到 Docker 运行时准备就绪),在其他系统上使用主机运行时;docker 或 native 可显式指定。Windows 始终使用 Docker。
WRM_MEDIUM_DOCKERPATH/标准 Desktop 路径上的 DockerCLI 覆盖项,不含 shell 参数。
WRM_MEDIUM_CONTAINER_IMAGE固定版本的已发布 WRM Linux 镜像可信的自定义运行时镜像;源代码仍会私密导入。
WRM_MEDIUM_PYTHONPATH 上的 Python用于私有虚拟环境的 Python 3.12+ 可执行文件。
WRM_MEDIUM_SSH_AUTH_SOCK未设置可选的 SSH Agent 套接字,仅限获准使用服务器端密钥的用户。

环境变量

变量默认值描述
PORT8080监听端口
LISTEN_ADDR:PORT完整监听地址,例如 127.0.0.1:8080(优先于 PORT)
DB_PATH./remote_manager.dbSQLite 数据库文件
ENCRYPTION_KEY–用于存储机密信息的自定义密钥(使用前 32 个字节;派生方式与 v9 相同)。
ENCRYPTION_KEY_FILE–从文件读取密钥(64 个十六进制字符表示原始 256 位密钥;其他内容均会进行哈希处理)。
(均未设置)<DB_PATH>.key首次启动时会在此处生成随机密钥(权限模式为 0600)。
HTTPS_CERT_FILE + HTTPS_KEY_FILE–使用此证书和密钥提供 HTTPS 服务(会发送 HSTS)。
HTTPS_SELF_SIGNED–1 = 创建并使用自签名证书(位于数据库旁的 wrm-selfsigned.crt/.key)。浏览器会提示一次;适用于局域网和没有 CA 的语音通话。
HTTPS_SELF_SIGNED_HOSTS–自签名证书的额外主机名/IP,使用逗号分隔。
WRM_RECORDINGS_DIR<DB dir>/recordings存储会话录制的位置
WRM_TRUST_PROXY–1 = 信任反向代理提供的 X-Real-IP / X-Forwarded-For / X-Forwarded-Proto / X-Forwarded-Host(用于速率限制和审计中的客户端 IP,以及安全 Cookie)。仅当 WRM 只能通过该代理访问时启用。
WRM_ALLOWED_ORIGINS–允许作为 Origin 的额外主机名(使用逗号分隔),例如代理重写 Host 标头时
WRM_ALLOW_ANY_ORIGIN–1 = 禁用 Origin 检查(不建议)
WRM_LOCKDOWN–1 = 启动时强制进入锁定状态:只有紧急管理员可以登录,AI 关闭,共享暂停;无法在 UI 中结束锁定状态
WRM_INITIAL_SECURITY_LEVEL–home / business / enterprise:在尚未选择安全级别时于启动时应用一次(供安装程序使用);WRM_SECURITY_LEVEL 会强制设置并锁定该级别
WRM_<POLICY>–强制应用管理面板中的策略,例如 WRM_REGISTRATION=open、WRM_REQUIRE_2FA=all、WRM_TURN_PUBLIC_IP=203.0.113.10、WRM_TURN_ENABLED=0、WRM_HOST_KEY_POLICY=strict。

策略(管理面板,或使用大写的 WRM_<KEY>)

键默认值含义
security_levelhomehome / business / enterprise,参见安全级别与安全态势;请在 管理面板 → 安全 中更改,而非在此处更改
require_https0仅允许通过 HTTPS(或从 localhost)登录、注册和使用 2FA
require_step_up0危险操作需要重新输入密码(并通过 2FA)确认,参见角色、团队、二次验证和紧急访问;Business 和 Enterprise 级别要求启用
step_up_minutes10二次验证确认的有效时长(1–240)
break_glass_ips–紧急访问管理员可登录的 IP 地址或网络(逗号分隔);留空 = 任意地址
local_loginall启用目录登录时,哪些人仍可使用密码登录:all / break_glass,参见目录登录(OIDC);Enterprise 级别要求设为 break_glass
oidc_revalidate_minutes60WRM 向身份提供商确认已登录的目录用户仍可登录的检查间隔(5–1440)
oidc_unverified_hours12目录会话在未成功检查的情况下持续此时长后结束(1–720)
alert_failed_signins10同一地址或同一用户名的登录失败达到多少次后触发安全警报(0 = 关闭),参见 SIEM 导出、警报与锁定
alert_failed_signins_minutes10统计登录失败次数的时间窗口(1–1440)
alert_break_glass / alert_new_admin / alert_secret_reveal / alert_ai_full_access / alert_audit_off1其他安全警报规则
ldap_sync_minutes15WRM 检查每个关联到 LDAP / Active Directory 目录的账户的频率(5–1440),参见 LDAP / Active Directory 和 SCIM
registrationclosedclosed / open,控制是否开放自行注册
require_2faoffoff / admins / all
password_min_length86–128
login_max_failures10密码错误达到此次数后锁定账户(15 分钟)
session_idle_hours168不活动达到此时长后退出登录
session_max_days30会话最长有效期
host_key_policytofutofu / strict / off
allow_server_keys0允许非管理员使用 Key file / Auto
max_upload_mb0服务端每个文件的上传限制(0 = 无限制)
allow_secret_export1允许用户导出自己的机密、导出密钥库中的私钥并显示保险库密码(需重新输入密码)
allow_link_shares1允许访客使用“任何持有链接的人均可访问”的共享
link_share_max_days0访客链接的最长有效天数(0 = 无限制);设置此项后,不带过期时间的链接将被拒绝
chat_file_max_mb5协作聊天中的文件大小(0 = 关闭)
voice_enabled1开启/关闭语音通话
voice_max_participants12每次通话人数
turn_enabled1内置 TURN 中继
turn_port3478中继端口(UDP + TCP)
turn_public_ipauto服务器位于 NAT 后方时的公网 IPv4 地址
turn_hostWRM host浏览器连接中继时使用的主机名
turn_relay_ports49152-65535中继音频的 UDP 端口范围
turn_allow_private0允许中继到专用/环回网络
ice_serversGoogle + Cloudflare STUN其他 STUN/TURN 服务(JSON)
audit_enabled1记录安全事件(始终记录管理员操作)。另见 AUDIT_ENABLED
audit_retention_days365审计日志、文件传输记录和聊天历史的保留时长(最少 7 天)
session_recording1录制终端会话。另见 SESSION_RECORDING_ENABLED
session_recording_input0同时录制按键(在密码提示处会屏蔽)
recording_retention_days90录制内容的保留时长(最少 7 天)
recording_max_mb100每个会话的最大录制文件大小(0 = 无限制)
tunnels_enabled1启用 SSH 隧道和跳板机后的 Web 界面;关闭后会停止运行中的隧道。另见 TUNNELS_ENABLED
tunnel_usersall哪些人可以使用隧道:all / admins(所有 who may 策略也接受 operators 和 teams:<names>)
tunnel_bind_any0允许非管理员监听网络地址(0.0.0.0、LAN IP),而非 127.0.0.1
tunnel_remote_forwardadminsoff / admins / all:远程端口转发(-R)
tunnel_idle_minutes0隧道无流量达到此分钟数后停止手动启动的隧道(0 = 从不停止)
broadcast_enabled1广播输入(同时向多个终端输入)。另见 BROADCAST_ENABLED
status_enabled1实时显示连接状态。另见 STATUS_ENABLED
status_interval_seconds60两次状态检查之间的秒数(15–3600)
status_jump_checks0通过登录跳板机检查其后的连接
addon_personalall哪些人可以安装仅自己可见的个人插件(off、admins、all);个人插件不能包含服务端代码
addon_httpall哪些人可以使用通过 WRM 访问网站的插件(off、admins、all);相关网站仍需管理员批准
workboard_ssh_metrics1Workboard 的 Server load 插件可通过 SSH(Linux)读取没有 Monitoring 的服务器的 CPU、RAM、负载和磁盘信息
desktop_enabled1在浏览器中使用 RDP / VNC / Telnet。另见 REMOTE_DESKTOP_ENABLED
guacd_address127.0.0.1:4822guacd 的主机:端口。另见 GUACD_ADDRESS
bmc_enabled1带外管理(BMC 电源、状态、控制台)。另见 BMC_ENABLED
serial_portsadmins哪些人可以使用 WRM 服务端的串行端口:off、admins、all
network_toolsall哪些人可以使用网络工具(端口检查、ping、traceroute、DNS、HTTP/TLS):off、admins、all
proxiesall哪些人可以定义已保存的代理:off、admins、all(所有人都可以使用与自己共享的代理)
notifications_enabled1通过 管理面板 → 通知 中的渠道发送通知。另见 NOTIFICATIONS_ENABLED
notify_min_interval_seconds60同一用户和渠道在此时间内最多发送一条消息(0–86400);其余消息会进入下一份摘要
git_enabled1Git 工作区(⎇ Git);关闭后将完全隐藏。另见 GIT_ENABLED
git_checksall哪些人可以运行 Git 检查(通过 SSH 发现和比较,只读):off、admins、all
git_check_interval_minutes60已启用定期检查的用户的 Git 检查间隔(0 = 不检查,最多 10080)
git_backup_wordsbkp,backup,bak,old,…Git 发现和比较时,将包含这些词之一的路径段视为副本/备份
git_check_parallel8一次 Git 检查同时比较的安装数量(跨所有服务器,1–64)
git_check_per_server2一次 Git 检查同时比较同一服务器上的安装数量(同一登录上的 SSH 会话,1–8)
git_update / git_upgrade / git_rollback / git_restartadmins哪些人可以更新(并打标签)、升级、回滚安装并重启其单元:off、admins、all
git_install / git_transferadmins哪些人可以在新服务器上安装服务,以及在服务器间迁移安装:off、admins、all
git_gitignore_mradmins哪些人可以通过助手创建 .gitignore 合并请求(GitLab)/拉取请求(GitHub):off、admins、all
git_schedule_grace_minutes30若 WRM 在计划运行或重启的时刻未运行,且已超过此时长,则跳过该任务(1–1440)
update_check1每天检查一次 update_repo 的 GitHub 发布版本(不会发送用户数据);隔离网络安装可设置 WRM_UPDATE_CHECK=off
update_repovedranius/web-browser-RDM-public用于检查和安装发布版本的 GitHub 仓库(owner/name)
update_signing_keys–额外的发布公钥(wrm-ed25519:…,逗号分隔),其签名必须包含在更新的 SHA256SUMS.txt 中,例如用于 update_repo 中的自有分支;本项目的密钥已内置
update_proxy–用于检查更新和下载的 HTTP 代理(例如 http://proxy.example.com:3128);留空 = 使用 HTTPS_PROXY / HTTP_PROXY
self_updateadmins哪些人可以通过版本徽标更新、回滚和重启 WRM:off、admins(Docker 中始终不可用)
ai_assistantoff哪些人可以使用 AI 助手:off、admins、all
ai_kill_switch0设为 1 会结束所有 AI 会话并阻止新会话
ai_modesread_only,ask允许的模式(read_only、ask、auto);模式规则只能进一步收窄范围
ai_default_moderead_only新会话在允许的情况下使用的模式:read_only、ask
ai_mode_rules[]JSON 规则 {"match": "tag"|"folder"|"connection"|"host", "value", "modes"};匹配的规则中限制最严格者优先
ai_personal_keysoff哪些人可以添加自己的提供商密钥:off、admins、all
ai_provider_kindsall允许的提供商类型:anthropic,openai,azure,bedrock,vertex,openai_compatible,opencode
ai_models–允许的模型,使用逗号分隔的模式(claude-*);留空 = 允许使用这些提供商的所有模型
ai_ollama_manage0允许管理员通过提供商向导使用 WRM 安装/启动/拉取 Ollama(WRM_AI_OLLAMA_MANAGE);关闭时,向导仅显示命令
ai_redact_output1将输出发送给提供商前遮盖机密(始终遮盖会话记录和审计内容)
screen_lock_modeserver屏幕锁定的严格程度:server(锁定的会话在解锁前返回 423)、remember(重新加载后仍保持锁定)、browser(仅锁定页面)
screen_lock_max_minutes0用户可选择的锁屏前最长空闲时间;0 = 由用户决定
screen_lock_pin1用户可使用个人 4–12 位 PIN 解锁屏幕
screen_lock_max_failures0解锁尝试输错达到此次数后退出浏览器会话;0 = 从不退出
appearance_default_themegraphite尚未选择主题的用户使用的主题:内置 ID 或 addon:<addon>:<theme>
appearance_custom_css1用户可为自己的界面添加 CSS
ai_show_thinking1在工作日志中显示助手的思考过程(推理摘要),并将其保留在会话记录中
ai_auto_titles1每次 AI 聊天在首次回答后自动生成简短标题(额外发送一次不使用工具的小型请求)
ai_share_notes1用户可以选择发送自己的连接备注
ai_transcript_retention_days90AI 会话记录在此时长后删除(1–3650)
ai_approval_timeout_seconds300未获答复的批准请求将被拒绝(30–3600)
ai_mcp_later_approvalrunMCP:若 AI 应用已停止等待后,用户才在 WRM 中批准请求,则立即运行调用(run),或仅允许 AI 重试(repeat)
ai_keep_saved_sessions1已保存的 AI 会话(AI sessions 中的 ☆)会在 ai_transcript_retention_days 期限后继续保留
ai_auto_max_minutes / ai_auto_max_actions60 / 50用户可选择的最长时限和最大操作数
ai_auto_until_grant1AI 连接(MCP)可使用无限时长、无限操作数的自动模式,直至连接失效
ai_allow_poweroffshutdown / reboot:off(禁止)或 ask(每次都需要批准,绝不自动执行)
ai_blocked_commands–在所有模式下均会拒绝的额外命令模式
ai_read_deny_paths–视为敏感的额外路径模式(不含 / 的模式会匹配文件名)
ai_delegate0助手可以将文本任务交给辅助模型
ai_delegate_provider0用于辅助模型的组织提供商 ID
ai_delegate_models–允许使用的辅助模型,逗号分隔;留空 = 从提供商目录中自动选择
ai_delegate_max_kb64单次委派最多可发送的文本量(1–1024 KiB)
ai_delegate_traininguser可将提示词用于训练的免费模型:off 表示从不,user 表示由每位用户决定(默认关闭),all 表示所有人均可使用
ai_opencodeall哪些人可以在助手中使用 OpenCode Agent:off、admins、all(仍受助手权限设置约束)
ai_opencode_version1.19.3WRM 安装的 OpenCode 版本
ai_opencode_registryhttps://registry.npmjs.orgWRM 下载 OpenCode 所用的 npm 注册表(HTTPS)
ai_opencode_path–自行提供的 OpenCode 二进制文件的绝对路径,替代 WRM 安装的版本
ai_opencode_max_sessions4同时运行的 OpenCode Agent 数量(1–50)
ai_opencode_sandboxoff在 WRM 主机上的 Docker 沙盒中运行 OpenCode 自带工具,每次使用都需批准:off、admins、all
ai_opencode_sandbox_imagedebian:stable-slim沙盒的 Docker 镜像(任何包含 shell 的镜像均可)
ai_full_access0AI 完全访问权限:WRM 原本会拒绝的所有操作都改为请求批准(每次都需批准,绝不自动执行);只读模式仍为只读
ai_full_access_modeall完全访问权限的适用范围:all(所有 AI 会话)、connection(具有 full_access 作用域的 AI 连接)、user(自行启用此功能的用户)
ai_full_access_blockedask完全访问模式下,ai_blocked_commands 中的命令需要批准(ask)或仍被拒绝(deny);内置的破坏性命令列表始终需要批准
ai_sensitive_readsask敏感文件:ask 表示用户批准每次读取后才读取(遮盖看起来像机密的值),deny 表示永不读取
ai_command_timeout_seconds60工具调用在此时长后停止
ai_output_max_kb64每次工具调用的输出上限及文件读取限制
ai_max_steps25每条用户消息可发起的模型请求数
ai_idle_minutes60空闲的 AI 会话将在此时长后结束
ai_mcp_enabled0提供 MCP 端点 /mcp 以及供 AI 应用使用的 OAuth 端点
ai_mcpadmins哪些人可以创建和使用 AI 连接:off、admins、all
ai_mcp_scopesall five允许的作用域:read_logs、run_readonly、run_with_approval、edit_file_with_approval、transfer
ai_provider_header_seconds900等待提供商响应标头的时长,30–7200 秒
ai_provider_request_seconds3600提供商请求的总时长,60–14400 秒
ai_provider_stream_idle_seconds600提供商数据流无活动时长,30–7200 秒
ai_mcp_modesread_only,ask,autoAI 连接允许的模式(模式规则会针对每个连接收窄范围)
ai_mcp_token_hours / ai_mcp_max_token_hours168 / 720令牌或 OAuth 批准的默认和最长有效时长
ai_mcp_oauth1为 AI 应用启用 OAuth 2.1(PKCE、动态客户端注册);0 = 仅限令牌
ai_mcp_redirect_urisclaude.ai, claude.com, ChatGPT, http://localhost:*OAuth 重定向 URI 允许列表(* = 任意文本;允许 https,或环回地址上的 http)
ai_mcp_allowed_origins–允许调用 /mcp 的浏览器来源(除 WRM 外)(CORS)
ai_mcp_public_url–AI 应用使用的 WRM 公网地址(反向代理)
ai_mcp_elicitation1同时在 AI 应用中请求批准(MCP elicitation)
ai_mcp_transfer_max_mb100transfer 作用域允许传输的最大文件大小
desktop_tunnel_bind127.0.0.1guacd 连接的临时跳板机隧道所绑定的地址(guacd 在 WRM 所在机器上运行时,请保留 127.0.0.1)
命令行
wrm -version                       print the version
wrm -reset-password USER           set a new temporary password (must be changed at sign-in)
wrm -reset-password USER -reset-2fa  … and turn off two-factor authentication
wrm -lockdown on|off|status        lockdown: only break-glass administrators can sign in (a running WRM applies it within 5 s)
    -lockdown-reason TEXT          the reason shown on the sign-in page (with -lockdown on)
wrm -healthcheck                   check /healthz of the local server (exit code 0 = healthy; for containers)
wrm -install-service               install WRM as a service that starts at boot, start it (see Service)
    -security-level LEVEL          home, business or enterprise on first start (kept in the service environment)
wrm -uninstall-service             stop and remove the service (the data stays)
wrm -service-status                is the service installed and running?
    -service-name NAME             service name (default wrm)
    -service-scope system|user     macOS: LaunchDaemon (boot) or LaunchAgent (login)
    -service-user ACCOUNT          Unix account the service runs as (default: you, or SUDO_USER)
wrm -no-service-prompt             do not ask on the console whether to install the service
wrm -env-file FILE                 read KEY=value lines before starting (variables already set win)
wrm -workdir DIR                   change to DIR before starting
wrm -mcp-stdio -url URL -token T   stdio bridge for MCP clients to the WRM server at URL (see AI desktop apps)
    -token-file FILE               read the token from FILE (or WRM_MCP_TOKEN; the URL also from WRM_MCP_URL)
    -ca-file FILE                  trust this CA / self-signed certificate (PEM) for the WRM server
wrm -addon-new TEMPLATE DIR        write an addon template (blank, fetch-and-render, grafana-panel, wasm-hook) into an empty DIR
    -addon-id ID                   use ID as the addon id
wrm -addon-lint DIR|ZIP            check an addon (schema, files, sandbox rules, secrets, permissions); exit 1 on an error
    -addon-lint-json               print the report as JSON
wrm -addon-dev DIR                 serve the addon's panel on 127.0.0.1 with the real CSP and a WRM stand-in, reload on change
    -addon-dev-port PORT           port of the dev server (default 8790)
    -addon-dev-private             allow private-network and plain-http sites in the dev server
wrm -release-verify SHA256SUMS.txt check SHA256SUMS.txt.sig with the built-in release key, and the SHA-256 of the listed files next to it
    -release-public-key KEY        also trust this public key (wrm-ed25519:…)
wrm -release-keygen FILE           (maintainers) new release key pair: private key to FILE (0600), public key printed
wrm -release-sign FILE             (maintainers) write FILE.sig; key from WRM_RELEASE_SIGNING_KEY or -release-key-file FILE

-service=… 由 WRM 写入服务定义;不用于交互操作。

GET /healthz(无需登录)会在服务器及其数据库正常运行时返回 {"status":"ok","version":…},否则返回 HTTP 503。可将其用于负载均衡器和监控。


Docker、服务、反向代理和防火墙

Docker

仓库包含一个 Dockerfile(Alpine 上的静态二进制文件,以非特权用户身份运行,数据存储在卷 /data 中,内置健康检查)和一个 docker-compose.yml:

docker compose up -d                       # build and start
WRM_TURN_PUBLIC_IP=203.0.113.10 docker compose up -d   # with voice relay: the IPv4 browsers reach this host at

发行版镜像也已发布到 GitHub Container Registry:docker run -d -p 8080:8080 -v wrm-data:/data ghcr.io/vedranius/wrm-pro:latest。

  • /data 存放数据库、加密密钥(remote_manager.db.key)、录制文件和自签名证书。请备份此卷,并单独保存一份密钥副本;或者将自己的密钥作为 Docker secret 提供(ENCRYPTION_KEY_FILE=/run/secrets/…,参见 docker-compose.yml 中的注释)。
  • compose 文件启用了 HTTPS_SELF_SIGNED=1。在 TLS 反向代理后方运行时,请移除该设置并设置 WRM_TRUST_PROXY=1。
  • 容器中的语音中继需要 WRM_TURN_PUBLIC_IP 和已发布的中继端口(49160-49200/udp,须与 WRM_TURN_RELAY_PORTS 一致)。
  • 容器内的 127.0.0.1 指向容器自身。compose 文件添加了 extra_hosts: ["host.docker.internal:host-gateway"],因此 Docker 主机上的代理可通过 host.docker.internal:<port> 访问(代理必须监听容器可访问的地址,例如 Docker 网桥)。使用 docker run 时,请添加 --add-host=host.docker.internal:host-gateway。
服务

**最简单的方法:**在终端中启动一次 WRM。它会询问:

WRM can run as a service that starts at boot (a systemd unit).
Install it as a service now? [y]es / [n]o / [d]on't ask again (default: no):

选择 Yes 会安装并启动服务,然后退出控制台进程;选择 No 会在下次启动时再次询问;选择 Don't ask again 后,选项会保存在 <DB_PATH>.service.json 中。以下情况不会弹出询问:标准输入不是终端、在容器中运行、作为服务运行、使用 -no-service-prompt 或 WRM_NO_SERVICE_PROMPT=1,或者服务已存在。脚本和管理员可直接使用标志:

sudo ./wrm-pro-v12.6.6-linux-amd64 -install-service          # systemd unit, enabled and started
./wrm-pro-v12.6.6-linux-amd64 -service-status
sudo ./wrm-pro-v12.6.6-linux-amd64 -uninstall-service        # the data stays

服务使用与交互式启动相同的数据目录和设置:工作目录、DB_PATH(会转换为绝对路径)、PORT / LISTEN_ADDR、密钥和证书文件、代理以及所有 WRM_* 变量都会写入 <data dir>/wrm.env(权限模式为 0600)。安装程序会检查服务账户是否能写入数据库及其目录,并打印所选的数据库路径。编辑该文件中的 DB_PATH 并重启服务,即可将其指向另一个 WRM 安装的数据库。

OS-install-service 的作用
Linux创建 /etc/systemd/system/wrm.service,包含 EnvironmentFile=、WorkingDirectory=、User=(当前用户或 SUDO_USER;也可使用 -service-user)、带重启速率限制的 Restart=on-failure,以及安全加固设置(NoNewPrivileges、带有数据和二进制文件夹 ReadWritePaths= 的 ProtectSystem=strict、ProtectHome=read-only、PrivateTmp、内核和 cgroup 保护、UMask=0077;对于低于 1024 的端口,设置 CAP_NET_BIND_SERVICE),然后启用该单元、清除之前的启动失败记录,并重启服务以应用新二进制文件。如果启动失败,安装程序会打印单元状态和近期日志条目。需要 root 权限:普通用户选择 Yes 时,WRM 会使用 sudo(或 doas)运行安装程序。如果没有 systemd,程序会说明这一点,并打印适用于当前 init 系统的命令。
macOS创建名为 local.wrm 的 launchd plist:/Library/LaunchDaemons 中的 LaunchDaemon(开机启动,需要 sudo;以当前用户身份运行),或 ~/Library/LaunchAgents 中的 LaunchAgent(登录时启动)。可在提示中选择,或使用 `-service-scope system
Windows创建真正的 Windows 服务(Service Control Manager)Web Remote Manager PRO,设为自动(延迟)启动;恢复操作为 3 s 后重启(也适用于 WRM 请求重启的情况);日志位于 <data dir>\wrm-service.log。需要管理员权限:提示会请求 Windows 授予权限(UAC);也可在以管理员身份运行打开的 PowerShell 中运行 .\wrm-pro-….exe -install-service。
FreeBSD创建 /usr/local/etc/rc.d/wrm,以当前用户身份通过 daemon(8) -r 运行 WRM(退出时重启),并运行 sysrc wrm_enable=YES 和 service wrm start。
OpenBSD创建使用 rc.subr 的 /etc/rc.d/wrm(设置 daemon_user,输出到 syslog),并运行 rcctl enable wrm 和 rcctl start wrm。
Android(Termux)及其他系统不支持:WRM 会说明这一点;请使用当前 init 系统或 tmux / screen。

-service-name NAME 可安装多个并行运行的实例(每个实例使用自己的数据目录)。

**手动配置(systemd):**如果你希望自行编写单元文件,例如 /etc/systemd/system/wrm.service:

[Unit]
Description=Web Remote Manager PRO
After=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=5

[Service]
User=wrm
WorkingDirectory=/opt/wrm
Environment=LISTEN_ADDR=127.0.0.1:8080
Environment=WRM_TRUST_PROXY=1
Environment=ENCRYPTION_KEY_FILE=/etc/wrm/encryption.key
ExecStart=/opt/wrm/wrm-pro-v12.6.6-linux-amd64 -service=systemd
Restart=on-failure
RestartForceExitStatus=75
SuccessExitStatus=75
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/wrm
PrivateTmp=true

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now wrm

-service=systemd 和退出代码 75 可让一键更新通过 systemd 重启 WRM;ReadWritePaths 必须包含二进制文件所在文件夹。

WRM 前端使用 nginx(TLS、WebSockets、流式传输和大文件上传):

server {
    listen 443 ssl http2;
    server_name wrm.example.com;
    # ssl_certificate ...; ssl_certificate_key ...;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;                # required: origin check
        proxy_set_header X-Real-IP $remote_addr;    # with WRM_TRUST_PROXY=1
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 3600s;                   # long-lived terminals
        proxy_buffering off;                        # live transfer/search progress
        client_max_body_size 0;                     # large uploads
    }
}

语音通话的防火墙设置:允许访问 WRM 服务的 UDP 和 TCP 3478(TURN)以及UDP 中继端口范围(49152-65535,或通过 turn_relay_ports 缩小范围)。在 NAT 后方(云虚拟机、家用路由器)时,请转发这些端口并设置 turn_public_ip。TURN 端口不会经由 nginx 代理。对于只允许 HTTPS 的网络,请在 443 端口运行启用 TLS 的 TURN 服务(例如 coturn),并在 Admin → Voice & network 中添加该服务。

使用 Caddy 配置 HTTPS

Caddy 会自动获取并续期证书,还能在无需额外设置的情况下代理 WebSocket——这是启用 HTTPS 最简单的方式。浏览器需要 HTTPS 才能将 WRM 安装为应用、使用麦克风并安全地使用 Cookie。WRM 通过 WRM_TRUST_PROXY=1 监听 127.0.0.1:8080(如上方服务配置所示)。/etc/caddy/Caddyfile:

# A public DNS name pointing to this server (ports 80 and 443 open): a Let's Encrypt certificate.
wrm.example.com {
    reverse_proxy 127.0.0.1:8080
}

只有内部名称或 IP 地址?让 Caddy 充当自己的证书颁发机构,并在每台打开 WRM 的计算机上信任该证书一次:

wrm.lan.example.com, 10.0.0.10 {
    tls internal
    reverse_proxy 127.0.0.1:8080
}
sudo systemctl reload caddy
# root certificate of Caddy's local CA, to import into the browsers' / systems' trusted roots:
sudo cat /var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt

Caddy 默认不限制请求正文大小,因此大型导入和上传都能正常进行。若在 Docker 中运行 WRM,请将 reverse_proxy 指向已发布的端口,并从 compose 文件中移除 HTTPS_SELF_SIGNED=1。


安全模型

另请参阅 SECURITY.md(如何报告漏洞、加固检查清单)。

  • **账户:**使用 bcrypt 哈希;TOTP 双重身份验证可选或必需,并提供一次性恢复码;默认关闭自主注册;支持账户锁定和按 IP 限速;对未知用户的响应采用恒定时间;管理员重置密码后强制更改密码;禁用或删除账户后立即在所有位置退出登录。
  • **会话:**在 HttpOnly/SameSite Cookie 中使用 256 位随机令牌(HTTPS 下使用 Secure),令牌以哈希形式存储;设有空闲和绝对过期时间;提供设备列表和远程退出登录功能。
  • 静态加密的机密信息:使用每次安装随机生成的 AES-256-GCM 密钥(或使用您自己的密钥),用于连接密码和密钥、SSH 密钥库及凭据保险库。机密信息绝不会发送到浏览器——不会发送给共享对象,也不会发送给凭据共享对象的用户——除非所有者在重新输入账户密码后明确导出或显示机密信息(策略 allow_secret_export,并记录审计日志)。数据库和密钥文件的权限设为 0600。
  • Web 安全:防范 CSRF(每次更改状态的 API 调用都检查自定义请求标头和 Origin)、检查 WebSocket Origin、采用严格的内容安全策略(不允许外部脚本,frame-ancestors 'none')、设置 X-Frame-Options、nosniff、Referrer-Policy: no-referrer(防止共享令牌通过 Referer 泄露)、Permissions-Policy;HTTPS 下启用 HSTS;限制请求大小;禁用目录列表;所有资源均在本地提供(运行时不依赖 CDN/供应链)。
  • **SSH 和 FTPS:**验证主机密钥(TOFU/严格模式);根据公共 CA 验证 FTPS 证书或固定证书。默认只有管理员可以访问服务端密钥文件。
  • **共享:**在每次文件操作、终端操作和房间操作中于服务端强制执行四种角色;支持仅限成员、仅限已登录用户或访客模式;使用签名密码 Cookie(密码更改后失效);支持过期、暂停和轮换链接;支持封禁;立即撤销已打开的终端和房间连接。
  • **协作:**身份由服务端分配;每个客户端使用独立的发送队列(速度慢的客户端不会阻塞房间);限制消息速率和大小;终端数据仅发送给监看者;按键仅发送给授予权限的共享者;文件下载绝不以内嵌方式呈现。
  • **语音:**使用 WebRTC 和 DTLS-SRTP;内置 TURN 中继仅接受发放给房间参与者的短时 HMAC 凭据,限制分配,并默认拒绝私有、环回和链路本地对等端(防止转入内部网络)。
  • 审计:记录登录(包括失败的登录)、账户和策略更改、连接、共享、加入房间和管理操作、终端会话、文件传输(含 SHA-256)及更改、主机密钥、导出、录制内容查看;数据存储在数据库中,采用仅追加和哈希链方式(可验证),并以 AUDIT … 行写入服务端日志(journald/syslog → SIEM)。审计详情中的机密信息会被编辑隐藏。
  • **会话录制:**终端输出采用 asciicast v2 格式,以 gzip 压缩,文件权限为 0600,SHA-256 存储在数据库中;除非启用按键录制,否则不录制按键(启用时会在密码提示处遮蔽);管理员、会话所属用户和连接所有者均可查看;每次查看都会记录审计日志。
  • **文件夹书签:**按用户区分;服务端填入变量并构建经过 shell 引号转义的 cd 命令,因此路径无法注入命令。共享参与者只能看到所有者标记为共享的书签(全局只读),且仅适用于共享中的连接。
  • **代码片段和广播:**代码片段按用户区分(仅管理员可共享代码片段,其他用户只读,且不会自动运行);连接时运行的代码片段来自连接所有者,并记入审计日志;广播输入由客户端键入用户自己的终端,执行危险命令前会请求确认,并为每个终端的每次开始和停止操作添加审计记录。
  • **带外管理:**BMC 密码经过加密(或从保险库获取,并遵循保险库的主机规则);Redfish 证书在首次使用时固定;ipmitool 通过环境变量获取密码(-E)——通过跳板主机时使用标准输入,绝不放在命令行中;电源操作和控制台操作会记录审计日志,且仅限连接所有者使用;串行端口默认仅供管理员使用。
  • **清单导入:**文件在内存中解析(CSV,或经过大小限制读取的 .xlsx 文件),绝不存储。NetBox 由 WRM 服务通过 HTTP(S) 使用您的令牌调用;拒绝指向其他服务的重定向和分页链接,限制响应大小;记住的令牌经过加密存储,绝不会返回给浏览器。
  • **SSH 密钥和保险库:**私钥和保险库密码在静态存储时经过加密,且仅在服务端使用。密钥通过 POSIX sh 脚本的标准输入发送到服务器(绝不放在命令行中);原地修改 authorized_keys,保留其他行、权限和 SELinux 上下文;WRM 拒绝移除其用于登录的密钥。共享凭据可供被共享者使用,但被共享者绝不能读取;主机列表限制凭据可发送到的位置(目标主机以及对这些用户开放的跳板主机)。轮换操作要么全部成功,要么全部失败;操作前先检查,并验证每次新登录,失败时回滚;从 passwd 输出中清除密码,且绝不记录密码。
  • **远程桌面:**WRM 使用已存储的凭据与 guacd 握手(绝不发送给浏览器),并仅转发显示指令和允许列表中的输入指令;guacd 的跳板主机隧道仅监听环回地址,且只在会话期间存在;会话会记录审计日志并录制。
  • **实时状态:**检查通过 WRM 服务发起普通 TCP 连接(不使用凭据,但可选通过跳板主机进行检查,使用跳板主机自身已保存的登录凭据);用户只能查看自己连接的状态。
  • 隧道和跳板主机:每一跳都经过身份验证和主机密钥验证;隧道归连接所有者所有(只有所有者可以启动;管理员可以停止任何隧道);默认监听 127.0.0.1;拒绝使用低于 1024 的端口;网络地址和远程转发仅供管理员使用(受策略限制);可全局关闭隧道或将其限制为仅管理员使用;每次启动、停止和出错操作都会记录审计日志及流量。网络地址上的隧道端口不受 WRM 登录保护——应将其视为该计算机上的开放端口。
  • **代理:**代理密码经过加密,绝不发送给浏览器,也不会显示给获授权者;共享密码的代理绝不通过获授权者自己的跳板主机访问;WRM 隧道代理不可共享;IPMI/SOL 绝不会悄悄绕过代理(会拒绝连接)。创建、更改、授权和测试操作都会记录审计日志(proxy.*),且每个会话都会记录其路由。
  • **通知:**通道机密信息经过加密,且只能写入;用户只能按名称和类型查看已启用的通道;消息只发送给连接或凭据的所有者;配置更改会以 admin.* 记录审计日志(始终记录)。
  • **快速连接、备注和网络工具:**快速连接是连接所有者的普通连接(执行相同的检查、加密、主机密钥验证和审计),并会过期;备注仅向所有者显示,且会作为转义文本呈现;网络工具仅接受主机名或地址(绝不接受选项或 shell 字符),从 WRM 服务或用户自己的 SSH 连接运行,每位用户一次只能运行一个,并记录审计日志(nettool.run)——使用 network_tools 加以限制。
  • **AI 助手:**模型只能通过 WRM 的工具执行操作;服务端权限引擎(只读分类器、审批、自动模式限制、始终禁止的破坏性操作列表、不可读取的敏感文件)负责决定每次调用,且只有用户可以更改模式。服务端输出作为不可信数据传递给模型,并按策略进行编辑隐藏;提供商密钥经过加密,绝不发送给浏览器;每个请求、工具调用和审批都会记录审计日志并录制。请参阅 SECURITY.md。
  • AI 桌面应用(MCP):/mcp 只接受 AI 连接的 bearer 令牌(绝不接受 WRM Cookie);令牌为随机值,以 SHA-256 形式存储,并绑定到用户、选定的连接、模式、作用域和过期时间,且可以撤销;OAuth 必须使用 PKCE(S256)、允许列表中的精确重定向 URI,并在正常登录后征得用户同意;拒绝来自外部浏览器源的请求,CORS 仅响应允许的源;每次工具调用均经过与内置助手相同的权限引擎和审计流程。请参阅 SECURITY.md 中的 MCP 威胁模型。
  • **传输:**使用 HTTPS(证书、反向代理或 HTTPS_SELF_SIGNED=1)。如果不使用 HTTPS,浏览器与 WRM 之间的密码和终端流量将不会加密,且浏览器会阻止使用麦克风。

限制

  • Ping 和 traceroute 使用 WRM 服务或源服务器上的命令(ping、traceroute/tracepath);如果没有这些命令,工具会说明这一点。应用(PWA)只能通过 HTTPS 和受信任的证书安装,或安装在 localhost 上。
  • IPMI 需要 ipmitool(安装在 WRM 服务或跳板主机上);WRM 服务上的 Serial-over-LAN 和串口需要在 Linux 上运行 WRM。电源操作一次只能针对一台服务器。
  • 清单导入支持 .xlsx 和 CSV,不支持旧版 .xls;NetBox 同步会更新并报告,但绝不会删除连接。
  • 密码轮换适用于可能运行 passwd 的 SSH 登录(Linux、BSD、macOS),不适用于 Windows/RDP、网络设备或 IPMI。谁有访问权限只显示登录用户的 ~/.ssh/authorized_keys。
  • RDP、VNC 和 Telnet 需要在 WRM 旁边运行 guacd(参见远程桌面);不提供 RDP 的文件传输和打印机重定向功能。
  • AI 助手适用于 SSH 和基于 SSH 的 SFTP 连接(不适用于 RDP/VNC/Telnet 或 BMC 控制台),且只运行非交互式命令(不支持编辑器、分页器或密码提示)。其只读分类器刻意设置得较严格:对于它不认识的无害命令,需要审批。不能使用消费级聊天订阅(Claude.ai、ChatGPT);通过 MCP 使用桌面 AI 应用的功能将于 v12.1.0 推出。
  • AI 连接(MCP)只能使用用户自己的 SSH 连接(不能使用与其共享的连接);OAuth 访问不会自动刷新,过期后用户必须重新批准该应用。/mcp 不提供独立事件流(GET),也不支持中断流的恢复;等待审批时被中断的调用会被取消。
  • 暂不支持 SSO/LDAP/SAML(使用带 2FA 的本地账户)。
  • 语音通话采用网状结构:最多约 12 人效果良好;更大的会议需要 SFU。
  • 不支持 SSH Agent 转发。跳板主机必须是 SSH 服务(不能使用 HTTP/SOCKS 代理作为跳板主机)。
  • 隧道端口在 WRM 机器上开放:当 WRM 在服务器上运行时,监听 127.0.0.1 的隧道无法从你的 PC 访问(参见隧道端口在哪里?)。
  • 服务器间传输和 ZIP 下载仅适用于 SSH/SFTP 服务器(不支持 FTP)。搜索文件内容需要服务器上有 grep。
  • 内置 TURN 中继使用 IPv4,且在 Android 版本中不可用(请在该版本中使用外部 TURN 服务)。

欢迎针对以上任何事项提出想法和拉取请求。参见 CONTRIBUTING.md。


API 参考

v13.7.0 端点
端点行为
GET / POST /api/auth/lock获取此登录会话的锁定状态 / 锁定会话({"reason": "manual"|"idle"|"hidden"|"os_locked"|"sleep"|"shortcut"}),并记录为 auth.locked。
POST /api/auth/lock/verify{"password"} 或 {"pin"}:解锁(auth.unlocked / auth.unlock_failed);每分钟尝试五次后返回 429,达到 screen_lock_max_failures 时返回 401 {"signed_out": true}。
PUT / DELETE /api/auth/lock/pin设置({"pin", "password"})或移除解锁 PIN。
GET / PUT /api/me/ui/appearance、/api/me/ui/lock用户的外观和屏幕锁定偏好设置(JSON 对象,256 KiB)。

在 server 模式下会话锁定时,其他所有经过身份验证的端点都会返回 423 Locked;/api/auth/me 会报告 screen_locked 以及 screen_lock 和 appearance 策略。

v12.4.4–v12.4.5 端点

所有端点都需要 WRM 会话以及有效的所有者/策略访问权限。修改数据的 /api/ 调用需要 WRM 的常规 CSRF 标头/来源。

端点行为
POST /api/git/medium/setup?confirm=1合并上传 tool、config 和可选的 ssh ZIP 文件(各 20 MiB);在后台保留设置并自动启动。空字段会恢复/复用导入内容。
GET /api/monitoring/logs?id=…有界的自动/手动根目录发现;渐进式 UI 会按服务汇总文件/根目录/警告。
GET /api/monitoring/log?id=…&root_path=…&path=…经授权的历史/实时分块,可选 scan=1、字节 offset、日期/时区/关键字;包含修改/事件范围/记录数元数据。
GET / PUT /api/monitoring/logs/settings?id=…服务的日志设置(扫描路径、排除项、路径模式、限制、日志、元数据源、方法)及默认值;只有所有者可以保存。
POST /api/monitoring/logs/discover?id=…现在使用日志设置发现日志(通过 SSH,或在必要时使用 SFTP)。
POST /api/monitoring/logs/grep?id=…{files, q, regex, case, word, context, max, from, to, timezone}:在服务上搜索已发现的文件;返回包含路径、行号、文本和解析时间的匹配项。
GET /api/monitoring/logs/lines?id=…&path=…&mode=tail|around|since单个已发现文件的行:使用 n,或 line/before/after,或使用 bytes(文件)/cursor(日志)进行后续读取。
GET /api/git/medium运行时/导入/依赖状态和工具 SHA-256;正在运行的 operation(op、user、start)、调用者的 steps 及其时间、pending_config / pending_ssh、running_since、last_exit 和 output_policy。
GET /api/git/medium/activity?limit=&output=1Medium 活动日志(最新优先):时间、用户、操作、结果、耗时、详情、错误、步骤,以及按 medium_log_output 提供的脱敏输出。用户可以查看自己的记录和共享记录。
GET /api/git/medium/log调用者正在运行的操作及原始工具进程的实时输出(已脱敏),由 medium_log_output 提供。
POST /api/git/medium/{tool,config,ssh}?confirm=1在字段 file 中上传 multipart ZIP;工具仅限管理员操作;展开后上限为 20 MiB。工具导入返回 202,并在后台准备运行时。配置会立即检查(若有原因则返回 400);配置/SSH 若留待下次启动,则返回包含 pending 的 202。若操作正在运行,409 会指出该操作。
GET, POST /api/git/medium/settings读取已屏蔽的原始运行时首选项 / 保存加密后的首选项。
POST /api/git/medium/docker管理员:{"accept": true, "accept_license": true} 会记录同意(Docker Desktop 需要许可证),并在后台安装、启动和等待 Docker(202);若已导入工具,随后准备运行时;{"accept": false} 会撤回同意。缺少 Docker 时,GET /api/git/medium 会报告 docker(installed、product、method、auto、allowed、needs_license、consent、why、command、note)。
POST /api/git/medium/{start,stop,prepare}在后台启动原始应用(202;轮询状态)/仅在空闲时停止(stop?force=1 会在 UI 中再次确认后,停止状态无法读取或报告有工作的工具)/管理员重试保留的工具设置。
GET /api/git/medium/native/config原生预览:已验证的部署配置摘要(项目、环境、带有 WRM 连接链接的服务)或验证错误。
POST /api/git/medium/native/link将 servers.yaml 中的服务关联到已保存的 SSH 连接({"server","conn_id"},conn_id 为 0 表示自动)。
GET /api/git/medium/native/refs?project=项目 WRM Git 源的分支和标签。
POST /api/git/medium/native/plan启动只读原生预览(project、environment、ref,可选的 servers、compare、excluded)。返回运行 ID。
GET /api/git/medium/native/plan/<id>预览的阶段、各服务的计划、与原始工具的比较及源检查;原生部署还会返回 deployable 和 revision。
GET /api/git/medium/native/plan/<id>/diff?server=&path=已完成计划中的一个变更文件:服务端和分支端的状态(text、missing、binary、too_large、symlink、dir、CRLF)、eol_only 和行差异。
GET /api/git/medium/native/config/files部署配置文件(名称、大小、哈希)、配置是否成功加载,以及用户是否可以编辑。
GET /api/git/medium/native/config/file?name=单个部署配置文件的文本和哈希。
POST /api/git/medium/native/config/files检查、保存、创建或删除文件(name、text、base_hash、check_only、delete)。仅当整个配置成功加载时才会保存;若文件在 base_hash 后发生变更,则返回 409。策略 medium_native。
GET /api/git/medium/native/config/git部署配置的 Git 状态:仓库和源、分支、已拉取的提交、分支头、behind、本地 changes、can_push。
POST /api/git/medium/native/config/git/pull将分支头设为 WRM 部署配置副本({"discard":true} 会丢弃本地更改;若存在本地更改则返回 409)。策略 medium_native。
POST /api/git/medium/native/config/git/push通过 Git 源的写入令牌验证、提交并推送本地更改(message,可选);若已更改的文件在 Git 上发生变动,则返回 409。策略 medium_native。
POST /api/git/medium/native/config/git/stop删除 WRM 的 Git 副本,改用导入的部署配置。策略 medium_native。
POST /api/git/medium/native/engine在 Docker 运行时和原生引擎之间切换项目({"project","engine":"docker"|"native"},策略 medium_native)。
POST /api/git/medium/native/deploy部署已完成的比较,或执行试运行(run_id、revision、confirm、dry_run)。返回 job_id 和 deploy_id。需要二次验证 medium.deploy。
GET /api/git/medium/native/history?project=&environment=按目标提供:current.json、锁、近期历史记录和回滚选项;stale_lock_minutes。
POST /api/git/medium/native/rollback回滚或执行回滚试运行(project、environment、deploy_id、servers、confirm、dry_run)。需要二次验证 medium.rollback。
POST /api/git/medium/native/lock/release释放过期锁(project、environment、server、锁所有者的 deploy_id)。需要二次验证 medium.lock_release。
GET /api/git/medium/native/jobs · GET /jobs/<id>?from= · POST /jobs/<id>/cancel调用者的原生部署和回滚:阶段、各目标的结果,以及从 from 开始的日志行;可在前往下一个目标之前取消。
/medium/*通过 WRM 身份验证、策略和来源检查保护原始 UI 和原生操作。
GET, POST /api/git/config-profiles列出 / 添加引用 {name,app,path,operator,content}。
DELETE /api/git/config-profiles/{id}删除自有配置档案。
POST /api/git/config-profiles/{id}/check检查匹配的安装;可选 {ids:[...]} 选择项。
GET /api/bitwarden, GET /api/bitwarden/keysCLI/账户状态 / 仅限原生 SSH 条目元数据。
POST /api/bitwarden/{login,unlock,sync,lock,logout}账户和仅驻留内存的解锁操作。登录时可按需接受 server,email,master_password,client_id,client_secret,method,code。
POST /api/folders/reorder在所有者/循环/深度限制下,通过 {id,parent_id,before_id} 或 {id,parent_id,after_id} 移动。
所有端点(登录、/api/auth/config、版本页面和分享页面除外)都需要会话 Cookie。除非另有说明,否则请求和响应均为 JSON。每个不安全的 /api 请求(POST/PUT/PATCH/DELETE)都必须发送 X-WRM-Request: 1(CSRF 保护),并在有 Origin 时将其设置为此服务器的地址。

账户

方法端点描述
GET/api/auth/config{first_run, registration_open, version};首次运行时还包括 security_level、security_level_fixed、secure_transport;登录需要 HTTPS 时包括 https_required;有可用更新时还包括 update、update_url
POST/api/auth/register创建账户(首位用户为管理员;之后仅在开放注册时可创建);首位用户可发送 security_level
POST/api/auth/login{username, password} → 用户,或 {mfa_required, mfa_token}
POST/api/auth/mfa{mfa_token, code}(TOTP 或恢复码)
POST/api/auth/logout退出登录
GET/api/auth/me当前用户、限制和策略;还包括 role、is_auditor、break_glass、teams 和 step_up: {required, minutes, totp}
GET/api/auth/oidc/start?provider=<id>目录登录:重定向到身份提供商(授权码 + PKCE)
POST/api/auth/oidc/start已登录用户可使用 {provider, mode} 中的 link、stepup 或 test(管理员);返回 {url, state},以便在新窗口中打开
GET/api/auth/oidc/callback提供商会返回到此处(请在提供商处注册此地址)
GET/api/auth/oidc/result?state=关联 / 步进验证 / 测试窗口的结果(done、ok、error、测试详情)
GET / POST/api/me/ldap查看已关联的目录账户和已启用的目录 / 关联一个目录账户 {directory, username, password}(需要重新确认)
DELETE/api/me/ldap/{id}取消关联目录账户(仍有本地密码的账户)
*/scim/v2/…面向身份提供商的 SCIM 2.0(Authorization: Bearer wrm_scim_…):Users、Groups、ServiceProviderConfig、ResourceTypes、Schemas
GET / DELETE/api/me/identities、/api/me/identities/{id}查看已关联的目录账户和可连接的提供商 / 取消关联一个账户(仅限有密码的账户)
POST/api/auth/step-up{password, code, action} 会为此会话确认 step_up_minutes;其他调用返回 403 且包含 step_up: true,表示需要进行此操作
GET/api/teams分享对话框中的团队 {teams: [{id, name, member_count}], mine}
GET / POST / DELETE/api/me/events · /api/me/events/read应用内通知:GET ?limit=(默认值为 50,最多 200)→ {events: [{id, event, title, body, at, read}], unread};POST /api/me/events/read {ids: […]} 或 {all: true};DELETE /api/me/events 清空列表
GET/api/addons可使用的已安装插件(管理员:所有组织插件;?personal=all 会添加 personal_others);每个插件都包含 key(id,或个人插件的 ~id)、asset_base、apiVersion、permissions、needs_approval、permissions_added;还包括 capabilities 和 personal_allowed
POST/api/addons/install安装 ZIP 文件(请求正文)。管理员默认安装为组织插件,除非设置 scope=personal;其他用户安装为个人插件。allow_downgrade=1 可安装较旧版本。拒绝时会返回 {error, code, hint}
POST/api/addons/{key}/enable · /disable · DELETE /api/addons/{key}管理插件:管理员管理组织插件,所有者管理个人插件;启用时会记录已批准的权限清单
POST · DELETE/api/addons/users/{user id}/{id}/disable · /api/addons/users/{user id}/{id}管理员:关闭或移除其他用户的个人插件
GET · POST/api/addons/{key}/instances查看你可见的 apiVersion 2 面板实例;创建 {name, shared}(shared:管理员、组织插件)
PATCH · DELETE/api/addons/{key}/instances/{iid}重命名 {name},或移除实例及其值和窗口
GET · PUT · DELETE/api/addons/{key}/instances/{iid}/store[/{k}]存储的值:全部({values, used, quota, writable})、单个键、写入 JSON 正文(32 KB,每个实例有单独配额)、删除
GET · POST/api/addons/{key}/instances/{iid}/export · /import导出实例的值,格式为 {"format": "wrm-addon-config", …};也可导入
PUT · DELETE/api/addons/{key}/instances/{iid}/window此实例的窗口状态(JSON 对象,4 KB)
POST/api/addons/{key}/instances/{iid}/http为面板发送请求 {method, url, headers, body, encoding, secret} → {ok, status, headers, body, encoding, truncated, code};拒绝时会返回 E_HTTP_* 代码
GET/api/addons/{key}/instances/{iid}/http/log实例最近 50 条请求(仅限你自己的请求;管理员可查看全部)
GET · PUT · DELETE/api/addons/{key}/instances/{iid}/secrets[/{name}]密钥状态(不显示密钥值);设置 {value, scope}(instance 或 own);使用 ?scope= 清除
POST · DELETE/api/addons/{key}/http · /api/addons/users/{user id}/{id}/http管理员:批准插件的网站 {private: [origins]} 或撤销批准
GET/api/addons/dev/schema.json · /api/addons/dev/llms.txtaddon.json 的 JSON Schema 和面向 AI 助手的插件指南(已登录用户)
GET/api/addons/dev/templates · /api/addons/dev/templates/{name}.zip?id=入门模板;可将其中一个作为 ZIP 下载,并在提供 id 时替换清单中的 id
POST/api/addons/dev/lint检查 ZIP(请求正文)但不安装 → {ok, errors, warnings, diagnostics: [{level, code, message, file, line, hint}], permissions, summary, csp};管理员和获准使用个人插件的用户(E_PERSONAL_OFF)
GET/api/addons/{key}/asset/{file}已启用插件的文件;apiVersion 2 面板的 HTML 会包含完整的 CSP;安装后发生更改的文件会返回 409 E_INTEGRITY
GET/api/workboard/metrics?id=你的一条 SSH/SFTP 连接的 CPU、RAM、负载、运行时间和磁盘信息:{conn_id, at, source: zabbix|ssh, cpu_percent, memory_percent, memory_total, load, cpu_count, uptime, disks: [{mount, percent, size_kb}], error};refresh=1 会跳过 25 秒缓存;如果关闭了通过 SSH 读取且没有最新的 Monitoring 样本,则返回 403
GET / PUT / DELETE/api/me/ui/{key}你的界面状态,key = layout(面板布局)、workboard 或 ai(我的 AI 设置:provider_id, model, mode, engine, thinking):GET → {value, updated_at}(未存储任何内容时 value 为 null),PUT {value: {…}}(JSON 对象,最多 64 KiB),DELETE 重置
POST/api/auth/password{current_password, new_password}
POST/api/auth/2fa/setup · enable · disable · recovery双重身份验证管理
GET / DELETE/api/auth/sessions[/{id}]已登录的设备 / 退出一个或所有其他设备
GET/api/users?q=用户目录(用于添加成员)
连接、文件夹、会话
方法端点描述
GET / POST/api/connections列出(不含密钥)/ 创建
GET / PUT / DELETE/api/connections/{id}读取 / 更新(密钥为空 = 保留;clear_password、clear_private_key)/ 删除
POST/api/connections/{id}/duplicate在服务端复制
POST/api/connections/{id}/secret{password, purpose: "show"|"copy"} → {username, password, private_key, key_path, source: connection|vault|key_store|bitwarden|server_key, source_name}(所有者;WRM 或目录密码,或仅 SSO 账户的新鲜 step-up;allow_secret_export;已审计)
POST/api/connections/{id}/name-from-hostname读取服务器的主机名(SSH)或 DNS 名称并重命名连接 → {name, hostname};未知主机密钥会返回 409 和 hostkey
POST/api/connections/bulk{action: "move"|"delete", ids, folder_id}
POST/api/connections/test测试连接(报告主机密钥问题)
POST/api/hostkeys/accept{host, fingerprint} 接受新的/已更改的主机密钥
GET / POST/api/folders · PUT / DELETE /api/folders/{id}文件夹:{name, parent_id, jump_id, proxy_id}(按所有者隔离,不允许循环,最多 32 层;视图会添加完整的 path)(其连接的默认值;视图会添加 jump_name、proxy_name)
GET / POST/api/sessions · PUT / DELETE /api/sessions/{id}工作区会话
GET/api/config/export不含密钥的导出(包含跳板主机和隧道)
POST/api/config/export使用密钥导出:{password}
POST/api/config/import导入 → {imported, skipped, tunnels}
POST/api/config/import/mremoteng{xml, password} 导入 mRemoteNG confCons.xml → {imported, folders, jump_hosts, tunnels, skipped, notes};需要主密码时返回 HTTP 400 和 need_password: true
POST/api/config/import/sshconfig{text, folder} 导入 OpenSSH 配置
POST/api/config/import/putty{data, folder} 导入 PuTTY .reg 导出文件(data = 文件内容,base64;UTF-16 或 UTF-8)→ 还会返回 {proxies, proxy_links}

导入文件最大可达 20 MB(/api/config/import* 和 /api/inventory/* 的请求正文最大可达 32 MB);超过限制时会返回 HTTP 413,并附上大小和限制值。

连接具有 jump_id(跳板主机连接 ID 或 null)和 web_path;列表还会返回 route(例如 "vpn-gw → bastion-dc1")和 tunnels(已配置的隧道数量)。

远程桌面

端点描述
/ws/desktop?id&width&height&dpi&tz[&share_token]用于 RDP/VNC/Telnet 连接的 WebSocket(子协议 guacamole)。WRM 执行 guacd 握手;随后浏览器交换 Guacamole 指令(显示 ← / 输入 →)。首条消息:隧道 ID;然后是 wrm-session(会话 ID、记录、路由)
GET /api/recordings/{id}/guac[?download=1]远程桌面会话录制(Guacamole 协议流)

RDP/VNC/TELNET 类型的连接具有 options(参见远程桌面);/api/recordings 中的会话具有 protocol 和 recording.format(asciicast-v2+gzip 或 guacamole+gzip)。

快速连接、备注和网络工具

端点描述
POST /api/connections/quick{target: "user@host:port" or "rdp://…", protocol?, password?, credential_id?, key_id?, jump_id?} → 新的临时连接(temporary: true)
PUT /api/connections/{id}{…, notes, temporary: false} — notes 用于设置备注,temporary: false 用于保留快速连接
GET /api/connections/{id}包含 notes(列表仅包含 has_notes)
POST /api/nettools{tool: ports|ping|traceroute|dns|http, target, ports?, source_id?} → {source, target, ms, ports: [{port, state: open|closed|filtered|error, ms, info}] | output | dns: {addresses, cname, mx, txt, ptr} | http: {status, tls, subject, issuer, not_after, days_left, names, trusted, trust_error}}
GET /manifest.webmanifest、GET /sw.jsWeb 应用清单和服务工作线程(可安装的应用)

带外管理

端点描述
GET /api/connections/{id}/bmc{type, power: on|off|unknown, health, manufacturer, model, serial, bios, cpus, cpu_model, memory_gib, bmc_model, bmc_firmware, power_watts, inlet_c, faults, actions, console}。证书发生更改时返回 502 和 hostkey
POST /api/connections/{id}/bmc{action: on|shutdown|restart|off|reset|cycle|nmi}
/ws/ssh?id&…&console=bmc|sol连接的服务器的串行控制台(与终端使用相同协议)

连接具有 bmc: {type: redfish|ipmi, host, username, password (write-only), credential_id, via_jump, console, ssh_port}({type: ""} 用于移除它;视图会添加 has_password、credential_name)。协议为 SERIAL 的连接以设备名称作为 host,并使用 options: {baud, data_bits, parity, stop_bits, flow}。

标签与资产清单

端点描述
POST /api/connections/bulk{action: "tag", ids, add: [tags], remove: [tags]} → {changed}
POST /api/inventory/parse{file_name, data (base64), sheet, header} → {sheets, sheet, encoding, delimiter, headers, rows (preview), total, mapping}
POST /api/inventory/import{file_name, data, sheet, header, mapping: {field: column}, options} → 导入结果。字段:name host port protocol username password folder tags env site rack role platform jump web_path
GET /api/inventory/netbox已保存的 NetBox 地址和筛选条件(has_token,绝不返回令牌)
POST /api/inventory/netbox/preview{query: {url, token, devices, vms, site, role, tenant, tag, status, host_from, env_field, insecure, remember}} → {rows, missing}
POST /api/inventory/netbox/import{query, rows, options} → 导入结果(imported、updated、skipped、notes)

options:{default_protocol, username, auth: ""|credential|key, credential_id, key_id, folder_mode: column|site|role|tenant|fixed|none, folder, tags, update}。连接具有 tags(数组;PUT 时省略该项会保留原标签),从 NetBox 导入的连接还具有 source: "netbox"。

SSH 密钥与凭据库

端点说明
GET /api/keys你的密钥库(公钥、指纹、used_by、deployed;绝不包含私钥)
POST /api/keys{name, comment, generate: {type: ed25519|rsa|ecdsa, bits}} 或 {name, key, passphrase}(私钥或公钥)。密钥已加密时返回 400 {need_passphrase: true}
PUT / DELETE /api/keys/{id}重命名 {name} / 删除(使用中时返回 409)
GET /api/keys/{id}/public公钥文件(.pub)
POST /api/keys/{id}/export{password, passphrase} → {private_key}(重新验证身份,策略 allow_secret_export)
POST /api/keys/{id}/deploy{conn_ids, use_key} → {results: [{conn_id, name, ok, already, switched, error}], ok, failed}
POST /api/keys/{id}/revoke{conn_ids} → {results: [{conn_id, name, ok, removed, error}], ok, failed}
GET /api/connections/{id}/authorized-keys{user, path, entries: [{line, key_type, bits, fingerprint, comment, options, key_id, key_name, current}], login_key}
DELETE /api/connections/{id}/authorized-keys?fingerprint=SHA256:…从服务中移除该密钥(WRM 自身的登录密钥返回 409)
GET /api/credentials你拥有、获授或与所有人共享的凭据(不含机密)
POST /api/credentials · PUT / DELETE /api/credentials/{id}{name, username, password, key_id, description, hosts, rotate_days, grants: [user ids], shared_all};PUT 时 password 为空则保留原值(仅所有者可用)
GET /api/credentials/{id}/usage使用该凭据的连接
POST /api/credentials/{id}/reveal{password} → {password, pending_password}(所有者、重新验证身份)
POST /api/credentials/{id}/rotate{mode: check|rotate, new_password} → 启动后台任务
GET /api/credentials/{id}/rotation{running, stage: preflight|change|rollback|done, ok, message, hosts: [{key, connections, state, error}]}

代理

端点说明
GET /api/proxies{proxies: [...], can_define, container}:你拥有、获授或与所有人共享的代理(不含机密;包含 url、warning: docker_loopback)
POST /api/proxies · PUT / DELETE /api/proxies/{id}{name, kind: socks5|socks4|http|wrm_tunnel, host, port, username, password, credential_id, remote_dns, tunnel_id, description, grants, shared_all};PUT 时 password 为空则保留原值(仅所有者可用;策略 proxies);连接或文件夹正在使用时拒绝 DELETE(返回 409)
POST /api/proxies/{id}/test{target?: "host:port"} → {ok, message, latency_ms}:连接到代理(并通过代理连接目标)

连接具有 proxy_id(和 jump_id):null = 使用文件夹设置,-1 = 不使用,否则为对应 ID。视图返回生效的 jump_id / proxy_id、已存储的 jump_choice / proxy_choice、jump_inherited / proxy_inherited、proxy_name 和 route。导出内容会注明代理(proxy_ref 和 proxies 列表)。

通知

端点说明
GET /api/notify{enabled, events, channels: [{id, name, kind, user_address, address_field}], subscriptions: [{event, channel_id, address}], prefs: {quiet_enabled, quiet_start, quiet_end, tz, lang}, pending}
PUT /api/notify{subscriptions: [...], prefs: {...}} 替换你的订阅和免打扰时段
POST /api/notify/test{channel_id, address} 向你发送测试消息(每 10 秒一次)
GET / POST /api/admin/notify/channels通知渠道(机密字段为空,包含 secrets_set)、渠道类型及其字段 · 创建 {name, kind, enabled, user_address, config: {…}}
PUT / DELETE /api/admin/notify/channels/{id}修改(机密字段为空则保留已存储的值;clear: [field] 可移除一个字段)· 删除
POST /api/admin/notify/channels/{id}/test{address?} 立即发送测试消息(服务出错时返回 HTTP 502 和错误信息)

事件:status.down、status.up、credential.rotation_due、credential.rotation_incomplete。 auth_method 为 KEY_REF 的连接包含 key_id,为 CREDENTIAL 的连接包含 credential_id(视图会添加 key_name、credential_name、credential_user)。导出文件会引用密钥和凭据(key_ref、credential_ref),而不会包含它们;导入时会使用你拥有的同名密钥或凭据。

代码片段与状态

方法端点描述
GET / POST/api/snippets我的代码片段和共享代码片段 / 创建 {name, command, description, group, scope: "all"|"folder"|"connection", scope_id, auto_run, shared}
PUT / DELETE/api/snippets/{id}更新 / 删除(所有者;管理员也可操作共享代码片段)
GET / POST/api/bookmarks我的文件夹书签 / 创建 {name, path, scope: "global"|"folder"|"tag"|"connection", scope_id, tag, color, note, start_dir, shared}
GET/api/bookmarks?conn={id}某个连接的书签,包含解析后的 resolved 路径和 cd 命令,以及 start(使用 share_token 时也会返回所有者共享的书签)
POST/api/bookmarks/resolve{id, conns: [...]} → {conn_id: {path, cd}}(广播组)
POST/api/bookmarks/reorder{ids: [...]}
POST/api/bookmarks/import-winscp请求正文:一个 WinSCP.ini → {found, imported, skipped}
PUT / DELETE/api/bookmarks/{id}更新(重命名、在不同范围间移动) / 删除
GET/api/status{enabled, interval, jump_checks, connections: {id: {state: "up"|"down"|"unknown", latency_ms, since, checked_at, error, banner, via, via_state}}}
POST/api/status/check{ids: [...]} 立即检查,也会通过跳板主机检查(每个用户每 3 s 一次)

连接还包含 monitor(实时状态开/关)。终端 WebSocket 接受 {"type":"broadcast","on":true\|false,"peers":n}(审计),并会在连接时自动运行代码片段执行后发送 {"type":"autorun","snippets":[…]}。

Git 工作区

方法端点描述
GET/api/git工作区状态:catalog、settings、sources(不含令牌)、targets、installs、bundle_apps、last_check_at、can_check
PUT/api/git/settings{mode: "auto"|"live"|"bundle", source_id, bundle_id, ref_mode: "catalog"|"default"|"branch", ref_branch, ref_overrides: {app: ref}, history_depth, conn_ids, monitor}
PUT/api/git/catalog整个目录(目录 JSON)
POST/api/git/catalog/import?mode=replace|merge导入目录 JSON
GET/api/git/catalog/export目录 JSON(下载)
PUT / DELETE/api/git/catalog/apps/{name}添加或更改 / 删除一个服务
POST/api/git/sources{kind: "gitlab"|"github"|"gitea", name, url, token};PUT / DELETE /api/git/sources/{id}(省略 token 时保留已存储的令牌)
POST/api/git/sources/{id}/test目录中各组的 {projects}
POST/api/git/suggest{project, ref} → {app, files}(根据仓库树生成目录条目)
POST/api/git/bundles请求体:一个 bundle .tar.gz → {result: {source, files, payload, warnings}, state}
POST/api/git/bundles/export{apps: [...]} → bundle .tar.gz
POST/api/git/targets/refresh{apps}(空 = 全部):解析引用并构建目标
GET/api/git/targets/{app}包含文件和逐文件历史记录的目标
POST/api/git/check{conn_ids (empty = the chosen servers), discover, refresh} → {result: {servers, installs, targets}, state}
POST/api/git/installs{conn_id, path, app, env}(手动添加)
GET / DELETE/api/git/installs/{id}包含文件状态的详情 / 忘记
GET/api/git/installs/{id}/diff?path={lines: [{op: " "|"-"|"+"|"@", a, b, s}], state, tracked, informational, reason, pattern, same, binary, too_big, missing_on_server, truncated}(服务端 → 目标;仓库中除受保护文件外的任意文件)
GET/api/git/installs/{id}/configuration按需提供已屏蔽的配置/设置,强制执行所有者权限和 git_checks
GET/api/git/installs/{id}/files目录和仓库中的所有文件:{files: [{path, kind, size, mtime, link, outside, on_server, in_git, tracked, state, reason, pattern, diffable, viewable}], truncated, git_partial, not_compared, target}
GET/api/git/installs/{id}/file?path=&side=server|git用于查看的单个文件:{side, size, hash, text | binary | too_big}
GET/api/git/installs/{id}/commitsVERSION.md 的提交与目标之间的 {from, to, count, commits: [{sha, title, author, date}]}
POST/api/git/check/jobs{install_ids, conn_ids, all, discover, refresh, stale_minutes, only_never} → 检查任务(一次一个)
GET/api/git/check/jobs/current?since=N{job: {id, state, phase, total, done, seq, items: [{install_id, state, error}], installs}}(在 N 之后完成的安装)
POST/api/git/check/jobs/current/cancel取消正在运行的检查任务
POST/api/git/plan{kind: "update"|"upgrade"|"stamp", ref, install_ids} → {items: [{install_id, prod, units, from_version, target, current, files: [{path, state, selected, local}], removed, counts, eligible}]}
GET/api/git/installs/{id}/backups.deploy-bak 中的备份,包含其中的文件、VERSION.md 和 updates.jsonl 行(策略 git_rollback)
POST/api/git/runs启动或安排运行:{kind: "update"|"upgrade"|"rollback"|"stamp"|"restart", ref, items: [{install_id, files, modified_ok, backup}], restart: {mode: "none"|"now"|"at"|"delay", at, delay_minutes}, schedule_at, checks: {service: command}, ignore_imports, force, stamp_partial, set_ref_override, confirm: {install_id: server name}}。安装 / 传输(立即执行):{kind: "install"|"transfer", provision: {conn_id, services: [{app, ref: ""|"bundle:<id>"|branch|"tag:…", path, env, files: [{path, mode: "template"|"copy"|"manual"|"skip", template, values: {field id: {value} | {cred_id, part}}, from_install, content}], unit: {kind: "systemd"|"supervisor", name, user, command, work_dir, enable}}], source_install, path, env, unit, overwrite, confirm: server name}, restart: {mode: "none"|"now"}, checks}
POST/api/git/provision/prepare{kind: "install", conn_id, services: [{app, ref, path}], overwrite} → {roots, prod, services: [{target, files, bytes, check: {exists, existing, files, version, parent, writable, free_kb, need_kb, tools, needs, errors, warnings}, slots: [{path, protected, in_repo, templates: [{path, available, fields: [{id, name, kind, default, secret}]}], copies}]}]};{kind: "transfer", conn_id, source_install, path, overwrite} → {source: {files, bytes, excluded, excluded_list, units, version}, check}
GET/api/git/runs历史记录和计划运行
GET/api/git/runs/{id}带实时进度的运行:包含 state、step、log、written、deleted、made_backup、dangling、health 的项目
GET/api/git/gitignore/{app}.gitignore 辅助工具:{repo, project, branch, file, current, has_current, note, extra: [{path, size, servers, pattern}], stacks: [{name, detected, reason, patterns}], protected, exclude, warnings: [{path, reason, template}], can_mr, mr_note, source_kind}
POST/api/git/gitignore/{app}/preview{patterns} → {content, added, lines, has_current, file}
POST/api/git/gitignore/{app}/download{patterns} → 新的 .gitignore(下载)
POST/api/git/gitignore/{app}/mr{patterns, confirm: project} → {url, branch, kind: "merge_request"|"pull_request"}(策略 git_gitignore_mr,写入令牌)
POST / DELETE/api/git/sources/{id}/hook启用或停用来源的 webhook(启用时 → {hook_id, path, secret},密钥仅此时显示)
POST/api/hooks/git/{hook_id}传入的 webhook(无需会话;GitLab X-Gitlab-Token、GitHub X-Hub-Signature-256、通用 X-WRM-Token 或 X-WRM-Signature + X-WRM-Timestamp)→ 202 {queued, services}
POST/api/git/feeds{name, url, header_name, header_value, interval_minutes};PUT / DELETE /api/git/feeds/{id}
POST/api/git/feeds/{id}/fetch立即获取并导入 → {status: "imported"|"unchanged", result, state}
PUT / DELETE/api/git/pipelines/{app}部署方式 CI pipeline:{kind: "jenkins"|"gitlab", url, username, project, ref, token};DELETE → 再次通过 SSH 传输文件
POST/api/git/env/adopt将某个或所有服务检测到的(派生)环境保存到目录({app?},策略 git_update,审计 git.env_adopted):{added, environments}
GET/api/git/env/overview带环境的服务(?auto=1 也会合并从检测到的安装中派生的环境,并标记为 auto,同时提供 auto 计数和 hosts:连接名称 → 主机名):{services: [{app, envs: [{name, destinations, confirm, allowed_refs, post_deploy}]}], envs, stale_minutes}
GET/api/git/env/cell?app=&env=单个概览单元格:{dests: [{server, path, exists, current, version_md, commit_md, ref_md, user_md, updated_md, behind, lock, error}], drift, target}
POST/api/git/env/plan{app, env, ref} → {id, ref_name, target, confirm, post_deploy, excluded: {path: {by, at}}, errors, dests: [{index, server, path, state_dir, exists, current, from_version, files: [{path, state: "new"|"changed"|"eol"|"same"|"removed"|"extra"|"protected"|"ignored", local, link, behind, tag, pattern}], counts, conflicts: [{path, kind, server}], fingerprint, lock, errors, warnings}]}(在内存中保留 2 小时,只能应用一次)
POST/api/git/runs(环境)部署:{kind: "update", env: {app, env, plan_id, exclude: [path], delete_removed, post_deploy, dry_run, confirm: environment name}, restart: {mode: "none"|"now"}, checks}。回滚:{kind: "rollback", env: {app, env, deploy_id, dests: [index], post_deploy, dry_run, confirm}, restart}
GET/api/git/env/history?app=&env={dests: [{server, path, current, error}], entries: [{action: "DEPLOY"|"ROLLBACK", id, rolled_back, by, at, version, commit, branch, previous, new, changed, deleted, excluded, restored, moved_aside, skipped, counts, result, post_deploy, server, path, dest}]}
POST/api/git/env/doctor{app, env} → {dests: [{server, path, checks: [{name, status: "ok"|"warn"|"fail"|"info", msg}]}]}
POST/api/git/env/unlock{app, env, dest, lock_id}:移除过期锁定(会在服务端再次检查;若锁定已更改则返回 409)
POST/api/git/env/exclude{app, env, path, scope: "service"|"env"} → {pattern, added}(带锚点并已转义;若某个模式已覆盖该文件,则不会添加)
DELETE/api/git/env/exclusions?app=&env=[&path=]清除记住的逐次运行排除项
GET/api/git/activity?app=&branch=&author=&since=&until=&refresh=1服务的推送和提交:{app, project, provider, since, until, branches, tracked, items: [{kind: "commit"|"push", at, author, login, branch, branches, ref_type, ref, sha, title, action, count, before, after, url}], authors: [{key, commits, pushes, branches, last}], by_branch: [{key, commits, pushes, authors, last, url}], truncated, rate_limited, rate_reset, notes, fetched_at, cached, calls}(日期为 YYYY-MM-DD,默认最近 30 天)
GET/api/git/activity/export.csv?…与上相同的条目,以 CSV 格式导出
GET/api/git/history/runs?<filters>不含环境的安装的 WRM 运行记录:{rows: [{at, action, source: "run", app, env, server, path, by, branch, version, commit, id, run_id, result, previous, counts, files, error, note, commit_url}]}
GET/api/git/history/cell?app=&env=&<filters>&refresh=1环境中每个目标位置的 history.jsonl(策略 git_checks):{app, env, rows, errors, at}
GET/api/git/history/export.csv?<filters>所有内容以 CSV 格式导出(筛选条件:app、env、server、who、branch、version、action = deploy|rollback|update|upgrade|install|transfer、since、until)
GET/api/git/where/cell?app=&env=&refresh=1环境的目标位置(策略 git_checks):{rows: [{app, env, server, path, kind: "env", exists, branch, commit, version, by, at, deploy_id, head, behind, commit_url, compare_url, branch_url, drift, locked, error}], drift, note}
GET/api/git/where/installs?app=&refresh=1从最近一次检查获取的不含环境的服务安装:{rows: [{… kind: "install", state}]}
GET/api/git/where/export.csv?app=&env=&server=矩阵以 CSV 格式导出
POST/api/git/runs/{id}/cancel取消计划运行(及其等待中的重启),或在当前安装完成后停止正在运行的任务
隧道与 Web 界面
方法端点描述
GET / PUT/api/connections/{id}/tunnels连接的隧道/替换这些隧道:[{id?, name, kind: "local"|"remote"|"dynamic", bind_host, bind_port, target_host, target_port, open_scheme, open_path, start_mode: "manual"|"connect"|"always"}]
GET/api/tunnels[?all=1]{tunnels: [...], policy} 我的隧道及其状态(running、state、listen、active、total、bytes_up、bytes_down、started_by 等);管理员:all=1 → 所有正在运行的隧道
POST/api/tunnels/{key}/start · …/stop启动(所有者)/停止(所有者或管理员)
POST/api/connections/{id}/open-webWeb 界面连接 → {url, direct, route}(存在跳转主机时会打开临时隧道)

远程文件(id = 连接 ID;共享连接需添加 share_token;角色必须允许执行相应操作)

方法端点描述
GET/api/remote/list?id&path列出文件夹内容
GET/api/remote/list-recursive?id&path列出路径下的所有文件
GET/api/remote/search?id&path&q&mode=name|content&max&hidden搜索(NDJSON 流)
GET / HEAD/api/remote/preview?id&path内嵌媒体/PDF,支持字节范围;metadata=1 返回类型/MIME/大小/语言,text=1 返回有长度限制、通过内容检测的文本,并附带 Prism 语言 ID
GET/api/remote/download?id&path下载文件
GET/api/remote/download-dir?id&path将文件夹下载为 ZIP(SFTP)
POST/api/remote/upload?id&path&overwrite分块上传,采用流式传输
POST/api/remote/mkdir?id&path创建文件夹
POST/api/remote/rename?id&old&new重命名/移动
DELETE/api/remote/delete?id&path&dir=0|1删除文件或文件夹
POST/api/remote/transfer服务端到服务端传输(NDJSON 进度)

共享

方法端点描述
GET / POST/api/shares我的共享/创建 {name, connection_ids, folder_ids, access_mode, guest_role, members:[{username, role}], password, public, expires_at}
GET / PUT / DELETE/api/shares/{id}详情/更新(也可更新 active、clear_password)/删除
POST/api/shares/{id}/rotate新链接
GET / POST/api/shares/{id}/members · PUT / DELETE …/members/{userID}成员和角色
GET/api/shares/{id}/participants · PUT …/participants/{pid}参与者历史记录;{role, banned}
GET/api/share/{token}共享信息、我的角色和权限、连接
POST/api/share/{token}/unlock · …/profile密码解锁 · 访客名称
GET/api/shared“与我共享”

管理(管理员)

方法端点描述
GET / POST/api/admin/users用户(包含 role、break_glass、teams)/ 创建 {username, password, role, …}
PUT / DELETE/api/admin/users/{id}{role, is_admin, break_glass, disabled, display_name} / 删除;?transfer_to=<id> 会先将该用户拥有的内容转交给该账户
GET/api/admin/users/{id}/handover该用户拥有的内容 {owned, suggested_user_id, suggested_username, suggested_reason, teams}
GET / POST/api/admin/oidc身份提供商(不会返回客户端密钥)、关联账户和重定向地址 / 创建提供商 {name, issuer, client_id, client_secret, scopes, redirect_uri, username_claim, require_mfa, mfa_values, jit, rules: [{claim, value, role, teams}], enabled}(增强验证)
PUT / DELETE/api/admin/oidc/{id}修改提供商(字段可选;client_secret 为空时保留已存储的密钥,clear_secret 会将其移除)/ 连同关联项一起移除(增强验证)
POST/api/admin/oidc/check{issuer} 分步连接测试
POST/api/admin/oidc/{id}/preview{claims, rules?} WRM 将分配的角色和团队
DELETE/api/admin/oidc/identities/{id}解除目录账户关联(增强验证)
GET / POST/api/admin/ldapLDAP 目录(不会返回服务账户密码)、关联账户和 sync_minutes / 创建目录 {name, kind: ad|ldap, url, ca_pem, bind_dn, bind_password, base_dn, user_filter, login_attr, id_attr, group_base, nested, jit, rules, enabled}(增强验证)
PUT / DELETE/api/admin/ldap/{id}修改目录(字段可选;bind_password 为空时保留已存储的密码,除非 url 发生变化;clear_bind_password 会将其移除)/ 连同关联项一起移除(增强验证)
POST/api/admin/ldap/check{…directory fields, directory?, username?} 分步连接测试(directory 使用该目录已存储的密码)
POST/api/admin/ldap/{id}/test{username, password} 测试登录:账户、群组、属性和映射,不会创建任何内容
POST/api/admin/ldap/{id}/sync立即检查该目录的关联账户:{checked, ended, updated, error}
DELETE/api/admin/ldap/identities/{id}解除目录账户关联(增强验证)
GET / POST/api/admin/scimSCIM 客户端、已配置账户和端点 / 创建客户端 {name, rules}:{id, token, endpoint},令牌仅显示一次(增强验证)
PUT / DELETE/api/admin/scim/{id}修改客户端名称或规则 / 撤销客户端(增强验证)
POST/api/admin/scim/{id}/rotate为客户端生成新令牌(增强验证)
GET / POST/api/admin/teams团队、成员以及提及这些团队的策略 / 创建 {name, description, members: [{user_id, lead}]}
PUT / DELETE/api/admin/teams/{id}修改(字段相同,均为可选)/ 删除;有策略提及该团队时返回 409
POST/api/admin/users/{id}/reset-password · reset-2fa · revoke-sessions · unlock账户操作
POST/api/admin/users/{id}/stop停止用户:禁用账户并结束所有内容(增强验证):{ok, user, ended: {sessions_ended, terminals_ended, rooms_left, tunnels_stopped, ai_sessions_ended, ai_connections_revoked, disabled}}
GET / PUT/api/admin/settings策略;GET 会为每项设置添加其 required 值和 deviation;PUT 接受 _deviation_notes: {key: reason},若值低于级别且未提供原因,则返回 400 {error, deviation: {key, value, required, level}}
GET / POST/api/admin/lockdown锁定状态 {on, reason, by, at, source, env, break_glass_admins} / {on, reason} 开启锁定(必须提供原因,并进行新一轮增强验证;会添加 ended 和 you_signed_out)或关闭锁定(仅限紧急访问管理员)
GET / POST/api/admin/siemSIEM 目标及其状态(state、sent、failed、waiting、last_ok_at、last_error、retry_at;不会返回密钥)、kinds、近期 alerts 和 hostname / 创建 {name, kind, url, config: {index, sourcetype, tenant_id, client_id, dcr_id, stream, facility, ca_pem, client_cert, actions}, secret, enabled, start_from: now|all}(增强验证)
PUT / DELETE/api/admin/siem/{id}修改目标(secret 为空时保留已存储的密钥,除非地址或类型发生变化;clear_secret 会将其移除)/ 删除目标(增强验证)
POST/api/admin/siem/{id}/test发送测试事件 {ok, error}
GET/api/admin/security安全态势:{level, level_locked, level_env, levels, rules, deviations, checks: [{id, kind, status: ok|warn|bad|info, value, required, recommended, env, count, deviation}], summary, version, host, generated_at}
POST/api/admin/security/level{level, preview, keep: {key: reason}, apply_now} → 计划 {from, to, changes, forced, kept, blockers, removed, affected};级别被强制指定或某个阻止项未被保留时返回 409
GET/api/admin/status状态、打开的终端、房间、中继
POST/api/admin/terminals/{id}/kill结束终端
GET/api/admin/shares所有共享项
GET / DELETE/api/admin/known-hosts[/{id}]主机密钥
GET/api/admin/audit?q&action&user&conn&session&from&to&before_id&limit[&format=csv]审计日志
GET/api/admin/audit/verify验证哈希链 {ok, checked, first_id, last_id, unsigned, broken_at, reason}
GET/api/admin/transfers?q&user&conn&direction&from&to&before_id&limit[&format=csv]文件传输
GET/api/version服务版本 {version};已知有更新版本时会包含 update
GET/healthz健康检查(无需登录)
更新(所有人都可查看状态;管理员可执行操作,策略为 self_update;容器中不可用)
方法端点说明
GET/api/update{current, latest, available, name, notes, url, published_at, checked_at, check_enabled, docker};管理员还可查看 {repo, error, service, platform, policy, can_update, blocked: ""|"docker"|"not_writable", docker_image, signature_keys (trusted release keys; 0 = signature not checked), local: {file, version}, rollback, progress: {state: "idle"|"downloading"|"verifying"|"installing"|"restarting"|"failed", version, done, total, error}}
POST/api/update/check立即检查 GitHub releases → 查看状态
POST/api/update/apply{version}:在后台下载、验证(已知发布密钥后验证签名 SHA256SUMS.txt.sig,根据 SHA256SUMS.txt 验证 SHA-256,并验证 -version)、替换并重启;查看 progress
POST/api/update/rollback切换回 <binary>.previous 并重启
POST/api/update/restart{local: true}:使用文件夹中最新的有效二进制文件重启(不带 local 时使用同一个二进制文件)

AI 助手(策略允许的已登录用户;连接必须是用户自己的连接,或共享给具有终端和文件更改权限的角色;共享连接请添加 ?share_token=)

方法端点说明
GET/api/ai/config{enabled, reason, providers: [{id, name, kind, scope, models, default_model}], modes, default_mode, personal_keys, redact_output, kill_switch, active: [sessions]…} — 不包含密钥
GET/api/ai/connections/{id}连接的 {allowed_modes, default_mode, rules, has_notes, sees}(以限制最严格的规则为准)
GET / POST / PUT / DELETE/api/ai/providers[/{id}]个人提供方(策略 ai_personal_keys);密钥仅可写入(api_key、access_key_id、secret_access_key、session_token、service_account;省略 = 不变,"" = 移除),响应中包含 has_api_key / has_access_key / has_service_account
POST/api/ai/providers/{id}/test发送一个极小请求 {model} → {ok, reply | error}
GET / POST/api/ai/sessions自有会话(?purpose=terminal|logs|file&conn_id=)/ 启动 {conn_id, provider_id, model, mode, purpose?: "logs"|"file", file_path?, resume_from?, auto: {allow, deny, path_allow, path_deny, minutes, max_actions}, confirm_auto, share_notes, engine?: "opencode", sandbox?: true, agent?: "build"|"plan"}
GET/api/ai/sessions?view=allAI 会话视图:所有类型的自有会话 ?kind=assistant|logs|file|opencode|mcp|saved|live&q=&conn_id=&before=&limit= → {sessions (with saved, preview, kind, can_continue), more, keep_saved, retention_days}
GET/api/ai/sessions/{id}会话及其(已脱敏的)记录
POST/api/ai/sessions/{id}/save{saved}:在保留期结束后继续保留自有会话
GET/api/ai/sessions/{id}/export?format=md|json下载自有会话的记录
GET/api/ai/sessions/{id}/events?since=N服务器发送事件:session、user、assistant_start、text、assistant_done、tool_call、approval_required、approval_resolved、tool_result、mode、usage、busy、notice、error、thinking、title、history、ended(已结束的会话会返回 ended 和 resumable)
POST/api/ai/sessions/{id}/prompt{text}
POST/api/ai/sessions/{id}/title{title}:重命名聊天
POST/api/ai/sessions/{id}/mode{mode, auto, confirm}
POST/api/ai/sessions/{id}/approvals/{approval}{decision: "approve"|"deny", command?, content?, note?}(仅限该会话的用户);不再等待处理的请求会返回 409 {error, decided: {outcome, by, via, at}}
POST/api/ai/sessions/{id}/stop · /kill取消正在运行的请求 / 结束会话
GET / PUT/api/ai/delegate用户的辅助模型(提供方、带有数据使用标签的模型、是否允许使用)/ {training: bool}(仅当 ai_delegate_training = user 时)
GET/api/admin/opencodeOpenCode 状态:已安装版本、二进制文件、适用于此主机的软件包、运行中的 Agent、安装日志(管理员)
POST/api/admin/opencode/install{confirm: true}:在后台下载、验证(sha512)并安装 OpenCode(管理员)
POST/api/ai/kill-all结束所有自有会话

AI 连接(MCP) — MCP 端点需要 bearer token;OAuth 端点为公开端点;其余端点需要登录 WRM

方法端点描述
POST / DELETE/mcpMCP 流式 HTTP(协议版本 2025-11-25、2025-06-18、2025-03-26):JSON-RPC initialize(返回 Mcp-Session-Id)、ping、tools/list、tools/call(JSON,或可承载 elicitation/create 和 notifications/progress 的事件流)、notifications/cancelled;DELETE 会结束 MCP 会话。Authorization: Bearer wrm_pat_… / wrm_oat_…;没有令牌时:返回 401,并附带 WWW-Authenticate: Bearer resource_metadata="…"。拒绝来自外部 Origin 的请求(403)
GET/.well-known/oauth-protected-resource[/mcp]RFC 9728 元数据:资源、授权服务器、作用域
GET/.well-known/oauth-authorization-serverRFC 8414 元数据
POST/oauth/registerRFC 7591 动态客户端注册 {client_name, redirect_uris, token_endpoint_auth_method}(重定向 URI 仅限 ai_mcp_redirect_uris 中的 URI)
GET/oauth/authorizeresponse_type=code、client_id、redirect_uri、code_challenge + 必需的 code_challenge_method=S256、state、scope、resource → WRM 的授权对话框
POST/oauth/tokengrant_type=authorization_code、code、redirect_uri、client_id、code_verifier → {access_token, token_type: "Bearer", expires_in, scope}(不提供刷新令牌)
POST/oauth/revokeRFC 7009 token
GET/api/mcp/config用户可以选择的内容:{enabled, reason, connections, modes, scopes, default_hours, max_hours, url, oauth, elicitation, instructions, description, version}
GET / POST/api/mcp/grants自己的 AI 连接 / 创建令牌 {name, conn_ids, mode, scopes, hours, auto, confirm_auto}(auto.until_grant:不设时间或操作限制,自 v12.6.1 起)→ {grant, token, url}(令牌仅在此处显示)
DELETE/api/mcp/grants/{id}撤销(结束其会话)
POST/api/mcp/revoke-all撤销自己所有的 AI 连接
GET/api/mcp/active用于指示器的 {live: [有打开会话的 AI 连接], pending: [待审批项]};通过 /api/ai/sessions/{id}/approvals/{approval} 作出决定
POST/api/mcp/claude-desktop适用于此 WRM 的 Claude Desktop 扩展 wrm-pro.mcpb {token}(可选;仅接受 wrm_pat_… 令牌)→ application/zip。审计记录为 mcp.desktop_extension
POST/api/mcp/full-access用户自己的完全访问权限 {on}:启用需要打开 ai_full_access,且 ai_full_access_mode = user(否则返回 403);关闭始终允许。审计记录为 mcp.full_access
GET / POST/api/mcp/authorize/{id}授权对话框:请求(client_name、redirect_host、scopes)/ {decision: "approve"|"deny", conn_ids, mode, scopes, hours} → {redirect}
GET / DELETE/api/admin/mcp/grants[/{id}],POST /api/admin/mcp/revoke-all所有 AI 连接;撤销一个或全部连接(管理员)
GET / DELETE/api/admin/mcp/clients[/{id}]已注册的 OAuth 应用;移除应用会撤销其 AI 连接
GET / POST / PUT / DELETE/api/admin/ai/providers[/{id}],POST …/{id}/test组织级提供商(管理员)
GET/api/admin/ai/providers/{id}/models提供商自己的模型列表(GET {base}/models)→ {ok, models | error};有审计记录
GET/api/ai/ollama/status[?url=]Ollama 检测 {running, version, models, binary, os, steps, can_manage, openai_base}(url 仅供管理员使用)
POST/api/ai/ollama/action{action: install|start|pull, model, url, confirm: true} → {run_id};需要管理员权限和策略 ai_ollama_manage,使用固定命令,每次只允许运行一项
GET/api/ai/ollama/runs[/{id}]最近运行记录及其输出(管理员)
GET/api/admin/ai/sessions?user&conn&status&limit,/api/admin/ai/sessions/{id}所有 AI 会话;可查看对话记录(查看操作会被审计)
POST/api/admin/ai/sessions/{id}/kill,/api/admin/ai/users/{id}/kill,/api/admin/ai/kill-all按会话、按用户或对所有人启用终止开关
PUT/api/admin/ai/users/{id}{blocked}:为某个用户关闭助手(并结束其会话)
GET/api/admin/ai/summary按用户统计用量、活跃会话、破坏性规则
终端会话与录制(管理员:全部;用户:自己的会话及其连接上的会话)
方法端点描述
GET/api/recordings?mine&q&user&conn&host&status&from&to&before_id&limit包含录制信息的终端会话
GET/api/recordings/{id}单个会话及其审计条目
GET/api/recordings/{id}/cast[?download=1]以 asciicast v2 格式提供的录制内容(application/x-asciicast)

WebSocket

端点描述
/ws/ssh?id&cols&rows[&share_token]终端。二进制帧 = 终端数据;文本帧 = JSON 控制消息(resize、pause、resume、ping、cwd(Shell 的工作目录)→ 服务端;带有 path 或 error 的 cwd、status(含 recording、session_id)、error、exit、hostkey ← 服务端)。关闭代码:1000 Shell 已退出,4001 连接失败/不允许,4002 SSH 连接丢失,4003 访问权限已撤销
/ws/events已登录用户的实时通知(sessions_changed、tunnels_changed、snippets_changed、bookmarks_changed、status_changed、ai_sessions_changed、mcp_changed)
/ws/share/{token}协作房间。客户端 → 服务端:chat、file、set-name、screen(start/stop/data/resize/snapshot)、watch、unwatch、control-request/grant/revoke/release、remote-input、voice-join/leave/signal/state、hand、mod(set-role/mute/unmute/stop-share/lower-hand/kick/ban)。服务端 → 客户端:welcome、participants、chat、file、system、screen、watch-request、control、control-request、remote-input、voice-peers/joined/left/signal、force-mute、role、kicked、closed、error

从源代码构建与发布

要求:Go(版本见 remote-manager/go.mod)。无需 C 编译器(纯 Go SQLite)。

git clone https://github.com/vedranius/web-browser-RDM-public.git
cd web-browser-RDM-public/remote-manager
go test -race -count=1 -timeout 45m ./...
go build -o wrm-server .
./wrm-server

可为任意平台交叉编译,例如 GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o wrm-linux-arm64 .;也可通过 bash remote-manager/build-all.sh 构建全部 13 个目标。

项目结构

remote-manager/
  main.go         HTTP server, routes, database schema & migrations, connections, folders, sessions, transfer
  security.go     server secret, encryption key management, security headers, CSRF, self-signed TLS, validation
  users.go        sign-in, 2FA step, sessions, password change, account administration
  totp.go         TOTP (RFC 6238), QR code, recovery codes
  settings.go     admin policies (database + WRM_<KEY> environment overrides)
  addons.go       addons: install, enable, assets; addons_v2.go: manifest v2, personal addons, instances, store, windows, CSP, integrity, permission sheets; addons_http.go: web requests for addons (allowlist, SSRF guard, secrets, approvals, log); addons_lint.go: addon lint and diagnostics; addons_dev.go: wrm -addon-dev and /api/addons/dev; addons_templates.go + addon_templates/: starter templates, wrm-bridge.js, schema, llms.txt
  audit.go        audit log (hash chain, append-only triggers), CSV export, integrity check, retention
  recording.go    terminal sessions, asciicast recorder, file transfer log, recordings & transfers API
  hostkeys.go     SSH host key verification (TOFU/strict), FTPS certificate pinning
  shares.go       sharing model: access modes, roles, members, participants, authorization
  collab.go       collaboration rooms: presence, chat, terminal sharing, control, voice signalling, moderation
  turn.go         built-in TURN relay for voice (turn_android.go: stub for Android)
  admin.go        open-terminal registry, admin status
  ssh_ws.go       SSH terminal WebSocket (binary frames, flow control, keepalive, reconnect codes)
  termcwd.go      working directory of a terminal's shell over a separate SSH exec channel (📂 Open here)
  service.go      run as a service: prompt, env file, service files, versions, newest binary in the folder, restarts
  service_unix.go / service_windows.go  systemd, launchd, rc.d installers / Windows service (SCM)
  update.go       update check against GitHub releases, verified self-update, rollback, restart
  roles.go        roles, who-policies (operators, teams:), step-up, break-glass, handover
  teams.go        teams, team members, teams in shares, admin team API
  oidc.go         directory sign-in: providers, PKCE sign-in, mapping rules, identities, revalidation, admin API
  oidc_jwt.go     OIDC discovery, signing keys (JWKS) and ID token verification
  ldap.go         LDAP / Active Directory: directories, sign-in, groups and mapping, regular check, admin and self-service API
  ldap_proto.go   LDAPv3 client: BER, LDAPS and StartTLS, bind, paged search, filter compiler
  scim.go         SCIM 2.0 provisioning: Users, Groups, tokens, groups as teams, admin API
  directory.go    endUserAccess: what ends when an account is stopped by any route
  siem.go         SIEM export: destinations, event format, syslog / file / Splunk / Elastic / Sentinel / HTTPS delivery, status, admin API
  alerts.go       security alert rules on the audit log
  lockdown.go     lockdown (UI, wrm -lockdown, WRM_LOCKDOWN) and Stop user
  security_level.go  security levels: rules, preview and apply, deviations, the first-run and start-up level, HTTPS for sign-in
  security_posture.go  the security posture checks for Admin → Security
  releasesign.go  release signatures (ed25519 over SHA256SUMS.txt): verification for the self-update, -release-keygen/-sign/-verify
  ai_engine.go    AI sessions: tool calls through the permission engine, approvals, kill switch, transcript, recording, the agent loop
  ai_policy.go    AI modes, mode rules (most restrictive wins), automatic-mode limits, the decision
  ai_classify.go  read-only command classifier and unreadable sensitive files
  ai_destructive.go  always-blocked destructive patterns
  ai_shell.go     shell command parser and glob matching for the AI checks
  ai_tools.go     the AI tools (fixed read scripts, run_command, file edits with diffs)
  ai_redact.go    redaction of secrets in AI output, transcripts and audit
  ai_llm.go       model calls: Anthropic Messages, OpenAI Chat Completions, Bedrock Converse; streaming, usage, cost
  ai_cloud.go     AWS SigV4, AWS event streams, Google service account tokens
  ai_provider.go  AI providers (organisation / personal), encrypted keys, schema
  ai_api.go       /api/ai and /api/admin/ai
  ai_ollama.go    Ollama detection / install / start / pull (audited), provider model lists
  ai_opencode.go  OpenCode Zen provider: models.dev catalog, free models, data-use labels, API family routing
  ai_delegate.go  delegate_task: helper models chosen by kind of job, fallback, training opt-in, /api/ai/delegate
  opencode_install.go  OpenCode download from the npm registry with sha512 check, /api/admin/opencode
  opencode_agent.go    OpenCode agents: managed opencode serve per session, its config, loopback MCP, event mapping, cleanup
  ai_transfer.go  transfer_file: SFTP copy between two sessions of one AI connection
  mcp_server.go   the MCP server at /mcp: streamable HTTP, JSON-RPC, tools, elicitation, origin and CORS checks
  mcp_tokens.go   AI connections (hashed tokens, scopes, expiry, revoke), policies, /api/mcp and /api/admin/mcp
  mcp_oauth.go    OAuth 2.1 for MCP clients: metadata, dynamic client registration, consent, PKCE, token, revoke
  mcp_stdio.go    the stdio bridge (wrm -mcp-stdio) for clients that only start local servers
  mcp_bundle.go   the Claude Desktop extension (wrm-pro.mcpb), the plugin's bundle (buildPluginMCPB) and the setup script for all AI apps (POST /api/mcp/setup-all): manifest, the Node.js bridge in mcpb/server/index.js, the icon
  files.go        file API: list, download, ZIP, streamed upload, mkdir, rename, delete
  search.go       recursive name / content search (NDJSON stream)
  sftp_pool.go    pooled SFTP connections with liveness checks
  conntest.go     "Test connection" endpoint
  jump.go         jump hosts: chains, dialing through hops (and their proxies), validation
  proxy.go        saved proxies: SOCKS5 / SOCKS4(a) / HTTP CONNECT clients, WRM tunnel proxies, routes, API
  notify.go       notifications: channels (SMTP, chat, push, webhook), subscriptions, digests, quiet hours
  tunnels.go      SSH tunnels (local, remote, SOCKS5), manager, reconnects, tunnels API, web interfaces
  importers.go    import from mRemoteNG confCons.xml and OpenSSH config
  putty.go        import of PuTTY sessions (.reg) with proxies, link to mRemoteNG PuttySession
  snippets.go     snippets (saved commands), variables, run on connect
  bookmarks.go    folder bookmarks: scopes, variables, shell-quoted cd, start directory, WinSCP import
  status.go       live up/down status monitor and API
  git.go          Git workspace: storage, settings, targets, API, diff
  git_source.go   GitLab API v4 / GitHub REST client, tree and blob cache, ref resolution, suggestions
  git_bundle.go   offline bundles: import and export (bundle.json + payload)
  folders.go      nested hierarchy, owner/cycle/depth validation and import ordering
  preview.go      authenticated SFTP/FTP byte-range streaming, content-detected text previews and language hints
  git_functionality.go runtime checks, redacted logs and configuration inspection
  git_scan.go     discovery and file hashing over SSH, VERSION.md, units, comparison
  git_monitor.go  periodic Git checks and their notifications
  git_deploy.go   deploy steps over SSH: backup, atomic writes, checks, rollback, VERSION.md, updates.jsonl, dangling imports, restarts
  git_runs.go     Git runs: plan, rolling execution, scheduling, live progress, policies, notifications, API
  git_provision.go  Git install and transfer: pre-checks, staged tar transfer, units, wizard API
  git_template.go   templates of per-host files: destinations, fields, filling, slots
  git_gitignore.go  .gitignore helper: candidates, warnings, preview, merge / pull request
  git_ci.go         optional CI: webhooks, bundles from CI artifacts, CI pipeline deploy method
  git_files.go      every file of an installation: listing with reasons, view, diff of any repository file, commits behind
  git_jobs.go       check jobs: partial, streamed and cancellable checks with concurrency limits
  git_env.go        environments: validation, plans with fingerprints, locks, server-side state, overview, history, doctor, API
  git_env_run.go    environment deploy and rollback runs: dry run, staged transfer, backup, manifest, history, post_deploy
  git_activity.go   Git activity: pushes and commits per branch and author, paging with rate limits, short cache, web links, CSV
  medium_config.go  Medium native: deploy-config reader and validator (the original tool's rules)
  medium_filter.go  Medium native: rsync exclude rules, allowed_refs matching
  medium_engine.go  Medium native: rsync-compatible diff over SFTP, server state, comparison with the original plan
  medium_native.go  Medium native: WRM Git source, server ↔ connection links, background previews, API
  medium_state.go   Medium native: server state in the original format (current.json, history.jsonl, lock owner), rollback choice
  medium_host.go    Medium native: writing to a destination (SFTP with sh over SSH)
  medium_deploy.go  Medium native: deployment (lock, re-plan, backup, upload, checksum check, post_deploy, history, pruning), jobs
  medium_rollback.go  Medium native: rollback from the backup manifests
  medium_deploy_api.go  Medium native: engine per project, deploy, history, rollback, lock release and job API
  git_medium_docker.go  Medium Docker: per-OS installation (Linux packages, Docker Desktop with signature and licence), consent, -setup-docker
  git_medium_ca.go      Medium certificates: the host's trusted roots (Windows stores, macOS keychains, CA bundle) and medium_ca_file for the Docker runtime
  git_where.go      deploy history (server history + WRM runs) and the "what is where" matrix with commits behind the branch head
  bmc.go          out-of-band management: Redfish and IPMI status and power, certificate pinning
  quick.go        quick connect (temporary connections and their cleanup), connection notes
  nettools.go     network tools: port check, ping, traceroute, DNS, HTTP/TLS check, from WRM or a server
  pwa.go          web app manifest and service worker (installable app)
  console.go      terminal backends: SSH shell, BMC SSH console, IPMI Serial-over-LAN, serial ports
  tty_linux.go    pseudo terminals and serial port settings (Linux); tty_other.go elsewhere
  inventory.go    tags, CSV/XLSX reader with column mapping, NetBox import and sync
  keys.go         SSH key store: generate/import, deploy/revoke (authorized_keys), who has access
  credentials.go  credentials vault: sharing, host lists, password rotation
  guac.go         remote desktop: guacd handshake, relay, recording (RDP / VNC / Telnet)
  helpers.go      origin check, login rate limiting, shared helpers
  security_test.go  unit tests (TOTP, roles, share access, CSRF, encryption migration, settings)
  upgrade_test.go   unit tests (upgrading databases from earlier builds, old URLs)
  integration_test.go  in-process SSH/SFTP server: connect → audit → recording, transfers, append-only audit
  tunnels_test.go      jump host chains, local/remote/SOCKS tunnels, policies, web interfaces
  snippets_test.go     snippets API, sharing, variables, run on connect, broadcast audit
  bookmarks_test.go    folder bookmarks: scopes, ownership, variables, cd quoting, shares, WinSCP.ini, start directory
  status_test.go       live status: up/down, banners, jump hosts, check now
  git_test.go          Git workspace: fake GitLab / GitHub / Gitea, branch-aware tags, blob cache, bundles, catalog, discovery and comparison on a fake SSH host, notifications
  git_deploy_test.go   Git deploy: VERSION.md / updates.jsonl formats, dangling imports; update, CRLF, protected files, stamp, rollback, failed check → rollback, scheduled restart (fake SSH host)
  git_gitignore_test.go  .gitignore helper: candidates from a check, preview, download, merge request only on explicit choice (fake GitLab), pull request (fake GitHub)
  folders_test.go hierarchy, cycle/owner/depth checks and config round trips
  git_functionality_test.go Supervisor group health, log/config redaction and symlink boundaries
  preview_test.go SFTP/FTP ranges, safe text preview and share permissions
  ai_availability_test.go SFTP providers without MCP and cross-window policy events
  git_files_test.go      every file of an installation (reasons, excluded file diff, symlinks, unreadable, quoting, commits) and check jobs (partial, stale, limits, cancel, last good result)
  git_ci_test.go         webhooks (GitLab token, GitHub HMAC, generic token / HMAC, replays, rate limit), artifact feed fetch and schedule, Jenkins job and GitLab pipeline runs
  git_env_test.go        environments: plan with CRLF-only files, dry run, typed confirmation, one-shot plans, fingerprint mismatch, lock contention, stale lock, own lock only, remembered and permanent exclusions, allowed_refs, nested paths, partial transfer, post_deploy failure, rollback (moved aside, symlinks skipped, removed directories, kept backups), doctor, drift
  git_activity_test.go   Git activity against fake GitLab / GitHub / Gitea: paging (X-Next-Page, Link, cursors), tracked branches, filters, author / branch summaries, links, cache, rate limits and 429, CSV escaping
  medium_deploy_test.go  Medium native engine: state format, rollback choice on the original's history, lock, deploy and rollback against real rsync with backups, plan mismatch, exclusions, post_deploy, partial deployment, pruning, deploy over SSH (fake server), API with policy, confirmation and engine checks
  medium_screens_test.go Medium file details (line diff, binary/large/CRLF), eol_only marking locally and over SSH with counts in history, the details API and the deploy-config editor (validation, stale hash, CRLF kept, create/delete, policy)
  medium_config_git_test.go deploy-config from Git with fake GitLab / GitHub / Gitea: pull, local changes, refused pull, push with conflict check and validation, discard, stop
  medium_build_user_test.go build user checks (root, missing account, readable WRM key) and a real build as nobody with a clean environment
  medium_native_test.go  Medium native: deploy-config validation, state paths, exclude rules and the diff against real rsync (fixed cases and random trees), server state, Git sources (fake GitLab / GitHub / Gitea), connection links, comparison run
  git_where_test.go      deploy history merged from two destinations and WRM runs (filters, cache, CSV with file lists, policy), what is where (commits behind the branch head, drift, installations, CSV)
  git_provision_test.go  Git install / transfer: templates, exclusions, units; install from the fake GitLab and from a bundle, vault values, overwrite refusal and backup, transfer A → B, policies
  quick_test.go        quick connect (targets, expiry, open terminals, limit), notes, network tools from WRM and through SSH, PWA endpoints
  bmc_test.go          Redfish (fake BMC, pinning, jump host, credential), IPMI with a fake ipmitool, SOL (local PTY and jump host), BMC SSH console, serial port on a PTY
  inventory_test.go    tags, CSV encodings/separators, XLSX import, NetBox import and sync (fake NetBox)
  keys_test.go         key store, deploy/revoke/who has access, vault sharing and rotation (fake SSH server with sh and passwd)
  guac_test.go         remote desktop relay against a fake guacd: handshake, filtering, recording, jump hosts
  importers_test.go    mRemoteNG (encryption formats, inheritance, master password) and OpenSSH config import
  putty_test.go        PuTTY .reg import (UTF-16 / UTF-8, defaults, proxies and their reuse, SSH proxy → jump host), link with mRemoteNG in both orders
  proxy_test.go        proxies (in-process SOCKS5 / HTTP CONNECT, with and without auth): terminal, SFTP, status, jump host + proxy, web interface, desktop relay, WRM tunnel proxy, errors, sharing, folder defaults
  review_fixes_test.go  FTP with EPSV through a proxy (fake FTP server), another user's tunnel refused as a proxy, folder defaults (own WRM tunnel, loops refused, PUT keeps choices), per-user status keys, notification fixes (recipient injection, mentions, reminders, AUTH LOGIN)
  notify_test.go       notification channels against fake HTTP endpoints and a fake SMTP server, digests, rate limit, quiet hours, status and rotation events
  import_limits_test.go  import size limits through the real middleware: multi-MB confCons.xml and CSV, HTTP 413 above the limit
  service_test.go      service files for every OS (golden files in testdata/service), env file, version comparison, newest binary in the folder
  releasesign_test.go  release signatures: round trip, tampering, wrong key or file, WRM context, key parsing, the command-line tools, self-update refusing unsigned or wrongly signed releases
  v138_ai_sessions_test.go  AI sessions view (own sessions only, filters, search, save, export, retention), personal AI settings, continuing an MCP session; MCP approvals given later run at once (and with repeat) and are checked again before they run, Deny in the app is final
  v12625_test.go       LDAP and SCIM against a fake LDAP server (LDAPS, StartTLS, AD nested groups, paging): protocol pieces and filter escaping, sign-in and mapping, refused accounts, the regular check ending access, linking, stored passwords not sent to a changed address, SCIM users, groups, PATCH and deprovisioning, the SCIM account linked on the first OIDC sign-in, disabling ends everything
  v12626_test.go       lockdown (sessions, sign-in, AI, shares, CLI state, break-glass only), Stop user and what it ends, every alert rule and its settings, SIEM delivery to fake Splunk, Elastic, Sentinel (with a fake Entra token endpoint) and HTTPS collectors over TLS, syslog over TLS (RFC 5424 framing, structured data), the JSON lines file, catching up after an outage, action filters and the stored secret not sent to a changed address
  v12624_test.go       directory sign-in against a fake identity provider: ID token checks (RS256/ES256, nonce, audience, expiry, alg none/HS256, key rotation), accounts from rules, role and team sync, refusals, browser binding and replay of the callback, MFA, local 2FA after a directory sign-in, revalidation (refused refresh, removed from the group, no refresh token), password sign-in limited to break-glass, linking, step-up and test sign-in, admin API
  v12623_test.go       roles and teams: who-policy values, auditor read-only and refused connections, step-up, break-glass networks and notifications, teams in shares, handover on delete
  v12622_test.go       security levels: rule comparison, preview, blockers and deviations, apply and sign-out, env lock, HTTPS for sign-in, level at start and first run, guest link lifetime
  fuzz_test.go         fuzz targets for the import parsers (mRemoteNG, SSH config, CSV/XLSX, PuTTY, WinSCP, configuration files, deploy-config YAML); seeds run with every go test
  update_test.go       self-update against a fake GitHub releases server: success and rollback, checksum mismatch, missing checksums file or line, missing asset, wrong -version, policy, Docker, local binary
  ai_policy_test.go    read-only classifier (many cases), destructive patterns (every rule, false positives), admin patterns, globs
  ai_engine_test.go    AI sessions against a fake Anthropic / OpenAI-compatible server and the fake SSH host: approve, edit, deny, timeout, read-only, destructive in every mode, automatic-mode limits, file edits with diffs, kill switch, most restrictive policy, keys never returned, redaction, audit, transcript and recording, prompt injection, the event stream
  mcp_test.go          an MCP client harness: initialize, tools/list, tools/call, elicitation; OAuth with PKCE failure and code reuse; token scopes and expiry; revoke and kill switch; approval round trip; read-only and scope enforcement; destructive block; prompt injection; audit; transfer; the stdio bridge; origin and CORS checks
  mcp_bundle_test.go   the Claude Desktop extension: download, manifest, token checks; its Node.js bridge end to end with an approval
  v13130_plugin_test.go  the Claude plugin: committed bridge bundle is current, no settings, no bin/; the bridge's browser sign-in (wrm_connect) end to end, saved connection, denial; the setup script for all AI apps run with sh against real config files
  v1265_test.go        Medium step by step: tool import steps with output, deploy-config checked at once and kept while preparing, failed start keeps its step, error and redacted output, activity log; 409 names the running operation and its user, visibility and medium_log_output; approve later after the AI app closed its session; grep/sed/find patterns are not taken for files
  v1266_test.go        Docker for Medium: backend choice, Linux packages after consent with steps and output, no rights shows -setup-docker, policy off, Windows and macOS Docker Desktop with download, signature and licence, permission denied, wrm -setup-docker
  ai_opencode_test.go  OpenCode Zen: catalog parsing, free and deprecated models, keyless use only of free models, API family routing, fallback without the catalog; delegation off, automatic choice, training opt-in, redaction, audit
  opencode_agent_test.go  OpenCode configuration (own tools off, WRM as MCP server), install with sha512 check against a fake registry, loopback-only tokens; with WRM_TEST_OPENCODE set, the real OpenCode binary end to end (WRM tools, approval in the chat, cleanup)
  opencode_sandbox_test.go  OpenCode sandbox: configuration (own tools on, shell/edit/web fetch ask, local provider rewritten), locked-down docker arguments without secrets, settings, a permission request becoming a WRM approval that cannot be edited (approve, deny with a note, other permissions refused); with WRM_TEST_OPENCODE and WRM_TEST_OPENCODE_SANDBOX=<image>, a real container end to end
  v12610_test.go       the canvas is wired (addon windows, floating panels on the canvas, Tools menu, top bar group and order, sessions keep addons); /api/me/ui takes 256 KiB
  addons_v2_test.go    addon platform v2: strict manifest and error codes, theme validation, personal addons (visibility, policy, no server code, admin kill switch), instances, store scopes and quota, windows, export/import, CSP with script hashes, integrity, approvals on growing updates, downgrades
  addons_http_test.go  addon web requests: http manifest validation and permission coverage, IP guard (loopback, private, metadata, CGNAT), proxy against a fake site (allowlist, approval, methods, paths, header filtering, secrets per instance and personal override, redirects, size cut, rate limit, coalescing, log), plain http and personal addons waiting for an administrator
  addons_lint_test.go  addon tools: every template lints clean and installs, lint findings with codes and lines, schema covers the manifest, llms.txt lists the codes, /api/addons/dev, the dev server (host check, token, CSP, store, web requests, env secrets, reload)
  v1269_test.go        in-app notifications (recorded without channels, per user, reminders once a day, mark read, clear, newest 200 kept, removed with the user); metrics parser; /api/workboard/metrics (own connections only, SSH error in the result, policy off, fresh and stale Monitoring sample); the page loads static/workboard.js
  v1268_test.go        /api/me/ui: per-user layout store (put, overwrite, reset, objects only, 64 KiB limit, unknown keys, signed out, removed with the user); the page loads static/layout.js and has every panel
  v1267_test.go        Medium certificates: host CA bundle and extra PEM file reach every container (mount, environment, image roots kept), expired and duplicate certificates left out, bad or missing file named
  v1264_test.go        ai_full_access_blocked: deny keeps the administrator's blocked commands refused under full access, the destructive list still asks; ask asks
  v1263_test.go        full access modes: every AI session with the switch alone (default), only connections with the scope, each user's own switch (403 when not allowed, audited)
  v1262_test.go        full access: blocked and destructive commands and secret files ask (also in automatic mode with *), policy off refuses again, read-only stays read-only
  v1261_test.go        "Allow everything": * with chains, variables and redirections, deny lists and blocked commands still apply, no time or action limit until the AI connection expires, panel sessions keep limits; approve later; approved, redacted reads of secret files
  ai_provider_test.go  SigV4 test vector, Bedrock Converse event stream, Vertex token exchange, Azure / OpenAI, Anthropic request shape, refusal, cancel, cost
  termcwd_test.go      the shell's working directory over SSH against the fake SSH host (a real sh on a PTY): start directory, after cd, a foreground job
  static/index.html          the entire web UI (embedded into the binary)
  static/git.js              the Git workspace (loaded when it is opened)
  static/ai.js               the AI assistant panel and the admin AI tab (loaded when used)
  static/mcp.js              AI connections (MCP): settings, indicator, approval cards, OAuth consent, admin tab (loaded when used)
  static/aisessions.js       the AI sessions panel and viewer; shared handling of decisions on requests that no longer wait
  static/layout.js           panel layout: dock zones, tab groups, splitters, floating windows, lock, Panels menu, per-user storage
  static/addons.js           Settings → Addons, addon panels and the v2 bridge (instances, store, watchdog, permission sheet, web requests, secrets)
  static/workboard.js        the Workboard: addon windows on the canvas, addon catalog, settings, docking addons as panels, canvas menu (grid, arrange, saved layouts, export/import)
  static/brand/              logo, favicon and app icons
  static/vendor/             xterm.js + addons and fonts (served locally, see THIRD-PARTY-LICENSES.txt)
  mcpb/server/index.js       the Node.js bridge of the Claude Desktop extension, the Claude plugin and the setup script for all AI apps (embedded; mcp_bundle.go): forwarding, wrm_connect sign-in, --setup
.claude-plugin/marketplace.json  Claude Code plugin marketplace of this repository
packaging/claude-plugin/wrm-pro/  the WRM PRO plugin for the Claude app and Claude Code: server/wrm.mcpb (the bridge, built by buildPluginMCPB), skills (wrm, wrm-safe-operator, linux-incident-triage), /wrm-pro:connect
.github/workflows/build.yml  CI: vet, gofmt, tests (race), JS syntax check, builds all platforms, Docker image (with a vulnerability scan), releases on tags
.github/workflows/security.yml  security checks: govulncheck, staticcheck, gosec (new findings only), gitleaks, actionlint and zizmor, dependency review
.github/workflows/codeql.yml  CodeQL code scanning (Go and JavaScript)
.github/workflows/scorecard.yml  OpenSSF Scorecard
.github/workflows/claude-security-review.yml  Claude security review of pull requests (needs the ANTHROPIC_API_KEY secret)
.github/workflows/nightly.yml  nightly fuzzing of the import parsers and an OWASP ZAP scan (signed out and as an administrator)
.github/security/            gosec baseline and the WRM checklist for the Claude review
.github/dependabot.yml       weekly Go module, GitHub Actions and Docker updates
.gitleaks.toml, remote-manager/staticcheck.conf  scanner settings
tools/gosec-baseline.js      compares a gosec report with the reviewed baseline
.claude/skills/wrm-security-review/  the security review every Claude Code session runs before a push
Dockerfile, docker-compose.yml  container image and one-command deployment
ARCHITECTURE.md              how WRM is built; extension plan status and touch points
docs/brand/                  logo kit (SVG + PNG: mark, lockup, app icons, favicon, social preview)

CI/CD: 每次推送都会构建全部 13 个目标和 Docker 镜像,并运行安全检查。推送标签 v* 会创建 GitHub Release,其中包含所有二进制文件、macOS 通用二进制文件、Linux x86_64/ARM64 AppImage、SHA256SUMS.txt 及其签名 SHA256SUMS.txt.sig(仓库密钥 RELEASE_SIGNING_KEY)、CycloneDX SBOM 和 GitHub 构建来源证明,并发布镜像 ghcr.io/vedranius/wrm-pro。


故障排除

对于 v12.4.4,AI 缺失/不可用的问题可在“设置”→“AI 助手”中诊断;请检查账户策略/终止开关、服务提供商可用性以及 SSH/SFTP 上下文。功能未经验证表示远程账户无法检查服务管理器、未配置单元/探测,或检查尚未完成;请查看其状态消息,并在需要时配置服务的健康检查端点。媒体无法播放可能是因为浏览器缺少编解码器支持,或 FTP 服务端不支持 SIZE/REST;请使用“下载”。同名服务端可通过完整文件夹路径加以区分;选择“父文件夹”以构建客户端/站点嵌套结构。

问题解决方法
Medium 原生部署:locked by … since …另一次部署(WRM 或原始工具)占用了目标位置。请等待其完成;崩溃后遗留的锁,在超过所示时长(由 medium_command_timeout 和 medium_transfer_timeout 决定)后,可在 History and rollback 中释放
Medium 原生部署:the plan changed since you reviewed it / plan changed比较后服务器或 deploy-config 发生了变化。请重新比较、检查新计划并部署
Medium 原生部署:Deploy 已禁用将项目切换为 WRM native(Engine),检查 medium_native 策略和 allowed_refs;对于需要构建步骤的项目,预览前请选择构建位置(WRM 主机、Linux 构建服务器或无)
目录登录:Sign-in refused: your directory account is not assigned to WRM没有规则匹配该令牌。使用该用户的账户进行 Test sign-in,查看其声明;在目录中分配应用角色或组,或添加规则。Entra 仅在应用注册的令牌配置中添加 groups 时才会发送该字段;对于所属组较多的用户,会以超额提示替代:请改用应用角色进行映射
目录登录:提供方提示重定向地址不匹配注册 Admin panel → Directory sign-in 中显示的确切地址;如果使用反向代理,请将提供方的重定向地址(或 ai_mcp_public_url)设为公开地址
目录登录:the ID token has expired / issued in the futureWRM 主机的时钟不正确;请同步时钟(NTP)
LDAP:Test connection 在 TLS 阶段失败WRM 主机不信任该证书,或证书中不包含你输入的地址:粘贴目录的 CA 证书(PEM),并使用证书中的名称(而非 IP 地址)
LDAP:Test connection 在端口 389 的 Connect 阶段失败服务器未提供 StartTLS:请在目录中启用 LDAPS 或 StartTLS(Active Directory 需要服务器证书),或在端口 636 使用 ldaps://
LDAP:Your directory account is not in a group that may use WRM没有规则匹配:使用该账户进行 Test sign-in,查看其组和属性,然后将用户添加到已映射的组,或添加规则
SIEM 目标显示 Failing,并出现 x509 或 certificateWRM 主机不信任收集器的证书:将其 CA 证书(PEM)粘贴到目标中
Sentinel:403 或 ForbiddenEntra 应用需要在数据收集规则上拥有 Monitoring Metrics Publisher 角色;请检查规则的不可变 ID 和流名称
所有人都已退出登录且无法登录WRM 处于锁定状态(登录页面会显示相关提示):由紧急管理员在 Admin panel → Security 中解除,或在主机上运行 wrm -lockdown off;如果设置了 WRM_LOCKDOWN=1,请移除该变量并重启
SCIM:Entra 报告 401 或 Unauthorized密钥令牌错误、已轮换或已撤销:在 SCIM provisioning 中创建新令牌,并将其粘贴到预配设置中
目录用户每隔几小时就会退出登录提供方未提供刷新令牌:将 offline_access 添加到作用域(并允许客户端使用),或调高 oidc_unverified_hours
面板消失,或标签页无法拖动Panels(顶部栏中的 ▦,或其 ⋯ 菜单中的选项)可显示和隐藏所有面板;该按钮上的 🔒 表示布局已锁定:在此处解锁。Reset the layout 会将所有面板恢复到初始位置
Medium:pip 失败并显示 certificate verify failed: self-signed certificate in certificate chain代理或防病毒软件正在检查 HTTPS。保持 medium_host_ca 开启(默认),然后再次按 Prepare runtime;如果 WRM 主机的证书存储中没有其根证书,请将其导出为 PEM 并设置 medium_ca_file
Request blocked by CSRF protection / 终端在代理后无法连接传递 Host 标头(proxy_set_header Host $host;)和 WebSocket 升级标头,或设置 WRM_ALLOWED_ORIGINS
AI:终端上没有 AI 按钮助手已关闭(ai_assistant)、未向你的账户开放、终止开关已开启、连接不是 SSH,或你的共享角色不允许使用终端和修改文件
AI:the policy does not allow the AI assistant on this connection针对此标签、文件夹、主机或 ID 的模式规则未设置任何模式;请联系管理员(Admin panel → AI assistant → Mode rules)
AI:只读模式下,执行无害命令也需要批准只读分类器只接受其识别为只读的命令(不含重定向、替换或变量)。请使用读取工具,在 ask 模式下批准,或将其添加到自动模式允许列表
AI:the provider answered HTTP 401/403/404检查密钥、模型名称(Bedrock:anthropic.… ID 或推理配置文件;Vertex:所在区域是否提供该模型)和基础 URL;提供方列表中的 Test 会发送一个小型请求
AI:HTTP 503(high demand)或 429提供方暂时过载:从 v12.2.0 起,WRM 会先重试最多三次(间隔 3、8 和 15 秒),然后才显示错误;请稍后重试或选择其他模型
AI:HTTP 413 / request too large(Groq 和其他具有每分钟令牌数限制的提供方)从 v12.2.0 起,WRM 会缩短对话中的长命令输出并重试;如果提供方的限制仍不足以容纳系统提示词和工具,请选择限制更高的模型
AI:Gemini 回答 missing a thought_signature已在 v12.2.0 修复:WRM 会将提供方工具调用中的 extra_content 原样发回。请更新 WRM
AI:Claude.ai / ChatGPT 订阅无法使用消费者聊天订阅无法供其他应用使用:请使用 API 密钥或公司网关,或通过 MCP 将聊天应用连接到 WRM(AI 桌面应用)
MCP:Claude Desktop 中没有 WRM 工具;claude_desktop_config.json 的 mcpServers 为空Claude Desktop 不会从该文件读取 HTTP 条目,而自定义连接器从 Anthropic 云端连接,无法访问你网络上的 WRM。请改为安装 WRM PRO 扩展(Settings → AI connections → Claude Desktop);扩展列在 Claude → Settings → Extensions 下,不在 mcpServers 中
Claude Code:添加 WRM 后显示 claude.ai connectors are disabled because ANTHROPIC_API_KEY or another auth source is set这不是 WRM 导致的:WRM 插件、claude mcp add 和设置脚本只会在 MCP 服务自身的 Authorization 标头中传递 WRM 令牌,绝不会设置 Claude 的登录信息。计算机上的某些设置定义了 ANTHROPIC_API_KEY、ANTHROPIC_AUTH_TOKEN、CLAUDE_CODE_OAUTH_TOKEN 或 apiKeyHelper(Claude Code 中的 /status 会显示身份验证来源)。请从环境变量中移除它(Windows:[Environment]::SetEnvironmentVariable('ANTHROPIC_API_KEY', $null, 'User')),并从 ~/.claude/settings.json 的 env / apiKeyHelper 中移除,然后重启终端和 Claude
MCP:AI 连接通过 * 设置为自动运行,但仍显示 The user denied this action 或 Not run在 v12.6.1 之前,长会话超过时间限制后会回退为询问;包含变量的命令即使设置了 * 也会询问。如果应用拒绝了该询问,命令就会被拒绝。请升级、编辑 AI 连接并按 Allow everything(不限制时间或操作)。现在拒绝消息会指出触发询问的规则
MCP:Not run yet … WRM keeps the request open没有人及时批准,或应用拒绝了该询问。请在 WRM 中(或实时面板中)批准卡片,然后让 AI 继续:它会重复调用,并且只会运行一次
MCP:设置中没有 AI connections 标签页MCP 已关闭(ai_mcp_enabled);如果策略 ai_mcp 不包含你,或终止开关已开启,该标签页会说明原因
MCP:claude.ai / ChatGPT 无法连接(couldn't reach the server、超时)托管连接器从提供方的云端连接:WRM 必须通过具有受信任证书的 HTTPS 从互联网访问。使用反向代理时,请透传 /mcp、/oauth/ 和 /.well-known/,关闭 /mcp(服务器发送事件)的响应缓冲,并设置 ai_mcp_public_url
MCP:the redirect URI … is not allowed应用的 OAuth 回调未列入 ai_mcp_redirect_uris;请管理员将其添加(Admin panel → AI connections)
MCP:HTTP 401 the token has expired / was revoked创建新令牌,或让应用重新连接(OAuth);令牌有效期为 ai_mcp_token_hours(最长为 ai_mcp_max_token_hours)
MCP:HTTP 403 origin not allowed使用其他来源的浏览器客户端:请将其添加到 ai_mcp_allowed_origins
MCP:更改被 Denied by WRM … run_readonly 拒绝AI 连接没有 run_with_approval 作用域;如果策略允许,请创建包含该作用域的连接
MCP:应用一直等待,没有任何反应有待处理的批准请求:请在 WRM 中(或应用中)对卡片作出回应;未回应的批准请求会在 ai_approval_timeout_seconds 后被拒绝
MCP:决定时显示“already approved / denied”有人(你在 AI 应用中,或在另一个 WRM 标签页中)已先行决定;消息会说明决定者和位置。“The AI stopped waiting”:请让 AI 重复调用
MCP stdio 桥接:certificate signed by unknown authority启动桥接时使用 -ca-file 指定 WRM 证书或你的 CA(PEM)
HOST KEY VERIFICATION FAILED服务器的 SSH 密钥已更改。如果你知道原因(例如重新安装),请在终端中点击 Trust this key(连接所有者/管理员),或在 Admin → Host keys 中忘记该主机
Microphone requires HTTPS / 没有麦克风请使用 HTTPS(证书、反向代理或 HTTPS_SELF_SIGNED=1)并在浏览器中允许使用麦克风;你也可以作为听众加入
语音:一直显示 Connecting… 或 Connection problem在 WRM 服务器上开放 UDP+TCP 3478 端口和中继端口范围;在 NAT 后,请设置 turn_public_ip 并转发这些端口;在限制严格的网络中,请添加 443/TLS 上的 TURN 服务器(Admin → Voice & network)
环境部署:the server or the repository changed since the plan was reviewed比较和部署之间有内容发生变化(服务器上的文件、另一次部署或新目标)。请重新比较、检查新计划并部署
环境部署:locked by … from …另一次部署占用了该目标位置的锁。请等待其完成;超过 max(30 min, 传输超时时间) 的锁属于 stale,计划会提供移除选项——只有在该位置没有部署正在运行时才移除
环境回滚显示 incomplete回滚涉及的服务器上某个文件或目录是符号链接,因此已跳过。请修复服务器(替换符号链接),然后再次回滚同一次部署
活动:the API rate limit was reached / 列表不完整Git 服务器限制每个令牌的 API 调用次数。请等待到所示时间,缩小日期范围或选择一个分支;结果会缓存 3 分钟
GitHub 上的活动显示提交记录,但没有推送记录令牌无法读取仓库活动信息(需要有读取仓库元数据的权限);提交记录仍会列出
Where:behind 显示 —无法读取分支头或比较结果(没有 API 来源、分支已不存在,或提交不在仓库中)
缺少注册标签页自助注册已关闭(默认)。管理员可以创建账户,或在 Security policies 中开放注册
服务无法启动 / -install-service 失败wrm -service-status;Linux:journalctl -u wrm;macOS / Windows / BSD:<data dir>/wrm-service.log。安装需要 root(sudo)或管理员权限(Windows)。服务设置位于 <data dir>/wrm.env
Update refused: … SHA256SUMS.txt …此版本没有校验和文件、没有此平台文件对应的条目,或下载文件与校验和不匹配。WRM 不会安装未经验证的文件;请等待完整版本发布,或手动替换二进制文件
WRM cannot write to the folder of its binary一键更新会在二进制文件所在目录写入内容。请为服务账户授予该目录的写入权限(启用了 ProtectSystem=strict 的 systemd 单元需要在 ReadWritePaths 中配置该目录),或手动更新
气隙网络中没有更新徽章这是预期情况:更新检查无法连接 GitHub。请使用 WRM_UPDATE_CHECK=off 关闭检查,或设置 update_proxy
📂 Open here:directory not found在服务器进程中未找到该 shell(非 OpenSSH 服务器、没有 /proc / ps),或无法读取其目录(例如 sudo -i 后的 root shell)。请让 shell 通过 OSC 7 报告目录(见 Windows、标签页和贴靠),或打开 home 或 /
管理员账户被锁定wrm -reset-password <user>(如有需要,添加 -reset-2fa)
Connection failed: unable to authenticate使用 Test connection 检查用户名/密码/密钥;对于 Key file/Auto,密钥必须存在于 WRM 服务器 上,且账户必须是管理员(或策略允许其操作)
没有 ● REC 徽章 / 没有录制内容Admin panel → Security policies → Session recording 已关闭,或被 WRM_SESSION_RECORDING / SESSION_RECORDING_ENABLED 强制关闭。请检查服务器日志中的 recording: 错误(例如录制文件夹不可写)
录制内容占用过多磁盘空间调低 recording_retention_days 或 recording_max_mb,或使用 WRM_RECORDINGS_DIR 移动录制内容
Verify integrity 报告链已损坏审计条目在 WRM 外部被更改或删除(直接在数据库中)。请从备份恢复数据库,并调查谁有权访问服务器
重启后已存储的密码无法使用加密密钥已更改(ENCRYPTION_KEY、ENCRYPTION_KEY_FILE 或数据库旁的 .key 文件)。请恢复原密钥,或重新输入密码
bastion cannot reach 10.0.0.21:22(或 jump host "…": …)跳板机无法连接到下一跳:请检查从跳板机上看到的主机:端口、防火墙,以及 sshd_config 中的 AllowTcpForwarding yes
隧道显示 🔴 Error / administratively prohibitedSSH 服务器拒绝转发(AllowTcpForwarding、PermitOpen,以及远程监听地址不是环回地址时的 GatewayPorts),或目标服务器无法从该服务器访问
启动隧道时显示 address already in useWRM 计算机上的另一个程序(或隧道)正在使用该端口。请选择其他端口,或将其留空(自动分配)
片段未显示在 ⚡ 选择器中片段的作用范围是一个文件夹或连接,与终端所在的不同。面板会显示所有片段(其他片段会变暗)
连接时运行未执行仅会运行适用于该连接且不包含 {{?…}} 提示的所有者片段;请检查审计日志中的 terminal.auto_run
书签未显示在 ★ 下方书签的作用范围属于另一个连接、文件夹或标签。在共享中,你只能看到所有者共享的书签(全局书签)
the directory … does not exist on this server书签路径(填入 {name}、{host}、$USER 后)在该服务器上不存在或不可读取。请编辑路径或缩小作用范围
广播危险命令前没有询问检查的是你在广播期间输入的内容,而不是从 shell 历史记录(↑)中调用的命令
所有连接都显示为灰色(没有状态点)实时状态已关闭(status_enabled),或连接未勾选 Monitor up/down status。第一轮检查会在 WRM 启动几秒后开始
服务器显示 🔴,但 SSH 正常连接中的端口与实际端口不同,或防火墙仅允许来自某些地址(不包括 WRM 服务器)的 SSH 连接。使用跳板机时,请使用跳板机而非直接连接
BMC:refused the login / the BMC user may not do this检查 BMC 用户和密码(或保管库凭据);执行电源操作需要 BMC 上的 Operator 或 Administrator 角色
BMC:not reachable管理网络通常只能从堡垒机访问:请在连接上设置跳板机并勾选 Through the jump host
IPMI:ipmitool is not installed在 WRM 服务器上运行 apt install ipmitool;如果通过跳板机访问 BMC,则在跳板机上运行。必须在 BMC 上启用 IPMI over LAN
串行控制台没有显示内容按 Enter。iDRAC:需要在 BIOS 中设置 Serial communication → Redirection;IPMI SOL:在 BMC 上启用 SOL,并在操作系统中启用串行控制台(console=ttyS1,115200)
串行端口:permission denied以属于 dialout 组的用户运行 WRM(或授予其设备访问权限)
没有 Install 按钮 / Install as an app 仅显示步骤或原因仅当浏览器支持立即安装时才会显示该按钮;否则,该行会显示适用于你浏览器的步骤(Chrome/Edge/Brave:地址栏中的图标或菜单;macOS 上的 Safari:File → Add to Dock;iPhone

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。