跳转至

openclaw fleet

openclaw fleet 管理称为 cell 的完整 OpenClaw 实例。每个 cell 拥有自己的 Gateway、状态、凭据、渠道账户、容器以及仅限回环的主机端口。为每个租户信任边界使用一个 cell;不要将一个共享 Gateway 用作对抗性多租户边界。

Fleet 处于实验性阶段。命令名称、标志、输出格式和容器配置可能在版本之间发生变化,且没有弃用窗口。

Fleet 支持 Docker 和 Podman。默认镜像为 ghcr.io/openclaw/openclaw:latest。

Fleet 已在 Linux 和 macOS 主机上测试。Windows 主机目前尚未测试。

Quick start

openclaw fleet create acme
openclaw fleet status acme
openclaw fleet list

fleet create 会连同 cell URL 一起仅打印一次生成的 Gateway Token。请立即保存该 Token,然后在该租户的 cell 内配置其渠道账户。

Tenant IDs

租户 ID 必须匹配:

^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$

这允许 1 到 40 个小写字母、数字和内部连字符。ID 必须以字母或数字开头和结尾。大写字母、下划线、斜杠、点、空白以及诸如 ../acme 的路径遍历字符串会被拒绝。

该 ID 会成为容器名称的一部分:openclaw-cell-<tenant>。

fleet create

创建一个 cell 并启动它:

openclaw fleet create acme

在固定端口上创建一个 Podman cell,而不启动它:

openclaw fleet create acme \
  --runtime podman \
  --port 19125 \
  --no-start

通过重复 --env 传递租户特定的环境变量:

openclaw fleet create acme \
  --env TZ=America/Los_Angeles \
  --env OPENCLAW_DISABLE_BONJOUR=1

环境变量键使用字母、数字和下划线,且不能以数字开头。值必须为单行,因为 Fleet 会通过受保护的运行时环境文件传递它们。Fleet 会拒绝尝试覆盖 存储和容器布局 中列出的受管容器路径和 Gateway Token 变量。

Fleet 在租户状态挂载上将 XDG_CACHE_HOME 默认设置为 /home/node/.openclaw/cache。显式的 --env XDG_CACHE_HOME=... 值在升级和恢复后仍然保留,包括等于当前默认值的值。

Create options

选项 默认值 描述
--image <ref> ghcr.io/openclaw/openclaw:latest 该 cell 的容器镜像。
--runtime <runtime> docker 容器 CLI:docker 或 podman。
--port <number> 从 19100 自动分配 回环主机端口。显式选择的端口不能属于另一个已注册的 cell。
--memory <value> 2g Docker/Podman 语法中的容器内存限制。
--cpus <value> 2 容器 CPU 限制。
--disk <size> 无 当存储后端支持配额时,限制容器可写层。
--network <mode> bridge 出站网络模式:bridge 或 internal。
--pids-limit <number> 512 容器中的最大进程数。
--env <KEY=VALUE> 无 向 cell 传递一个环境变量。多个值时重复使用。
--gateway-token <value> 随机 32 位十六进制 Token 使用提供的 Gateway Token 而不是生成一个。参见 Token 处理。
--no-start 启动 cell 创建容器但不启动它。
--json 人类可读输出 打印机器可读输出。

自动分配会选择 19100 及以上的第一个未使用的注册表端口。Fleet 会拒绝重复的租户 ID 以及已分配给另一个 cell 的显式端口。

镜像引用作为单个容器运行时参数传递。空引用和以 - 开头的值会被拒绝,以免镜像被解释为 Docker 或 Podman 选项。

所选的 Docker 或 Podman 端点必须是本地的。Fleet 会在保留端口或创建本地状态之前拒绝远程 Docker 上下文、DOCKER_HOST 端点和远程 Podman 服务。不支持远程 cell 主机。

当 Fleet 启动新 cell 时,create 会等待最多约一分钟,直到其 Gateway 响应 /healthz。如果 cell 未变为健康状态,Fleet 会保留其容器和注册表行,以便使用 fleet status、fleet logs 或显式删除。--no-start 会跳过此健康检查关卡。不健康的新 cell 生成的 Gateway Token 不会丢失——它仍保留在容器环境中(docker|podman inspect),并且由于该 cell 尚未处理任何流量,先执行 fleet rm --force 再重新创建始终是一种安全的替代方案。

Pinning by digest

Create 和 upgrade 接受通过摘要固定的镜像引用,例如 --image ghcr.io/openclaw/openclaw@sha256:<digest>。Fleet 会将镜像引用原样传递给 Docker 或 Podman,这使得操作员可以让 cell 使用不可变的镜像字节,而不是使用会变化的标签。

