跳到正文
FunCoding

搜索

搜索文档、文章、Skill 和 MCP

SSH backend

Sandboxing tools on an arbitrary SSH-accessible machine, and its remote-canonical workspace

The remote utility contract, authentication material, and the remote-canonical workspace this backend seeds once.

SSH backend

Use backend: "ssh" to sandbox exec, file tools, and media reads on an arbitrary SSH-accessible machine.

The remote environment must provide /bin/sh, python3, and GNU-compatible stat (-c) and readlink (-f, -n) for the filesystem bridge. These utilities must be available to the non-interactive SSH command, not just an interactive login shell. The Gateway host does not need these remote utilities: a macOS or Windows Gateway can use an SSH target that supplies them. This is a remote utility contract, not a Linux-only Gateway requirement.

Canonical workspace and parent-directory paths retain their whitespace, including embedded and trailing newlines, during remote reads and writes. Remove and rename operations follow in-mount parent-directory aliases while acting on the final entry itself. Removing a final symlink leaves its target intact; parents that resolve outside the allowed mounts are rejected.

New remote workspaces are uploaded into a private staging directory before publication. When supported, fs-safe publishes with atomic no-replace directory rename: renameat2 on Linux or renameatx_np on macOS.

On Linux filesystems that reject RENAME_NOREPLACE, including gVisor volume mounts, fs-safe checks that the destination is absent and falls back to directory rename. This never exposes an empty claim as a completed workspace. Targets present at the check are preserved, and file or nonempty-directory competitors cannot be replaced. An empty directory created after that check can be replaced. macOS still requires its native no-replace primitive. Existing remote workspaces continue to be adopted without reseeding.

{
  agents: {
    defaults: {
      sandbox: {
        mode: "all",
        backend: "ssh",
        scope: "session",
        workspaceAccess: "rw",
        ssh: {
          target: "user@gateway-host:22",
          workspaceRoot: "/tmp/openclaw-sandboxes",
          strictHostKeyChecking: true,
          updateHostKeys: true,
          identityFile: "~/.ssh/id_ed25519",
          certificateFile: "~/.ssh/id_ed25519-cert.pub",
          knownHostsFile: "~/.ssh/known_hosts",
          // Or use SecretRefs / inline contents instead of local files:
          // identityData: { source: "env", provider: "default", id: "SSH_IDENTITY" },
          // certificateData: { source: "env", provider: "default", id: "SSH_CERTIFICATE" },
          // knownHostsData: { source: "env", provider: "default", id: "SSH_KNOWN_HOSTS" },
        },
      },
    },
  },
}

Defaults: command: "ssh", workspaceRoot: "/tmp/openclaw-sandboxes", strictHostKeyChecking: true, updateHostKeys: true.

  • Lifecycle: OpenClaw creates a per-scope remote root under sandbox.ssh.workspaceRoot. On first use after create or recreate, it seeds that remote workspace from the local workspace once. After that, exec, read, write, edit, apply_patch, prompt media reads, and inbound media staging run directly against the remote workspace over SSH. OpenClaw does not sync remote changes back to the local workspace automatically.
  • Authentication material: identityFile/certificateFile/knownHostsFile reference existing local files. identityData/certificateData/knownHostsData accept inline strings or SecretRefs, resolved through the normal secrets runtime snapshot, written to temp files with mode 0600, and deleted when the SSH session ends. If both a *File and *Data variant are set for the same item, *Data wins for that session.
  • Remote-canonical consequences: the remote SSH workspace becomes the real sandbox state after the initial seed. Host-local edits made outside OpenClaw after the seed step are not visible remotely until you recreate the sandbox. openclaw sandbox recreate deletes the per-scope remote root and seeds again from local on next use. Browser sandboxing is not supported on this backend, and sandbox.docker.* settings do not apply to it.