import Image from 'next/image'

# Connecting bucket to the sandbox

To enable persistence of the data in the sandbox we can use a bucket to store the data. We are leveraging the fuse file system to mount the bucket to the sandbox.

You will need to build a custom sandbox template with the fuse file system installed. The guide how to build a custom sandbox template can be found [here](/guide/custom-sandbox).

## Google Cloud Storage

### Prerequisites

To use the Google Cloud Storage we'll need to have a bucket and a service account. The service account can be created [here](https://console.cloud.google.com/iam-admin/serviceaccounts), the bucket can be created [here](https://console.cloud.google.com/storage).

If you want to write to the bucket the service account must have the `Storage Object Admin` role for this bucket.

The guide how to create a service account key can be found [here](https://cloud.google.com/iam/docs/keys-create-delete#iam-service-account-keys-create-console).

### Mounting the bucket

To use the Google Cloud Storage we need to install the `gcsfuse` package. There's simple `Dockerfile` that can be used to create a container with the `gcsfuse` installed.

```docker
FROM ubuntu:latest

RUN apt-get update && apt-get install -y gnupg lsb-release wget

RUN lsb_release -c -s > /tmp/lsb_release
RUN GCSFUSE_REPO=$(cat /tmp/lsb_release); echo "deb https://packages.cloud.google.com/apt gcsfuse-$GCSFUSE_REPO main" | tee /etc/apt/sources.list.d/gcsfuse.list
RUN wget -O - https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -

RUN apt-get update && apt-get install -y gcsfuse

```

The actual mounting of the bucket is done in runtime during the start of the sandbox. The `gcsfuse` command is used to mount the bucket to the sandbox.

<CodeGroup isRunnable={false}>
```js {{ language: 'js' }}
import { Sandbox } from 'e2b'

const sandbox = await Sandbox.create({ template: '<your template id>' })
await sandbox.filesystem.makeDir("/home/user/bucket")
await sandbox.uploadFile("key.json")

const process = await sandbox.process.start("sudo gcsfuse <flags> --key-file /home/user/key.json <bucket-name> /home/user/bucket")
const output = await process.wait()
if (output.exitCode) {
    throw Error(output.stderr)
}
```

```python {{ language: 'python' }}
from e2b import Sandbox

with Sandbox(template="<your template id>") as sandbox:
    sandbox.filesystem.make_dir("/home/user/bucket")
    sandbox.upload_file("key.json")

    process = sandbox.process.start("sudo gcsfuse <flags> --key-file /home/user/key.json <bucket-name> /home/user/bucket")
    output = process.wait()
    if output.exit_code:
        raise Exception(output.stderr)

```
</CodeGroup>

### Flags

The list of all flags can be found [here](https://cloud.google.com/storage/docs/gcsfuse-cli#options).

### Allow the default user to access the files

To allow the default user to access the files we can use the following flags:

```
-o allow_other -file-mode=777 -dir-mode=777
```

## Amazon S3

For Amazon S3 we can use the `s3fs` package. The `Dockerfile` is similar to the one for the Google Cloud Storage.

```docker
FROM ubuntu:latest

RUN apt-get update && apt-get install s3fs
```

Similarly to the Google Cloud Storage, the actual mounting of the bucket is done in runtime during the start of the sandbox. The `s3fs` command is used to mount the bucket to the sandbox.

<CodeGroup isRunnable={false}>
```js {{ language: 'js' }}
import { Sandbox } from 'e2b'

const sandbox = await Sandbox.create({ template: '<your template id>' })
await sandbox.filesystem.makeDir("/home/user/bucket")
const process = await sandbox.process.start("s3fs <flags> <bucket-name> /home/user/bucket", { env: { AWS_ACCESS_KEY_ID="<AWS_ACCESS_KEY_ID>", AWS_SECRET_ACCESS_KEY="<AWS_SECRET_ACCESS_KEY>"} })
const output = await process.wait()
if (output.exitCode) {
    throw Error(output.stderr)
}
```

```python {{ language: 'python' }}
from e2b import Sandbox

with Sandbox(template="<your template id>") as sandbox:
    sandbox.filesystem.make_dir("/home/user/bucket")
    process = sandbox.process.start("s3fs <flags> <bucket-name> /home/user/bucket", env={"AWS_ACCESS_KEY_ID": "<AWS_ACCESS_KEY_ID>", "AWS_SECRET_ACCESS_KEY": "<AWS_SECRET_ACCESS_KEY>"})
    output = process.wait()
    if output.exit_code:
        raise Exception(output.stderr)

```
</CodeGroup>

### Flags

The list of all flags can be found [here](https://manpages.ubuntu.com/manpages/xenial/man1/s3fs.1.html).

### Allow the default user to access the files

To allow the default user to access the files add the following flag:

```
-o allow_other
```

## Cloudflare R2

For Cloudflare R2 we can use very similar setup as for S3. The `Dockerfile` is the same as for S3. The mounting is slightly different, we need to specify the endpoint for R2. The environment variables are still prefixed with `AWS_`.

<CodeGroup isRunnable={false}>
```js {{ language: 'js' }}
import { Sandbox } from 'e2b'

const sandbox = await Sandbox.create({ template: '<your template id>' })
await sandbox.filesystem.makeDir("/home/user/bucket")
const process = await sandbox.process.start("s3fs -o url=https://<ACCOUNT ID>.r2.cloudflarestorage.com <flags> <bucket-name> /home/user/bucket", { env: { AWS_ACCESS_KEY_ID="<R2_ACCESS_KEY_ID>", AWS_SECRET_ACCESS_KEY="<R2_SECRET_ACCESS_KEY>"} })
const output = await process.wait()
if (output.exitCode) {
    throw Error(output.stderr)
}
```

```python {{ language: 'python' }}
from e2b import Sandbox

with Sandbox(template="<your template id>") as sandbox:
    sandbox.filesystem.make_dir("/home/user/bucket")
    process = sandbox.process.start("s3fs -o url=https://<ACCOUNT ID>.r2.cloudflarestorage.com <flags> <bucket-name> /home/user/bucket", env={"AWS_ACCESS_KEY_ID": "<AWS_ACCESS_KEY_ID>", "AWS_SECRET_ACCESS_KEY": "<AWS_SECRET_ACCESS_KEY>"})
    output = process.wait()
    if output.exit_code:
        raise Exception(output.stderr)

```
</CodeGroup>

### Flags

It's the same as for S3.