创建结果包含租户 ID、容器名称、主机端口、Gateway token 和本地 URL。即使在 JSON 输出中,也应将其视为包含机密信息,因为它包含 token。

磁盘限制

--disk 仅限制容器可写层。通过绑定挂载的按租户状态目录和认证目录仍保留在主机存储中;如果这些目录也需要硬性限制,请使用主机文件系统的项目配额。

运行时/存储后端 --disk 支持
XFS 上的 Docker overlay2 需要 XFS pquota 挂载选项。
Docker btrfs 或 zfs 由存储驱动支持。
Podman overlay 需要 XFS 后备存储。
其他后端 容器创建会失败,并显示守护进程错误以及 Fleet 的后端指导。

出口策略

模式 Docker Podman
bridge 支持;默认情况下出站出口不受限制。 支持;默认情况下出站出口不受限制。
internal 被拒绝,因为 Docker 不会在内部网络上保留已发布的回环 Gateway 端口。 支持;回环 Gateway 保持发布,同时出站出口被阻止。

对于 Docker,请保持 bridge 模式,并使用主机防火墙规则(例如 DOCKER-USER 链)来强制出站策略。

fleet list

按租户 ID 顺序列出单元:

openclaw fleet list
openclaw fleet ls
openclaw fleet list --json

表格包含:

列 含义
tenant 租户 ID。
state 来自 Docker 或 Podman 检查的实时容器状态。unknown 表示运行时不可用,或者存在一个与单元名称相同的容器,但其 Fleet 所有权标签与注册表记录不匹配(这是冲突或篡改信号——在操作前请手动检查)。
port 映射到单元 Gateway 的回环主机端口。
image 记录的容器镜像。
created 单元创建时间。

当 Docker 或 Podman 不可用时,注册表行仍保持可见;只有实时状态会变为 unknown。

fleet status

检查一个单元:

openclaw fleet status acme
openclaw fleet status acme --json

人类可读状态包含来自单元记录运行时的 Runtime: docker 或 Runtime: podman。这标识为单元选择的容器引擎,而不是该引擎当前是否可用。JSON 输出保留现有的 runtime 字段。

状态会组合 fleet 注册表行、实时容器检查,以及一次简短的尽力而为请求,目标为:

http://127.0.0.1:<host-port>/healthz

健康结果为 ok、failed 或 skipped。/healthz 证明 Gateway 存活,而不是所有已配置通道或插件的完全就绪。当没有可用的本地端点可检查时,探测会被跳过。

fleet logs

将单元的容器日志直接流式输出到终端:

openclaw fleet logs acme
openclaw fleet logs acme --follow
openclaw fleet logs acme --timestamps
openclaw fleet logs acme --tail 200
openclaw fleet logs acme --since 10m

Fleet 在读取任何日志之前会验证已注册容器的所有权标签,因此它会拒绝使用预期单元名称的外部容器。流会固定到该被检查的容器 ID,因此并发替换无法将其重定向到更新的代际。按 Ctrl-C 可结束 --follow,而不会将操作员停止视为命令失败。日志输出会经过脱敏过滤器,在到达终端之前将单元当前的 Gateway token 替换为 <redacted>。

使用 --timestamps 可在原始流中包含 Docker 或 Podman 时间戳。它可以与 --follow、--tail 和 --since 组合使用。

fleet logs 没有 --json 模式,因为容器日志是原始 stdout/stderr 流。对于脚本,请使用 --tail 限制输出,并使用普通 shell 重定向或管道。

fleet start、fleet stop 和 fleet restart

使用已记录的运行时控制现有 cell:

openclaw fleet start acme
openclaw fleet stop acme
openclaw fleet restart acme

这些命令会解析已注册的容器名称,验证所有权,并针对该已检查容器的 ID 执行操作。如果租户未知,或已记录的运行时无法执行该操作,则命令会失败。

fleet upgrade

重新拉取已记录的镜像并替换 cell 容器:

openclaw fleet upgrade acme

将 cell 迁移到另一个镜像:

openclaw fleet upgrade acme --image ghcr.io/openclaw/openclaw:<version>

升级会拉取目标镜像,检查现有容器和每个 cell 的网络,停止并删除容器,然后重新创建并启动它。替换会保留相同的主机端口、数据目录、每个 cell 的桥接网络、运行时配置、资源限制、重启策略、Fleet 管理的环境变量,以及最初通过 --env 提供的值。挂载的状态在容器替换后仍然保留;镜像默认环境变量可能会随目标镜像而变化。

替换只有在 Gateway 在 cell 的环回端口上响应 /healthz 后才会提交,这与官方 compose 文件使用的健康检查约定一致。如果替换容器退出、陷入崩溃循环,或大约一分钟内未能变为健康状态,则会被删除,并恢复之前的容器,因此损坏的镜像不会导致正在运行的 cell 停止工作。

