> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kvelden.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Platform Storage Configuration

> Configure the shared S3 storage backend that the Enclave appliance uses to store encrypted files for all tenants.

<Info>
  This page is for the person who deployed the Enclave appliance and completed first-boot setup. That account has access to **Admin → Platform Infra → Storage** to configure infrastructure. If you are an organisation owner connecting your own S3 bucket (BYOS), see [Storage](/enclave/storage) instead.
</Info>

## Overview

The appliance needs a storage backend to persist encrypted file data. All data written to storage is **ciphertext only** — the appliance encrypts every file before it leaves the application layer.

| Backend                    | Best for                                                                     |
| -------------------------- | ---------------------------------------------------------------------------- |
| **AWS S3 / S3-compatible** | Cloud-adjacent or hybrid deployments; high durability                        |
| **NFS**                    | Fully on-premise or air-gapped environments with existing NAS infrastructure |
| **Local Disk**             | Single-node evaluation deployments only                                      |

Configuration is done at **Admin → Platform Infra → Storage**.

***

## AWS S3 — end to end

### Step 1 — Create an S3 bucket

1. Sign in to the **AWS Console** → navigate to **S3 → Create bucket**
2. Enter a bucket name (e.g. `enclave-platform-storage`) and choose an AWS region
3. Keep **Block all public access** enabled (default)
4. Leave other settings as default, or enable versioning and server-side encryption if your security policy requires it
5. Click **Create bucket** — note the bucket name and region; you will enter these in Enclave

***

### Choose your authentication method

The appliance runs on VMware and has no EC2 instance profile. Two options are available:

<Tabs>
  <Tab title="Assume Role (recommended)">
    The appliance authenticates using a dedicated IAM user and then assumes a role that holds the S3 permissions. Credentials for S3 access are never stored — only the base user credentials and the role ARN.

    <Note>
      If you already created an `enclave-appliance` IAM user for the KMS Assume Role setup, skip Step 2 and reuse that user. You only need to add the new AssumeRole permission in Step 4b.
    </Note>

    ***

    **Step 2 — Create a dedicated IAM user for the appliance**

    1. In the AWS Console, go to **IAM → Users → Create user**
    2. User name: `enclave-appliance` (or any name you prefer)
    3. On the **Set permissions** step, do not attach any permissions — click **Next**
    4. Click **Create user**
    5. Open the new user → **Security credentials** tab → **Create access key**
    6. Choose **"Application running outside AWS"** → click **Next** → **Create access key**
    7. **Save the Access Key ID and Secret Access Key** — you will need these in Step 5

    ***

    **Step 3 — Create an IAM role for S3 access**

    1. Go to **IAM → Roles → Create role**
    2. Trusted entity type: **AWS account** → **This account** (same account as the user)
    3. Click **Next** — do not attach any permissions yet
    4. **Role name**: `enclave-s3-role` (or any name you prefer)
    5. Click **Create role**

    ***

    **Step 4 — Set the trust policy to allow the appliance user to assume this role**

    1. Open the `enclave-s3-role` role → **Trust relationships** tab → **Edit trust policy**
    2. Replace the entire content with:

    ```json theme={null}
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Sid": "AllowEnclaveApplianceToAssume",
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::YOUR_ACCOUNT_ID:user/enclave-appliance"
        },
        "Action": "sts:AssumeRole"
      }]
    }
    ```

    Replace `YOUR_ACCOUNT_ID` with your 12-digit AWS account ID. Because the principal is an **IAM user** (not a role), AWS validates it immediately — no "Invalid principal in policy" error.

    3. Click **Update policy**

    ***

    **Step 4b — Allow the appliance user to call AssumeRole**

    1. Go to the `enclave-appliance` user → **Permissions** tab → **Add permissions** → **Create inline policy**
    2. JSON editor — paste:

    ```json theme={null}
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::YOUR_ACCOUNT_ID:role/enclave-s3-role"
      }]
    }
    ```

    If the user already has an inline policy from KMS setup, add this statement to the existing policy's `Statement` array instead of creating a new one.

    3. Name the policy `enclave-assume-s3-role` → **Create policy**

    ***

    **Step 4c — Attach S3 permissions to the role**

    1. Go back to the `enclave-s3-role` role → **Permissions** tab → **Add permissions** → **Create inline policy**
    2. JSON editor — paste:

    ```json theme={null}
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Sid": "EnclavePlatformS3Access",
        "Effect": "Allow",
        "Action": [
          "s3:GetObject",
          "s3:PutObject",
          "s3:DeleteObject",
          "s3:ListBucket",
          "s3:GetBucketLocation",
          "s3:HeadBucket"
        ],
        "Resource": [
          "arn:aws:s3:::YOUR_BUCKET_NAME",
          "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        ]
      }]
    }
    ```

    Replace `YOUR_BUCKET_NAME` with your bucket name from Step 1.

    3. Name the policy `enclave-s3-permissions` → **Create policy**
    4. Copy the **Role ARN** from the role Summary page — you will need it in Step 5

    ***

    **Step 5 — Configure in Enclave Admin**

    Log in to the Admin Panel → go to **Admin → Platform Infra → Storage** → **Add Storage**:

    | Field             | Value                                               |
    | ----------------- | --------------------------------------------------- |
    | Storage type      | S3                                                  |
    | Auth method       | Assume Role                                         |
    | Access Key ID     | `enclave-appliance` user access key (from Step 2)   |
    | Secret Access Key | `enclave-appliance` user secret key (from Step 2)   |
    | Role ARN          | `arn:aws:iam::YOUR_ACCOUNT_ID:role/enclave-s3-role` |
    | Bucket            | Bucket name from Step 1                             |
    | Region            | AWS region of the bucket                            |
    | Endpoint          | Leave blank for standard AWS S3                     |
    | Path Prefix       | Optional subdirectory                               |

    Click **Test Connection** — a successful test confirms the role assumption and a live S3 head-check.

    Click **Save** → then **Activate** on the storage row.
  </Tab>

  <Tab title="Static Credentials">
    Use an IAM user's access key and secret directly. Simpler to set up; suitable for S3-compatible stores (MinIO, Ceph, Wasabi, Backblaze B2) that do not support role assumption.

    <Warning>
      Static credentials are stored encrypted in the appliance database. Rotate them at least every 90 days and restrict the IAM user to the specific bucket.
    </Warning>

    ***

    **Step 2 — Create an IAM user with S3 permissions**

    1. In the AWS Console, go to **IAM → Users → Create user**
    2. User name: `enclave-s3` (or any name you prefer)
    3. On the **Set permissions** step, choose **Attach policies directly** → click **Create policy**
    4. Switch to the **JSON** editor and paste:

    ```json theme={null}
    {
      "Version": "2012-10-17",
      "Statement": [{
        "Sid": "EnclavePlatformS3Access",
        "Effect": "Allow",
        "Action": [
          "s3:GetObject",
          "s3:PutObject",
          "s3:DeleteObject",
          "s3:ListBucket",
          "s3:GetBucketLocation",
          "s3:HeadBucket"
        ],
        "Resource": [
          "arn:aws:s3:::YOUR_BUCKET_NAME",
          "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        ]
      }]
    }
    ```

    Replace `YOUR_BUCKET_NAME` with your bucket name from Step 1.

    5. Name the policy `enclave-s3-policy` → **Create policy**
    6. Back in the user creation wizard, attach the new policy → **Next** → **Create user**

    ***

    **Step 3 — Create access keys for the user**

    1. Open the `enclave-s3` user → **Security credentials** tab → **Create access key**
    2. Choose **"Application running outside AWS"** → **Next** → **Create access key**
    3. **Save the Access Key ID and Secret Access Key**

    ***

    **Step 4 — Configure in Enclave Admin**

    Log in to the Admin Panel → go to **Admin → Platform Infra → Storage** → **Add Storage**:

    | Field             | Value                                                                                                     |
    | ----------------- | --------------------------------------------------------------------------------------------------------- |
    | Storage type      | S3                                                                                                        |
    | Auth method       | Static Credentials                                                                                        |
    | Access Key ID     | IAM user access key                                                                                       |
    | Secret Access Key | IAM user secret key                                                                                       |
    | Bucket            | Bucket name from Step 1                                                                                   |
    | Region            | AWS region of the bucket (use `us-east-1` or the closest region for S3-compatible stores)                 |
    | Endpoint          | Leave blank for AWS S3; enter the API URL for S3-compatible stores (e.g. `https://minio.yourcompany.com`) |
    | Path Prefix       | Optional subdirectory                                                                                     |

    Click **Test Connection** — a successful test confirms a live S3 head-check.

    Click **Save** → then **Activate** on the storage row.
  </Tab>
