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

# Object Storage (S3-compatible)

> Production storage guidance for Teable: public/private buckets, permissions, and CORS

<Callout type="warning">
  For production deployments, use **S3-compatible object storage** (such as S3, MinIO, OSS/OBS/COS with S3-compatible endpoints, or another S3-compatible service) with **public/private dual buckets**.
</Callout>

## Why two buckets?

Teable stores different types of files in different buckets:

* **Public bucket**: avatars, form cover images, and other assets that must be publicly accessible.
* **Private bucket**: attachments and other content that should be protected and accessed via signed URLs.

## Required environment variables

At minimum, configure:

* **Provider**
  * `BACKEND_STORAGE_PROVIDER`: `s3` or `minio`
* **Buckets**
  * `BACKEND_STORAGE_PUBLIC_BUCKET`
  * `BACKEND_STORAGE_PRIVATE_BUCKET`
* **Public access base URL**
  * `STORAGE_PREFIX`: should be the **public bucket** access base URL (or CDN in front of it)

### S3 provider

```bash theme={null}
BACKEND_STORAGE_PROVIDER=s3
BACKEND_STORAGE_S3_REGION=us-west-2
BACKEND_STORAGE_S3_ENDPOINT=https://s3.us-west-2.amazonaws.com
BACKEND_STORAGE_S3_ACCESS_KEY=***REDACTED***
BACKEND_STORAGE_S3_SECRET_KEY=***REDACTED***

BACKEND_STORAGE_PUBLIC_BUCKET=your-public-bucket
BACKEND_STORAGE_PRIVATE_BUCKET=your-private-bucket

# Public bucket base URL (or CDN)
STORAGE_PREFIX=https://your-public-bucket.s3.us-west-2.amazonaws.com
```

### MinIO provider

```bash theme={null}
BACKEND_STORAGE_PROVIDER=minio
BACKEND_STORAGE_MINIO_ENDPOINT=minio.example.com
BACKEND_STORAGE_MINIO_PORT=443
BACKEND_STORAGE_MINIO_USE_SSL=true
BACKEND_STORAGE_MINIO_ACCESS_KEY=***REDACTED***
BACKEND_STORAGE_MINIO_SECRET_KEY=***REDACTED***

BACKEND_STORAGE_PUBLIC_BUCKET=public
BACKEND_STORAGE_PRIVATE_BUCKET=private
STORAGE_PREFIX=https://minio.example.com
```

## Public bucket requirements (must-do)

### 1) Public read access

The **public bucket must allow public read** for objects.

If you use AWS S3, you can set a bucket policy like:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::your-public-bucket/*"
    }
  ]
}
```

<Note>
  AWS S3 may require you to adjust **Block Public Access** settings for the public bucket. Please follow your organization’s security policy.
</Note>

### 2) CORS (allow any origin)

For browser access, configure CORS on the **public bucket** to allow cross-origin requests.

AWS S3 example:

```json theme={null}
[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "HEAD"],
    "AllowedOrigins": ["*"],
    "ExposeHeaders": ["ETag", "x-amz-request-id", "x-amz-id-2"],
    "MaxAgeSeconds": 3000
  }
]
```

If you use **direct browser uploads** (presigned PUT), you may also need `PUT` in `AllowedMethods`.

## Private bucket guidance

* Keep the **private bucket** non-public.
* Teable accesses private objects via **signed URLs**.
* If your provider supports “bucket endpoint” for private access, you can configure:
  * `BACKEND_STORAGE_PRIVATE_BUCKET_ENDPOINT` (optional)

## Azure / GCP note

Teable uses **S3 APIs** for object storage. Azure Blob Storage and Google Cloud Storage are **not S3-native**.

* If you are on **Azure** or **GCP**, you can still use `BACKEND_STORAGE_PROVIDER=s3` as long as you point to an S3 endpoint (for example, AWS S3) and your Teable runtime can reach it.
* Or use an **S3-compatible** storage:
  * MinIO (self-managed) as the S3 endpoint
  * Another managed S3-compatible service (your choice)
