--- title: Mount External Storage description: Mount external object storage (Amazon S3, Cloudflare R2, Tigris, Supabase Storage, Google Cloud Storage, Azure Blob), cloud storage like Box, and filesystems into Daytona sandboxes using FUSE. --- Mount object storage (Amazon S3, Cloudflare R2, Tigris, Supabase Storage, Google Cloud Storage, Azure Blob), cloud storage like Box, and filesystems like Archil and MesaFS into a Daytona sandbox as a regular directory. The sandbox reads from and writes to the bucket as if it were a local directory, so existing tools, scripts, and agents work without changes. This is useful for bringing in datasets, model weights, or build artifacts that already live in your own cloud account. External storage mounts and [Daytona Volumes](/docs/en/volumes/) are complementary FUSE-based mechanisms — both expose remote object storage as a regular sandbox directory, both can be shared across sandboxes, and both persist beyond any individual sandbox's lifetime. The main distinction is **where the data physically lives**: Daytona Volumes are hosted on Daytona's own S3-compatible object store, while external mounts connect to a bucket or filesystem hosted on another provider (Amazon S3, Cloudflare R2, Tigris, Supabase Storage, GCS, Azure Blob, Box, Archil, MesaFS). External storage is mounted using FUSE. Daytona supports two approaches, and each provider section below shows both — pick whichever fits your workflow: - **Pre-built snapshot** — build a [snapshot](/docs/en/snapshots/) once with the FUSE tool (`mount-s3`, `gcsfuse`, `blobfuse2`, `rclone`) built-in, then launch every sandbox from that snapshot. Cold starts are fast and predictable. Best for production. - **Runtime install** — launch a default sandbox and `apt-get install` the FUSE tool when the sandbox starts. Adds time to sandbox startup, but you don't manage snapshots. Best for quick experiments. Both approaches end with the same mount command and the same usage — the only difference is when the FUSE tool gets installed. ## Mount an Amazon S3 bucket Mount an S3 bucket using [Mountpoint for Amazon S3 ↗](https://github.com/awslabs/mountpoint-s3) — AWS's official FUSE client, optimized for high throughput on S3. **Credentials** — set `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` in your local environment. The snippets below pass them into the sandbox via `envVars`, and `mount-s3` reads them from there. ### Pre-built snapshot Build a snapshot with `mount-s3` preinstalled, then launch all S3-enabled sandboxes from that snapshot. This removes per-sandbox package install work, keeps cold starts predictable, and gives you a reusable baseline image for production workloads. #### Build a snapshot Create a reusable snapshot that installs `mount-s3` and its system dependencies. After it finishes, every sandbox launched from `fuse-s3` already has the mount binary available. ```python from daytona import CreateSnapshotParams, Daytona, Image daytona = Daytona() image = ( Image.base("daytonaio/sandbox") .run_commands( "sudo apt-get update " "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget", 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' '&& wget -O /tmp/mount-s3.deb ' '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' "&& sudo apt-get install -y /tmp/mount-s3.deb " "&& rm /tmp/mount-s3.deb", ) ) daytona.snapshot.create( CreateSnapshotParams(name="fuse-s3", image=image), on_logs=print, ) ``` ```typescript import { Daytona, Image } from '@daytona/sdk' const daytona = new Daytona() const image = Image.base('daytonaio/sandbox').runCommands( 'sudo apt-get update ' + '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget', 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' + '&& wget -O /tmp/mount-s3.deb ' + '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' + '&& sudo apt-get install -y /tmp/mount-s3.deb ' + '&& rm /tmp/mount-s3.deb', ) await daytona.snapshot.create( { name: 'fuse-s3', image }, { onLogs: console.log }, ) ``` ```ruby require 'daytona' daytona = Daytona::Daytona.new image = Daytona::Image .base('daytonaio/sandbox') .run_commands( 'sudo apt-get update ' \ '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget', 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' \ '&& wget -O /tmp/mount-s3.deb ' \ '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' \ '&& sudo apt-get install -y /tmp/mount-s3.deb ' \ '&& rm /tmp/mount-s3.deb' ) daytona.snapshot.create( Daytona::CreateSnapshotParams.new(name: 'fuse-s3', image: image), on_logs: proc { |chunk| print(chunk) } ) ``` ```go import ( "context" "fmt" "log" "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types" ) ctx := context.Background() client, err := daytona.NewClient() if err != nil { log.Fatal(err) } image := daytona.Base("daytonaio/sandbox"). Run("sudo apt-get update && sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget"). Run(`arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" && ` + `wget -O /tmp/mount-s3.deb "https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" && ` + `sudo apt-get install -y /tmp/mount-s3.deb && rm /tmp/mount-s3.deb`) _, logChan, err := client.Snapshot.Create(ctx, &types.CreateSnapshotParams{ Name: "fuse-s3", Image: image, }) if err != nil { log.Fatal(err) } for line := range logChan { fmt.Print(line) } ``` ```java import io.daytona.sdk.Daytona; import io.daytona.sdk.Image; public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { Image image = Image.base("daytonaio/sandbox") .runCommands( "sudo apt-get update " + "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget", "arch=\"$(dpkg --print-architecture | sed s/amd64/x86_64/)\" " + "&& wget -O /tmp/mount-s3.deb " + "\"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb\" " + "&& sudo apt-get install -y /tmp/mount-s3.deb " + "&& rm /tmp/mount-s3.deb" ); daytona.snapshot().create("fuse-s3", image, System.out::println); } } } ``` #### Launch and mount Pass AWS credentials as environment variables on sandbox creation. `mount-s3` reads them automatically. ```python import os from daytona import CreateSandboxFromSnapshotParams, Daytona daytona = Daytona() sandbox = daytona.create( CreateSandboxFromSnapshotParams( snapshot="fuse-s3", env_vars={ "AWS_ACCESS_KEY_ID": os.environ["AWS_ACCESS_KEY_ID"], "AWS_SECRET_ACCESS_KEY": os.environ["AWS_SECRET_ACCESS_KEY"], }, ) ) mount_path = "/home/daytona/s3" # mount-s3 daemonizes by default and reads AWS_* from the environment sandbox.process.exec(f"mkdir -p {mount_path}") sandbox.process.exec(f"mount-s3 my-bucket {mount_path}") # Read and write through the mount as if it were a local directory sandbox.process.exec(f"echo 'hello from Daytona' > {mount_path}/hello.txt") response = sandbox.process.exec(f"cat {mount_path}/hello.txt") print(response.result) ``` ```typescript import { Daytona } from '@daytona/sdk' const daytona = new Daytona() const sandbox = await daytona.create({ snapshot: 'fuse-s3', envVars: { AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID!, AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY!, }, }) const mountPath = '/home/daytona/s3' // mount-s3 daemonizes by default and reads AWS_* from the environment await sandbox.process.executeCommand(`mkdir -p ${mountPath}`) await sandbox.process.executeCommand(`mount-s3 my-bucket ${mountPath}`) // Read and write through the mount as if it were a local directory await sandbox.process.executeCommand(`echo 'hello from Daytona' > ${mountPath}/hello.txt`) const response = await sandbox.process.executeCommand(`cat ${mountPath}/hello.txt`) console.log(response.result) ``` ```ruby require 'daytona' daytona = Daytona::Daytona.new sandbox = daytona.create( Daytona::CreateSandboxFromSnapshotParams.new( snapshot: 'fuse-s3', env_vars: { 'AWS_ACCESS_KEY_ID' => ENV.fetch('AWS_ACCESS_KEY_ID'), 'AWS_SECRET_ACCESS_KEY' => ENV.fetch('AWS_SECRET_ACCESS_KEY') } ) ) mount_path = '/home/daytona/s3' # mount-s3 daemonizes by default and reads AWS_* from the environment sandbox.process.exec(command: "mkdir -p #{mount_path}") sandbox.process.exec(command: "mount-s3 my-bucket #{mount_path}") # Read and write through the mount as if it were a local directory sandbox.process.exec(command: "echo 'hello from Daytona' > #{mount_path}/hello.txt") response = sandbox.process.exec(command: "cat #{mount_path}/hello.txt") puts response.result ``` ```go import ( "context" "fmt" "log" "os" "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types" ) ctx := context.Background() client, err := daytona.NewClient() if err != nil { log.Fatal(err) } sandbox, err := client.Create(ctx, types.SnapshotParams{ Snapshot: "fuse-s3", SandboxBaseParams: types.SandboxBaseParams{ EnvVars: map[string]string{ "AWS_ACCESS_KEY_ID": os.Getenv("AWS_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY": os.Getenv("AWS_SECRET_ACCESS_KEY"), }, }, }) if err != nil { log.Fatal(err) } mountPath := "/home/daytona/s3" // mount-s3 daemonizes by default and reads AWS_* from the environment if _, err := sandbox.Process.ExecuteCommand(ctx, "mkdir -p "+mountPath); err != nil { log.Fatal(err) } if _, err := sandbox.Process.ExecuteCommand(ctx, "mount-s3 my-bucket "+mountPath); err != nil { log.Fatal(err) } // Read and write through the mount as if it were a local directory if _, err := sandbox.Process.ExecuteCommand(ctx, "echo 'hello from Daytona' > "+mountPath+"/hello.txt"); err != nil { log.Fatal(err) } response, err := sandbox.Process.ExecuteCommand(ctx, "cat "+mountPath+"/hello.txt") if err != nil { log.Fatal(err) } fmt.Println(response.Result) ``` ```java import io.daytona.sdk.Daytona; import io.daytona.sdk.Sandbox; import io.daytona.sdk.model.CreateSandboxFromSnapshotParams; import io.daytona.sdk.model.ExecuteResponse; import java.util.Map; public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setSnapshot("fuse-s3"); params.setEnvVars(Map.of( "AWS_ACCESS_KEY_ID", System.getenv("AWS_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY", System.getenv("AWS_SECRET_ACCESS_KEY") )); Sandbox sandbox = daytona.create(params); String mountPath = "/home/daytona/s3"; // mount-s3 daemonizes by default and reads AWS_* from the environment sandbox.getProcess().executeCommand("mkdir -p " + mountPath); sandbox.getProcess().executeCommand("mount-s3 my-bucket " + mountPath); // Read and write through the mount as if it were a local directory sandbox.getProcess().executeCommand( "echo 'hello from Daytona' > " + mountPath + "/hello.txt"); ExecuteResponse response = sandbox.getProcess().executeCommand( "cat " + mountPath + "/hello.txt"); System.out.println(response.getResult()); } } } ``` ### Runtime install Start from a default sandbox and install `mount-s3` during startup before running the mount command. This is useful for quick testing and temporary environments where you do not want to maintain a custom snapshot, with the tradeoff of slower cold starts. ```python import os from daytona import CreateSandboxBaseParams, Daytona daytona = Daytona() sandbox = daytona.create( CreateSandboxBaseParams( env_vars={ "AWS_ACCESS_KEY_ID": os.environ["AWS_ACCESS_KEY_ID"], "AWS_SECRET_ACCESS_KEY": os.environ["AWS_SECRET_ACCESS_KEY"], }, ) ) # Install mount-s3 at runtime sandbox.process.exec( "sudo apt-get update " "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget" ) sandbox.process.exec( 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' '&& wget -O /tmp/mount-s3.deb ' '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' "&& sudo apt-get install -y /tmp/mount-s3.deb" ) # Mount and use mount_path = "/home/daytona/s3" sandbox.process.exec(f"mkdir -p {mount_path} && mount-s3 my-bucket {mount_path}") response = sandbox.process.exec(f"ls {mount_path}") print(response.result) ``` ```typescript import { Daytona } from '@daytona/sdk' const daytona = new Daytona() const sandbox = await daytona.create({ envVars: { AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID!, AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY!, }, }) // Install mount-s3 at runtime await sandbox.process.executeCommand( 'sudo apt-get update ' + '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget', ) await sandbox.process.executeCommand( 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' + '&& wget -O /tmp/mount-s3.deb ' + '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' + '&& sudo apt-get install -y /tmp/mount-s3.deb', ) // Mount and use const mountPath = '/home/daytona/s3' await sandbox.process.executeCommand(`mkdir -p ${mountPath} && mount-s3 my-bucket ${mountPath}`) const response = await sandbox.process.executeCommand(`ls ${mountPath}`) console.log(response.result) ``` ```ruby require 'daytona' daytona = Daytona::Daytona.new sandbox = daytona.create( Daytona::CreateSandboxBaseParams.new( env_vars: { 'AWS_ACCESS_KEY_ID' => ENV.fetch('AWS_ACCESS_KEY_ID'), 'AWS_SECRET_ACCESS_KEY' => ENV.fetch('AWS_SECRET_ACCESS_KEY') } ) ) # Install mount-s3 at runtime sandbox.process.exec( command: 'sudo apt-get update ' \ '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget' ) sandbox.process.exec( command: 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' \ '&& wget -O /tmp/mount-s3.deb ' \ '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' \ '&& sudo apt-get install -y /tmp/mount-s3.deb' ) # Mount and use mount_path = '/home/daytona/s3' sandbox.process.exec(command: "mkdir -p #{mount_path} && mount-s3 my-bucket #{mount_path}") response = sandbox.process.exec(command: "ls #{mount_path}") puts response.result ``` ```go import ( "context" "fmt" "log" "os" "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types" ) ctx := context.Background() client, err := daytona.NewClient() if err != nil { log.Fatal(err) } sandbox, err := client.Create(ctx, types.SnapshotParams{ SandboxBaseParams: types.SandboxBaseParams{ EnvVars: map[string]string{ "AWS_ACCESS_KEY_ID": os.Getenv("AWS_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY": os.Getenv("AWS_SECRET_ACCESS_KEY"), }, }, }) if err != nil { log.Fatal(err) } // Install mount-s3 at runtime if _, err := sandbox.Process.ExecuteCommand(ctx, "sudo apt-get update && sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget"); err != nil { log.Fatal(err) } if _, err := sandbox.Process.ExecuteCommand(ctx, `arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" && `+ `wget -O /tmp/mount-s3.deb "https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" && `+ `sudo apt-get install -y /tmp/mount-s3.deb`); err != nil { log.Fatal(err) } // Mount and use mountPath := "/home/daytona/s3" if _, err := sandbox.Process.ExecuteCommand(ctx, "mkdir -p "+mountPath+" && mount-s3 my-bucket "+mountPath); err != nil { log.Fatal(err) } response, err := sandbox.Process.ExecuteCommand(ctx, "ls "+mountPath) if err != nil { log.Fatal(err) } fmt.Println(response.Result) ``` ```java import io.daytona.sdk.Daytona; import io.daytona.sdk.Sandbox; import io.daytona.sdk.model.CreateSandboxFromSnapshotParams; import io.daytona.sdk.model.ExecuteResponse; import java.util.Map; public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setEnvVars(Map.of( "AWS_ACCESS_KEY_ID", System.getenv("AWS_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY", System.getenv("AWS_SECRET_ACCESS_KEY") )); Sandbox sandbox = daytona.create(params); // Install mount-s3 at runtime sandbox.getProcess().executeCommand( "sudo apt-get update " + "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget"); sandbox.getProcess().executeCommand( "arch=\"$(dpkg --print-architecture | sed s/amd64/x86_64/)\" " + "&& wget -O /tmp/mount-s3.deb " + "\"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb\" " + "&& sudo apt-get install -y /tmp/mount-s3.deb"); // Mount and use String mountPath = "/home/daytona/s3"; sandbox.getProcess().executeCommand( "mkdir -p " + mountPath + " && mount-s3 my-bucket " + mountPath); ExecuteResponse response = sandbox.getProcess().executeCommand("ls " + mountPath); System.out.println(response.getResult()); } } } ``` ## Mount a Cloudflare R2 bucket Cloudflare R2 is S3-compatible, so the same `mount-s3` tool works. Pass an explicit `--endpoint-url` pointing at your R2 account. **Credentials** — set `R2_ACCOUNT_ID`, `R2_ACCESS_KEY_ID`, and `R2_SECRET_ACCESS_KEY` in your local environment. R2 is S3-compatible, so the snippets below pass your R2 keys into the sandbox via `envVars` under the `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` names that `mount-s3` expects. ### Pre-built snapshot Build a snapshot with `mount-s3` preinstalled, then launch all R2-enabled sandboxes from that snapshot. The mount flow stays identical to S3 except for the R2 `--endpoint-url`, and startup remains fast because installation is done once at snapshot build time. #### Build a snapshot Create a reusable snapshot that installs the same `mount-s3` tool used for S3. R2 remains S3-compatible, so this snapshot is identical to S3 setup and only the runtime mount command changes. ```python from daytona import CreateSnapshotParams, Daytona, Image daytona = Daytona() image = ( Image.base("daytonaio/sandbox") .run_commands( "sudo apt-get update " "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget", 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' '&& wget -O /tmp/mount-s3.deb ' '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' "&& sudo apt-get install -y /tmp/mount-s3.deb " "&& rm /tmp/mount-s3.deb", ) ) daytona.snapshot.create( CreateSnapshotParams(name="fuse-r2", image=image), on_logs=print, ) ``` ```typescript import { Daytona, Image } from '@daytona/sdk' const daytona = new Daytona() const image = Image.base('daytonaio/sandbox').runCommands( 'sudo apt-get update ' + '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget', 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' + '&& wget -O /tmp/mount-s3.deb ' + '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' + '&& sudo apt-get install -y /tmp/mount-s3.deb ' + '&& rm /tmp/mount-s3.deb', ) await daytona.snapshot.create( { name: 'fuse-r2', image }, { onLogs: console.log }, ) ``` ```ruby require 'daytona' daytona = Daytona::Daytona.new image = Daytona::Image .base('daytonaio/sandbox') .run_commands( 'sudo apt-get update ' \ '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget', 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' \ '&& wget -O /tmp/mount-s3.deb ' \ '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' \ '&& sudo apt-get install -y /tmp/mount-s3.deb ' \ '&& rm /tmp/mount-s3.deb' ) daytona.snapshot.create( Daytona::CreateSnapshotParams.new(name: 'fuse-r2', image: image), on_logs: proc { |chunk| print(chunk) } ) ``` ```go import ( "context" "fmt" "log" "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types" ) ctx := context.Background() client, err := daytona.NewClient() if err != nil { log.Fatal(err) } image := daytona.Base("daytonaio/sandbox"). Run("sudo apt-get update && sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget"). Run(`arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" && ` + `wget -O /tmp/mount-s3.deb "https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" && ` + `sudo apt-get install -y /tmp/mount-s3.deb && rm /tmp/mount-s3.deb`) _, logChan, err := client.Snapshot.Create(ctx, &types.CreateSnapshotParams{ Name: "fuse-r2", Image: image, }) if err != nil { log.Fatal(err) } for line := range logChan { fmt.Print(line) } ``` ```java import io.daytona.sdk.Daytona; import io.daytona.sdk.Image; public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { Image image = Image.base("daytonaio/sandbox") .runCommands( "sudo apt-get update " + "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget", "arch=\"$(dpkg --print-architecture | sed s/amd64/x86_64/)\" " + "&& wget -O /tmp/mount-s3.deb " + "\"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb\" " + "&& sudo apt-get install -y /tmp/mount-s3.deb " + "&& rm /tmp/mount-s3.deb" ); daytona.snapshot().create("fuse-r2", image, System.out::println); } } } ``` #### Launch and mount Pass your R2 credentials into the sandbox as `AWS_*` environment variables and mount with the R2 endpoint URL. This keeps the authentication flow compatible with `mount-s3` while targeting your Cloudflare account. ```python import os from daytona import CreateSandboxFromSnapshotParams, Daytona daytona = Daytona() # R2 credentials live in your Cloudflare dashboard under R2 > Manage API Tokens account_id = os.environ["R2_ACCOUNT_ID"] sandbox = daytona.create( CreateSandboxFromSnapshotParams( snapshot="fuse-r2", env_vars={ "AWS_ACCESS_KEY_ID": os.environ["R2_ACCESS_KEY_ID"], "AWS_SECRET_ACCESS_KEY": os.environ["R2_SECRET_ACCESS_KEY"], }, ) ) mount_path = "/home/daytona/r2" sandbox.process.exec(f"mkdir -p {mount_path}") sandbox.process.exec( f"mount-s3 --endpoint-url https://{account_id}.r2.cloudflarestorage.com " f"my-r2-bucket {mount_path}" ) response = sandbox.process.exec(f"ls {mount_path}") print(response.result) ``` ```typescript import { Daytona } from '@daytona/sdk' const daytona = new Daytona() // R2 credentials live in your Cloudflare dashboard under R2 > Manage API Tokens const accountId = process.env.R2_ACCOUNT_ID! const sandbox = await daytona.create({ snapshot: 'fuse-r2', envVars: { AWS_ACCESS_KEY_ID: process.env.R2_ACCESS_KEY_ID!, AWS_SECRET_ACCESS_KEY: process.env.R2_SECRET_ACCESS_KEY!, }, }) const mountPath = '/home/daytona/r2' await sandbox.process.executeCommand(`mkdir -p ${mountPath}`) await sandbox.process.executeCommand( `mount-s3 --endpoint-url https://${accountId}.r2.cloudflarestorage.com ` + `my-r2-bucket ${mountPath}`, ) const response = await sandbox.process.executeCommand(`ls ${mountPath}`) console.log(response.result) ``` ```ruby require 'daytona' daytona = Daytona::Daytona.new # R2 credentials live in your Cloudflare dashboard under R2 > Manage API Tokens account_id = ENV.fetch('R2_ACCOUNT_ID') sandbox = daytona.create( Daytona::CreateSandboxFromSnapshotParams.new( snapshot: 'fuse-r2', env_vars: { 'AWS_ACCESS_KEY_ID' => ENV.fetch('R2_ACCESS_KEY_ID'), 'AWS_SECRET_ACCESS_KEY' => ENV.fetch('R2_SECRET_ACCESS_KEY') } ) ) mount_path = '/home/daytona/r2' sandbox.process.exec(command: "mkdir -p #{mount_path}") sandbox.process.exec( command: "mount-s3 --endpoint-url https://#{account_id}.r2.cloudflarestorage.com " \ "my-r2-bucket #{mount_path}" ) response = sandbox.process.exec(command: "ls #{mount_path}") puts response.result ``` ```go import ( "context" "fmt" "log" "os" "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types" ) ctx := context.Background() client, err := daytona.NewClient() if err != nil { log.Fatal(err) } // R2 credentials live in your Cloudflare dashboard under R2 > Manage API Tokens accountID := os.Getenv("R2_ACCOUNT_ID") sandbox, err := client.Create(ctx, types.SnapshotParams{ Snapshot: "fuse-r2", SandboxBaseParams: types.SandboxBaseParams{ EnvVars: map[string]string{ "AWS_ACCESS_KEY_ID": os.Getenv("R2_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY": os.Getenv("R2_SECRET_ACCESS_KEY"), }, }, }) if err != nil { log.Fatal(err) } mountPath := "/home/daytona/r2" if _, err := sandbox.Process.ExecuteCommand(ctx, "mkdir -p "+mountPath); err != nil { log.Fatal(err) } if _, err := sandbox.Process.ExecuteCommand(ctx, "mount-s3 --endpoint-url https://"+accountID+".r2.cloudflarestorage.com "+ "my-r2-bucket "+mountPath); err != nil { log.Fatal(err) } response, err := sandbox.Process.ExecuteCommand(ctx, "ls "+mountPath) if err != nil { log.Fatal(err) } fmt.Println(response.Result) ``` ```java import io.daytona.sdk.Daytona; import io.daytona.sdk.Sandbox; import io.daytona.sdk.model.CreateSandboxFromSnapshotParams; import io.daytona.sdk.model.ExecuteResponse; import java.util.Map; public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { // R2 credentials live in your Cloudflare dashboard under R2 > Manage API Tokens String accountId = System.getenv("R2_ACCOUNT_ID"); CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setSnapshot("fuse-r2"); params.setEnvVars(Map.of( "AWS_ACCESS_KEY_ID", System.getenv("R2_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY", System.getenv("R2_SECRET_ACCESS_KEY") )); Sandbox sandbox = daytona.create(params); String mountPath = "/home/daytona/r2"; sandbox.getProcess().executeCommand("mkdir -p " + mountPath); sandbox.getProcess().executeCommand( "mount-s3 --endpoint-url https://" + accountId + ".r2.cloudflarestorage.com " + "my-r2-bucket " + mountPath); ExecuteResponse response = sandbox.getProcess().executeCommand("ls " + mountPath); System.out.println(response.getResult()); } } } ``` ### Runtime install Start from a default sandbox and install `mount-s3` during startup, then mount your bucket with the R2 `--endpoint-url`. This path is convenient for prototyping or one-off tasks, but each new sandbox pays the package installation cost. ```python import os from daytona import CreateSandboxBaseParams, Daytona daytona = Daytona() account_id = os.environ["R2_ACCOUNT_ID"] sandbox = daytona.create( CreateSandboxBaseParams( env_vars={ "AWS_ACCESS_KEY_ID": os.environ["R2_ACCESS_KEY_ID"], "AWS_SECRET_ACCESS_KEY": os.environ["R2_SECRET_ACCESS_KEY"], }, ) ) # Install mount-s3 sandbox.process.exec( "sudo apt-get update " "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget" ) sandbox.process.exec( 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' '&& wget -O /tmp/mount-s3.deb ' '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' "&& sudo apt-get install -y /tmp/mount-s3.deb" ) # Mount with R2 endpoint mount_path = "/home/daytona/r2" sandbox.process.exec( f"mkdir -p {mount_path} && " f"mount-s3 --endpoint-url https://{account_id}.r2.cloudflarestorage.com " f"my-r2-bucket {mount_path}" ) response = sandbox.process.exec(f"ls {mount_path}") print(response.result) ``` ```typescript import { Daytona } from '@daytona/sdk' const daytona = new Daytona() const accountId = process.env.R2_ACCOUNT_ID! const sandbox = await daytona.create({ envVars: { AWS_ACCESS_KEY_ID: process.env.R2_ACCESS_KEY_ID!, AWS_SECRET_ACCESS_KEY: process.env.R2_SECRET_ACCESS_KEY!, }, }) // Install mount-s3 await sandbox.process.executeCommand( 'sudo apt-get update ' + '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget', ) await sandbox.process.executeCommand( 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' + '&& wget -O /tmp/mount-s3.deb ' + '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' + '&& sudo apt-get install -y /tmp/mount-s3.deb', ) // Mount with R2 endpoint const mountPath = '/home/daytona/r2' await sandbox.process.executeCommand( `mkdir -p ${mountPath} && ` + `mount-s3 --endpoint-url https://${accountId}.r2.cloudflarestorage.com ` + `my-r2-bucket ${mountPath}`, ) const response = await sandbox.process.executeCommand(`ls ${mountPath}`) console.log(response.result) ``` ```ruby require 'daytona' daytona = Daytona::Daytona.new account_id = ENV.fetch('R2_ACCOUNT_ID') sandbox = daytona.create( Daytona::CreateSandboxBaseParams.new( env_vars: { 'AWS_ACCESS_KEY_ID' => ENV.fetch('R2_ACCESS_KEY_ID'), 'AWS_SECRET_ACCESS_KEY' => ENV.fetch('R2_SECRET_ACCESS_KEY') } ) ) # Install mount-s3 sandbox.process.exec( command: 'sudo apt-get update ' \ '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget' ) sandbox.process.exec( command: 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' \ '&& wget -O /tmp/mount-s3.deb ' \ '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' \ '&& sudo apt-get install -y /tmp/mount-s3.deb' ) # Mount with R2 endpoint mount_path = '/home/daytona/r2' sandbox.process.exec( command: "mkdir -p #{mount_path} && " \ "mount-s3 --endpoint-url https://#{account_id}.r2.cloudflarestorage.com " \ "my-r2-bucket #{mount_path}" ) response = sandbox.process.exec(command: "ls #{mount_path}") puts response.result ``` ```go import ( "context" "fmt" "log" "os" "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types" ) ctx := context.Background() client, err := daytona.NewClient() if err != nil { log.Fatal(err) } accountID := os.Getenv("R2_ACCOUNT_ID") sandbox, err := client.Create(ctx, types.SnapshotParams{ SandboxBaseParams: types.SandboxBaseParams{ EnvVars: map[string]string{ "AWS_ACCESS_KEY_ID": os.Getenv("R2_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY": os.Getenv("R2_SECRET_ACCESS_KEY"), }, }, }) if err != nil { log.Fatal(err) } // Install mount-s3 if _, err := sandbox.Process.ExecuteCommand(ctx, "sudo apt-get update && sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget"); err != nil { log.Fatal(err) } if _, err := sandbox.Process.ExecuteCommand(ctx, `arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" && `+ `wget -O /tmp/mount-s3.deb "https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" && `+ `sudo apt-get install -y /tmp/mount-s3.deb`); err != nil { log.Fatal(err) } // Mount with R2 endpoint mountPath := "/home/daytona/r2" if _, err := sandbox.Process.ExecuteCommand(ctx, "mkdir -p "+mountPath+" && "+ "mount-s3 --endpoint-url https://"+accountID+".r2.cloudflarestorage.com "+ "my-r2-bucket "+mountPath); err != nil { log.Fatal(err) } response, err := sandbox.Process.ExecuteCommand(ctx, "ls "+mountPath) if err != nil { log.Fatal(err) } fmt.Println(response.Result) ``` ```java import io.daytona.sdk.Daytona; import io.daytona.sdk.Sandbox; import io.daytona.sdk.model.CreateSandboxFromSnapshotParams; import io.daytona.sdk.model.ExecuteResponse; import java.util.Map; public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { String accountId = System.getenv("R2_ACCOUNT_ID"); CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setEnvVars(Map.of( "AWS_ACCESS_KEY_ID", System.getenv("R2_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY", System.getenv("R2_SECRET_ACCESS_KEY") )); Sandbox sandbox = daytona.create(params); // Install mount-s3 sandbox.getProcess().executeCommand( "sudo apt-get update " + "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget"); sandbox.getProcess().executeCommand( "arch=\"$(dpkg --print-architecture | sed s/amd64/x86_64/)\" " + "&& wget -O /tmp/mount-s3.deb " + "\"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb\" " + "&& sudo apt-get install -y /tmp/mount-s3.deb"); // Mount with R2 endpoint String mountPath = "/home/daytona/r2"; sandbox.getProcess().executeCommand( "mkdir -p " + mountPath + " && " + "mount-s3 --endpoint-url https://" + accountId + ".r2.cloudflarestorage.com " + "my-r2-bucket " + mountPath); ExecuteResponse response = sandbox.getProcess().executeCommand("ls " + mountPath); System.out.println(response.getResult()); } } } ``` ## Mount a Tigris bucket Mount a Tigris bucket with the same `mount-s3` tool used for S3. Pass `--endpoint-url https://t3.storage.dev`, because Tigris uses one global endpoint with no per-account subdomain. Tigris also supports bucket snapshots and copy-on-write forks through request headers, so each sandbox can use an isolated writable bucket without duplicating source data. **Credentials** — set `TIGRIS_STORAGE_ACCESS_KEY_ID` and `TIGRIS_STORAGE_SECRET_ACCESS_KEY` in your local environment. The snippets below pass these into the sandbox via `envVars` under the `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` names that `mount-s3` expects. ### Pre-built snapshot Build a snapshot with `mount-s3` preinstalled, then launch Tigris sandboxes from that snapshot. The mount flow matches S3 except for the Tigris `--endpoint-url`, and startup stays fast because installation happens once during snapshot build. #### Build a snapshot Create a reusable snapshot that installs `mount-s3`. Because Tigris is S3-compatible, this setup matches S3 and only the runtime mount command changes. ```python from daytona import CreateSnapshotParams, Daytona, Image daytona = Daytona() image = ( Image.base("daytonaio/sandbox") .run_commands( "sudo apt-get update " "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget", 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' '&& wget -O /tmp/mount-s3.deb ' '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' "&& sudo apt-get install -y /tmp/mount-s3.deb " "&& rm /tmp/mount-s3.deb", ) ) daytona.snapshot.create( CreateSnapshotParams(name="fuse-tigris", image=image), on_logs=print, ) ``` ```typescript import { Daytona, Image } from '@daytona/sdk' const daytona = new Daytona() const image = Image.base('daytonaio/sandbox').runCommands( 'sudo apt-get update ' + '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget', 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' + '&& wget -O /tmp/mount-s3.deb ' + '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' + '&& sudo apt-get install -y /tmp/mount-s3.deb ' + '&& rm /tmp/mount-s3.deb', ) await daytona.snapshot.create( { name: 'fuse-tigris', image }, { onLogs: console.log }, ) ``` ```ruby require 'daytona' daytona = Daytona::Daytona.new image = Daytona::Image .base('daytonaio/sandbox') .run_commands( 'sudo apt-get update ' \ '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget', 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' \ '&& wget -O /tmp/mount-s3.deb ' \ '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' \ '&& sudo apt-get install -y /tmp/mount-s3.deb ' \ '&& rm /tmp/mount-s3.deb' ) daytona.snapshot.create( Daytona::CreateSnapshotParams.new(name: 'fuse-tigris', image: image), on_logs: proc { |chunk| print(chunk) } ) ``` ```go import ( "context" "fmt" "log" "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types" ) ctx := context.Background() client, err := daytona.NewClient() if err != nil { log.Fatal(err) } image := daytona.Base("daytonaio/sandbox"). Run("sudo apt-get update && sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget"). Run(`arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" && ` + `wget -O /tmp/mount-s3.deb "https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" && ` + `sudo apt-get install -y /tmp/mount-s3.deb && rm /tmp/mount-s3.deb`) _, logChan, err := client.Snapshot.Create(ctx, &types.CreateSnapshotParams{ Name: "fuse-tigris", Image: image, }) if err != nil { log.Fatal(err) } for line := range logChan { fmt.Print(line) } ``` ```java import io.daytona.sdk.Daytona; import io.daytona.sdk.Image; public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { Image image = Image.base("daytonaio/sandbox") .runCommands( "sudo apt-get update " + "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget", "arch=\"$(dpkg --print-architecture | sed s/amd64/x86_64/)\" " + "&& wget -O /tmp/mount-s3.deb " + "\"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb\" " + "&& sudo apt-get install -y /tmp/mount-s3.deb " + "&& rm /tmp/mount-s3.deb" ); daytona.snapshot().create("fuse-tigris", image, System.out::println); } } } ``` #### Launch and mount Pass Tigris credentials into the sandbox as `AWS_*` environment variables, then mount with the Tigris endpoint URL. This keeps authentication compatible with `mount-s3` while targeting your Tigris account. ```python import os from daytona import CreateSandboxFromSnapshotParams, Daytona daytona = Daytona() sandbox = daytona.create( CreateSandboxFromSnapshotParams( snapshot="fuse-tigris", env_vars={ "AWS_ACCESS_KEY_ID": os.environ["TIGRIS_STORAGE_ACCESS_KEY_ID"], "AWS_SECRET_ACCESS_KEY": os.environ["TIGRIS_STORAGE_SECRET_ACCESS_KEY"], }, ) ) mount_path = "/home/daytona/tigris" sandbox.process.exec(f"mkdir -p {mount_path}") sandbox.process.exec( f"mount-s3 --endpoint-url https://t3.storage.dev " f"my-tigris-bucket {mount_path}" ) response = sandbox.process.exec(f"ls {mount_path}") print(response.result) ``` ```typescript import { Daytona } from '@daytona/sdk' const daytona = new Daytona() const sandbox = await daytona.create({ snapshot: 'fuse-tigris', envVars: { AWS_ACCESS_KEY_ID: process.env.TIGRIS_STORAGE_ACCESS_KEY_ID!, AWS_SECRET_ACCESS_KEY: process.env.TIGRIS_STORAGE_SECRET_ACCESS_KEY!, }, }) const mountPath = '/home/daytona/tigris' await sandbox.process.executeCommand(`mkdir -p ${mountPath}`) await sandbox.process.executeCommand( `mount-s3 --endpoint-url https://t3.storage.dev ` + `my-tigris-bucket ${mountPath}`, ) const response = await sandbox.process.executeCommand(`ls ${mountPath}`) console.log(response.result) ``` ```ruby require 'daytona' daytona = Daytona::Daytona.new sandbox = daytona.create( Daytona::CreateSandboxFromSnapshotParams.new( snapshot: 'fuse-tigris', env_vars: { 'AWS_ACCESS_KEY_ID' => ENV.fetch('TIGRIS_STORAGE_ACCESS_KEY_ID'), 'AWS_SECRET_ACCESS_KEY' => ENV.fetch('TIGRIS_STORAGE_SECRET_ACCESS_KEY') } ) ) mount_path = '/home/daytona/tigris' sandbox.process.exec(command: "mkdir -p #{mount_path}") sandbox.process.exec( command: 'mount-s3 --endpoint-url https://t3.storage.dev ' \ "my-tigris-bucket #{mount_path}" ) response = sandbox.process.exec(command: "ls #{mount_path}") puts response.result ``` ```go import ( "context" "fmt" "log" "os" "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types" ) ctx := context.Background() client, err := daytona.NewClient() if err != nil { log.Fatal(err) } sandbox, err := client.Create(ctx, types.SnapshotParams{ Snapshot: "fuse-tigris", SandboxBaseParams: types.SandboxBaseParams{ EnvVars: map[string]string{ "AWS_ACCESS_KEY_ID": os.Getenv("TIGRIS_STORAGE_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY": os.Getenv("TIGRIS_STORAGE_SECRET_ACCESS_KEY"), }, }, }) if err != nil { log.Fatal(err) } mountPath := "/home/daytona/tigris" if _, err := sandbox.Process.ExecuteCommand(ctx, "mkdir -p "+mountPath); err != nil { log.Fatal(err) } if _, err := sandbox.Process.ExecuteCommand(ctx, "mount-s3 --endpoint-url https://t3.storage.dev "+ "my-tigris-bucket "+mountPath); err != nil { log.Fatal(err) } response, err := sandbox.Process.ExecuteCommand(ctx, "ls "+mountPath) if err != nil { log.Fatal(err) } fmt.Println(response.Result) ``` ```java import io.daytona.sdk.Daytona; import io.daytona.sdk.Sandbox; import io.daytona.sdk.model.CreateSandboxFromSnapshotParams; import io.daytona.sdk.model.ExecuteResponse; import java.util.Map; public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setSnapshot("fuse-tigris"); params.setEnvVars(Map.of( "AWS_ACCESS_KEY_ID", System.getenv("TIGRIS_STORAGE_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY", System.getenv("TIGRIS_STORAGE_SECRET_ACCESS_KEY") )); Sandbox sandbox = daytona.create(params); String mountPath = "/home/daytona/tigris"; sandbox.getProcess().executeCommand("mkdir -p " + mountPath); sandbox.getProcess().executeCommand( "mount-s3 --endpoint-url https://t3.storage.dev " + "my-tigris-bucket " + mountPath); ExecuteResponse response = sandbox.getProcess().executeCommand("ls " + mountPath); System.out.println(response.getResult()); } } } ``` ### Runtime install Start from a default sandbox, install `mount-s3` during startup, then mount with the Tigris `--endpoint-url`. This path is convenient for prototyping or one-off tasks, but each new sandbox repeats package installation. ```python import os from daytona import CreateSandboxBaseParams, Daytona daytona = Daytona() sandbox = daytona.create( CreateSandboxBaseParams( env_vars={ "AWS_ACCESS_KEY_ID": os.environ["TIGRIS_STORAGE_ACCESS_KEY_ID"], "AWS_SECRET_ACCESS_KEY": os.environ["TIGRIS_STORAGE_SECRET_ACCESS_KEY"], }, ) ) # Install mount-s3 sandbox.process.exec( "sudo apt-get update " "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget" ) sandbox.process.exec( 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' '&& wget -O /tmp/mount-s3.deb ' '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' "&& sudo apt-get install -y /tmp/mount-s3.deb" ) # Mount with Tigris endpoint mount_path = "/home/daytona/tigris" sandbox.process.exec( f"mkdir -p {mount_path} && " f"mount-s3 --endpoint-url https://t3.storage.dev " f"my-tigris-bucket {mount_path}" ) response = sandbox.process.exec(f"ls {mount_path}") print(response.result) ``` ```typescript import { Daytona } from '@daytona/sdk' const daytona = new Daytona() const sandbox = await daytona.create({ envVars: { AWS_ACCESS_KEY_ID: process.env.TIGRIS_STORAGE_ACCESS_KEY_ID!, AWS_SECRET_ACCESS_KEY: process.env.TIGRIS_STORAGE_SECRET_ACCESS_KEY!, }, }) // Install mount-s3 await sandbox.process.executeCommand( 'sudo apt-get update ' + '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget', ) await sandbox.process.executeCommand( 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' + '&& wget -O /tmp/mount-s3.deb ' + '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' + '&& sudo apt-get install -y /tmp/mount-s3.deb', ) // Mount with Tigris endpoint const mountPath = '/home/daytona/tigris' await sandbox.process.executeCommand( `mkdir -p ${mountPath} && ` + `mount-s3 --endpoint-url https://t3.storage.dev ` + `my-tigris-bucket ${mountPath}`, ) const response = await sandbox.process.executeCommand(`ls ${mountPath}`) console.log(response.result) ``` ```ruby require 'daytona' daytona = Daytona::Daytona.new sandbox = daytona.create( Daytona::CreateSandboxBaseParams.new( env_vars: { 'AWS_ACCESS_KEY_ID' => ENV.fetch('TIGRIS_STORAGE_ACCESS_KEY_ID'), 'AWS_SECRET_ACCESS_KEY' => ENV.fetch('TIGRIS_STORAGE_SECRET_ACCESS_KEY') } ) ) # Install mount-s3 sandbox.process.exec( command: 'sudo apt-get update ' \ '&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget' ) sandbox.process.exec( command: 'arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" ' \ '&& wget -O /tmp/mount-s3.deb ' \ '"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" ' \ '&& sudo apt-get install -y /tmp/mount-s3.deb' ) # Mount with Tigris endpoint mount_path = '/home/daytona/tigris' sandbox.process.exec( command: "mkdir -p #{mount_path} && " \ 'mount-s3 --endpoint-url https://t3.storage.dev ' \ "my-tigris-bucket #{mount_path}" ) response = sandbox.process.exec(command: "ls #{mount_path}") puts response.result ``` ```go import ( "context" "fmt" "log" "os" "github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types" ) ctx := context.Background() client, err := daytona.NewClient() if err != nil { log.Fatal(err) } sandbox, err := client.Create(ctx, types.SnapshotParams{ SandboxBaseParams: types.SandboxBaseParams{ EnvVars: map[string]string{ "AWS_ACCESS_KEY_ID": os.Getenv("TIGRIS_STORAGE_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY": os.Getenv("TIGRIS_STORAGE_SECRET_ACCESS_KEY"), }, }, }) if err != nil { log.Fatal(err) } // Install mount-s3 if _, err := sandbox.Process.ExecuteCommand(ctx, "sudo apt-get update && sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget"); err != nil { log.Fatal(err) } if _, err := sandbox.Process.ExecuteCommand(ctx, `arch="$(dpkg --print-architecture | sed s/amd64/x86_64/)" && `+ `wget -O /tmp/mount-s3.deb "https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb" && `+ `sudo apt-get install -y /tmp/mount-s3.deb`); err != nil { log.Fatal(err) } // Mount with Tigris endpoint mountPath := "/home/daytona/tigris" if _, err := sandbox.Process.ExecuteCommand(ctx, "mkdir -p "+mountPath+" && "+ "mount-s3 --endpoint-url https://t3.storage.dev "+ "my-tigris-bucket "+mountPath); err != nil { log.Fatal(err) } response, err := sandbox.Process.ExecuteCommand(ctx, "ls "+mountPath) if err != nil { log.Fatal(err) } fmt.Println(response.Result) ``` ```java import io.daytona.sdk.Daytona; import io.daytona.sdk.Sandbox; import io.daytona.sdk.model.CreateSandboxFromSnapshotParams; import io.daytona.sdk.model.ExecuteResponse; import java.util.Map; public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setEnvVars(Map.of( "AWS_ACCESS_KEY_ID", System.getenv("TIGRIS_STORAGE_ACCESS_KEY_ID"), "AWS_SECRET_ACCESS_KEY", System.getenv("TIGRIS_STORAGE_SECRET_ACCESS_KEY") )); Sandbox sandbox = daytona.create(params); // Install mount-s3 sandbox.getProcess().executeCommand( "sudo apt-get update " + "&& sudo apt-get install -y --no-install-recommends libfuse2 ca-certificates wget"); sandbox.getProcess().executeCommand( "arch=\"$(dpkg --print-architecture | sed s/amd64/x86_64/)\" " + "&& wget -O /tmp/mount-s3.deb " + "\"https://s3.amazonaws.com/mountpoint-s3-release/latest/${arch}/mount-s3.deb\" " + "&& sudo apt-get install -y /tmp/mount-s3.deb"); // Mount with Tigris endpoint String mountPath = "/home/daytona/tigris"; sandbox.getProcess().executeCommand( "mkdir -p " + mountPath + " && " + "mount-s3 --endpoint-url https://t3.storage.dev " + "my-tigris-bucket " + mountPath); ExecuteResponse response = sandbox.getProcess().executeCommand("ls " + mountPath); System.out.println(response.getResult()); } } } ``` ### Mount a copy-on-write fork per sandbox A Tigris bucket fork is a new bucket created from a snapshot of a source bucket. The fork shares underlying storage with the source until written to — new writes go only to the fork, and the source bucket and other forks are unaffected. Fork creation is constant-time regardless of source bucket size. This pattern fits Daytona sandboxes when each sandbox needs a writable copy of a shared dataset (model weights, fixtures, golden data) without duplicating it on every launch. **Prerequisite** — the source bucket must be created with snapshots enabled. This is a one-time setup, done outside the per-sandbox flow: ```typescript import { createBucket } from '@tigrisdata/storage' await createBucket('my-source-bucket', { enableSnapshot: true }) ``` In any S3 SDK, send a `CreateBucket` request with the header `X-Tigris-Enable-Snapshot: true`. The `@tigrisdata/agent-kit` package wraps this workflow as `createForks()`. It snapshots the source bucket and creates one or more forks in a single call. Passing `credentials: { role: 'Editor' }` also creates a scoped access key per fork, so each sandbox can read and write only its own fork bucket instead of the full account. ```typescript import { createForks, teardownForks } from '@tigrisdata/agent-kit' import { Daytona } from '@daytona/sdk' const SOURCE_BUCKET = 'my-source-bucket' // 1. Snapshot the source and create a fork with a scoped access key const { data: forkSet, error } = await createForks(SOURCE_BUCKET, 1, { credentials: { role: 'Editor' }, }) if (error) throw error const fork = forkSet.forks[0] // 2. Launch the sandbox with the fork's scoped credentials const daytona = new Daytona() const sandbox = await daytona.create({ snapshot: 'fuse-tigris', envVars: { AWS_ACCESS_KEY_ID: fork.credentials!.accessKeyId, AWS_SECRET_ACCESS_KEY: fork.credentials!.secretAccessKey, }, }) // 3. Mount the fork bucket const mountPath = '/home/daytona/tigris' await sandbox.process.executeCommand(`mkdir -p ${mountPath}`) await sandbox.process.executeCommand( `mount-s3 --endpoint-url https://t3.storage.dev ${fork.bucket} ${mountPath}`, ) try { const response = await sandbox.process.executeCommand(`ls ${mountPath}`) console.log(response.result) } finally { await daytona.delete(sandbox) await teardownForks(forkSet) // revokes the scoped key and deletes the fork bucket } ``` To run the same workflow from a language without an `agent-kit` equivalent, use any S3 SDK and send the headers documented below. Send `X-Tigris-Snapshot: true` on `CreateBucket` for the source name, then capture `X-Tigris-Snapshot-Version` from the response. Next, send `CreateBucket` for the fork name with `X-Tigris-Fork-Source-Bucket` and `X-Tigris-Fork-Source-Bucket-Snapshot`. Mount the fork with the same `mount-s3` snippets shown above, replacing the bucket name with the fork bucket. #### Reference: Tigris-specific headers These headers drive snapshot and fork operations over the S3 API. Use them with any AWS SDK (boto3, aws-sdk-go-v2, aws-sdk-java-v2, aws-sdk-ruby) by attaching a request interceptor. | Header | Sent on | Purpose | | ------------------------------------------ | ----------------------------------------- | ------------------------------------------------------------------------------ | | **`X-Tigris-Enable-Snapshot: true`** | **`CreateBucket`** (new source) | Enable snapshots on a new bucket. Required before snapshotting it. | | **`X-Tigris-Snapshot: true`** | **`CreateBucket`** (existing source name) | Take a snapshot of the bucket. Optional **`; name=