Skip to main content

OpenSandbox

OpenSandbox is AstraBox's built-in sandbox service. An RuntimeProfile tells AstraBox which sandbox image, network access, and lifecycle options an Agent uses. When a Session starts, AstraBox creates or claims an OpenSandbox sandbox, runs the Agent program in /workspace, and keeps the conversation and other product records outside the sandbox.

OpenSandbox provides the sandbox lifecycle, command execution, file access, and service endpoints. Because the Agent runs in deployment-owned infrastructure, it can continue working after the developer's computer disconnects. Users can return through the console, API, or a configured integration.

Choose a deployment​

DeploymentBest forWhere sandboxes run
Bundled DockerEvaluation, development, and one trusted hostSeparate containers on the AstraBox host
KubernetesMultiple nodes, prewarmed capacity, snapshots, and cluster controlsPods managed by the OpenSandbox controller
Existing OpenSandbox serviceOrganizations that operate sandbox infrastructure separatelyThe Docker or Kubernetes runtime configured for that service

The maintained Compose deployment uses bundled Docker. See Deploy AstraBox for the single-host setup and the data that must be backed up.

OpenSandbox also maintains its own server and Kubernetes deployment guides. AstraBox uses the OpenSandbox Lifecycle API and does not replace the controller, container runtime, or cluster network described there.

Run sandboxes on Kubernetes​

Install the OpenSandbox controller and CRDs, then create the namespace where sandbox Pods will run. AstraBox checks that the namespace, selected workload CRD, Kubernetes API access, and required permissions are available; it does not create cluster-scoped resources or namespaces.

The maintained Compose overlay runs AstraBox outside the cluster and creates sandbox Pods inside it. Copy a kubeconfig to a location readable by the container, then provide addresses that are valid from both networks:

sudo install -o 999 -g 999 -m 600 "$HOME/.kube/config" \
"$HOME/astrabox-kubeconfig"

export ASTRABOX_KUBECONFIG_HOST_PATH="$HOME/astrabox-kubeconfig"
export ASTRABOX_SANDBOX_SERVER_KUBE_API_SERVER=https://10.0.1.7:6443
export ASTRABOX_SERVER_BIND_IP=10.0.1.7
export ASTRABOX_MCP_PROXY_BASE_URL=http://10.0.1.7:8088
export ASTRABOX_ALLOWED_HOSTS=10.0.1.7
export ASTRABOX_LITELLM_BASE_URL=https://llm.example.com

scripts/compose.sh -f containers/compose.kubernetes.yaml up -d

The addresses serve different paths:

  • AstraBox must reach the Kubernetes API address, and its TLS certificate must cover that address.
  • Sandbox Pods must reach the AstraBox callback address and the model gateway.
  • Browsers must use a hostname included in ASTRABOX_ALLOWED_HOSTS.

The tested workload type is batchsandbox, backed by batchsandboxes.sandbox.opensandbox.io. An installation that uses the Agent Sandbox CRD can set ASTRABOX_SANDBOX_SERVER_KUBE_WORKLOAD_PROVIDER=agent-sandbox instead.

Publish every selected sandbox image to a registry available to the cluster. Use immutable image tags or digests so new and prewarmed Pods start with the same software. Clusters that add nodes on demand may also need a longer ASTRABOX_SANDBOX_SERVER_KUBE_CREATE_TIMEOUT_SECONDS for node startup and image pulls.

Connect an existing OpenSandbox service​

Set the Lifecycle API address and its named API key in the AstraBox server process environment:

ASTRABOX_SANDBOX_OPENAPI_BASE_URL=https://sandbox-control.example.com
ASTRABOX_SANDBOX_API_KEY_SECRET_NAME=opensandbox-api-key
OPENSANDBOX_API_KEY=REPLACE_WITH_LIFECYCLE_API_KEY

The secret provider reads process environment, not the product's encrypted Vault. It uppercases the reference name and replaces hyphens with underscores. For a container deployment, explicitly inject these settings into the server container; exporting them on the host alone does not add them to the bundled Compose files. The platform-replica recipe includes that environment-file configuration for an external Kubernetes-backed service.