Gateway Token 有意不存储在 Fleet 注册表中。在删除旧容器之前,Fleet 会读取其环境变量,并将 OPENCLAW_GATEWAY_TOKEN 带入替换容器。如果该 Token 不存在于你控制的任何其他位置,请勿在升级前手动删除旧容器。

fleet backup 和 fleet restore

备份一个已停止的 cell:

openclaw fleet stop acme
openclaw fleet backup acme --out ./acme.tgz

将该归档恢复到已注册的 cell:

openclaw fleet restore acme --from ./acme.tgz

这些是主机操作员特权命令。归档包含租户状态和身份验证密钥,创建时权限为 0600,必须像凭据一样存储。备份会拒绝正在运行的 cell,以便一致地捕获 SQLite 状态。恢复会拒绝正在运行的 cell,除非提供 --force;它只替换该租户的状态,轮换 Gateway Token,并只打印一次新 Token。Fleet 一次备份一个租户;所有租户的备份是单独的操作员操作。

恢复需要一个已停止的现有容器,因为其已检查的运行时配置会提供替换容器的限制、用户映射、环境变量来源和镜像。如果已注册的容器已被带外删除,请先运行 fleet rm <tenant> --force(不带 --purge-data),使用预期镜像和 --no-start 重新创建 cell,然后重试恢复。首次删除会保持两个租户数据目录完整。

两个命令都接受 --max-bytes <bytes> 以限制归档或提取的文件数据,并且两者都应用相同的固定一百万归档路径段预算,因此仅包含元数据的归档炸弹无法耗尽主机 inode,并且每个被接受的备份都保持可恢复。备份接受 --out <path>,两个命令都支持 --json。

归档只包含常规文件和目录。备份从不跟踪或存储符号链接、硬链接、套接字或设备节点;跳过的数量会在结果中报告。恢复会拒绝包含任何其他条目类型的归档,忽略归档中的所有权,并在应用 cell 运行时所有者之前限制恢复的文件和目录权限。可重建的符号链接树(例如工作区中的 node_modules)必须在恢复后在 cell 内重新安装。

fleet doctor

审计所有 cell 或一个租户,而不更改运行时或文件系统状态:

openclaw fleet doctor
openclaw fleet doctor acme --json

Doctor 会检查运行时本地性、所有权标签、健康状态、加固、资源限制、环回端口绑定、Token 是否存在、网络所有权和出口模式,以及私有状态目录权限。警告会描述已停止的 cell 或所有权差异;任何失败的检查项都会设置非零进程退出码。

fleet rm

从运行时和注册表中移除一个已停止的 cell,同时保留租户数据:

openclaw fleet rm acme

正在运行的容器需要 --force:

openclaw fleet rm acme --force

同时永久删除 cell 数据:

openclaw fleet rm acme --purge-data --force

Fleet 在删除其专用桥接网络之前会删除 cell 容器。--purge-data 需要 --force。在递归删除之前,Fleet 会解析两个 Fleet 拥有的根目录和两个每租户目录。每个目标必须是确切的预期租户叶目录,严格位于其根目录内,并且不是符号链接。这些包含检查可防止损坏的注册表路径或跨租户符号链接将删除重定向到其他位置。

当确切的预期租户目录已经不存在时,清除可以重试。这允许后续调用在部分文件系统故障后完成清理,而不会放宽对仍然存在的目录的路径检查。

存储和容器布局

cell 状态和旧版身份验证配置加密密钥在活动的 OpenClaw 状态目录下使用独立的每租户主机路径:

<state-dir>/fleet/cells/<tenant>/
<state-dir>/fleet/auth-profile-secrets/<tenant>/

第一个目录挂载到 /home/node/.openclaw。第二个目录挂载到 /home/node/.config/openclaw,与官方 Docker 配置中旧版 OAuth 迁移密钥的挂载一致。这两个目录在正常删除和升级后都会保留;fleet rm --purge-data --force 会在分别进行包含检查后删除这两个目录。

当前 OAuth Token 材料以明文形式存储在普通状态挂载下的 SQLite 中,包括访问、刷新和 ID Token 值。单独的密钥可以恢复旧版加密的 sidecar 凭据;它不会加密当前的 SQLite 行,也不会保护它们免受仅状态备份或副本的影响。请将 cell 状态备份和共享副本视为凭据,因为它们可能包含可用的 OAuth 材料。

在首次启动前,Fleet 使用 gateway.mode=local、token 认证、LAN 容器绑定以及针对分配的主机端口的 Control UI origins 初始化单元配置。token 值不会写入该配置;它保留在容器环境中。

Fleet 使用以下环境变量值固定官方镜像的容器路径:

