A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

Ronil Rangaiya
Jun 29, 2023
  4106
(1 votes)

Enabling Cloud Support for CMS 12 - a look under the hood

In this post I'll explore configuration of Azure resources for self managed (non-DXP) deployments.

For DXP deployments, the recommended way is to use the EPiServer.CloudPlatform.Cms package and simply add the following line

if (!_webHostingEnvironment.IsDevelopment())
{
       //For DXP deployments
       services.AddCmsCloudPlatformSupport(_configuration);
}

What about Azure deployments?

Recently I was setting up a CMS 12 solution to deploy to my Azure instance for R&D. I used the AddCmsCloudPlatformSupport method to see if it worked - to my surprise it did and I couldn't see any issues during my preliminary tests. However I wanted to understand what exactly this method does and if there are any reasons not to use it for non-DXP usage, so I set out to decompile the CloudPlatform assembly and this is what I found out.

AddCmsCloudPlatformSupport Deconstructed

List of services currently configured by this method:

services.AddApplicationInsights();
services.AddAzureBlobProvider();
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<BlobProvidersOptions>, ValidateAzureBlobProviderOptionsConfigurer>());
services.AddCloudPlatformHealthCheck();
services.AddAzureEventProvider();
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<EventProviderOptions>, ValidateAzureEventProviderOptionsConfigurer>());
services.ConfigureDatabase();
services.ConfigureClientGeolocationOptions();
services.AddDataProtectionToBlobStorage(configuration);
services.ConfigureTelemetryOptions();
services.AddCloudPlatformForwardedFor();

Digging deeper into each method, I was able to uncover its purpose.

AddApplicationInsights

Configures Application Insights and registers the client JavaScript SDK for real user monitoring.

AddAzureBlobProvider

This is an extension method available in EPiServer.Azure to add the AzureBlobProvider. 

public static IServiceCollection AddAzureBlobProvider(
      this IServiceCollection services,
      Action<AzureBlobProviderOptions> configureOptions = null)
    {
      services.Configure<BlobProvidersOptions>((Action<BlobProvidersOptions>) (options =>
      {
        options.DefaultProvider = "azure";
        options.AddProvider<AzureBlobProvider>("azure");
      }));
      if (configureOptions != null)
        services.Configure<AzureBlobProviderOptions>(configureOptions);
      services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<AzureBlobProviderOptions>, AzureBlobProviderOptionsConfigurer>());
      return services;
    }

By default this is configured to use the EPiServerAzureBlobs connection string (if specified) in environment configuration and creates a container name "mysitemedia".

AddCloudPlatformHealthCheck

Registers the CMS health and warmup health checks. Refer to this blog for more details and how to add custom health checks.

AddAzureEventProvider

Similar to the AddAzureBlobProvider method, this is an extension method available in EPiServer.Azure to add the AzureEventProvider and by default uses the EPiServerAzureEvents connection string (if specified) in environment configuration and creates a topic named "mysiteevents".

ConfigureDatabase

Sets updateDatabaseSchema to true to apply automatic database updates.

ConfigureClientGeolocationOptions

Sets the request header names to use for user personalisation - EPiServer.Personalisation.ClientGeolocationOptions

options.IPAddressHeader = "X-Forwarded-For";
options.LocationHeader = "CF-IPCountry";

AddDataProtectionToBlobStorage

Extension method in EPiServer.CloudPlatform.Cms to add data protection for BLOB storage using Azure Key Vault.

ConfigureTelemetryOptions

Enables sending user telemetry diagnostics to Optimizely.

AddCloudPlatformForwardedFor

Enables and configures the Forwarded Header Middleware for CDN and load balancer scenarios.

What I ended up with

With this knowledge, I realised not all configured services were relevant to my scenario so my configuration now looks like:

 //Configuration for self-hosted Azure deployments
services.AddApplicationInsightsTelemetry();
services.AddServiceProfiler();
services.AddAzureBlobProvider(options => options.ContainerName = "mosey-media");
services.AddAzureEventProvider(options => options.TopicName = "mosey-events");
services.Configure((Action<DataAccessOptions>)(options => options.UpdateDatabaseSchema = true));

Note, my use case is for R&D purposes so the above is a starting point and a real-world implementation of non-DXP deployment will likely require additional configuration.

To Summarise

AddCmsCloudPlatformSupport is specifically used for the configuration of services for DXP. While it looks like you can also use it for non-DXP deployments, configuring services directly is the way to go to gain more control of your cloud configuration options (and avoid potential breaking changes from future updates to the EPiServer.CloudPlatform.Cms package).

I hope this post helps to provide the context and direction for enabling cloud support for your Azure deployments. 

Jun 29, 2023

Comments

valdis
valdis Jun 29, 2023 08:13 AM

lovely "under the hood" post! it's great to explain what's actually going on - so you know the platform more! 👍

Scott Reed
Scott Reed Jun 29, 2023 08:38 AM

Nice write up, regarding the AddCloudPlatformHealthChecks for anyone interested, I did a breakdown of that area and how to add your own in one of my blogs as well https://world.optimizely.com/blogs/scott-reed/dates/2023/3/optimizely-dxp-health-checks-and-creating-custom-checks/ that goes a bit more in depth in that area

Tomas Hensrud Gulla
Tomas Hensrud Gulla Jun 29, 2023 08:54 AM

Nice!

Ronil Rangaiya
Ronil Rangaiya Jun 29, 2023 09:33 AM

Nice one Scott, thanks for sharing

Please login to comment.
Latest blogs
A day in the life of an Optimizely OMVP: Unlock the Power of Unified Search: Introducing Custom Data Management for Optimizely Graph

Bring all your data together in one searchable experience The Challenge: Siloed Data, Fragmented Search Every organisation has data spread across...

Graham Carr | Jan 16, 2026

Alt text is retrieved for images imported from CMP-DAM in Optimizely CMS 12.

Introduction Although image alt text is stored as metadata in CMP/DAM, it is not automatically rendered in browser HTML. This document outlines the...

Deepmala S | Jan 16, 2026

Announcing Stott Security Version 4.0

January 2026 marks the release of Stott Security v4, a significant update to the popular web security add-on for Optimizely CMS 12, with more than...

Mark Stott | Jan 16, 2026

Optimizely Graph Best Practices - Content Modelling and Querying

Introduction With the Mando Group team having worked extensively with Optimizely Graph over the last 12+ months, we have uncovered a number of best...

Jon Williams | Jan 16, 2026

ScheduledJob overview Blazor component

I have always felt that the admin UI for scheduled jobs in Optimizely is harder to use than it needs to be. To check a job you have to go into admi...

Per Nergård (MVP) | Jan 15, 2026

Our OPAL solution for Innovation Challenge: Persona based Content Optimization

  Introduction Marketing success depends on one core principle : connection. We have may seen many marketing campaigns fail because they fail make...

Ratish | Jan 15, 2026 |