Solari

Volumes

A volume is durable storage that outlives any single machine. Create one once, then attach it to a sandbox at start-up and read and write it at a path of your choosing. When the machine goes away, the data stays. (Not yet available on desktops — see the callout below.)

Use a volume for anything you want to keep across runs and share between machines: datasets and model weights, a package cache, build artifacts, scraped output. Unlike a snapshot, which freezes a whole machine at a moment in time, a volume is a live folder you mount and keep writing to.

Volumes are live on sandboxes — Beta

Volumes work today on sandboxes, in every isolation mode (shared, dedicated, and hardened). They are not yet available on desktops — that host fleet doesn’t carry the mount build yet. The volume itself mounts host-side through gcsfuse, using a per-volume downscoped credential minted for that mount, not the shared instance-wide credential a machine otherwise runs with.

A create that asks for volumes on a desktop, or on a sandbox pool that hasn’t picked up the mount build yet, is refused with a 409 HostCapabilityMissing rather than silently handed back with nothing mounted — see the errors page.

Create a volume

Volumes live on the volumes namespace of a SandboxClient (or DesktopClient). Creating one gives you back a volumeId you can attach later. A volume starts empty and belongs to your organization.

import { SandboxClient } from "@solarisdk/sandbox"

const sandboxes = new SandboxClient({
  apiKey: process.env.SOLARI_API_KEY!,
  baseUrl: "https://api.getsolari.com",
})

const vol = await sandboxes.volumes.create({
  name: "datasets",
  sizeMb: 4096,               // optional soft size hint
  metadata: { team: "ml" },   // optional free-form tags
})
console.log(vol.volumeId)     // vol_0d10088366248dc85ee1489c9a96b1cc
import os
from solari_sandbox import SyncSandboxClient

sandboxes = SyncSandboxClient(api_key=os.environ["SOLARI_API_KEY"], base_url="https://api.getsolari.com")

vol = sandboxes.volumes.create(name="datasets", size_mb=4096, metadata={"team": "ml"})
print(vol["volumeId"])

List, fetch, and delete

The client mirrors the same four calls in every SDK. Deleting a volume is idempotent: deleting one that is already gone still succeeds.

const all = await sandboxes.volumes.list()         // every volume in your org
const one = await sandboxes.volumes.get(vol.volumeId)
await sandboxes.volumes.delete(vol.volumeId)       // idempotent
all_ = sandboxes.volumes.list()
one = sandboxes.volumes.get(vol["volumeId"])
sandboxes.volumes.delete(vol["volumeId"])

Attach a volume to a sandbox

Pass volumes when you create a sandbox. Each entry maps a volumeId to a mount path inside the machine. The path appears as an ordinary folder. Read and write it like any other directory.

The path shape depends on isolation mode: on isolation:"dedicated" or "hardened" it must be absolute (/data). On isolation:"shared" it must instead be a short name — letters, digits, _ and - only, no slashes — because a shared sandbox’s filesystem is namespaced per context; the gateway mounts it under that context’s own root. Mixing the two up is a 400 naming the field.

// dedicated / hardened: absolute path
const sbx = await sandboxes.create({
  template: "base",
  volumes: [{ volumeId: vol.volumeId, path: "/data" }],
})
await sbx.connect()

// Everything under /data persists on the volume, not the sandbox.
await sbx.files.write("/data/results.json", JSON.stringify(output))

// isolation: "shared": short name, not a path
const shared = await sandboxes.create({
  template: "base",
  isolation: "shared",
  volumes: [{ volumeId: vol.volumeId, path: "datasets" }],
})
sbx = sandboxes.create(
    template="base",
    volumes=[{"volumeId": vol["volumeId"], "path": "/data"}],
)

Two volumes cannot share the same mount path (or name, on shared) in one machine. A machine can mount several volumes at once, but each volume is single-attach — mounting one that is already attached to a different machine returns a 409. Detach it (stop or release the other machine) before mounting it elsewhere.

Volumes vs. snapshots
Reach for a volume when you want a folder of data that many machines read and write over time. Reach for a snapshot when you want to freeze a whole prepared machine and stamp out ready-to-go copies of it.
An attached volume is a real folder
Attach a volume at start-up and its path is a real folder inside the machine. Data written there survives the machine and reappears when the same volume is attached to a fresh one.
Clean up volumes you're done with
A volume keeps its data, and uses storage, until you delete it, even after every machine that used it is gone. Remove the ones you no longer need.