AstraBox must be able to reach both the Lifecycle API and the sandbox endpoints returned by that API. Require OpenSandbox API-key authentication whenever the service is exposed beyond a trusted loopback network. The bundled lifecycle service listens only inside the AstraBox container and does not need a second public endpoint.

Persistent workspaces (ASTRABOX_SANDBOX_WORKSPACE_VOLUME) with an existing service require its Kubernetes runtime. OpenSandbox's Docker runtime mounts a volume sub-path by binding that directory under the volume's Docker mount point, and a workspace view volume is mounted there only while a container uses it by name, so every sandbox would receive an empty /workspace. The bundled lifecycle service has Docker mount the sub-path instead (see Docker requirements); a service started from upstream's opensandbox-server does not. The Lifecycle API does not report which runtime a service uses (/health and /version carry no runtime), so AstraBox cannot refuse the combination at startup. Each conversation fails instead when its sandbox is created or starts: with the service on the AstraBox host, with workspace ... is not a mergerfs view.

Prepare sandbox images​

Each sandbox image contains the Agent program, system packages, accounts, and background services needed by every Session that uses it. Bundled images use /workspace as the Session workspace.

Add common software to a custom image based on the corresponding bundled image, then select that image under Sandbox image or template in Management console → RuntimeProfiles. Do not depend on a per-Session setup script: a prewarmed sandbox can exist before the Session that claims it.

The OpenSandbox provider serves AstraBox's sandbox contract with the execd that OpenSandbox starts in every sandbox: files, commands, and long-lived processes such as the terminal's shell and the Pi program go to execd, and endpoints come from OpenSandbox's endpoint API. The bundled images require AIO because their boot and workload-account lifecycle ends in /opt/gem/run.sh; a custom base image needs an equivalent lifecycle and a matching entrypoint.

The Container Reference describes the image and workspace layout. The deployment selects CPU and memory limits and scheduling requests through ASTRABOX_SANDBOX_* for conversation-owned boxes, ASTRABOX_SHARED_SANDBOX_* for Agent-shared boxes, and ASTRABOX_ASSISTANT_SANDBOX_* for Assistant workspace boxes. See the defaults in Configuration. Each kind uses its one recipe for cold, prepared, and replacement creation; these are not RuntimeProfile fields. The provider-fitted limits and requests are part of an Agent's prepared generation, so a resource change retires unclaimed capacity without resizing Session-owned boxes. When the bundled lifecycle server runs sandboxes on this host's Docker, the CPU limit is lowered to the host's CPU count, because Docker refuses a limit above it; on Kubernetes, and with an existing OpenSandbox service, the recipe is sent as is. Disk, GPU access, and cluster admission remain OpenSandbox deployment concerns.

Use prewarmed capacity​

Enable prewarming on an Agent to keep its complete runtime ready before a user starts a conversation. Both tenancy modes use OpenSandbox's official SDK client pool for creation, coordination, replenishment, retries, and atomic acquisition. With Agent tenancy, a claimed box becomes the Agent's shared placement and keeps its root, with isolated directories for each conversation. With conversation tenancy, the claiming Session owns the whole box; if persistent storage is configured, the platform binds its workspace view to the new or existing Session directory before activating the prepared runtime. Neither mode changes a running Session's workspace. Multi-process or multi-machine deployments use ASTRABOX_AGENT_PREWARM_REDIS_URL for the SDK client pool's shared state.

Both modes prepare the engine before reporting available capacity, and claiming activates that prepared runtime. For conversation tenancy, preparation runs in the SDK's pre-publication callback; its transient receipt stays in the box's private home, outside Workspace. Shared tenancy prepares an isolated engine slot in its resident box. Neither receipt is the durable SessionStore.

Changing a conversation-tenancy Agent's startup configuration replaces its unclaimed pool inventory. Already claimed boxes remain with their Sessions. For shared tenancy, injectable configuration changes replace the waiting engine slot without replacing the resident box.

