Documentation Index
Fetch the complete documentation index at: https://mintlify.com/opensandbox-group/OpenSandbox/llms.txt
Use this file to discover all available pages before exploring further.
OpenSandbox exposes a runtime-neutral Volume abstraction that lets you attach persistent or shared storage to any sandbox. Depending on your deployment target — Docker, Kubernetes, or a host machine — you choose the appropriate backend: pvc for Docker named volumes and Kubernetes PersistentVolumeClaims, ossfs for Alibaba Cloud OSS buckets, or host for bind-mounting a directory from the host filesystem. All backends share the same SDK shape, so switching runtimes requires only a config change.
The pvc backend maps to a Docker named volume on Docker runtimes and to a Kubernetes PersistentVolumeClaim on Kubernetes runtimes. It is the recommended alternative to host-path mounts because Docker manages the storage location and no allowlist is needed.Why named volumes over host paths?
| Host path (host backend) | Named volume (pvc backend) |
|---|
| Security | Exposes host filesystem paths | Docker manages storage location; no host path exposed |
| Setup | Requires allowed_host_paths allowlist | No allowlist needed |
| Cross-sandbox sharing | All containers must agree on a host path | Reference the same volume name |
| Portability | Tied to host directory structure | Works on any Docker host |
| Lifecycle | User manages host directories | docker volume create/rm |
Scenarios
| # | Scenario | Description |
|---|
| 1 | Read-write mount | Mount a named volume for bidirectional file I/O |
| 2 | Read-only mount | Mount a named volume that sandboxes cannot modify |
| 3 | Cross-sandbox sharing | Two sandboxes share data through the same named volume |
| 4 | SubPath mount | Mount only a subdirectory of a named volume (consistent with K8s PVC subPath) |
Prerequisites
# Start the server
uv pip install opensandbox-server
opensandbox-server init-config ~/.sandbox.toml --example docker
opensandbox-server
# Create and seed the named volume
docker volume create opensandbox-pvc-demo
docker run --rm -v opensandbox-pvc-demo:/data alpine \
sh -c "echo 'hello-from-named-volume' > /data/marker.txt"
# Install the Python SDK
uv pip install opensandbox
docker pull ubuntu:latest
Python (async)
from opensandbox import Sandbox
from opensandbox.models.sandboxes import PVC, Volume
sandbox = await Sandbox.create(
image="ubuntu",
volumes=[
Volume(
name="my-data",
pvc=PVC(claimName="my-named-volume"),
mountPath="/mnt/data",
readOnly=False, # optional, default is False
subPath="datasets/train", # optional, mount a subdirectory
),
],
)
Python (sync)
from opensandbox import SandboxSync
from opensandbox.models.sandboxes import PVC, Volume
sandbox = SandboxSync.create(
image="ubuntu",
volumes=[
Volume(
name="my-data",
pvc=PVC(claimName="my-named-volume"),
mountPath="/mnt/data",
subPath="datasets/train", # optional
),
],
)
TypeScript
import { Sandbox } from "@alibaba-group/opensandbox";
const sandbox = await Sandbox.create({
image: "ubuntu",
volumes: [
{
name: "my-data",
pvc: { claimName: "my-named-volume" },
mountPath: "/mnt/data",
readOnly: false,
subPath: "datasets/train", // optional
},
],
});
Java / Kotlin
Volume volume = Volume.builder()
.name("my-data")
.pvc(PVC.of("my-named-volume"))
.mountPath("/mnt/data")
.readOnly(false)
.subPath("datasets/train") // optional
.build();
Sandbox sandbox = Sandbox.builder()
.image("ubuntu")
.volume(volume)
.build();
Cleanup
docker volume rm opensandbox-pvc-demo
Run the full scenario script with:SANDBOX_IMAGE=ubuntu SANDBOX_DOMAIN=localhost:8080 uv run python examples/docker-pvc-volume-mount/main.py
The ossfs backend mounts an Alibaba Cloud OSS bucket into the sandbox using FUSE. The server host must run Linux with ossfs installed and FUSE support enabled.OSSFS is not supported when the OpenSandbox server runs on Windows. The server host must be Linux.
Server configuration
Add an optional [storage] section to ~/.sandbox.toml to set the local mount root:[runtime]
type = "docker"
[storage]
ossfs_mount_root = "/mnt/ossfs"
Then start the server:Prerequisites
uv pip install opensandbox
export SANDBOX_DOMAIN=localhost:8080
export SANDBOX_IMAGE=ubuntu
export OSS_BUCKET=your-bucket
export OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com
export OSS_ACCESS_KEY_ID=your-ak
export OSS_ACCESS_KEY_SECRET=your-sk
Python SDK usage
from opensandbox import Sandbox
from opensandbox.models.sandboxes import OSSFS, Volume
sandbox = await Sandbox.create(
image="ubuntu",
volumes=[
Volume(
name="oss-data",
ossfs=OSSFS(
bucket="your-bucket",
endpoint="oss-cn-hangzhou.aliyuncs.com",
# version="2.0", # optional, default is "2.0"
accessKeyId="your-ak",
accessKeySecret="your-sk",
),
mountPath="/mnt/data",
subPath="train", # optional
readOnly=False, # optional
)
],
)
- Current implementation supports inline credentials only (
accessKeyId/accessKeySecret).
- Mounting is on-demand in Docker runtime (mount-or-reuse), not pre-mounted for all buckets.
ossfs.version exists in API/SDK with enum "1.0" | "2.0", and defaults to "2.0" when omitted.
- Docker runtime applies version-specific mount argument encoding:
1.0 mounts via ossfs ... -o <option>; 2.0 mounts via ossfs2 mount ... -c <config-file> where options are written as --<option> config lines.
options values must be raw payloads without leading - (for example: allow_other, umask=0022).
Run the full example:uv run python examples/docker-ossfs-volume-mount/main.py
On Kubernetes, the pvc backend maps to a PersistentVolumeClaim. Data written to a PVC outlives the sandbox process, so files are still present when a follow-up sandbox mounts the same claim.OpenSandbox supports three modes depending on who owns the PVC lifecycle:| Mode | createIfNotExists | deleteOnSandboxTermination | Who owns the PVC |
|---|
| Bring your own | false | ignored | You (provisioned out-of-band) |
| Server-managed, persistent | true | false (default) | You (after first create) |
| Server-managed, ephemeral | true | true | Server |
Prerequisites
Install a CSI driver that matches your storage backend, then install the Python SDK:uv pip install opensandbox
Mode 1 — Bring your own PVC
Apply the PVC before creating any sandbox:apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
namespace: opensandbox
spec:
accessModes:
- ReadWriteOnce
storageClassName: <your-storage-class>
resources:
requests:
storage: 10Gi
kubectl apply -f pvc.yaml
kubectl get pvc my-pvc -n opensandbox # should be Bound
Mount it from a sandbox:from opensandbox import Sandbox
from opensandbox.models.sandboxes import PVC, Volume
sandbox = await Sandbox.create(
image="python:3.11",
volumes=[
Volume(
name="data-volume",
pvc=PVC(
claimName="my-pvc",
createIfNotExists=False, # never auto-provision a BYO claim
),
mountPath="/mnt/data",
readOnly=False,
),
],
)
result = await sandbox.commands.run("ls -la /mnt/data")
print("\n".join(msg.text for msg in result.logs.stdout))
Mode 2 — Server-managed, persistent
The server creates the PVC on first use and keeps it after the sandbox terminates:sandbox = await Sandbox.create(
image="python:3.11",
volumes=[
Volume(
name="cache",
pvc=PVC(
claimName="agent-cache",
createIfNotExists=True,
deleteOnSandboxTermination=False, # default: keep the PVC
storageClass="alibaba-cloud-disk-ssd", # optional
storage="20Gi", # optional
accessModes=["ReadWriteOnce"], # optional
),
mountPath="/mnt/cache",
),
],
)
Mode 3 — Server-managed, ephemeral
The server provisions the PVC and deletes it when the sandbox terminates:sandbox = await Sandbox.create(
image="python:3.11",
timeout=600,
volumes=[
Volume(
name="scratch",
pvc=PVC(
claimName=f"scratch-{run_id}", # unique per run
createIfNotExists=True,
deleteOnSandboxTermination=True,
storage="5Gi",
),
mountPath="/mnt/scratch",
),
],
)
Pool mode does not support volumes — use template mode instead. PVCs created with deleteOnSandboxTermination=true are exclusively owned by the creating sandbox; a second sandbox attempting to mount the same claimName is rejected with 409 CONFLICT.
Run the end-to-end example:export OPEN_SANDBOX_API_KEY=your-api-key
export OPEN_SANDBOX_BASE_URL=http://localhost:8080
export SANDBOX_PVC_NAME=my-pvc
python examples/kubernetes-pvc-volume-mount/main.py
The host backend bind-mounts a directory from the server host into the sandbox. It is ideal for sharing datasets, model checkpoints, or configuration files during local development.In production, always configure allowed_host_paths in ~/.sandbox.toml to prevent sandboxes from accessing sensitive host directories. An empty list allows all paths.
Scenarios
| # | Scenario | Description |
|---|
| 1 | Read-write mount | Mount a host directory for bidirectional file exchange |
| 2 | Read-only mount | Provide shared data that sandboxes cannot modify |
| 3 | SubPath mount | Mount a specific subdirectory from the host path |
Prerequisites
Start the server and configure the allowlist:# ~/.sandbox.toml
[storage]
allowed_host_paths = ["/tmp/opensandbox-data", "/data/shared"]
Create host directories and seed test data:mkdir -p /tmp/opensandbox-data
echo "hello-from-host" > /tmp/opensandbox-data/marker.txt
mkdir -p /tmp/opensandbox-data/datasets/train
echo -e "id,value\n1,100\n2,200\n3,300" > /tmp/opensandbox-data/datasets/train/data.csv
Install the SDK:uv pip install opensandbox
docker pull ubuntu:latest
Python (async)
from opensandbox import Sandbox
from opensandbox.models.sandboxes import Host, Volume
sandbox = await Sandbox.create(
image="ubuntu",
volumes=[
Volume(
name="my-data",
host=Host(path="/data/shared"),
mountPath="/mnt/data",
readOnly=False, # optional, default is False
subPath="subdir", # optional, mount a subdirectory
),
],
)
Python (sync)
from opensandbox import SandboxSync
from opensandbox.models.sandboxes import Host, Volume
sandbox = SandboxSync.create(
image="ubuntu",
volumes=[
Volume(
name="my-data",
host=Host(path="/data/shared"),
mountPath="/mnt/data",
),
],
)
TypeScript
import { Sandbox } from "@alibaba-group/opensandbox";
const sandbox = await Sandbox.create({
image: "ubuntu",
volumes: [
{
name: "my-data",
host: { path: "/data/shared" },
mountPath: "/mnt/data",
readOnly: false,
},
],
});
Java / Kotlin
Volume volume = Volume.builder()
.name("my-data")
.host(Host.of("/data/shared"))
.mountPath("/mnt/data")
.readOnly(false)
.build();
Sandbox sandbox = Sandbox.builder()
.image("ubuntu")
.volume(volume)
.build();
Run the full scenario script:HOST_VOLUME_PATH=/tmp/opensandbox-data uv run python examples/host-volume-mount/main.py
References