diff --git a/docs/cli/fleet.md b/docs/cli/fleet.md index 50d22a83857d..6d54b980b9a1 100644 --- a/docs/cli/fleet.md +++ b/docs/cli/fleet.md @@ -10,7 +10,7 @@ title: "Fleet" `openclaw fleet` manages complete OpenClaw instances called **cells**. Each cell has its own Gateway, state, credentials, channel accounts, container, and loopback-only host port. Use one cell for each tenant trust boundary; do not use one shared Gateway as a hostile multi-tenant boundary. -Fleet is **experimental**. Command names, flags, output shapes, and the container profile can change between releases without a deprecation window while the surface settles. +Fleet is **experimental**. Command names, flags, output shapes, and the container profile can change between releases without a deprecation window. Fleet supports Docker and Podman. The default image is `ghcr.io/openclaw/openclaw:latest`. @@ -86,7 +86,7 @@ Automatic allocation selects the first unused registry port at or above `19100`. Image references are passed as one container-runtime argument. Empty references and values beginning with `-` are rejected so an image cannot be interpreted as a Docker or Podman option. -The selected Docker or Podman endpoint must be local. Fleet rejects remote Docker contexts, `DOCKER_HOST` endpoints, and remote Podman services before reserving a port or creating local state; remote cell hosts need a separate storage and endpoint contract and are deferred from this MVP. +The selected Docker or Podman endpoint must be local. Fleet rejects remote Docker contexts, `DOCKER_HOST` endpoints, and remote Podman services before reserving a port or creating local state. Remote cell hosts are not supported. When Fleet starts a new cell, create waits up to about a minute for its Gateway to answer `/healthz`. If the cell does not become healthy, Fleet leaves its container and registry row intact for `fleet status`, `fleet logs`, or explicit removal. `--no-start` skips this health gate. The generated Gateway token of an unhealthy new cell is not lost - it remains in the container environment (`docker|podman inspect`), and because the cell has served no traffic yet, `fleet rm --force` followed by a fresh create is always a safe alternative. diff --git a/docs/docs_map.md b/docs/docs_map.md index aa9d7dc05e09..cd589f231da9 100644 --- a/docs/docs_map.md +++ b/docs/docs_map.md @@ -3588,7 +3588,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`. - H2: Trust boundary - H2: Isolation ladder - H2: Quick start - - H2: Deferred from the MVP + - H2: Current scope - H2: Related ## gateway/multiple-gateways.md diff --git a/docs/gateway/multi-tenant-hosting.md b/docs/gateway/multi-tenant-hosting.md index 594dbaaf60bc..9c5ca35f5861 100644 --- a/docs/gateway/multi-tenant-hosting.md +++ b/docs/gateway/multi-tenant-hosting.md @@ -1,4 +1,5 @@ --- +doc-schema-version: 1 summary: "Host multiple tenant trust domains as one isolated OpenClaw Gateway cell per tenant" read_when: - You are hosting OpenClaw for multiple users or organizations @@ -12,7 +13,7 @@ OpenClaw's default security model is one trusted operator boundary per Gateway, `openclaw fleet` calls each isolated instance a **cell**. A cell is a full Gateway in a hardened container with its own state, credentials, workspace, channel accounts, token, and loopback-only host port. -Fleet is **experimental**: its commands, flags, and container profile can change between releases without a deprecation window while the surface settles. +Fleet is **experimental**: its commands, flags, and container profile can change between releases without a deprecation window. Fleet is tested on Linux and macOS hosts. Windows hosts are currently untested. @@ -24,11 +25,11 @@ Use one cell per tenant so each trust domain has a separate Gateway process, con ## Architecture -The Fleet CLI is a host-side lifecycle supervisor. It records cells in the OpenClaw state database and asks a local Docker or Podman runtime to create, inspect, start, stop, replace, and remove their containers. Remote runtime endpoints are rejected because Fleet's bind paths and loopback URLs belong to the local host; remote cell hosts are deferred until they have an explicit storage and endpoint contract. Fleet does not proxy tenant messages and does not add a shared application-level data path between cells. +The Fleet CLI is a host-side lifecycle supervisor. It records cells in the OpenClaw state database and asks a local Docker or Podman runtime to create, inspect, start, stop, replace, and remove their containers. Remote runtime endpoints are not supported because Fleet's bind paths and loopback URLs belong to the local host. Fleet does not proxy tenant messages and does not add a shared application-level data path between cells. Each cell runs the official `ghcr.io/openclaw/openclaw` image on its own user-defined bridge network. Separate bridges prevent direct container-IP traffic between cells while retaining outbound NAT access for providers and channels. Outbound egress is unrestricted by default. Podman cells can use `--network internal` to block egress while preserving the published loopback Gateway port. Docker internal networks break that published port, so Fleet rejects the combination; enforce Docker egress policy with host firewall rules such as the `DOCKER-USER` chain instead. The cell Gateway listens on port `18789` inside the container, while the runtime publishes it only to `127.0.0.1:` on the host. An operator can place an approved reverse proxy, SSH tunnel, or tailnet in front of that loopback endpoint when remote access is needed. -Persistent Gateway state comes from `/fleet/cells//` and is mounted at `/home/node/.openclaw`. Auth-profile encryption keys come from the separate `/fleet/auth-profile-secrets//` host path and are mounted at `/home/node/.config/openclaw`, matching the official [Docker persistence layout](/install/docker#storage-and-persistence). The key is not nested beneath the ordinary state mount. Per-tenant channel accounts terminate inside the cell that owns them, so there is no shared channel account or shared inbound message router in the Fleet MVP. +Persistent Gateway state comes from `/fleet/cells//` and is mounted at `/home/node/.openclaw`. Auth-profile encryption keys come from the separate `/fleet/auth-profile-secrets//` host path and are mounted at `/home/node/.config/openclaw`, matching the official [Docker persistence layout](/install/docker#storage-and-persistence). The key is not nested beneath the ordinary state mount. Per-tenant channel accounts terminate inside the cell that owns them; Fleet does not provide a shared channel account or inbound message router. The official image defaults to the non-root `node` user with UID 1000. Fleet uses host-compatible user mappings so private bind mounts stay writable: Podman uses `keep-id`, rootful Docker uses the invoking non-root identity, and rootless Docker maps container root to the unprivileged daemon user. Docker and Podman apply a private `:Z` relabel when host SELinux is active. The container profile avoids privileged host features and is rootless-friendly, but rootless operation is a host runtime choice and prerequisite, not something Fleet enables automatically. @@ -44,7 +45,7 @@ The baseline prevents accidental wildcard network exposure and removes common co Choose the boundary that matches the tenants you host: -1. **Hardened container baseline.** Fleet drops all Linux capabilities, enables `no-new-privileges`, applies PID, memory, CPU, and optional writable-layer disk limits, uses separate persistent mounts and per-cell networks, and publishes only to host loopback. Bridge networking leaves egress unrestricted; use Podman `--network internal` or Docker host firewall policy when a cell must not initiate outbound connections. This is the MVP profile for tenants that trust the operator and host. +1. **Hardened container baseline.** Fleet drops all Linux capabilities, enables `no-new-privileges`, applies PID, memory, CPU, and optional writable-layer disk limits, uses separate persistent mounts and per-cell networks, and publishes only to host loopback. Bridge networking leaves egress unrestricted; use Podman `--network internal` or Docker host firewall policy when a cell must not initiate outbound connections. This is the default profile for tenants that trust the operator and host. 2. **Stronger container or VM isolation.** For higher-risk workloads, configure Docker or Podman to use a stronger OCI isolation runtime such as gVisor or Kata Containers, or place cells in microVMs. This is runtime or infrastructure configuration; Fleet's `--runtime docker|podman` option chooses the container CLI, not the OCI isolation backend. See Docker's [alternative container runtimes](https://docs.docker.com/engine/daemon/alternative-runtimes/) and the [Docker VM runtime guide](/install/docker-vm-runtime). 3. **Separate machines for hostile tenants.** Do not co-locate hostile tenants in one OpenClaw process or OS user. When tenants do not trust the same host operator or need a stronger administrative boundary, use separate VMs or physical hosts with separate runtime administration. @@ -86,16 +87,16 @@ openclaw fleet rm acme --purge-data --force See the [`openclaw fleet` CLI reference](/cli/fleet) for every command and option. -## Deferred from the MVP +## Current scope -The first Fleet release deliberately leaves these surfaces to later designs: +Fleet does not provide these surfaces: - Shared channel accounts or a shared ingress router - Slimmed-down per-tenant host processes instead of complete OpenClaw instances - Remote cell hosts managed by one supervisor - A tenant self-service portal, billing plane, or delegated administration UI -These features need explicit identity, routing, authorization, and failure-domain contracts. They should not be approximated by sharing one Gateway or its credentials across tenants. They are also not Fleet's lane: Fleet stays a single-host lifecycle supervisor, and multi-machine, identity-governed fleets belong to a dedicated control-plane layer above it. +These capabilities need explicit identity, routing, authorization, and failure-domain contracts. Do not approximate them by sharing one Gateway or its credentials across tenants. Fleet is a single-host lifecycle supervisor; multi-machine, identity-governed fleets require a separate control-plane layer. ## Related