The platform chooses the Agent version, persistent workspace mount, credentials, and startup requirements. OpenSandbox supplies sandbox lifecycle and pool machinery; it does not participate in AstraBox's user/session workflow.

A RuntimeProfile can give each conversation a separate sandbox or let one Agent's conversations share a sandbox. Shared-sandbox mode still gives each conversation its own Linux user and workspace, but the conversations share a container and network namespace. It therefore requires the advanced sandbox permission level and an OpenSandbox deployment configured for isolated sessions.

Every bundled Agent program runs each conversation under its own account in shared-sandbox mode. AstraBox refuses a claimed sandbox that cannot attest isolated-session support; it does not fall back to unisolated execution.

Pause and resume sandboxes​

A RuntimeProfile can pause an idle sandbox instead of terminating it when the OpenSandbox deployment supports snapshots. Pause commits the sandbox root filesystem to an OCI image and releases its compute. Resume keeps the sandbox ID and restores the files, but starts new processes; ordinary process memory is not restored.

The supported Kubernetes path requires:

  • the OpenSandbox snapshot controller and image committer;
  • access to the containerd socket used by sandbox Pods;
  • an OCI registry reachable for snapshot push and pull; and
  • registry credentials in the sandbox namespace when the registry is private.

Verify the complete write, pause, resume, and read path before enabling pause for production RuntimeProfiles:

astrabox verify-opensandbox-snapshots

For Linux overlayfs nodes, the optional snapshot differ avoids scanning unchanged parent image files when creating snapshots.

Apply a retention policy to the snapshot registry. Deleting OpenSandbox snapshot metadata does not by itself garbage-collect the OCI image data. See OpenSandbox's Pause and Resume guide for the controller and registry requirements.

Without a workspace volume, files remain available only while the same sandbox or a verified filesystem snapshot is retained. With a volume, workspace files remain on the backing filesystem independently of the sandbox. Native session state is stored in AstraBox's database in either mode. Assistant hibernation saves that state and releases its sandbox; it is not OpenSandbox pause. See Assistants and workspace storage.

Configure networking and credential protection​

Use Management console → RuntimeProfiles → Network access to allow every outbound destination or only the hosts an Agent needs. AstraBox combines this choice with the model endpoint, platform callback, declared Plugin sources, allowed remote MCP servers, and destinations authorized by assigned Credentials. See IP Addresses for firewall and stable-egress configuration.

The maintained deployment keeps real model, remote MCP, and external API credentials outside the sandbox by default:

ASTRABOX_SANDBOX_CREDENTIAL_VAULT=true
ASTRABOX_SANDBOX_EGRESS_MODE=dns+nft

The OpenSandbox outbound proxy gives the Agent program opaque placeholders and adds real values only to matching outbound requests. Every deployment used for prepared capacity uses the same standard OpenSandbox create request as cold capacity: AstraBox supplies the effective network policy and enables the proxy, then OpenSandbox provisions it and returns per-sandbox endpoint authentication to the SDK. AstraBox does not configure a deployment-wide egress token. See Protect credentials used by Agents for the supported request matches and verification flow.

OpenSandbox does not offer header delivery for environment-variable credentials. Its credential substitution names whole request parts, and its header scope covers every request header, so it cannot confine a placeholder to one named header. Use substitution delivery with this backend.

For HTTPS services that accept HTTP Basic, including private Git repositories, create an http_basic Credential in an AstraBox Vault and assign the Vault to the Agent. Supply the clean repository URL, username, and write-only password or token. The provider translates that intent into OpenSandbox's native auth.type="basic" binding; no Git credential helper, token-bearing clone URL, or secret environment variable is installed in the sandbox. The binding is available before Skill and Plugin downloads on cold and prepared startup paths.

The binding matches HTTPS on port 443, the exact configured path and its descendants, and GET, HEAD, or POST. Credentials are not injected into other repository paths. This is an authentication method, not a Git-specific engine capability. See the Vault configuration example and OpenSandbox's native Git credential guide.