变量 容器值
HOME /home/node
OPENCLAW_HOME /home/node
OPENCLAW_STATE_DIR /home/node/.openclaw
OPENCLAW_CONFIG_PATH /home/node/.openclaw/openclaw.json
OPENCLAW_WORKSPACE_DIR /home/node/.openclaw/workspace
XDG_CACHE_HOME /home/node/.openclaw/cache
OPENCLAW_GATEWAY_TOKEN 生成或提供的单元 token

XDG_CACHE_HOME 是此表中唯一可覆盖的生成默认值。其他列出的容器路径变量和 OPENCLAW_GATEWAY_TOKEN 仍由 Fleet 管理。

官方镜像默认使用非 root 的 node 用户,UID 为 1000。Fleet 保持私有 0700 绑定挂载可写,而不使其全局可访问。rootful Docker 以调用方的非 root UID 和 GID 运行单元;rootless Docker 使用容器 UID 0,它映射到守护进程用户命名空间内调用方的非特权主机用户。Podman 使用 keep-id 以及调用方的 UID 和 GID。当 Fleet 本身以 root 身份在 rootful 运行时上运行时,它会保留镜像用户,并将初始挂载文件分配给 UID/GID 1000。

在 SELinux 主机上,Docker 和 Podman 挂载会接收私有的 :Z 重标记。如果你恢复或迁移单元数据,请确保绑定挂载路径对有效容器用户可写。该配置支持 rootless,但主机上的 Docker 或 Podman 必须已配置为 rootless 运行;Fleet 不会将 rootful 守护进程转换为 rootless 守护进程。

安全配置

Fleet 对每个单元应用以下配置:

控制项 应用配置 原因
Linux capabilities --cap-drop=ALL Gateway 是 Node.js 进程,无需添加 Linux capabilities。
权限提升 --security-opt no-new-privileges 防止进程通过 setuid 或 setgid 二进制文件获取权限。
初始化进程 --init 回收后代进程并转发容器生命周期信号。
进程限制 --pids-limit 512 默认 限制 fork 和进程耗尽。
内存限制 --memory 2g 默认 限制单元内存使用。
CPU 限制 --cpus 2 默认 限制单元 CPU 使用。
可写层磁盘 可选 --disk 当运行时存储后端支持配额时,限制容器层。
重启策略 --restart unless-stopped 重启失败的单元,而不覆盖有意停止。
主机发布 127.0.0.1:<host-port>:18789 仅 使 Gateway 不暴露在通配符主机接口上。
单元网络 每个单元一个 bridge 或 Podman 内部网络 隔离容器 IP 流量,并可选择阻止 Podman 出站流量。
容器身份 与主机匹配的用户映射 保持私有绑定挂载可写,而不授予全局访问权限。
持久状态 每单元挂载;无共享状态挂载 将租户配置、凭据、会话和工作区保留在该租户的数据树中。
容器命令 node dist/index.js gateway --bind lan --port 18789 监听容器网络,以便仅回环的主机端口映射能够访问它。

Fleet 从不挂载 /var/run/docker.sock,不使用 --privileged 或主机网络,也不添加 capabilities。每个单元的 bridge 是跨单元隔离边界,而不是出站防火墙:单元保留提供商和通道所需的网络出站访问。使用代理、SSH 隧道或符合你部署的 tailnet 配置来前置回环端口。http://127.0.0.1:<port> 只能从 Fleet 主机直接访问。

该配置可隔离租户容器,但不能保护租户免受 Fleet 操作员、容器运行时管理员或已失陷主机的影响。有关完整的信任模型和更强的隔离选项,请参阅 多租户托管。

Token 处理

默认情况下,fleet create 会生成一个密码学随机的 32 位十六进制 Gateway token,并在创建结果中打印一次。请将其存储在你批准的密钥管理器中,并避免在日志中捕获创建输出。

--gateway-token 会将自定义 token 放入本地进程参数中,这些参数可能保留在 shell 历史中或在进程列表中可见。除非现有密钥管理工作流要求提供值,否则优先使用生成的 token。

token 以及通过 --env 传递的每个值都存在于容器环境中。Fleet 会将它们写入一个短生命周期的 mode-0600 环境文件,仅将该文件的路径传递给 Docker 或 Podman,并在运行时命令结束后删除它。在 openclaw fleet create --gateway-token ... 或 --env KEY=VALUE 中显式输入的值仍可能在外层 openclaw 进程参数和 shell 历史中可见。

容器环境变量不会向受信任的主机操作员隐藏:Docker 或 Podman 管理员可以通过容器检查读取它们。Fleet 的“仅显示一次”说明描述的是常规 CLI 输出,而不是对主机管理员的防护。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw