---
title: Configuring Azure storage
related:
  - https://docs.kentico.com/13/configuring-xperience/managing-sites/configuring-settings-for-sites/settings-system/settings-performance.md
  - https://docs.kentico.com/13/deploying-websites/running-xperience-on-microsoft-azure/configuring-azure-cdn.md
  - https://docs.kentico.com/13/deploying-websites/running-xperience-on-microsoft-azure/developing-for-microsoft-azure-best-practices.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

In some situations, it may be beneficial to store the files of an on‑premise website on a **Microsoft Azure Blob Storage** account rather than on a local disk.

- For example, if your server has a limited storage capacity and you need to save large amounts of file data. Using Microsoft Azure may be more convenient than upgrading your server, especially if the increased requirements are only temporary.
- The same applies when running Xperience in [Azure Web Apps](https://docs.kentico.com/13/deploying-websites/running-xperience-on-microsoft-azure/deploying-to-azure-web-apps.md) (where use of Blob storage is optional).

> **Info:** **Mapping files to storage accounts supporting only unencrypted (HTTP) connections**
>
> By default, the system expects the connected Azure storage accounts to use HTTPS exclusively (this behavior can be enabled via the [Security transfer required](https://docs.microsoft.com/en-us/azure/storage/common/storage-require-secure-transfer) setting available in the [Azure portal](https://portal.azure.com)). If you do not wish to run your blob storage instance over HTTPS, or the blob storage instance does not support the configuration (classic storage accounts), you need to perform additional configuration of the system. See [Mapping files to storage accounts supporting only unencrypted (HTTP) connections](#mapping-files-to-storage-accounts-supporting-only-unencrypted-http-connections) for details.

> **Note:** **File name case**
>
> Unlike standard Windows file systems, the Microsoft Azure Blob storage is case-sensitive. To ensure consistent behavior, Xperience automatically converts all file and folder names to lower case when processing files on Azure storage.

## Mapping files to Azure storage

Mapping folders to Azure storage allows you to store large files (e.g., media library files) on a shared storage and, optionally, use Azure CDN for their distribution. To map folders to Azure storage, use the API and the built-in Azure storage provider.

The following scenario demonstrates mapping of [media library files](https://docs.kentico.com/13/managing-website-content/working-with-files/media-library-files.md) to Azure storage:

1.

<!-- dev-model:mvc start -->

**MVC 5 development model.** Applies only when building with ASP.NET MVC 5. If this page also covers ASP.NET Core, that version is in its own block.

Add the following keys to the _appSettings_ section of your MVC and administration projects' **web.config** file. Specify the storage account name and primary access key:

```html

<add key="CMSAzureAccountName" value="StorageAccountName" />
<add key="CMSAzureSharedKey" value="PrimaryAccessKey" />

```

<!-- dev-model:mvc end -->

<!-- dev-model:core start -->

**ASP.NET Core development model.** Applies only when building with ASP.NET Core. If this page also covers MVC 5, that version is in its own block.

Add the following keys to the _web.config_ file of the administration application and the _appsettings.json_ file of the Core live site application. Specify the storage account name and primary access key:

```xml title="web.config"

<add key="CMSAzureAccountName" value="StorageAccountName" />
<add key="CMSAzureSharedKey" value="PrimaryAccessKey" />

```

```js title="appsettings.json"

"CMSAzureAccountName": "StorageAccountName",
"CMSAzureSharedKey": "PrimaryAccessKey"

```

<!-- dev-model:core end -->

> **Info:** The values for these keys can be found in the Azure portal:
>
> 1. Open the [Azure Management Portal](https://portal.azure.com).
> 2. Open **Storage accounts**.
> 3. Select your storage.
> 4. Switch to the **Access keys** tab.
>    - Use the **Storage account name** and one of the provided access key values.

2. Open the Xperience solution in Visual Studio.
3. Create a [custom module class](https://docs.kentico.com/13/custom-development/creating-custom-modules/initializing-modules-to-run-custom-code.md). Add the class into a custom _Class Library_ project within the solution.

   - **Note**: For basic execution of initialization code, you only need to [register a \\](https://docs.kentico.com/13/custom-development/creating-custom-modules/initializing-modules-to-run-custom-code.md) through the API. You do NOT need to create a new module within the **Modules** application in the administration interface.
4. Override the module's **OnInit** method and perform the following:

   - Create a new instance of the Azure storage provider.
   - (Optional) Specify the target container using the **CustomRootPath** property of the provider.
   - (Optional) You can specify whether you want the container to be publicly accessible using the **PublicExternalFolderObject** property of the provider. _True_ means the container is publicly accessible.
   - Map a directory to the provider. This is the directory that you want to store in the container. You can map the directory containing media libraries ("_\~//Media_") or individual media libraries ("_\~//Media/_"). Mapping subfolders of media libraries is not supported.

```csharp

using CMS;
using CMS.Base;
using CMS.DataEngine;
using CMS.IO;

// Registers the custom module into the system
[assembly: RegisterModule(typeof(CustomInitializationModule))]

public class CustomInitializationModule : Module
{
    // Module class constructor, the system registers the module under the name "CustomInit"
    public CustomInitializationModule()
        : base("CustomInit")
    {
    }

    // Contains initialization code that is executed when the application starts
    protected override void OnInit()
    {
        base.OnInit();

        // Creates a new StorageProvider instance for Azure
        var mediaProvider = StorageProvider.CreateAzureStorageProvider();

        // Specifies the target container
        mediaProvider.CustomRootPath = "mymediacontainer";

        // Makes the container publicly accessible
        mediaProvider.PublicExternalFolderObject = true;

        // Maps the local media library directory to the storage provider
        StorageHelper.MapStoragePath("~/MySite/Media/", mediaProvider);
    }
}

```

5. Save the file and Rebuild the solution.
6. Deploy the assembly containing the custom storage provider code to the live site application (in addition to the Xperience administration project).

The system now stores files from the _\~/MySite/Media/_ folder in _mymediacontainer_ in Azure storage. See the [Media library notes](#media-library-notes) section on this page for additional information about media libraries when using Azure storage.

> **Info:** **Using Azure storage for multiple projects**
>
> We do not recommend using a single shared storage for multiple projects (for example production and testing instances), because the projects would overwrite each others' files.
>
> However, you can use the **mediaProvider.CustomRootPath** property (as described on this page) to map each project to a different container. This configuration ensures each project has its own section of the storage.

### Mapping media files on instances with multiple sites

By default, each site has its own separate media folder in the project's file system: _\~//media_

To map all media folders to Azure storage on Xperience instances with multiple sites, we recommend using a shared root folder for media libraries:

1. Open the **Settings** application in Xperience.
2. Navigate to the **Content -> Media** settings category.
3. Set the **Media libraries folder** to a custom folder (globally), for example: _\~/SharedMedia_
4. Enable the **Use site-specific subfolders for custom media libraries folder** setting to ensure that individual library folders are separated by site.
5. Click **Save**.
6. Move any existing media library files to the new location.

You can then map the shared media folder to your Azure storage (using the API described above).

If you wish to use the default media folder locations, you need to map each site's media folder in the code – for each site, create and configure a separate _StorageProvider_ instance and call the _StorageHelper.MapStoragePath_ method for the corresponding media folder.

### Mapping files to storage accounts supporting only unencrypted (HTTP) connections

By default, the system expects the connected Azure storage accounts to use HTTPS exclusively (this behavior can be enabled via the [Security transfer required](https://docs.microsoft.com/en-us/azure/storage/common/storage-require-secure-transfer) setting available in the [Azure portal](https://portal.azure.com)). If you do not wish to run your blob storage instance over HTTPS, or the blob storage instance does not support the configuration (classic storage accounts), you need to perform additional configuration of the system.

When mapping the file system or media library files to such accounts, you must include the [CMSAzureBlobEndPoint ](#optional-web.config-settings-for-azure-storage) configuration key in the configuration files of both applications. The key's value needs to contain the full endpoint URL of the external storage account and explicitly specify the _HTTP_ protocol:

<!-- dev-model:mvc start -->

**MVC 5 development model.** Applies only when building with ASP.NET MVC 5. If this page also covers ASP.NET Core, that version is in its own block.

```xml title="web.config"

<appSettings>
    ...
    <add key="CMSAzureBlobEndPoint" value="http://_StorageAccountName_.blob.core.windows.net" />
</appSettings>

```

<!-- dev-model:mvc end -->

<!-- dev-model:core start -->

**ASP.NET Core development model.** Applies only when building with ASP.NET Core. If this page also covers MVC 5, that version is in its own block.

```xml title="web.config - administration application"

<appSettings>
    ...
    <add key="CMSAzureBlobEndPoint" value="http://_StorageAccountName_.blob.core.windows.net" />
</appSettings>

```

```js title="appsettings.json - live site application"

"CMSAzureBlobEndPoint": "http://_StorageAccountName_.blob.core.windows.net"

```

<!-- dev-model:core end -->

## Media library notes

Using Azure Blob storage as an external storage for your project has some specific effects on media libraries.

### Mapping subfolders of media libraries is not possible

Mapping subfolders of media libraries is not supported by the system. You can map either the directory  containing the media libraries ("_\~//Media_") or individual media libraries ("_\~//Media/_").

### Storing too many files in one media library folder

Note that storing a large number of media files in a single folder can significantly affect the performance of user interface when editing files in the Media library application. The performance of the website, however, is not affected. See [Media library limitations when storing files in an external storage](https://docs.kentico.com/13/configuring-xperience/configuring-the-environment-for-content-editors/configuring-media-libraries.md#media-library-limitations-when-storing-files-in-an-external-storage) for details.

### Using permanent links when CMSAzurePublicContainer key is set to true

If all the following conditions are true:

- you use Azure Blob storage as an external storage
- and you set the _CMSAzurePublicContainer_ key to _true_
- and you want to use [content staging](https://docs.kentico.com/13/deploying-websites/content-staging.md)

then **use Permanent links** when linking to media files in media libraries.

The reason is that when using the _CMSAzurePublicContainer_ key, direct file links contain the name of the storage in the URL. These links are not updated when staging files to another server, which is typically connected to a different storage. As a result, staged links incorrectly target files from the source server's storage, or may become broken if the files are not exactly mirrored on the staging servers. Permanent links do not contain the name of the storage, and automatically target the correct storage for each server.

## Optional web.config settings for Azure storage

| Key                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| CMSAzureTempPath        | The system uses the specified folder to store temporary files on a local disk, for example when transferring large files to or from the storage account.<br>**Sample value**<br>`  <add key="CMSAzureTempPath" value="C:\AzureTemp" />
 `<br>` 
"CMSAzureTempPath": "C:\\AzureTemp"
 `                                                                                                                                                                                                             |
| CMSAzureCachePath       | Specifies a folder on a local disk where files requested from the storage account are cached. This helps minimize the amount of blob storage operations, which saves time and resources.<br>**Sample value**<br>` 
 <add key="CMSAzureCachePath" value="C:\AzureCache" />
 `<br>` 
"CMSAzureCachePath": "C:\\AzureCache"
 `                                                                                                                                                                        |
| CMSAzureBlobEndPoint    | Sets the endpoint used for the connection to the blob service of the specified storage account. If you wish to use the default endpoint, remove the setting completely from the appropriate files.<br>**Sample value**<br>` 
 <add key="CMSAzureBlobEndPoint" value="http://127.0.0.1:10000/devstoreaccount1" />
 `<br>` 
"CMSAzureBlobEndPoint": "http://127.0.0.1:10000/devstoreaccount1"
 `                                                                                                     |
| CMSAzurePublicContainer | Indicates if the blob container used to store the application's files is public. If true, it will be possible to access files directly through the URL of the appropriate blob service, for example:<br>_**http://.blob.core.windows.net/media/imagelibrary/logo.png**_<br>See the [Media library notes](#media-library-notes) section before settings this key to true.<br>**Sample value**<br>` 
 <add key="CMSAzurePublicContainer" value="true" />
 `<br>` 
"CMSAzurePublicContainer": true
 ` |
| CMSAzureCDNEndpoint     | URL of the HTTP endpoint of a [Azure Blob storage CDN](https://docs.kentico.com/13/deploying-websites/running-xperience-on-microsoft-azure/configuring-azure-cdn.md).<br>**Note**: If you set the CMSAzureCDNEndpoint key, you also need to set the blob storage container as public via the **CMSAzurePublicContainer** key.<br>**Sample value**<br>` 
 <add key="CMSAzureCDNEndpoint" value="xperience123.vo.msecnd.net" />
 `<br>` 
"CMSAzureCDNEndpoint": "xperience123.vo.msecnd.net"
 `      |
| CMSDownloadBlobTimeout  | Specifies the timeout interval in minutes for importing files from Azure Blob storage into Xperience.<br>The default value is _1.5_ minutes. Increase the interval if you encounter problems when importing large (about 2GB) files.<br>**Sample value**<br>`  <add key="CMSDownloadBlobTimeout" value="50" />
 `<br>` 
"CMSDownloadBlobTimeout": 50
 `                                                                                                                                            |
