> For the complete documentation index, see [llms.txt](https://docs.carto.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.carto.com/carto-self-hosted/configuration/data-and-storage/configure-your-own-buckets.md).

# Configure your own buckets

This guide covers how to configure CARTO to use your cloud storage buckets. If you haven't created and configured them yet (CORS, IAM permissions), start with [Object Storage prerequisites](/carto-self-hosted/planning/prerequisites/object-storage.md) first.

Every CARTO Self-Hosted installation requires the following buckets:

{% tabs %}
{% tab title="☸️ Kots (Admin Console)" %}

| Bucket            | Required | Description                                                                        | Example contents            |
| ----------------- | -------- | ---------------------------------------------------------------------------------- | --------------------------- |
| **Temp Bucket**   | Yes      | Upload and import datasets into CARTO                                              | `.csv`, `.geojson`, `.zip`  |
| **Assets Bucket** | Yes      | Stores map thumbnails and customization assets (logos, markers, etc.)              | `.png`                      |
| **Export Bucket** | Optional | Export data from your data warehouse — create only if you use data export features | `.csv`, `.json`, `.parquet` |
| {% endtab %}      |          |                                                                                    |                             |

{% tab title="🛞 Helm (customizations.yaml)" %}

| Bucket                | Required | Config key                                                   | Description                                                                        | Example contents            |
| --------------------- | -------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------- | --------------------------- |
| **Import Bucket**     | Yes      | `workspaceImportsBucket`                                     | Upload and import datasets into CARTO                                              | `.csv`, `.geojson`, `.zip`  |
| **Thumbnails Bucket** | Yes      | `workspaceThumbnailsBucket`                                  | Stores map thumbnails and customization assets (logos, markers, etc.)              | `.png`                      |
| **Export Bucket**     | Optional | `workspaceExportsBucket` (BigQuery) / `awsExportBucket` (S3) | Export data from your data warehouse — create only if you use data export features | `.csv`, `.json`, `.parquet` |
| {% endtab %}          |          |                                                              |                                                                                    |                             |
| {% endtabs %}         |          |                                                              |                                                                                    |                             |

***

## Configuration notes

### Assets / Thumbnails bucket access

By default, all thumbnail objects are configured to be **publicly accessible**. This ensures that features like custom branding and map markers function correctly.

{% tabs %}
{% tab title="☸️ Kots (Admin Console)" %} <img src="/files/iX0yYSxrIcdJH0mbRf9w" alt="Kots" width="18">

You can change this in the Admin Console using the "**Assets bucket is Public**" config.

<figure><img src="/files/5TQ1BeUShzgMnhJ8yIbO" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="warning" %}
Setting the bucket to private will disable the public markers feature since it relies on public image assets.
{% endhint %}
{% endtab %}

{% tab title="🛞 Helm (customizations.yaml)" %} <img src="/files/5mQydBQdQ20MZUxbcOKQ" alt="Helm" width="18">

To make thumbnails private, set in your <mark style="color:orange;">customizations.yaml</mark>:

```yaml
appConfigValues:
  workspaceThumbnailsPublic: "false"
```

{% hint style="warning" %}
Some features (branding, custom markers) require **public access**.
{% endhint %}
{% endtab %}
{% endtabs %}

To maintain a private bucket while still enabling these features, configure your bucket with a hybrid access model:

1. **Allow public objects**: The bucket policy must allow individual objects to be made public, even if the bucket itself is private by default.
2. **Enable fine-grained ACLs**: Enable Access Control Lists (ACLs) so CARTO can set `public-read` permissions on specific thumbnail files.
3. **Disable server-side encryption**: Bucket-level server-side encryption is often incompatible with public ACLs and must be disabled.

### Export bucket provider requirements

| Data Warehouse              | Required Storage Provider |
| --------------------------- | ------------------------- |
| **BigQuery**                | Google Cloud Storage      |
| **Snowflake**               | AWS S3                    |
| **Redshift**                | AWS S3                    |
| **Amazon RDS (PostgreSQL)** | AWS S3                    |
| **Oracle**                  | AWS S3                    |

***

## Bucket configuration

{% tabs %}
{% tab title="☸️ Kots (Admin Console)" %} <img src="/files/iX0yYSxrIcdJH0mbRf9w" alt="Kots" width="18">

In the Admin Console → Config, select your preferred storage provider:

<figure><img src="/files/rl9zYv5vITovxRVBQXHk" alt=""><figcaption></figcaption></figure>

{% tabs %}
{% tab title="Google Cloud Storage" %}

