Skip to content
Object Storage Buckets

Mount Object Storage Buckets

Sandboxes support mounting S3-compatible object storage buckets internally using FUSE technology, allowing you to read and write remote object storage data as if it were local files. Sufy Kodo object storage is compatible with the AWS S3 protocol and can be mounted directly using the s3fs tool.

Use Cases

  • Accessing large amounts of pre-stored data (e.g., datasets, model files) within a sandbox.
  • Sharing the same remote data across multiple sandboxes.
  • Persisting files generated in a sandbox to object storage for long-term retention.

Important Notes

  • Object storage mounting relies on network transfer, so read/write performance is lower than local file systems. It is not suitable for high-frequency I/O scenarios.
  • File operations are non-atomic, meaning there is a risk of local success but remote write failure.
  • Suitable for low-frequency read/write and performance-insensitive data access scenarios.
  • The runtime environment requires a usable FUSE device (/dev/fuse).
  • Before using -o allow_other, you must enable user_allow_other in the environment (see the template configuration below).
  • It is recommended to unmount (fusermount -u) before destroying a sandbox to reduce the risk of incomplete writes.
  • In production code, environment variables in examples should be validated and shell-escaped.

Prerequisites: Create a Template with s3fs

Install s3fs and configure static FUSE settings in your sandbox template's Dockerfile. Since the sandbox runs as the user by default, pre-create the mount directory during the build phase:

dockerfile
FROM e2b/base:latest

