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
| Deployment | Best for | Where sandboxes run |
|---|---|---|
| Bundled Docker | Evaluation, development, and one trusted host | Separate containers on the AstraBox host |
| Kubernetes | Multiple nodes, prewarmed capacity, snapshots, and cluster controls | Pods managed by the OpenSandbox controller |
| Existing OpenSandbox service | Organizations that operate sandbox infrastructure separately | The 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:
| Runtime | OpenSandbox support in AstraBox |
|---|---|
| runc | General use, limited networking, and protected credential delivery |
| gVisor | Additional syscall isolation; OpenSandbox networking and Credential Vault are unavailable |
| Kata | VM-backed isolation with networking and Credential Vault support |
| Firecracker | Kubernetes 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
ipBlockfrompeer 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.shdoes 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.
| Symptom | Check |
|---|---|
| Pod remains pending | Controller and CRD status, sandbox namespace, node capacity, image reference, and registry access |
| Kubernetes API reports TLS errors | Route to the configured API address and the names covered by its certificate |
| Session waits after the sandbox is ready | Route from AstraBox to the Agent service, including direct versus relayed endpoints |
| Agent prepared capacity remains unavailable | prepared-runtime state, image, entrypoint, permissions, and Redis connectivity |
| A resumed sandbox is missing files | Snapshot controller, containerd socket, registry credentials, and the snapshot verifier |