1. Create the following buckets in GCS:
   * **Assets Bucket**
   * **Temp Bucket**
   * Optionally, create the **Data export Bucket** if you plan to export data from your data warehouse.

{% hint style="info" %}
Custom markers won't work unless the Assets bucket is public.
{% endhint %}

2. Configure CORS on the Temp and Assets buckets:

```json
[
  {
    "origin": ["*"],
    "method": ["GET", "PUT", "POST"],
    "responseHeader": [
      "Content-Type", "Content-MD5", "Content-Disposition",
      "Cache-Control", "x-goog-content-length-range", "x-goog-meta-filename"
    ],
    "maxAgeSeconds": 3600
  }
]
```

{% hint style="info" %}
How do I set up CORS? Check the [provider docs](https://cloud.google.com/storage/docs/using-cors).
{% endhint %}

3. Ensure the identity used to access your GCS buckets has the `roles/storage.admin` role over the buckets.
4. In the Admin Console, provide the **Project ID** of the GCP project where your GCS buckets are located.
5. Specify the names of the GCS buckets.
   {% endtab %}

{% tab title="AWS S3" %}

1. Create the following buckets in your AWS S3 account:
   * **Assets Bucket**
   * **Temp Bucket**
   * **Data export Bucket** (optional)

{% hint style="info" %}
Custom markers won't work unless the Assets bucket is public.
{% endhint %}

{% hint style="danger" %}
When creating your S3 buckets:

* **ACLs must be enabled.**
* If server-side encryption is enabled, the user must be granted KMS key permissions (see [AWS documentation](https://repost.aws/knowledge-center/s3-bucket-access-default-encryption)).
  {% endhint %}

2. Configure CORS on the Temp and Assets buckets:

```json
[
  {
    "AllowedHeaders": ["Content-Type", "Content-MD5", "Content-Disposition", "Cache-Control"],
    "AllowedMethods": ["PUT", "POST", "GET"],
    "AllowedOrigins": ["*"],
    "ExposeHeaders": [],
    "MaxAgeSeconds": 3600
  }
]
```

{% hint style="info" %}
How do I set up CORS? Check the [provider docs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html).
{% endhint %}

3. Provide an **Access Key ID** and **Secret Access Key** with read/write access over the buckets.
4. Configure the **region** where the buckets are located. All buckets must be in the same AWS region.
5. Specify the names of the AWS buckets.

**For Redshift exports** — create an IAM role with the following settings:

Trusted entity type: `Custom trust policy` — replace `<your_aws_user_arn>`:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "<your_aws_user_arn>" },
      "Action": ["sts:AssumeRole", "sts:TagSession"]
    }
  ]
}
```

Add permissions (omit export bucket if not needed):

```json
{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::<your_aws_s3_data_export_bucket_name>" },
    { "Effect": "Allow", "Action": "s3:*Object", "Resource": "arn:aws:s3:::<your_aws_s3_data_export_bucket_name>/*" },
    { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::<your_aws_s3_temp_bucket_name>" },
    { "Effect": "Allow", "Action": "s3:*Object", "Resource": "arn:aws:s3:::<your_aws_s3_temp_bucket_name>/*" }
  ]
}
```

Specify the ARN of the role and the name of the exports bucket in the CARTO Self-Hosted configuration.

{% hint style="info" %}
In case you'd like to enable importing data to Redshift, it's not mandatory to provide the exports bucket's name, but you'll have to follow [these instructions](/carto-user-manual/settings/advanced-settings/configuring-s3-bucket-for-redshift-imports.md) once the CARTO Self-Hosted deployment is ready.
{% endhint %}

**For Snowflake exports** — create an IAM role with the same trust policy and the following permissions policy:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::<your_aws_s3_data_export_bucket_name>" },
    { "Effect": "Allow", "Action": "s3:*Object", "Resource": "arn:aws:s3:::<your_aws_s3_data_export_bucket_name>/*" }
  ]
}
```

Specify the ARN of the role and the data export bucket name in the CARTO Self-Hosted configuration.
{% endtab %}

{% tab title="Azure Blob Storage" %}

1. Create the following containers in your Azure Blob storage account:
   * **Assets Bucket**
   * **Temp Bucket**
   * **Data export Bucket** (optional)

{% hint style="info" %}
Custom markers won't work unless the Assets bucket is public.
{% endhint %}

2. Configure CORS on the Temp and Assets buckets at the **storage account level**:

```json
[
  {
    "origin": ["*"],
    "method": ["GET", "PUT", "POST"],
    "responseHeader": [
      "Content-Type", "Content-MD5", "Content-Disposition",
      "Cache-Control", "Access-Control-Request-Headers", "X-MS-Blob-Type"
    ],
    "maxAgeSeconds": 3600
  }
]
```

