Files
50230616d5 refactor(runtime): retire Community image dependencies (#3386)
* feat(sandbox): default to official Alpine sandbox image

default_sandbox_image() now returns docker.io/library/alpine:3.22, a generic
version-qualified official image, so a fresh install no longer depends on the
community sandbox image catalog. All compute drivers (docker, podman,
kubernetes, vm) inherit this fallback.

Part of #3116.

Signed-off-by: Akram
Signed-off-by: Akram <akram.benaissi@gmail.com>

* feat(deploy): default deployment configs to the official Alpine sandbox image

Update the shared gateway default_image, Helm chart values, the standalone
Kubernetes manifest, and the dev gateway task scripts to use
docker.io/library/alpine:3.22 instead of the community base image, consistent
with default_sandbox_image(). GPU e2e image-build base is left unchanged (CUDA
needs a glibc base).

Part of #3116.

Signed-off-by: Akram
Signed-off-by: Akram <akram.benaissi@gmail.com>

* feat(driver): default to numeric non-root identity for USER-less images

With the default sandbox image now Alpine, images that declare no OCI USER
must start instead of being rejected. When the image declares no USER and
the policy requests none, the Podman and Docker drivers now supply a numeric
non-root identity (DEFAULT_SANDBOX_UID/GID = 1000) instead of rejecting,
matching the numeric-identity behavior of the Kubernetes and VM drivers. The
supervisor's resolved-identity path runs the sandbox as a synthesized
non-root account without the account existing in the image. Images that
declare a USER keep the OCI resolution path unchanged.

Part of #3116.

Signed-off-by: Akram <akram.benaissi@gmail.com>
Signed-off-by: Evan Lezar <elezar@nvidia.com>

* test(conformance): use Alpine workload image

Signed-off-by: Evan Lezar <elezar@nvidia.com>

* refactor(policy): drop community image /app path from default policy

The restrictive default policy granted read-only access to /app, a directory
that only existed in the community base image. A generic Alpine default has no
/app, so remove it. Landlock best-effort already ignores absent paths; this
just stops advertising a community-specific layout in the default.

Part of #3116.

Signed-off-by: Akram
Signed-off-by: Akram <akram.benaissi@gmail.com>

* docs(config): document Alpine default images

Signed-off-by: Evan Lezar <elezar@nvidia.com>

* fix(podman): report early sandbox termination

Signed-off-by: Evan Lezar <elezar@nvidia.com>

* fix(podman): initialize rootless workspace ownership

Signed-off-by: Evan Lezar <elezar@nvidia.com>

* fix(sandbox): qualify NVIDIA Ubuntu default

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(podman): initialize rootful default workspace

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* feat(sftp): add native sandbox adapter

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(sftp): gate runtime helper support to Linux

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(sftp): support standard OpenSSH file operations

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(sftp): harden rename and special file handling

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* refactor(runtime): remove community image dependencies

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* test(e2e): build provider readiness tool fixture

Signed-off-by: Drew Newberry <anewberry@nvidia.com>

* fix(e2e): use a dedicated Noble fixture for Docker tests

Signed-off-by: Evan Lezar <elezar@nvidia.com>

---------

Signed-off-by: Akram
Signed-off-by: Akram <akram.benaissi@gmail.com>
Signed-off-by: Evan Lezar <elezar@nvidia.com>
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
Co-authored-by: Evan Lezar <elezar@nvidia.com>
Co-authored-by: Drew Newberry <anewberry@nvidia.com>
2026-09-22 14:43:51 +02:00
..

openshell-driver-podman

The Podman compute driver runs inside the gateway and uses the native libpod REST API over a Unix socket. Each sandbox has two independent containers:

  • openshell-sandbox owns the agent process in the workload container.
  • openshell-supervisor evaluates policy, holds gateway credentials, and proxies approved egress in a separate companion container.

The driver provisions placement, identity, credentials, transport, and lifecycle. The shared isolation interface supplies exec, attach, signal, terminate, binary identity, DNS, TCP, and loopback-forwarding semantics.

Runtime posture

Property Workload Supervisor
UID/GID Pinned non-root workload identity Same mapped identity
Capabilities Drop all; add none Drop all; add none
Seccomp Runtime default plus sandbox-installed filters Runtime default
Network none; loopback only Podman host network
Gateway JWT and upstream credentials Never mounted Podman secrets
User volumes and CDI devices Workload only Never mounted
Channel Private named volume, writable Same volume, read-only

Podman creates the namespaces and volume ownership before the workload runs. Rootless operation uses the operator's Podman service and subordinate-ID configuration; it does not require adding capabilities to either container. The supervisor joins the workload's user namespace only to preserve UID/GID mapping for shared-volume access. PID, mount, and network namespaces remain separate. The channel volume uses shared SELinux relabeling (:z).

Before starting either container, the driver uploads volume-relative archives directly to the channel and workspace volume destinations. A rootfs upload on a stopped Podman container does not populate nested named volumes. Restart restores only the channel bootstrap into the existing channel volume, preserving the workspace. The workload starts before the supervisor so its user namespace exists when the supervisor joins it; a stopped supervisor resolves that namespace again on its next start.

The runtime must pass the sandbox's unprivileged enforcement probe, including nested seccomp notification and Landlock. Unsupported runtime defaults fail closed; do not switch to an unconfined profile or add capabilities.

Protected channel and network enforcement

agent -> openshell-sandbox === authenticated gRPC / private UDS === supervisor -> network
         network=none           TCP, DNS, control streams         policy + gateway JWT

The workload has no external interface or published port. Seccomp socket mediation carries TCP and DNS through one authenticated gRPC connection. DNS remains supervisor-mediated; general UDP is unsupported. The driver sets net.ipv4.ip_unprivileged_port_start=0 in the isolated workload network namespace so the sandbox's loopback DNS relay can bind port 53 without a capability. No nftables or nested network namespace setup runs in the sandbox.

The channel contains the sandbox bootstrap and sandbox-side TLS identity only. Supervisor private keys and the runtime descriptor stay in the supervisor's private filesystem. Landlock denies agent access to the top-level /.openshell control hierarchy. The driver verifies Podman's reported network=none fence before launch and restart. Host networking applies to the supervisor, not the agent.

Gateway sessions use the existing sandbox JWT and optional configured mTLS bundle. The sandbox/supervisor channel always uses its separate, per-sandbox mutual TLS material. These are distinct authentication relationships.

Identity and trusted binaries

Both workload and supervisor images are pinned by immutable image ID. The driver reads account files from a stopped workload-image container; it never executes the image to resolve an account. Policy identity fields override OCI USER independently. Named users/groups resolve against that image, including supplementary groups. Root and unresolved identities fail before provisioning. Images must not prepopulate the reserved /.openshell hierarchy; this prevents image-controlled symlinks from aliasing private control state into user mounts.

sandbox_runtime_image supplies the statically linked musl /openshell-sandbox binary. Podman's read-only image volume delivers it to the workload; user-namespace modes that cannot use image volumes retain the trusted binary extraction path. supervisor_image supplies the dynamically linked glibc /openshell-supervisor binary outside the workload. Image and request environment belong to agent children, never the supervisor process.

Lifecycle and readiness

Create builds both stopped containers and stages the private archives before starting either container. The sandbox does not execute the agent until the supervisor authenticates and confirms the common boundary contract. Failed creation removes only containers created by that attempt, then cleans up driver-owned volumes and secrets.

Stop retains both containers, workspace, channel, and secrets. Start restores the consumed sandbox bootstrap from a copy in the supervisor's private filesystem, verifies the fence, and starts the same pair. A failed supervisor start stops the workload. Delete removes the companion first, then the workload, channel, workspace, and driver-owned secrets. User-owned volumes are retained.

Only workload containers appear in sandbox list/watch results. Readiness uses the supervisor's private health socket; there is no shell, legacy marker, or TCP-listener shortcut. Watch reconciliation and supervisor exit/removal events stop a running workload whose companion is unavailable. The gateway also requires the authenticated supervisor session before publishing Ready.

Mounts, GPUs, and configuration

User bind, volume, tmpfs, and image mounts and CDI GPU selection remain native Podman features and apply only to the workload. Bind mounts require the operator's enable_bind_mounts opt-in. Reserved control paths and the workspace root cannot be replaced. User-owned volumes are never created or deleted.

See gateway configuration for operator settings and NETWORKING.md for supervisor networking. The supervisor uses Podman's host network and owns the upstream proxy settings. Omit health_check_interval_secs to disable Podman's periodic health command. Explicit zero is invalid. OpenShell still gates readiness on the supervisor's authenticated health signal.

Gateway OTLP configuration continues to export compute-driver spans under the openshell-driver-podman service, preserving gateway trace context.