Skip to content

Mount S3-compatible object storage buckets as local filesystem paths. Access object storage using standard file operations.

When to mount buckets

Mount S3-compatible buckets when you need:

  • Persistent data - Data survives sandbox destruction
  • Large datasets - Process data without downloading
  • Shared storage - Multiple sandboxes access the same data
  • Cost-effective persistence - Cheaper than keeping sandboxes alive

Mount an R2 bucket

JavaScript
import { getSandbox } from "@cloudflare/sandbox";
const sandbox = getSandbox(env.Sandbox, "data-processor");
// Mount R2 bucket
await sandbox.mountBucket("my-r2-bucket", "/data", {
endpoint: "https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
});
// Access bucket with standard filesystem operations
await sandbox.exec("ls", { args: ["/data"] });
await sandbox.writeFile("/data/results.json", JSON.stringify(results));
// Use from Python
await sandbox.exec("python", {
args: [
"-c",
`
import pandas as pd
df = pd.read_csv('/data/input.csv')
df.describe().to_csv('/data/summary.csv')
`,
],
});

Credentials

Automatic detection

Set credentials as Worker secrets and the SDK automatically detects them:

Terminal window
npx wrangler secret put R2_ACCESS_KEY_ID
npx wrangler secret put R2_SECRET_ACCESS_KEY
JavaScript
// Credentials automatically detected from environment
await sandbox.mountBucket("my-r2-bucket", "/data", {
endpoint: "https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
});

Explicit credentials

Pass credentials directly when needed:

JavaScript
await sandbox.mountBucket("my-r2-bucket", "/data", {
endpoint: "https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
credentials: {
accessKeyId: env.R2_ACCESS_KEY_ID,
secretAccessKey: env.R2_SECRET_ACCESS_KEY,
},
});

Mount bucket subdirectories

Mount a specific subdirectory within a bucket using the prefix option. Only contents under the prefix are visible at the mount point:

JavaScript
// Mount only the /uploads/images/ subdirectory
await sandbox.mountBucket("my-bucket", "/images", {
endpoint: "https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
prefix: "/uploads/images/",
});
// Files appear at mount point without the prefix
// Bucket: my-bucket/uploads/images/photo.jpg
// Mounted path: /images/photo.jpg
await sandbox.exec("ls", { args: ["/images"] });
// Write to subdirectory
await sandbox.writeFile("/images/photo.jpg", imageData);
// Creates my-bucket:/uploads/images/photo.jpg
// Mount different prefixes to different paths
await sandbox.mountBucket("datasets", "/training-data", {
endpoint: "https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
prefix: "/ml/training/",
});
await sandbox.mountBucket("datasets", "/test-data", {
endpoint: "https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
prefix: "/ml/testing/",
});

Read-only mounts

Protect data by mounting buckets in read-only mode:

JavaScript
await sandbox.mountBucket("dataset-bucket", "/data", {
endpoint: "https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
readOnly: true,
});
// Reads work
await sandbox.exec("cat", { args: ["/data/dataset.csv"] });