{% hint style="info" %}
How do I set up CORS? Check the [provider docs](https://learn.microsoft.com/en-us/rest/api/storageservices/cross-origin-resource-sharing--cors--support-for-the-azure-storage-services#enabling-cors-for-azure-storage).
{% endhint %}

3. Provide an **Access Key** from the storage account's Security properties.
4. Specify the names of the containers.
   {% endtab %}
   {% endtabs %}
   {% endtab %}

{% tab title="🛞 Helm (customizations.yaml)" %} <img src="/files/5mQydBQdQ20MZUxbcOKQ" alt="Helm" width="18">

{% tabs %}
{% tab title="Google Cloud Storage" %}
Add the following lines to your <mark style="color:orange;">customizations.yaml</mark> and replace the `<values>` with your own settings:

```yaml
appConfigValues:
  storageProvider: "gcp"
  workspaceImportsBucket: <import_bucket_name>
  workspaceImportsPublic: <false|true>
  workspaceThumbnailsBucket: <thumbnails_bucket_name>
  workspaceThumbnailsPublic: <false|true>
  thumbnailsBucketExternalURL: <public or authenticated external bucket URL>
  googleCloudStorageProjectId: <gcp_project_id>
```

> `thumbnailsBucketExternalURL` can be `https://storage.googleapis.com/<thumbnails_bucket_name>/` for public access or `https://storage.cloud.google.com/<thumbnails_bucket_name>/` for authenticated access.

Select a **Service Account** that will be used by CARTO to interact with the buckets:

* Using a custom Service Account for both buckets and CARTO services (required for Workload Identity).
* Using a dedicated Service Account **only for the buckets**.

Grant the selected Service Account the role `roles/iam.serviceAccountTokenCreator` at the Service Account permissions level (not project level).

Grant the selected Service Account the role `roles/storage.admin` on the buckets.

**\[OPTIONAL]** Pass GCP credentials as secrets — only if using a dedicated Service Account for buckets:

Option 1 — automatically create the secret:

```yaml
appSecrets:
  googleCloudStorageServiceAccountKey:
    value: |
      <REDACTED>
```

> `appSecrets.googleCloudStorageServiceAccountKey.value` should be in plain text, preserving multiline format.

Option 2 — using an existing secret:

```bash
kubectl create secret generic \
  [-n my-namespace] \
  mycarto-google-storage-service-account \
  --from-file=key=<PATH_TO_YOUR_SECRET.json>
```

```yaml
appSecrets:
  googleCloudStorageServiceAccountKey:
    existingSecret:
      name: mycarto-google-storage-service-account
      key: key
```

{% endtab %}

{% tab title="AWS S3" %}
Add the following lines to your <mark style="color:orange;">customizations.yaml</mark> and replace the `<values>` with your own settings:

```yaml
appConfigValues:
  storageProvider: "s3"
  workspaceImportsBucket: <import_bucket_name>
  workspaceImportsPublic: <false|true>
  workspaceThumbnailsBucket: <thumbnails_bucket_name>
  workspaceThumbnailsPublic: <false|true>
  thumbnailsBucketExternalURL: <external bucket URL>
  awsS3Region: <s3_buckets_region>
```

> `thumbnailsBucketExternalURL` should be `https://<thumbnails_bucket_name>.s3.amazonaws.com/`

Pass your AWS credentials as secrets:

Option 1 — automatically create a secret:

```yaml
appSecrets:
  awsAccessKeyId:
    value: "<REDACTED>"
  awsAccessKeySecret:
    value: "<REDACTED>"
```

> `appSecrets.awsAccessKeyId.value` and `appSecrets.awsAccessKeySecret.value` should be in plain text.

Option 2 — using an existing secret:

```bash
kubectl create secret generic \
  [-n my-namespace] \
  mycarto-custom-s3-secret \
  --from-literal=awsAccessKeyId=<REDACTED> \
  --from-literal=awsSecretAccessKey=<REDACTED>
```

> Use the same namespace where you are installing the Helm chart.

```yaml
appSecrets:
  awsAccessKeyId:
    existingSecret:
      name: mycarto-custom-s3-secret
      key: awsAccessKeyId
  awsAccessKeySecret:
    existingSecret:
      name: mycarto-custom-s3-secret
      key: awsSecretAccessKey
```

{% endtab %}

{% tab title="Azure Blob Storage" %}
Add the following lines to your <mark style="color:orange;">customizations.yaml</mark> and replace the `<values>` with your own settings:

```yaml
appConfigValues:
  storageProvider: "azure-blob"
  azureStorageAccount: <storage_account_name>
  workspaceImportsBucket: <import_bucket_name>
  workspaceImportsPublic: <false|true>
  workspaceThumbnailsBucket: <thumbnails_bucket_name>
  thumbnailsBucketExternalURL: <external bucket URL>
  workspaceThumbnailsPublic: <false|true>
```

> `thumbnailsBucketExternalURL` should be `https://<azure_resource_group>.blob.core.windows.net/<thumbnails_bucket_name>/`

Pass your Access Key as a secret:

Option 1 — automatically create the secret:

```yaml
appSecrets:
  azureStorageAccessKey:
    value: "<REDACTED>"
```

> `appSecrets.azureStorageAccessKey.value` should be in plain text.

Option 2 — using an existing secret:

```bash
kubectl create secret generic \
  [-n my-namespace] \
  mycarto-custom-azure-secret \
  --from-literal=azureStorageAccessKey=<REDACTED>
```

```yaml
appSecrets:
  azureStorageAccessKey:
    existingSecret:
      name: mycarto-custom-azure-secret
      key: azureStorageAccessKey
```

{% endtab %}
{% endtabs %}
{% endtab %}
{% endtabs %}

***

## Data export bucket

{% tabs %}
{% tab title="☸️ Kots (Admin Console)" %} <img src="/files/iX0yYSxrIcdJH0mbRf9w" alt="Kots" width="18">

For Redshift and Snowflake exports, an IAM role must be created and configured. Refer to the Redshift and Snowflake configuration steps in the **AWS S3** tab above, then specify the ARN and bucket name in the Admin Console.
{% endtab %}

{% tab title="🛞 Helm (customizations.yaml)" %} <img src="/files/5mQydBQdQ20MZUxbcOKQ" alt="Helm" width="18">

### BigQuery

1. Grant read/write permissions to the CARTO service account on the GCS export bucket.
2. Add to your <mark style="color:orange;">customizations.yaml</mark>:

```yaml
appConfigValues:
  workspaceExportsBucket: <YOUR_EXPORTS_BUCKET>
```

### Snowflake and Redshift

Snowflake and Redshift require an AWS S3 bucket for data exports. Create an IAM user with programmatic credentials if not already done.

{% hint style="info" %}
If you already configured the Import and Thumbnails buckets using AWS S3, you can reuse the same IAM user.
{% endhint %}

Create an IAM role with the following settings:

1. Trusted entity type: `Custom trust policy` — replace `<your_aws_user_arn>`:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "<your_aws_user_arn>" },
      "Action": ["sts:AssumeRole", "sts:TagSession"]
    }
  ]
}
```

2. Add permissions policy — replace `<your_aws_s3_bucket_name>`:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::<your_aws_s3_bucket_name>" },
    { "Effect": "Allow", "Action": "s3:*Object", "Resource": "arn:aws:s3:::<your_aws_s3_bucket_name>/*" }
  ]
}
```