</Tabs>

<Note>
  S3-compatible stores (MinIO, Ceph Object Gateway, Wasabi, Backblaze B2) work with Static Credentials. Set **Endpoint** to the store's S3-compatible API URL and leave **Region** as the closest AWS region or the region your store is configured with.
</Note>

***

## NFS

NFS is the recommended option for fully on-premise or air-gapped deployments without cloud object storage.

### Prerequisites

* NFS v3 or v4 share exported and mountable from the appliance VM
* The share must be mounted on the appliance **before** configuring storage in Enclave — the appliance does not mount NFS shares itself
* Read/write permissions for the `enclave` process user on the mount point

### Mount the NFS share on the appliance

SSH into the appliance VM and mount the share:

```bash theme={null}
sudo mount -t nfs your-nfs-server:/export/enclave /mnt/enclave-storage
```

To persist across reboots, add to `/etc/fstab`:

```
your-nfs-server:/export/enclave  /mnt/enclave-storage  nfs  defaults,_netdev  0  0
```

### Configure in Enclave

Go to **Admin → Platform Infra → Storage** → **Add Storage** → select **NFS**:

| Field       | Value                                        |
| ----------- | -------------------------------------------- |
| Mount Point | `/mnt/enclave-storage` (or your chosen path) |

Click **Test Connection**, then **Save** and **Activate**.

***

## Local Disk

Local disk writes encrypted file data directly to the appliance VM's disk. Suitable for evaluation only.

<Warning>
  Local disk storage is not replicated. If the VM disk is lost, all file data is lost. Do not use local disk for production deployments.
</Warning>

Go to **Admin → Platform Infra → Storage** → **Add Storage** → select **Local Disk**:

| Field       | Value                                                                |
| ----------- | -------------------------------------------------------------------- |
| Mount Point | An absolute path on the appliance disk (e.g. `/var/enclave/storage`) |

The path must exist and be writable before saving.

***

## Activating

After saving, the backend must be **activated** before the appliance routes file uploads to it:

1. In **Admin → Platform Infra → Storage**, locate the saved backend
2. Click **Activate**
3. The appliance immediately begins using this backend for all new file uploads

<Warning>
  Only one platform storage backend can be active at a time. Activating a new backend does not migrate existing files — files in the previous backend remain there. Contact [support@kvelden.com](mailto:support@kvelden.com) if you need to migrate data between backends.
</Warning>

***

## Tenant BYOS

Once platform storage is active, organisation owners can connect their own S3 bucket through **Organisation → Storage**. BYOS overrides platform storage for that organisation's files at the chosen scope. See [Storage](/enclave/storage) for tenant-facing setup.
