# Buckets

Defining file buckets: memory, disk, global backends, and permissions.

A bucket is named storage that backs file values (`f"bucket:/path"`). You have a few options when defining a bucket:

* Memory for non-peristent storage.
* A folder on disk for persistence.
* A global backend driven by environment variables.

Once a bucket is defined, you can then read and write to files inside it through the [file functions](/docs/reference/query-language/functions/database-functions/file.md).

Full statement detail: [`DEFINE BUCKET`](/docs/reference/query-language/statements/define/bucket.md). For how pointers look in queries, see [Working with files](/docs/learn/schema-management/files/working-with-files.md).

## Example usage

A bucket backend can be set as "memory" for non-persistent in-memory storage, or as "file:/", followed by the path, for storage on disk.

### Memory backend

The simplest way to experiment with a bucket for files is by using the memory backend:

```surql
DEFINE BUCKET my_bucket BACKEND "memory";
```

Once this is defined, `my_bucket` can be accessed by using a file pointer: a path prefixed by an `f`.

```surql
-- Create a file by adding some content
f"my_bucket:/my_book.txt".put("Once there were four children whose names were Peter,
  Susan,
  Edmund,
  and Lucy.");
-- Copy it to a new file name
f"my_bucket:/my_book.txt".copy("lion_witch_wardrobe.txt");
-- Read the file as bytes
f"my_bucket:/lion_witch_wardrobe.txt".get();
-- Cast the bytes to a string
<string>f"my_bucket:/lion_witch_wardrobe.txt".get();
```

### File backend

A file backend can be chosen for a bucket by typing `"file:"` and then the rest of the path, if necessary.

```surql
DEFINE BUCKET my_bucket BACKEND "file:/some_directory";
DEFINE BUCKET my_bucket BACKEND "file:/some_directory";
```

A check will then be made to see if the `SURREAL_BUCKET_FOLDER_ALLOWLIST` environment variable contains the path, without which the following error will be generated.

```surql
'File access denied: /some_directory'
```

The following command can be used to start running an instance in which a bucket with a file backend can be defined.

```bash
# Unix
SURREAL_BUCKET_FOLDER_ALLOWLIST="/" surreal start --user root --pass \
  secret --allow-experimental files

# Windows (PowerShell)
$env:SURREAL_BUCKET_FOLDER_ALLOWLIST = "/" 
surreal start --user root --pass secret --allow-experimental files
```

### Global backend

A global backend can also be selected, allowing all namespaces and databases access to the same file storage.

If no backend is selected, the database will search for the environment variable `SURREAL_GLOBAL_BUCKET` and assign this as the global bucket. In this case, files will have a `namespace/database` prefix added (e.g. `my_global_bucket:/test_ns/test_db/somefile.txt`). A second `SURREAL_GLOBAL_BUCKET_ENFORCED` environment variable can also be used, which when set to `true` will enforce usage of the global bucket.

If a global backend is set, then a `DEFINE BUCKET` statement can be as short as `DEFINE BUCKET` plus its local name, as the rest of the logic is done via environment variables.

```surql
DEFINE BUCKET my_bucket;

-- Writes to e.g. `my_global_bucket:/test_ns/test_db/my_bucket/my_book.txt`
f"my_bucket:/my_book.txt".put("Once there were four children whose names were Peter,
  Susan,
  Edmund,
  and Lucy.");
```

## Setting permissions on buckets

By default, the permissions on a bucket will be set to FULL unless otherwise specified.

```surql
DEFINE BUCKET my_bucket BACKEND "memory";
INFO FOR DB;
```

```surql title="Response"
{
  accesses: {},
  analyzers: {},
  apis: {},
  buckets: {
    my_bucket: "DEFINE BUCKET my_bucket BACKEND 'memory'
      PERMISSIONS FULL"
  },
  configs: {},
  functions: {},
  models: {},
  modules: {},
  params: {},
  sequences: {},
  tables: {},
  users: {}
}
```

You can set permissions on buckets to control who can perform operations on the files stored in them using the `PERMISSIONS` clause. In the clause three additional variables are available:
- `$action`: The action to be executed (`put`, `get`, `head`, `delete`, `copy`, `rename`, `exists`, `list`)
- `$file`: The [file pointer](/docs/reference/query-language/language-primitives/data-types/files.md) of the file to be accessed
- `$target`: The target [file pointer](/docs/reference/query-language/language-primitives/data-types/files.md) in copy/rename operations

```surql
-- Set permissions for the bucket
DEFINE BUCKET admin_bucket BACKEND "memory"
  PERMISSIONS WHERE $auth.admin = true
```