3. Update your <mark style="color:orange;">customizations.yaml</mark>:

```yaml
appConfigValues:
  awsExportBucket: <BUCKET_NAME>
  awsExportBucketRegion: <REGION>
  exportAwsRoleArn: <ROLE_ARN>
```

Pass your AWS credentials as secrets:

Option 1 — automatically create the secret:

```yaml
appSecrets:
  exportAwsSecretAccessKey:
    value: <REDACTED>
  exportAwsAccessKeyId:
    value: <REDACTED>
```

> `appSecrets.exportAwsSecretAccessKey.value` and `appSecrets.exportAwsAccessKeyId.value` should be in plain text, preserving the multiline and correctly tabulated.

Option 2 — using an existing secret:

```bash
kubectl create secret generic \
  [-n my-namespace] \
  mycarto-export-aws-access-key \
  --from-literal=key-id=<ACCESS_KEY_ID> \
  --from-literal=key-secret=<ACCESS_KEY_SECRET>
```

```yaml
appSecrets:
  exportAwsSecretAccessKey:
    existingSecret:
      name: mycarto-export-aws-access-key
      key: key-id
  exportAwsAccessKeyId:
    existingSecret:
      name: mycarto-export-aws-access-key-id
      key: key-secret
```

### Amazon RDS for PostgreSQL

The export bucket for Amazon RDS can be configured from the CARTO platform UI after deployment. See [Configuring S3 bucket integration for Amazon RDS for PostgreSQL exports](/carto-user-manual/settings/advanced-settings/configuring-s3-bucket-integration-for-rds-for-postgresql-exports-in-builder.md).
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.carto.com/carto-self-hosted/configuration/data-and-storage/configure-your-own-buckets.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
