# Connect Storage Bucket
<subtitle>Use s3fs to mount an S3-compatible object storage bucket to a local directory in the sandbox, enabling you to read and write remote objects as if they were local files.</subtitle>

## Environment Setup

Before using the SDK, make sure the `AGENTBOX_API_KEY` environment variable is configured.

> [!NOTE]
> You can obtain your API key from the [Console API Keys page](https://console.ucloud.cn/modelverse/experience/api-keys).

```bash
export AGENTBOX_API_KEY=your_api_key
```

---

## Feature Overview

`s3fs` is a FUSE-based tool that allows you to mount S3-compatible buckets (such as UCloud US3, AWS S3, Cloudflare R2, etc.) to a local directory. You can operate on objects in the storage bucket just like a local file system.

The sandbox runs on Debian by default, and you can install s3fs directly via `apt-get`.

---

## Using via CLI

### 1. Create Sandbox and Install s3fs

```bash
# Create a sandbox and enter the terminal
ucloud-sandbox-cli sbx cr base

# Install s3fs in the sandbox terminal
user@ucloud:~$ sudo apt-get update && sudo apt-get install -y s3fs

# Verify installation
user@ucloud:~$ s3fs --version
Amazon Simple Storage Service File System V1.90 (commit:unknown) with GnuTLS(gcrypt)
```

### 2. Configure Credentials

Create a credential file in the format `AccessKeyID:SecretAccessKey`.

> [!NOTE]
> Please refer to your cloud provider’s documentation for obtaining S3 AccessKeyID and SecretAccessKey.

```bash
# Write credentials
user@ucloud:~$ sudo vim /root/.passwd-s3fs
# File content format: access-token:secret-access-token

# Set permissions
user@ucloud:~$ sudo chmod 600 /root/.passwd-s3fs
```

### 3. Mount the Bucket

```bash
# Create mount directory
user@ucloud:~$ mkdir /home/user/s3-data

# Mount S3-compatible bucket
# The sandbox can use the internal endpoint for Ulanqab:
# http://internal.s3-cn-wlcb.ufileos.com
# or other public S3 endpoints.

user@ucloud:~$ sudo s3fs <bucket-name> /home/user/s3-data \
  -o url=<S3EndpointURL> \
  -o passwd_file=/root/.passwd-s3fs \
  -o dbglevel=info \
  -o curldbg,use_path_request_style,allow_other,nomixupload \
  -o retries=1 \
  -o multipart_size=8 \
  -o multireq_max=8 \
  -o parallel_count=32
```

### 4. Verify Mount

```bash
user@ucloud:~$ ls /home/user/s3-data/
gpt-oss-20b  qwen3-32b  ufile-log
```

### 5. File Operations

After mounting successfully, you can read and write objects in the bucket just like local files.

```bash
# Upload file (copy to mount directory)
user@ucloud:~$ cp local-file.txt /home/user/s3-data/

# Download file (copy from mount directory)
user@ucloud:~$ cp /home/user/s3-data/remote-file.txt ./

# Delete file
user@ucloud:~$ rm /home/user/s3-data/remote-file.txt
```

### 6. Unmount Bucket

```bash
user@ucloud:~$ sudo umount /home/user/s3-data
```

---

## Using via Python SDK

Below is a complete example demonstrating how to install s3fs, mount a bucket, and perform file operations within the sandbox using the SDK.

```python
import os
import time
from ucloud_sandbox import Sandbox

# S3 configuration (read from environment variables)
S3_ACCESS_KEY = os.environ.get("S3_ACCESS_KEY", "")
S3_SECRET_KEY = os.environ.get("S3_SECRET_KEY", "")
S3_BUCKET = os.environ.get("S3_BUCKET", "bucket_name")
S3_ENDPOINT = os.environ.get("S3_ENDPOINT", "http://internal.s3-cn-wlcb.ufileos.com")
MOUNT_DIR = "/home/user/s3-data"

# Create sandbox
sbx = Sandbox.create(timeout=120)

# 1. Install s3fs
result = sbx.commands.run(
    "sudo apt-get update && sudo apt-get install -y s3fs",
    timeout=120,
)
result = sbx.commands.run("s3fs --version")
print(f"s3fs version: {result.stdout.strip().splitlines()[0]}")

# 2. Configure S3 credentials
sbx.files.write("/root/.passwd-s3fs", f"{S3_ACCESS_KEY}:{S3_SECRET_KEY}")
sbx.commands.run("sudo chmod 600 /root/.passwd-s3fs")

# 3. Create mount directory
sbx.files.make_dir(MOUNT_DIR)

# 4. Mount bucket
sbx.commands.run(
    f"sudo s3fs {S3_BUCKET} {MOUNT_DIR} "
    f"-o url={S3_ENDPOINT} "
    f"-o passwd_file=/root/.passwd-s3fs "
    f"-o dbglevel=info "
    f"-o curldbg,use_path_request_style,allow_other,nomixupload "
    f"-o retries=1 "
    f"-o multipart_size=8 "
    f"-o multireq_max=8 "
    f"-o parallel_count=32"
)

# Verify mount
result = sbx.commands.run(f"df -h | grep s3fs")
print(f"Mount info: {result.stdout.strip()}")

# 5. File operations
# Write file to bucket
test_file = f"{MOUNT_DIR}/sdk_test_{int(time.time())}.txt"
sbx.files.write(test_file, "Hello from AgentBox SDK!")

# Read file from bucket
content = sbx.files.read(test_file)
print(f"Read content: {content}")

# List directory
result = sbx.commands.run(f"ls {MOUNT_DIR} | head -10")
print(f"Directory contents:\n{result.stdout}")

# Delete test file
sbx.commands.run(f"rm {test_file}")

# 6. Unmount bucket
sbx.commands.run(f"sudo umount {MOUNT_DIR}")

# Cleanup sandbox
sbx.kill()
```

---

## Parameter Description

| Parameter              | Description                                                                                               |
| ---------------------- | --------------------------------------------------------------------------------------------------------- |
| `<bucket-name>`        | Bucket name without domain suffix. For example, if the US3 bucket is `test.cn-bj.ufileos.com`, use `test` |
| `-o url`               | S3 API endpoint. Required for non-AWS services like UCloud US3 and Cloudflare R2                          |
| `-o passwd_file`       | Path to credential file                                                                                   |
| `-o multipart_size=8`  | Multipart upload size (MB), currently only supports 8MB                                                   |
| `-o multireq_max=8`    | Files larger than 8MB will use multipart upload                                                           |
| `-o parallel_count=32` | Number of parallel operations, improves concurrency (recommended ≤128)                                    |
| `-o allow_other`       | Allow non-root users to access the mount directory                                                        |
| `-o retries=1`         | Retry count on failure                                                                                    |

---

## Permission Recommendation

> [!NOTE]
> If you want non-root users to read and write the mount directory, add the `-o allow_other` option and optionally set `-o uid=<user_id> -o gid=<group_id>`.

---

## Notes

> [!WARNING]
> Objects with paths that do not comply with Linux file path conventions may be visible in the console but will not appear in the mounted directory. File listing operations may be slow; it is recommended to directly operate on specific files using commands like `cp` or `rm`.

---

## Performance Reference

| Operation | Throughput                               |
| --------- | ---------------------------------------- |
| Write     | ~40 MB/s                                 |
| Read      | Up to ~166 MB/s (depends on concurrency) |
