# Upload Provider Configuration for Strapi Cloud

> Source: https://docs.strapi.io/cloud/advanced/upload

External storage like S3 or Cloudinary requires plugin setup, security middleware, and Cloud variables.

Strapi Cloud comes with a local upload provider out of the box. However, it can also be configured to use a third-party upload provider, if needed.

:::note
For the file size and memory-based limits that apply to uploads, see [Upload size limits for Strapi Cloud](/cloud/advanced/upload-size-limits).
:::

## Configuring a third-party upload provider

:::caution
Please be advised that Strapi is unable to provide support for third-party upload providers.
:::

:::prerequisites

- A local Strapi project running on `v4.8.2+`.
- Credentials for a third-party upload provider (see [Strapi Market](https://market.strapi.io/providers)).

:::

Configuring a third-party upload provider for use with Strapi Cloud requires the following 4 configuration steps, followed by a deployment:

1. Install the provider plugin in your local Strapi project.
2. Configure the provider in your local Strapi project.
3. Configure the security middleware in your local Strapi project.
4. Add environment variables to the Strapi Cloud project.

### Install the provider plugin

Using either `npm` or `yarn`, install the provider plugin in your local Strapi project as a package dependency by following the instructions in the respective entry for that provider in the [Marketplace](https://market.strapi.io/providers).

### Configure the provider

To configure a third-party upload provider in your Strapi project, create or edit the plugins configuration file for your production environment `/config/env/production/plugins.js|ts` by adding upload configuration options as follows:

```js title=/config/env/production/plugins.js

module.exports = ({ env }) => ({
// … some unrelated plugins configuration options
// highlight-start
upload: {
   config: {
      // … provider-specific upload configuration options go here
   }
// highlight-end
// … some other unrelated plugins configuration options
}
});
```
```ts title=/config/env/production/plugins.ts

// … some unrelated plugins configuration options
// highlight-start
upload: {
   config: {
      // … provider-specific upload configuration options go here
   }
// highlight-end
// … some other unrelated plugins configuration options
}
});
```

:::caution
The file structure must match the above path exactly, or the configuration will not be applied to Strapi Cloud.
:::

Each provider will have different configuration settings available. Review the respective entry for that provider in the [Marketplace](https://market.strapi.io/providers).

**Example:**
<Tabs groupId="js-ts">
<TabItem value="js" label="JavaScript">
<Tabs groupId="upload-examples" >
<TabItem value="cloudinary" label="Cloudinary">

```js title=/config/env/production/plugins.js
module.exports = ({ env }) => ({
  // ...
  upload: {
    config: {
      provider: 'cloudinary',
      providerOptions: {
        cloud_name: env('CLOUDINARY_NAME'),
        api_key: env('CLOUDINARY_KEY'),
        api_secret: env('CLOUDINARY_SECRET'),
      },
      actionOptions: {
        upload: {},
        uploadStream: {},
        delete: {},
      },
    },
  },
  // ...
});
```

</TabItem >
:::tip
For full S3 provider configuration details (credential formats, extended options, S3-compatible services), see the [Amazon S3 provider](/cms/configurations/media-library-providers/amazon-s3) page in the CMS documentation.
:::

```js title=/config/env/production/plugins.js
module.exports = ({ env }) => ({
  // ...
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        baseUrl: env('CDN_URL'),
        rootPath: env('CDN_ROOT_PATH'),
        s3Options: {
          credentials: {
            accessKeyId: env('AWS_ACCESS_KEY_ID'),
            secretAccessKey: env('AWS_ACCESS_SECRET'),
          },
          region: env('AWS_REGION'),
          params: {
            ACL: env('AWS_ACL', 'public-read'),
            signedUrlExpires: env('AWS_SIGNED_URL_EXPIRES', 15 * 60),
            Bucket: env('AWS_BUCKET'),
          },
        },
      },
      actionOptions: {
        upload: {},
        uploadStream: {},
        delete: {},
      },
    },
  },
  // ...
});
```

<TabItem value="ts" label="TypeScript">
<Tabs groupId="upload-examples" >
<TabItem value="cloudinary" label="Cloudinary">

```ts title=/config/env/production/plugins.ts

  // ...
  upload: {
    config: {
      provider: 'cloudinary',
      providerOptions: {
        cloud_name: env('CLOUDINARY_NAME'),
        api_key: env('CLOUDINARY_KEY'),
        api_secret: env('CLOUDINARY_SECRET'),
      },
      actionOptions: {
        upload: {},
        uploadStream: {},
        delete: {},
      },
    },
  },
  // ...
});
```

</TabItem >
```ts title=/config/env/production/plugins.ts

  // ...
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        baseUrl: env('CDN_URL'),
        rootPath: env('CDN_ROOT_PATH'),
        s3Options: {
          credentials: {
            accessKeyId: env('AWS_ACCESS_KEY_ID'),
            secretAccessKey: env('AWS_ACCESS_SECRET'),
          },
          region: env('AWS_REGION'),
          params: {
            ACL: env('AWS_ACL', 'public-read'),
            signedUrlExpires: env('AWS_SIGNED_URL_EXPIRES', 15 * 60),
            Bucket: env('AWS_BUCKET'),
          },
        },
      },
      actionOptions: {
        upload: {},
        uploadStream: {},
        delete: {},
      },
    },
  },
  // ...
});
```

### Configure the security middleware

Due to the default settings in the Strapi security middleware you will need to modify the `contentSecurityPolicy` settings to properly see thumbnail previews in the Media Library.

:::caution
On Strapi Cloud, `NODE_ENV` is always set to `production`. Changes to the global `config/middlewares.ts` file are overwritten on each deploy and will not take effect. Place your Security Middleware customizations in `config/env/production/middlewares.ts` instead. See [Middleware Configuration for Strapi Cloud](/cloud/advanced/middlewares) for details.
:::

To do this in your Strapi project:

1. Navigate to `/config/env/production/middlewares.js` or `/config/env/production/middlewares.ts` in your Strapi project.
2. Replace the default `strapi::security` string with the object provided by the upload provider.

**Example:**
```js title=/config/env/production/middlewares.js
module.exports = [
  // ...
  {
    name: 'strapi::security',
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          'connect-src': ["'self'", 'https:'],
          'img-src': [
            "'self'", 
            'data:', 
            'blob:', 
            'market-assets.strapi.io', 
            'res.cloudinary.com'
          ],
          'media-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'res.cloudinary.com',
          ],
          upgradeInsecureRequests: null,
        },
      },
    },
  },
  // ...
];
```
```js title=/config/env/production/middlewares.js
module.exports = [
  // ...
  {
    name: 'strapi::security',
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          'connect-src': ["'self'", 'https:'],
          'img-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'yourBucketName.s3.yourRegion.amazonaws.com',
          ],
          'media-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'yourBucketName.s3.yourRegion.amazonaws.com',
          ],
          upgradeInsecureRequests: null,
        },
      },
    },
  },
  // ...
];
```
```ts title=/config/env/production/middlewares.ts

  // ...
  {
    name: 'strapi::security',
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          'connect-src': ["'self'", 'https:'],
          'img-src': [
            "'self'", 
            'data:', 
            'blob:', 
            'market-assets.strapi.io', 
            'res.cloudinary.com'
          ],
          'media-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'res.cloudinary.com',
          ],
          upgradeInsecureRequests: null,
        },
      },
    },
  },
  // ...
];
```
```ts title=/config/env/production/middlewares.ts

  // ...
  {
    name: 'strapi::security',
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          'connect-src': ["'self'", 'https:'],
          'img-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'yourBucketName.s3.yourRegion.amazonaws.com',
          ],
          'media-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'yourBucketName.s3.yourRegion.amazonaws.com',
          ],
          upgradeInsecureRequests: null,
        },
      },
    },
  },
  // ...
];
```

:::tip
Before pushing the above changes to GitHub, add environment variables to the Strapi Cloud project to prevent triggering a rebuild and new deployment of the project before the changes are complete.
:::

### Strapi Cloud configuration

1. Log into Strapi Cloud and click on the corresponding project on the Projects page.
2. Click on the **Settings** tab and choose **Variables** in the left menu.
3. Add the required environment variables specific to the upload provider.
4. Click **Save**.

**Example:**

| Variable            | Value                   |
|---------------------|-------------------------|
| `CLOUDINARY_NAME`   | your_cloudinary_name    |
| `CLOUDINARY_KEY`    | your_cloudinary_api_key |
| `CLOUDINARY_SECRET` | your_cloudinary_secret  |
| Variable            | Value                  |
|---------------------|------------------------|
| `AWS_ACCESS_KEY_ID` | your_aws_access_key_id |
| `AWS_ACCESS_SECRET` | your_aws_access_secret |
| `AWS_REGION`        | your_aws_region        |
| `AWS_BUCKET`        | your_aws_bucket        |
| `CDN_URL`           | your_cdn_url           |
| `CDN_ROOT_PATH`     | your_cdn_root_path     |

### Deployment

To deploy the project and use the third-party upload provider, push the changes from earlier. This will trigger a rebuild and new deployment of the Strapi Cloud project.

Once the application finishes building, the project will use the new upload provider.

:::strapi Custom Provider
If you want to create a custom upload provider, please refer to the [Providers](/cms/features/media-library#providers) documentation in the CMS Documentation.
:::