Select a sandbox runtime​

ASTRABOX_SANDBOX_SECURE_RUNTIME selects one container runtime for the deployment. Leave it empty for runc, or use a runtime already installed on the host or cluster:

RuntimeOpenSandbox support in AstraBox
runcGeneral use, limited networking, and protected credential delivery
gVisorAdditional syscall isolation; OpenSandbox networking and Credential Vault are unavailable
KataVM-backed isolation with networking and Credential Vault support
FirecrackerKubernetes only, with a matching Kata/Firecracker RuntimeClass

OpenSandbox's outbound proxy requires the iptables NAT table, which gVisor does not provide. A sandbox that combines gVisor with OpenSandbox network rules is rejected instead of starting without those rules. Use separate deployments when Agents need different runtime policies. OpenSandbox's Secure Container Runtime guide contains the current installation requirements.

Publish sandbox services safely​

AstraBox can connect directly to an endpoint returned by OpenSandbox or ask the Lifecycle API to relay HTTP, SSE, and WebSocket traffic (ASTRABOX_SANDBOX_ENDPOINT_VIA_SERVER_PROXY). The maintained Docker deployment connects directly: its bundled Lifecycle API runs in the AstraBox container and publishes sandbox ports on the Docker bridge gateway, which AstraBox reaches from the same container. Use the relay only when AstraBox cannot reach the sandbox endpoints. The relay removes Cookie and Authorization headers and replaces Host on every request, so the DeepSeek Harness and Hermes engines cannot authenticate to their in-box services through it.

Kubernetes deployments can use direct Pod routing or the OpenSandbox ingress component for platform-to-sandbox traffic. Browser-facing features — HTML preview, the Browser panel and expose_port — require the ingress Gateway. Direct Pod addresses are cluster-only; returning one to a public console does not make it reachable from a user's browser. The bundled Kubernetes backend refuses browser endpoint requests in direct mode with configuration guidance. Before exposing a sandbox service to an untrusted network, enable OpenSandbox Secure Access and configure matching signing keys for AstraBox and the ingress component. AstraBox checks Session access before issuing a short-lived signed URL.

Issuing a browser endpoint exempts its bound Agent-conversation sandbox from conversation-idle parking for that sandbox's lifetime. Application traffic goes directly to the Gateway, so console silence cannot establish that the application is unused. Sandbox expiry and explicit termination still apply. A replacement sandbox needs its own endpoint before it receives this exemption.

Configure a browser-facing Kubernetes Gateway​

Install the official OpenSandbox ingress Gateway in opensandbox-system, with gateway.dataplaneNamespace=opensandbox, gateway.gatewayRouteMode=uri, and gateway.secureAccess.existingSecret naming a Secret in that namespace. Its keys entry contains a=<base64-encoded-secret>; key ID a must match the server configuration. Keep the Secret and the lifecycle server's key private. The official chart at commit c806a49c62ee1fc3baa036165e9044e7b0efd97f has chart and image version 1.1.1. With that checkout and a provisioned signing Secret, install it using:

helm upgrade --install opensandbox-ingress \
./manifests/charts/ingress-gateway \
--namespace opensandbox-system \
--set gateway.gatewayRouteMode=uri \
--set gateway.secureAccess.existingSecret=opensandbox-ingress-signing

Give the Gateway a browser-reachable hostname, for example sandbox.example.com, and terminate TLS at the deployment's ingress or reverse proxy. Forward the complete path to the Gateway's Service on port 80, and support WebSocket upgrades. Do not strip the sandbox ID or signed routing prefix: the Gateway validates and removes it. With Caddy in the cluster, the site is:

sandbox.example.com {
reverse_proxy opensandbox-ingress-gateway.opensandbox-system.svc.cluster.local:80
}

Configure AstraBox's bundled lifecycle server with the same hostname and key:

ASTRABOX_SANDBOX_SERVER_RUNTIME=kubernetes
ASTRABOX_SANDBOX_SERVER_INGRESS_MODE=gateway
ASTRABOX_SANDBOX_SERVER_INGRESS_GATEWAY_ADDRESS=sandbox.example.com
ASTRABOX_SANDBOX_SERVER_INGRESS_ROUTE_MODE=uri
ASTRABOX_SANDBOX_ENDPOINT_SCHEME=https
ASTRABOX_SANDBOX_SECURE_ACCESS=true
ASTRABOX_SANDBOX_SERVER_INGRESS_SIGNING_KEY_ID=a
ASTRABOX_SANDBOX_SERVER_INGRESS_SIGNING_KEY=<same-base64-encoded-secret>

The address contains no URL scheme; ASTRABOX_SANDBOX_ENDPOINT_SCHEME sets the data-plane scheme independently of the lifecycle API. An HTTPS console needs HTTPS endpoints: HTTP iframe or WebSocket traffic is blocked as mixed content. Header routing cannot be used by an ordinary browser link. When connecting an external lifecycle service, configure its native [ingress] settings with the same topology; AstraBox's ASTRABOX_SANDBOX_SERVER_* settings configure only the bundled server. See the vendor's Secure Access guide.

Enable Secure Access before creating the sandboxes that will use it; changing the server configuration does not enable it on existing boxes. Check the Gateway's /status.ok endpoint and TLS certificate for deployment health. Acceptance still requires opening HTML resources and controlling the Browser from the actual console origin. Local Docker requires its published execd endpoint to be reachable by the user's browser; Kubernetes Gateway settings do not configure the Docker runtime.

Isolate sandbox Pods from the rest of the cluster​

A sandbox Pod listens on several ports bound to all interfaces — the in-box control runner, each engine's backend forwarder, the base image's web UI (which fronts a JupyterLab and a VNC desktop), execd and the egress sidecar. OpenSandbox creates no NetworkPolicy, so by Kubernetes' default any Pod in the cluster — including another tenant's sandbox — can open a connection to those ports. Apply a NetworkPolicy to the sandbox namespace so a sandbox Pod accepts ingress only from the platform, not from other Pods.

The control runner and the Codex backend forwarder also refuse a connection that does not carry a credential derived from the deployment's own secret, so reaching those two ports is not enough to use them. The policy is what keeps other Pods from reaching the rest.

AstraBox ships one at containers/kubernetes/sandbox-ingress-networkpolicy.yaml. It selects sandbox Pods by the astrabox.managed-by: astrabox label, restricts ingress only (a sandbox's own outbound path is unaffected), and as shipped admits the OpenSandbox ingress-gateway namespace. Apply it, and add the source your platform reaches sandboxes from:

  • Gateway / Secure Access mode: the shipped manifest is complete — every platform request reaches sandboxes through the ingress gateway, which the policy already admits.
  • Direct Pod routing: add an ipBlock from peer for the address a sandbox Pod sees the lifecycle server as. That address is cluster and CNI specific (the node or masquerade address, or the server's own container network when it runs off-cluster); determine it for your cluster rather than copying a value. scripts/k8s-testbed.sh does this for the single-node testbed by admitting its Docker bridge networks and the node address.

This is defence in depth: it only takes effect on a CNI that enforces NetworkPolicy (k3s's built-in controller does; some managed clusters ship a CNI that ignores it), so it is a second layer, not the sandbox's only control.

Inspect a deployment​

Open Management console → Sandboxes to see the state, image, expiration, network rules, Credentials, and diagnostics reported for each sandbox.

SymptomCheck
Pod remains pendingController and CRD status, sandbox namespace, node capacity, image reference, and registry access
Kubernetes API reports TLS errorsRoute to the configured API address and the names covered by its certificate
Session waits after the sandbox is readyRoute from AstraBox to the Agent service, including direct versus relayed endpoints
Agent prepared capacity remains unavailableprepared-runtime state, image, entrypoint, permissions, and Redis connectivity
A resumed sandbox is missing filesSnapshot controller, containerd socket, registry credentials, and the snapshot verifier