# Install s3fs
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y s3fs && rm -rf /var/lib/apt/lists/*

# Enable user_allow_other to allow non-root users to use the -o allow_other mount option
RUN sed -i 's/#user_allow_other/user_allow_other/' /etc/fuse.conf

# Pre-create the mount directory and assign ownership to the default user
RUN mkdir -p /mnt/bucket && chown user:user /mnt/bucket

The /dev/fuse device is provided by the sandbox runtime, so it should not be modified in the Dockerfile build step. If your runtime image requires a permission adjustment, run sudo chmod 666 /dev/fuse after the sandbox starts and before mounting the bucket.

After building a custom template with s3fs, create a sandbox using that template to use the mount feature. For details on creating and building custom templates, refer to the Sandbox Template documentation.

Note: If you do not use a custom template, you can perform the above configuration at runtime using sudo, but this must be repeated each time a sandbox is created. It is recommended to bake the configuration into the template.

Mounting a Sufy Kodo Bucket

Sufy Kodo is compatible with the AWS S3 protocol. Use the S3 endpoint for the corresponding region to mount via s3fs.

Mounting steps:

  1. Write the AccessKey and SecretKey to a credentials file and set permissions to 600.
  2. Use the s3fs command to mount the bucket to the specified directory.
javascript
import "dotenv/config";
import { Sandbox } from "@e2b/code-interpreter";

async function main() {
  const KODO_ACCESS_KEY = process.env.KODO_ACCESS_KEY;
  const KODO_SECRET_KEY = process.env.KODO_SECRET_KEY;
  const KODO_BUCKET_NAME = process.env.KODO_BUCKET_NAME;
  const KODO_S3_ENDPOINT = process.env.KODO_S3_ENDPOINT; // e.g., https://s3.cn-east-1.sufycs.com
  const MOUNT_DIR = "/mnt/bucket";

  if (
    !KODO_ACCESS_KEY ||
    !KODO_SECRET_KEY ||
    !KODO_BUCKET_NAME ||
    !KODO_S3_ENDPOINT
  ) {
    throw new Error(
      "Missing required env vars: KODO_ACCESS_KEY, KODO_SECRET_KEY, KODO_BUCKET_NAME, KODO_S3_ENDPOINT",
    );
  }

  // Production recommendation: validate and escape user-controlled parameters before inserting into shell commands.
  const shellEscape = (value) => `'${value.replace(/'/g, `'\\''`)}'`;

  const sandbox = await Sandbox.create("your-s3fs-template");

  try {
    // Write credentials file (default sandbox user is 'user')
    await sandbox.files.write(
      "/home/user/.passwd-s3fs",
      `${KODO_ACCESS_KEY}:${KODO_SECRET_KEY}`,
    );
    await sandbox.commands.run("chmod 600 /home/user/.passwd-s3fs");

    // Mount the bucket (mount directory pre-created in template Dockerfile)
    await sandbox.commands.run(
      `s3fs ${shellEscape(KODO_BUCKET_NAME)} ${MOUNT_DIR} -o url=${shellEscape(KODO_S3_ENDPOINT)} -o allow_other -o use_path_request_style -o passwd_file=/home/user/.passwd-s3fs`,
    );

    // Wait for mount to be ready (s3fs initialization takes a few seconds)
    await sandbox.commands.run(
      `for i in $(seq 1 10); do mountpoint -q ${MOUNT_DIR} && touch ${MOUNT_DIR}/.ready 2>/dev/null && rm -f ${MOUNT_DIR}/.ready && break; sleep 1; done`,
    );

    // Verify mount result
    const files = await sandbox.commands.run(`ls ${MOUNT_DIR}`);
    console.log("Bucket contents:", files.stdout);

    // Read and write like local files
    await sandbox.commands.run(`echo "hello kodo" > ${MOUNT_DIR}/test.txt`);
    const result = await sandbox.commands.run(`cat ${MOUNT_DIR}/test.txt`);
    console.log(result.stdout); // Output: hello kodo\n
  } finally {
    await sandbox.commands.run(`fusermount -u ${MOUNT_DIR}`).catch(() => {});
    await sandbox.kill();
  }
}

main();

Parameter Description

ParameterDescription
KODO_ACCESS_KEYSufy AccessKey
KODO_SECRET_KEYSufy SecretKey
KODO_BUCKET_NAMEBucket name
KODO_S3_ENDPOINTS3-compatible endpoint, e.g., https://s3.cn-east-1.sufycs.com
MOUNT_DIRMount directory path inside the sandbox (must be pre-created in the template)

s3fs Mount Options

OptionDescription
-o urlEndpoint URL of the S3-compatible service
-o allow_otherAllow other users to access the mount directory (requires user_allow_other)
-o use_path_request_styleUse path-style URL (required for Sufy Kodo)
-o passwd_fileSpecify the credentials file path (default is ~/.passwd-s3fs)

For more s3fs configuration and usage, refer to the Sufy Kodo S3FS Usage Guide.

S3-Compatible Service Domains

KODO_S3_ENDPOINT must be the S3-compatible domain for the bucket's region. The following are the domains for each region:

Storage RegionRegion IDEndpoint
East China - Zhejiangcn-east-1https://s3.cn-east-1.sufycs.com
East China - Zhejiang 2cn-east-2https://s3.cn-east-2.sufycs.com
North China - Hebeicn-north-1https://s3.cn-north-1.sufycs.com
South China - Guangdongcn-south-1https://s3.cn-south-1.sufycs.com
North America - Los Angelesus-north-1https://s3.us-north-1.sufycs.com
Asia Pacific - Singaporeap-southeast-1https://s3.ap-southeast-1.sufycs.com
Asia Pacific - Hanoiap-southeast-2https://s3.ap-southeast-2.sufycs.com
Asia Pacific - Ho Chi Minhap-southeast-3https://s3.ap-southeast-3.sufycs.com

For a complete list of domains, refer to the Sufy Kodo S3-Compatible Service Domains.

Mounting an AWS S3 Bucket

s3fs also supports mounting AWS S3. The process is similar; simply replace the credentials and endpoint information.

javascript
import "dotenv/config";
import { Sandbox } from "@e2b/code-interpreter";

async function main() {
  const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
  const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
  const AWS_BUCKET_NAME = process.env.AWS_BUCKET_NAME;
  const AWS_REGION = process.env.AWS_REGION || "us-east-1";
  const MOUNT_DIR = "/mnt/bucket";

  if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY || !AWS_BUCKET_NAME) {
    throw new Error(
      "Missing required env vars: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_BUCKET_NAME",
    );
  }

  // Production recommendation: validate and escape user-controlled parameters before inserting into shell commands.
  const shellEscape = (value) => `'${value.replace(/'/g, `'\\''`)}'`;

  const sandbox = await Sandbox.create("your-s3fs-template");

  try {
    // Write credentials file (default sandbox user is 'user')
    await sandbox.files.write(
      "/home/user/.passwd-s3fs",
      `${AWS_ACCESS_KEY_ID}:${AWS_SECRET_ACCESS_KEY}`,
    );
    await sandbox.commands.run("chmod 600 /home/user/.passwd-s3fs");

    // Mount the bucket
    await sandbox.commands.run(
      `s3fs ${shellEscape(AWS_BUCKET_NAME)} ${MOUNT_DIR} -o allow_other -o endpoint=${shellEscape(AWS_REGION)} -o url=${shellEscape(`https://s3.${AWS_REGION}.amazonaws.com`)} -o passwd_file=/home/user/.passwd-s3fs`,
    );

    // Verify mount result
    const files = await sandbox.commands.run(`ls ${MOUNT_DIR}`);
    console.log("Bucket contents:", files.stdout);
  } finally {
    await sandbox.commands.run(`fusermount -u ${MOUNT_DIR}`).catch(() => {});
    await sandbox.kill();
  }
}

main();

Mounting Other S3-Compatible Storage

Any object storage service compatible with the AWS S3 protocol can be mounted using s3fs. In addition to replacing the url, AccessKey, and SecretKey, it is recommended to specify the access style:

  • If the service requires path-style access, add -o use_path_request_style.
  • If the service supports virtual-hosted-style access, you can omit -o use_path_request_style.

Generic example:

javascript
import "dotenv/config";
import { Sandbox } from "@e2b/code-interpreter";

async function main() {
  const S3_ACCESS_KEY = process.env.S3_ACCESS_KEY;
  const S3_SECRET_KEY = process.env.S3_SECRET_KEY;
  const S3_BUCKET_NAME = process.env.S3_BUCKET_NAME;
  const S3_ENDPOINT_URL = process.env.S3_ENDPOINT_URL; // e.g., https://minio.example.com
  const MOUNT_DIR = "/mnt/bucket";

  if (!S3_ACCESS_KEY || !S3_SECRET_KEY || !S3_BUCKET_NAME || !S3_ENDPOINT_URL) {
    throw new Error(
      "Missing required env vars: S3_ACCESS_KEY, S3_SECRET_KEY, S3_BUCKET_NAME, S3_ENDPOINT_URL",
    );
  }

  // Production recommendation: validate and escape user-controlled parameters before inserting into shell commands.
  const shellEscape = (value) => `'${value.replace(/'/g, `'\\''`)}'`;

  const sandbox = await Sandbox.create("your-s3fs-template");

  try {
    await sandbox.files.write(
      "/home/user/.passwd-s3fs",
      `${S3_ACCESS_KEY}:${S3_SECRET_KEY}`,
    );
    await sandbox.commands.run("chmod 600 /home/user/.passwd-s3fs");

    await sandbox.commands.run(
      `s3fs ${shellEscape(S3_BUCKET_NAME)} ${MOUNT_DIR} -o url=${shellEscape(S3_ENDPOINT_URL)} -o allow_other -o use_path_request_style -o passwd_file=/home/user/.passwd-s3fs`,
    );

    const files = await sandbox.commands.run(`ls ${MOUNT_DIR}`);
    console.log("Bucket contents:", files.stdout);
  } finally {
    await sandbox.commands.run(`fusermount -u ${MOUNT_DIR}`).catch(() => {});
    await sandbox.kill();
  }
}

main();