All pages
Powered by GitBook
1 of 11

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Server setup

This section describes different ways of setting up servers for use with Umbraco

This section describes different ways of setting up servers for use with Umbraco

Secure Sockets Layer (SSL) and HTTPS

We strongly encourage the use of HTTPS with Umbraco installations especially in production environments. Using HTTPS will greatly enhance the security of your website, see the Security reference for more information.

File & folder permissions

To ensure a stable and smoothly running Umbraco installation, these permissions need to be set correctly.

Hosting v9+ in IIS

Information about hosting a v9 application using IIS.

Load Balanced setup

Information on how to deploy Umbraco in a Load Balanced scenario and other details to consider when setting up Umbraco for load balancing.

Running Umbraco on Azure Web Apps

Best practices for running Umbraco on Azure Web Apps.

Runtime modes

The runtime mode setting optimizes Umbraco for the best development experience or optimal production environment.

Running Umbraco in Docker

Overview of topics to consider when running Umbraco in Docker.

File And Folder Permissions

Information on file and folder permissions required for Umbraco sites

To ensure a stable and smoothly running Umbraco installation, these permissions need to be set correctly. These permissions should be set up before or during the installation of Umbraco.

The main account that requires 'modify' file permissions to be set on the folders below, is the account used start Umbraco. If Umbraco is hosted in IIS this will be the Application Pool Identity for the IIS website. Usually IIS APPPOOL\appPoolName or a specific local account or in some circumstances Network Service. If in doubt, ask your server admin / hosting company. Additionally, the Internet User (IUSR) account and IIS_IUSRS account only require 'read only' access to the site's folders.

Generally, when developing locally with Visual Studio or Rider, permissions do not need to be strictly applied.

If you have any specific static files/media items/etc, you should add the appropriate permissions accordingly.

The permissions documentation should allow you to run a plain Umbraco install successfully.

File / folder
Permission
Comment

/appSettings*.json

Modify / Full control

Only needed for setting database and a global identifier during installation. So can be set to read-only afterwards for enhanced security.

/App_Plugins

Modify / Full control

Should always have modify rights as the folder and its files are used by packages. Not part of your project by default.

/umbraco

Modify / Full control

Should always have modify rights as the folder and its files are used for cache and storage.

/Views

Modify / Full control

Should always have modify rights as the folder and its files are used for Templates, Partial views, and Macro files.

/wwwroot/css

Modify / Full control

Should always have modify rights as the folder and its files are used for css files.

/wwwroot/media

Modify / Full control

Should always have modify rights as the folder and its files are used for Media files uploaded via the Umbraco CMS backoffice.

/wwwroot/scripts

Modify / Full control

Should always have modify rights as the folder and its files are used for script files.

Running Umbraco On Azure Web Apps

This section describes best practices with running Umbraco on Azure Web Apps

What are Azure Web Apps

They have been called a few names in the past, many people still know Azure Web Apps as Azure Web Sites.

App Service is a fully Managed Platform for professional developers that brings a rich set of capabilities to web, mobile and integration scenarios. Quickly create and deploy mission critical web Apps that scale with your business by using Azure App Service.

You can read more about them here

Umbraco will run on Azure Web Apps but there are some configuration options and specific Azure Web Apps environment limitations to be aware of.

Recommended configuration

You need to add these configuration values. E.g in a json configuration source like appSettings.json:

{
    "Umbraco": {
        "CMS": {
            "Global": {
                "MainDomLock" : "FileSystemMainDomLock"
            },
            "Hosting": {
                "LocalTempStorageLocation": "EnvironmentTemp"
            },
            "Examine": {
                "LuceneDirectoryFactory": "SyncedTempFileSystemDirectoryFactory"
            }
        }
    }
}

You can also copy the following JSON directly into your Azure Web App configuration via the Advanced Edit feature.

Advanced Edit
{
  "name": "UMBRACO__CMS__Global__MainDomLock",
  "value": "FileSystemMainDomLock",
  "slotSetting": false
},
{
  "name": "UMBRACO__CMS__Hosting__LocalTempStorageLocation",
  "value": "EnvironmentTemp",
  "slotSetting": false
},
{
  "name": "UMBRACO__CMS__Examine__LuceneDirectoryFactory",
  "value": "SyncedTempFileSystemDirectoryFactory",
  "slotSetting": false
}

Remember to add an ASPNETCORE_ENVIRONMENT variable with values Development, Staging, or Production.

The minimum recommended Azure SQL Tier is "S2", however noticeable performance improvements are seen in higher Tiers

If you are load balancing or require the scaling ("scale out") ability of Azure Web Apps then you need to consult the Load Balancing documentation. This is due to the fact that a lot more needs to be configured to support scaling/auto-scaling.

Storage

It is important to know that Azure Web Apps uses a remote file share to host the files to run your website. This is due to the files running your website do not exist on the machine running your website. In many cases this isn't an issue. It can become one if you have a large amount of IO operations running over remote file-share.

Issues with read-only filesystems

Although Umbraco can be configured to use environmental storage it still requires its working-directory to be writable. If Umbraco is deployed to a read-only file system it will fail to boot.

For example, Azure's Run from Package feature is not supported by Umbraco. To check if your web app is using this feature you can check the WEBSITE_RUN_FROM_PACKAGE environment variable.

Scaling

If you require the scaling ("scale out") ability of Azure Web Apps you need to consult the Load Balancing documentation. This is due to the fact that a lot more needs to be configured to support scaling/auto-scaling.

Web worker migrations

It's important to know that Azure Web Apps may move your website between their 'workers' at any given time. This is normally a transparent operation. In some cases you may be affected by it if any of your code or libraries use the following variables:

  • Environment.MachineName (or equivalent)

When your site is migrated to another worker, these variables will change. You cannot rely on these variables remaining static for the lifetime of your website.

How to find the Linux App Service Logs

The quickest way to get to your logs is using the following URL template and replacing {app} with your Web App name:

https://{app}.scm.azurewebsites.net/api/logstream

You can also find this in the KUDU console by clicking Advanced Tools > Log Stream on the Web App in the Azure Portal.

Web App secret management

Consult the Azure Key Vault documentation if you would like to directly reference Azure Key Vault Secrets to your Azure Web App.

Hosting Umbraco in IIS

Information on hosting Umbraco on IIS

Configuring IIS for .NET

  • Install the .NET Core Runtime and download the Hosting Bundle. Ensure you download the correct .NET version as per the Requirements article.

  • Restart IIS (net stop was /y followed by net start w3svc)

  • Create a site in IIS and ensure that the .NET Common Language Runtime (CLR) version is set to No Managed Code for the Application Pool.

IIS Application Pool

Publish website for manual deployment to IIS

You can use the dotnet CLI to compile and collate all files required for hosting

dotnet publish -o ../deployment-artefacts -f net7.0

Alternatively, you can use the File Transfer Protocol (FTP) publishing in Visual Studio to compile and collate all the required files for the application to run.

In Visual Studio, select the Umbraco web project in the Solution Explorer and choose the Publish... command.

Publish...

Deploy a website for automated deployment with Azure DevOps to IIS

You can use the IIS Release task in Azure DevOps to deploy your website to your Web Server. This task is a wrapper for MSDeploy.exe and can be configured as preferred.

Environment Variables in ApplicationHost.config

In the Management section you find the Configuration Editor:

IIS Website Configuration

One section is of particular interest:

  • In the first, left hand dropdown list (Section:) choose: system.webServer/aspNetCore section.

  • In the second, right hand dropdown list (From:) choose: ApplicationHost.config <location path='[YOUR-SITENAME]'>. This ensures your settings will be stored in a machine specific file. The configuration files might end in a public repository and should not contain sensitive data like Connection Strings or Simple Mail Transfer Protocol (SMTP) configuration with username and password. Additionally, by default the configuration file will be overwritten during each publish processes.

IIS Configuration Editor

Find the line named environmentVariables and open the dialog to add environment variables. These work similar to the launchSettings. You can define ASPNETCORE_ENVIRONMENT and create an appSettings.[ASPNETCORE_ENVIRONMENT].json file. Or even better create environment variables for sensitive settings like passwords. There are some differences to launchSettings.json configuration:

  • Variable names need to change the object structure form JSON by combining the segments with double underscore __ e.g. ConnectionStrings__umbracoDbDSN

  • Escaped backslashes \\ e.g. serverName\\databaseInstanceName are replaced by single backslash \ e.g. DATABASESERVER123\SQL2017

IIS Hosting models

IIS can host .NET applications using 2 different hosting models

  • In-process (default)

  • In-process hosting runs a .NET app in the same process as its IIS worker process

  • Out-of-process - to enable this model you need to edit your .csproj file and add:

<PropertyGroup>
  <AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
</PropertyGroup>

Out-of-process .NET apps run separately from the IIS worker process. The module controls the management of the Kestrel server and requests are proxied between them.

Advanced Techniques With Flexible Load Balancing

This describes some more advanced techniques that you could achieve with flexible load balancing

The election process that runs during the startup of an Umbraco instance determines the server role that instance will undertake.

There are two server roles to be aware of for flexible load balancing:

  • SchedulingPublisher - The Umbraco instance usually used for backoffice access, responsible for running scheduled tasks.

  • Subscriber - A scalable instance that subscribes to content updates from the SchedulingPublisher server, not recommended to be used for backoffice access.

These new terms replace 'Master and Replica', in Umbraco versions 7 and 8.

Explicit SchedulingPublisher server

It is recommended to configure an explicit SchedulingPublisher server since this reduces the amount of complexity that the election process performs.

The first thing to do is create a couple of small classes that implement IServerRoleAccessor one for each of the different server roles:

then you'll need to replace the default IServerRoleAccessor for the your custom registrars. You'll can do this by using the SetServerRegistrar() extension method on IUmbracoBuilder from a .

Now that your subscriber servers are using your custom SubscriberServerRoleAccessor class, they will always be deemed 'Subscriber' servers and will not attempt to run the automatic server role election process or task scheduling.

By setting your SchedulingPublisher server to use your custom SchedulingPublisherServerRoleAccessor class, it will always be deemed the 'SchedulingPublisher' and will always be the one that executes all task scheduling.

Subscriber servers - Read-only database access

This description pertains only to Umbraco database tables

In some cases infrastructure admins will not want their front-end servers to have write access to the database. By default front-end servers will require write full access to the following tables:

  • umbracoServer

  • umbracoNode

This is because by default each server will inform the database that they are active and more importantly it is used for task scheduling. Only a single server can execute task scheduling and these tables are used for servers to use a server role election process without the need for any configuration. So in the case that a subscriber server becomes the SchedulingPublisher task scheduler, it will require write access to all of the Umbraco tables.

In order to have read-only database access configured for your front-end servers, you need to implement the configuration mentioned above.

Now that your subscriber servers are using your custom SubscriberServerRoleAccessor class, they will always be deemed 'Subscriber' servers and will not attempt to run the automatic server role election process or task scheduling. Because you are no longer using the default ElectedServerRoleAccessor they will not try to ping the umbracoServer table.

If using on Azure WebApps then write-permissions are required for the following tables for all server roles including 'Subscriber'.

  • umbracoLock

  • umbracoKeyValue

SQL Server Replica databases cannot be used as they are read-only without replacing the default MainDomLock with a custom provider.

Controlling how often the load balancing instructions from the database are processed and pruned

The configurations can be adjusted to control how often the load balancing instructions from the database are processed and pruned.

Below is shown how to do this from a JSON configuration source.

Options:

  • TimeToRetainInstructions - The timespan to keep instructions in the database; records older than this number will be pruned.

  • MaxProcessingInstructionCount - The maximum number of instructions that can be processed at startup; otherwise the server cold-boots (rebuilds its caches)

  • TimeBetweenSyncOperations - The timespan to wait between each sync operations

  • TimeBetweenPruneOperations - The timespan to wait between each prune operation

These setting would normally be applied to all environments as they are added to the global app settings. If you need these settings to be environment specific, we recommend using .

public class SchedulingPublisherServerRoleAccessor : IServerRoleAccessor
{
    public ServerRole CurrentServerRole => ServerRole.SchedulingPublisher;
}

public class SubscriberServerRoleAccessor : IServerRoleAccessor
{
    public ServerRole CurrentServerRole => ServerRole.Subscriber;
}
// This should be executed on your single `SchedulingPublisher` server
builder.SetServerRegistrar<SchedulingPublisherServerRoleAccessor>();

// This should be executed on your `Subscriber` servers
builder.SetServerRegistrar<SubscriberServerRoleAccessor>();
{
    "Umbraco": {
        "CMS": {
            "Global": {
                "DatabaseServerMessenger": {
                    "MaxProcessingInstructionCount": 1000,
                    "TimeBetweenPruneOperations": "00:01:00",
                    "TimeBetweenSyncOperations": "00:00:05",
                    "TimeToRetainInstructions": "2.00:00:00"
                }
            }
        }
    }
}
Composer
Explicit SchedulingPublisher server
SqlMainDomLock
environment specific appSetting files

Logging With Load Balancing

Umbraco v8+ uses Serilog for logging. When load balancing Umbraco consideration should be given as to how the log files from each server will be accessed.

There are many Serilog Sinks available. One of these may be appropriate to store logs for all servers in a central repository such as Azure Application Insights or Elmah.io.

For more information, see SeriLog Provided Sinks.

Standalone File System

No file replication is configured, deployment handles updating files on the different servers.

If the file system on your servers isn't performing any file replication then no Umbraco configuration file changes are necessary. However Media will need to be configured to use a shared location such as Blob storage or S3.

Depending on the configuration and performance of the environment's local storage you might need to consider Examine Directory Factory Options and the Umbraco temporary storage location.

Synchronised File System

The servers are performing file replication, updates to a file on one server, updates the corresponding file on any other servers.

If the file system on your servers is performing file replication then the Umbraco temporary folder (~/umbraco/Data/TEMP) must be excluded from replication.

If the file system on your servers is located on shared storage you will need to configure Umbraco to locate the Umbraco temporary folder outside of the shared storage.

Replication techniques

A common way to replicate files on Windows Server is to use [DFS](https://msdn.microsoft.com/en-us/library/windows/desktop/bb540031(v=vs.85), which is included with Windows Server.

Additional DFS resources:

  • Overview of DFS Replication in Windows Server 2008 R2

  • Watch an intro to installing and working with DFS

There are other alternatives for file replication out there, some free and some licensed. You'll need to decide which solution is best for your environment.

Non-replicated files

When deploying Umbraco in a load balanced scenario using file replication, it is important to ensure that not all files are replicated - otherwise you will experience file locking issues. Here are the folders and files that should not be replicated:

  • ~/umbraco/Data/TEMP/*

Alternatively store the Umbraco temporary files in the local server's 'temp' folder and set Examine to use a Directory Factory.

Achieve this by changing the value of the LuceneDirectoryFactory setting to 'TempFileSystemDirectoryFactory' in the appsettings.json. The downside is that if you need to view temporary files you'll have to find it in the temp files. Locating the file this way isn't always clear.

Below is shown how to do this in a Json configuration source.

{
    "Umbraco": {
        "CMS": {
            "Examine": {
                "LuceneDirectoryFactory" : "TempFileSystemDirectoryFactory"
            }
        }
    }
}
  • ~/umbraco/Logs/*

    • This is optional and depends on how you want your logs configured (see below)

If for some reason your file replication solution doesn't allow you to not replicate specific files folders (which it should!!) then you can use an alternative approach by using virtual directories.

The following is not the recommended setup but it is a viable alternative:

  • Copy the ~/umbraco/Data/TEMP directory to each server, outside of any replication areas or to a unique folder for each server.

  • Create a virtual directory (not a virtual application) in the ~/umbraco/Data/ folder, and name it TEMP. Point the virtual directory to the folder you created in step 2.

  • You may delete the ~/umbraco/Data/TEMP folder from the file system - not IIS as this may delete the virtual directory - if you wish.

IIS Setup

IIS configuration is pretty straightforward with file replication. IIS is only reading files from its own file system like a normal IIS website.

Mixture of standalone & synchronised

In some scenarios you have a mixture of standalone and synchronised file systems. An example of this is Azure Web Apps where the file system isn't replicated between backoffice and front end servers but is replicated between all front end servers, in this configuration you should follow the steps for synchronised file systems.

There is a specific documentation for load balancing with Azure Web Apps

Examine Directory Factory Options

  • The TempFileSystemDirectoryFactory allows Examine to store indexes directly in the environment temporary storage directory, and should be used instead of SyncTempEnvDirectoryFactory mentioned above.

{
    "Umbraco": {
        "CMS": {
            "Examine": {
                "LuceneDirectoryFactory" : "TempFileSystemDirectoryFactory"
            }
        }
    }
}
  • The SyncedTempFileSystemDirectoryFactory enables Examine to sync indexes between the remote file system and the local environment temporary storage directory, the indexes will be accessed from the temporary storage directory. This setting is needed because Lucene has issues when working from a remote file share so the files need to be read/accessed locally. Any time the index is updated, this setting will ensure that both the locally created indexes and the normal indexes are written to. This will ensure that when the app is restarted or the local environment temp files are cleared out that the index files can be restored from the centrally stored index files.

{
    "Umbraco": {
        "CMS": {
            "Examine": {
                "LuceneDirectoryFactory" : "SyncedTempFileSystemDirectoryFactory"
            }
        }
    }
}

If you are load balancing with Azure Web Apps make sure to check out the article we have for that specific set-up.

Advanced techniques

Once you are familiar with how flexible load balancing works, you might be interested in some advanced techniques.

Running Umbraco in Docker

Exactly how you choose to compose your Dockerfile will depend on your project specific needs. This section is not intended as a comprehensive guide, rather as an overview of topics to be aware of when hosting in Docker.

What is Docker

Docker is a platform for developing, shipping, and running applications in containers. Multiple services exist for hosting these containers. For more information, refer to the official Docker Documentation

The Docker file system

By default, files created inside a container are written to an ephemeral, writable container layer. This means that the files don't persist when the container is removed, and it's challenging to get files out of the container. Additionally, this writable layer is not suitable for performance-critical data processing.

This has implications when running Umbraco in Docker.

For more information, refer to the Docker documentation on storage.

General file system consideration

In general, when working with files and Docker you work in a "push" fashion with read-only layers. When you build, you take all your files and "push" them into this read-only layer.

This means that you should avoid making files on the fly, and instead rely on building your image.

In an Umbraco context, this means you should not create or edit template, script or stylesheet files via the backoffice. These should be deployed as part of your web application and not managed via Umbraco.

Similarly, you shouldn't use InMemory modelsbuilder, since that also relies on creating files on the disk. While this is not a hard requirement, it doesn't provide any value unless you are live editing your site.

Instead, configure models builder to use "source code" mode in development, and "none" in production, as described when using runtime modes.

Logs

Umbraco writes logs to the /umbraco/Logs/ directory. Due to the performance implications of writing to a writable layer, and the limited size, it is recommended to mount a volume to this directory.

Data

The /umbraco/Data/ directory is used to store temporary files, such as file uploads. Considering the limitations of the writable layer, you should also mount a volume to this directory.

Media

It's recommended to not store media in the writable layer. This is for similar performance reasons as logs, but also for practical hosting reasons. You likely want to persist media files between containers.

One solution is to use bind mounts. The ideal setup, though, is to store the media and ImageSharp cache externally. For more information, refer to the Azure Blob Storage documentation.

Required files

Your solution may require some specific files to run, such as license files. You will need to pass these files into the container at build time, or mount them externally.

HTTPS

When running websites in Docker, it's common to do so behind a reverse proxy or load balancer. In these scenarios you will likely handle SSL termination at the reverse proxy. This means that Umbraco will not be aware of the SSL termination, and will complain about not using HTTPS.

Umbraco checks for HTTPS in two locations:

  1. The HstsCheck health check - This will result in a failed healthcheck.

  2. The UseHttpsValidator - This will result in a build error, if Production runtime mode is used.

To avoid these checks failing, you can remove them in your project.

Health Check

The health check must be removed via configuration, through the appsettings.json file, environment variables, or similar. For more information see the Health Check documentation.

The HstsCheck key is E2048C48-21C5-4BE1-A80B-8062162DF124 so the appsettings will look something like:

  "Umbraco": {
    "CMS": {
      "HealthChecks" : {
        "DisabledChecks": [
          {
            "Id": "E2048C48-21C5-4BE1-A80B-8062162DF124"
          }
        ]
      },
      {...}

Runtime mode validator

The UseHttpsValidator must be removed through code For more information see the Runtime mode documentation.

The code to remove the validator can look something like:

using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Infrastructure.Runtime.RuntimeModeValidators;

namespace MySite;

public class DockerChecksRemover : IComposer
{
    public void Compose(IUmbracoBuilder builder)
        => builder.RuntimeModeValidators().Remove<UseHttpsValidator>();
}

Umbraco in Load Balanced Environments

Information on how to deploy Umbraco in a Load Balanced scenario and other details to consider when setting up Umbraco for load balancing

Information on how to deploy Umbraco in a Load Balanced scenario and other details to consider when setting up Umbraco for load balancing.

Overview

Configuring and setting up a load balanced server environment requires planning, design and testing. This document should assist you in setting up your servers, load balanced environment and Umbraco configuration.

This document assumes that you have a fair amount of knowledge about:

  • Umbraco

  • IIS 10+

  • Networking & DNS

  • Windows Server

  • .NET5+

It is highly recommended that you setup your staging environment to also be load balanced so that you can run all of your testing on a similar environment to your live environment.

Design

These instructions make the following assumptions:

  • All web servers can communicate with the database where Umbraco data is stored

  • You are running Umbraco 9.0.0 or above

  • You will designate a single server to be the backoffice server for which your editors will log into for editing content. Umbraco will not work correctly if the backoffice is behind the load balancer.

There are three design alternatives you can use to effectively load balance servers:

  1. You use cloud based auto-scaling appliances like Microsoft's Azure Web Apps

  2. Each server hosts copies of the load balanced website files and a file replication service is running to ensure that all files on all servers are up to date

  3. The load balanced website files are located on a centralized file share (SAN/NAS/Clustered File Server/Network Share)

You will need a load balancer to do your load balancing.

How Umbraco load balancing works

In order to understand how to host your site it is best to understand how Umbraco's flexible load balancing works.

The following diagram shows the data flow/communication between each item in the environment:

Umbraco flexible load balancing diagram

The process is as follows:

  • Administrators and editors create, update, delete data/content on the backoffice server

  • These events are converted into data structures called "instructions" and are stored in the database in a queue

  • Each front-end server checks to see if there are any outstanding instructions it hasn't processed yet

  • When a front-end server detects that there are pending instructions, it downloads them and processes them and in turn updates it's cache, cache files and indexes on its own file system

  • There can be a delay between content updates and a front-end server's refreshing, this is expected and normal behaviour.

Scheduling and server role election

Although there is a backoffice server designated for administration, by default this is not explicitly set as the "Scheduling server". In Umbraco there can only be a single scheduling server which performs the following 3 things:

  • Keep alive service - to ensure scheduled publishing occurs

  • Scheduled tasks - to initiate any configured scheduled tasks

  • Scheduled publishing - to initiate any scheduled publishing for documents

Automatic Server Role Election

Umbraco will automatically elect a "Scheduling server" to perform the above services. This means that all of the servers will need to be able to resolve the URL of either: itself, the Backoffice server, the internal load balancer, or the public address.

There are two server roles:

  • SchedulingPublisher - Usually this is the backoffice instance.

  • Subscriber - These are the scalable front-end instances - not recommended to be used for backoffice access.

These new terms replace 'Master and Replica', in Umbraco versions 7 and 8.

Each instance will be allocated a role by the automatic server role election process, but they can also be set explicitly (recommended)

For example, In the following diagram the node f02.mysite.local is the elected "Scheduling server". In order for scheduling to work it needs to be able to send requests to itself, the Backoffice server, the internal load balancer or the public address. The address used by the "Scheduling server" is called the "umbracoApplicationUrl".

Umbraco flexible load balancing diagram

By default, Umbraco will set the "umbracoApplicationUrl" to the address made by the first accepted request when the AppDomain starts. It is assumed that this address will be a DNS address that the server can resolve.

For example, if a public request reached the load balancer on www.mysite.com, the load balancer may send the request on to the servers with the original address: www.mysite.com. By default the "umbracoApplicationUrl" will be www.mysite.com. However, load balancers may route the request internally under a different DNS name such as "f02.mysite.local" which by default would mean the "umbracoApplicationUrl" is "f02.mysite.local". In any case the elected "Scheduling server" must be able to resolve this address.

In many scenarios this is fine, but in case this is not adequate there's a few of options you can use:

  • Recommended: set your front-end(s) (non-admin server) to be explicit subscriber servers by creating a custom IServerRegistrar, this means the front-end servers will never be used as the SchedulingPublisher server role.

  • Set the UmbracoApplicationUrl property in the WebRouting section of the CMS config

Common load balancing setup information

The below section applies to all ASP.NET load balancing configurations.

Server Configuration

This section describes the configuration options depending on your hosting setup:

  1. Azure Web Apps - You use cloud based auto-scaling appliances like Microsoft's Azure Web Apps

  2. File Replication - Each server hosts copies of the load balanced website files and a file replication service is running to ensure that all files on all servers are up to date

  3. Centralized file share - The load balanced website files are located on a centralized file share (SAN/NAS/Clustered File Server/Network Share)

Full documentation is available here

Data Protection

The replacement for Machine Keys in ASP.NET Core are called Data Protection. You will need to setup data protection to the same keys on all servers, without this you will end up with view state errors, validation errors and encryption/decryption errors since each server will have its own generated key.

ASP.NET Core supports multiple ways to share keys. Use the official docs to find a description that fits your setup the best.

Session State and Distributed Cache

It is required to setup a distributed cache, like DistributedSqlServerCache or an alternative provider (see https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed for more details). The distributed cache is used by the session in your application, which is used by the default TempDataProvider in MVC.

Because Umbraco in some cases uses TempData, your setup needs to be configured with a distributed cache.

Logging

There are some logging configurations to take into account no matter what type of load balancing environment you are using.

Full documentation is available here

Testing

Your staging environment should also be load balanced so that you can see any issues relating to load balancing in that environment before going to production.

You'll need to test this solution a lot before going to production. You need to ensure there are no windows security issues, etc... The best way to determine issues is have a lot of people testing this setup and ensuring all errors and warnings in your application/system logs in Windows are fixed.

Ensure to analyze logs from all servers and check for any warnings and errors.

Unattended upgrades

When upgrading it is possible to run the upgrades unattended.

Find steps on how to enable the feature for a load balanced setup in the General Upgrades article.

FAQs

Here's some common questions that are asked regarding Load Balancing with Umbraco:

Question> Why do I need to have a single web instance for Umbraco admin?

TL:DR You must not load balance the Umbraco backoffice, you will end up with data integrity or corruption issues.

The reason you need a single server is because there is no way to guarantee transactional safety between servers. This is because we don't currently use database level locking, we only use application (c#) level locks to guarantee transactional data integrity which is only possible to work on one server. If you have multiple admins saving and publishing at once between servers then the order in which this data is read and written to the database absolutely must be consistent otherwise you will end up with data corruption.

Additionally, the order in which cache instructions are written to the cache instructions table is important for LB, this order is guaranteed by having a single admin server.

Question> Can my SchedulingPublisher backoffice admin server also serve front-end requests?

Yes. There are no problems with having your SchedulingPublisher backoffice admin server also serve front-end request.

However, if you wish to have different security policies for your front-end servers and your back office servers, you may choose to not do this.

Load Balancing Azure Web Apps

Ensure you read the Load Balancing overview and general Azure Web Apps documentation before you begin - you will need to ensure that your ASP.NET Core & logging configurations are correct.

Azure Requirements

  • 2 x App service plans with 1 x web app in each:

    • One for the backoffice (Administrative) environment

    • One for your scalable public-facing environment (Public)

  • 1 x SQL server that is shared with these 2 web apps

The setup above will allow for the proper scaling of the Administrative and Public web apps.

The App Service plan with the Administrative web app should only be scaled up. The reason for this is that the web app needs to stay as a single instance.

The App Service plan with the Public web app can be scaled both out and up.

Loadbalancing infrastructure on Azure web apps

Lucene/Examine configuration

The single instance Backoffice Administrative Web App should be set to use SyncedTempFileSystemDirectoryFactory.

The multi-instance Scalable Public Web App should be set to use TempFileSystemDirectoryFactory.

Umbraco TEMP files

When an instance of Umbraco starts up it generates some 'temporary' files on disk. In a normal IIS environment, these would be created within the folders of the Web Application. In an Azure Web App, we want these to be created in the local storage of the actual server that Azure happens to be used for the Web App. So we set this configuration setting to 'true' and the temporary files will be located in the environment temporary folder. This is required for both the performance of the website as well as to prevent file locks from occurring due to the nature of Azure Web Apps shared files system.

{
    "Umbraco": {
        "CMS": {
            "Hosting": {
                "LocalTempStorageLocation" : "EnvironmentTemp"
            }
        }
    }
}

Host synchronization

Umbraco runs within a .NET Host.

When a host restarts, the current host 'winds down' while another host is started. This means there can be more than one live host during a restart. Restarts can occur in many scenarios including when an Azure Web App auto-transitions between hosts, you scale the instances or you utilize slot swapping.

Some file system based services in Umbraco such as the Published Cache and Lucene files can only be accessed by a single host at once. Umbraco manages this synchronization by an object called IMainDom.

By default Umbraco v9.4 & 9.5 uses a system-wide semaphore locking mechanism. This mechanism only works on Windows systems and doesn't work with multi-instance Azure Web Apps. We need to swap it out for an alternative file system based locking mechanism by using the following appSetting. With Umbraco v10+ FileSystemMainDomLock is the default setting.

{
    "Umbraco": {
        "CMS": {
            "Global": {
                "MainDomLock" : "FileSystemMainDomLock"
            }
        }
    }
}

Apply this setting to both the SCHEDULINGPUBLISHER Administrative server and the SUBSCRIBER scalable public-facing servers.

Steps to set-up an environment

  1. Create an Azure SQL database

  2. Install Umbraco on your backoffice administrative environment and ensure to use your Azure SQL Database

  3. Install Umbraco on your scalable public-facing environment and ensure to use your Azure SQL Database

  4. Test: Perform some content updates on the administrative environment, ensure they work successfully in that environment, then verify that those changes appear on the scalable public-facing environment

  5. Fix the backoffice environment to be the SCHEDULINGPUBLISHER scheduling server and the scalable public-facing environment to be SUBSCRIBERs - see Setting Explicit Server Roles

Ensure all Azure resources are in the same region to avoid connection lag.

Scaling

Do not scale your backoffice administrative environment this is not supported and can cause issues.

The public-facing subscriber Azure Web Apps can be manually or automatically scaled up or down and is supported by Umbraco's load balancing.

Deployment considerations

Since you have 2 x web apps, when you deploy you will need to deploy to both places - There are various automation techniques you can use to simplify the process. That is outside the scope of this article.

This also means that you should not be editing templates or views on a live server as SchedulingPublisher and Subscriber environments do not share the same file system. Changes should be made in a development environment and then pushed to each live environment.

Runtime Modes

This section describes how to use the runtime mode setting to optimize Umbraco for the best development experience or optimal production environment.

Configuring the runtime mode

You can configure the runtime mode to optimize Umbraco for different development experiences and environments by setting Umbraco:CMS:Runtime:Mode to one of the available modes:

  • BackofficeDevelopment (default)

  • Development

  • Production

This can be done via the appsettings.json file, environment variables, or any other .NET configuration provider (like Azure Key Vault/App Configuration). Although this setting affects how Umbraco behaves at runtime, some modes have prerequisites on how the project is built/published. Make sure to read the descriptions of each mode before changing this setting from the default BackofficeDevelopment mode, as incorrect configuration can result in your application not starting (by throwing a BootFailedException).

BackofficeDevelopment mode

The BackofficeDevelopment mode is the default behavior for Umbraco: it does not optimize Umbraco for any specific environment and does not have any prerequisites. This mode allows for rapid development (without having to recompile/rebuild your project), including all development from within the backoffice.

Development mode

The Development mode can be used when you're developing from an IDE (like Visual Studio, VS Code, or Rider) or the dotnet CLI (e.g. using dotnet watch). It is a recommended prerequisite if you want to use the Production mode in your production environment.

This mode disables in-memory ModelsBuilder generation and validates the following setting:

  • Umbraco:CMS:ModelsBuilder:ModelsMode is not set to InMemoryAuto.

If you want to use the generated models, use SourceCodeAuto or SourceCodeManual, which requires manually recompiling the project after the models have changed (e.g. after updating Document Types, Media Types, Member Types, or Data Types). Razor views (cshtml files) will still be automatically compiled at runtime, allowing you to quickly iterate on the rendered output from templates, (macro) partial views, and view components.

The recommended approach to enable Development mode is to update the appsettings.json file with the following settings:

Ensure your models are generated by running Umbraco and navigating to Settings > Models Builder > Generate models. You can remove the following properties from your csproj project file to enable the compilation of Razor views (which also ensures your views do not contain compilation errors and is a prerequisite for enabling Production mode):

Fix any compilation errors you might get after this, e.g. if you accidentally referenced deleted models or properties. Running the application will still show the rendered content and you're now ready to optionally enable Production mode on your production environment.

Ensure you have the <CopyRazorGenerateFilesToPublishDirectory>true</CopyRazorGenerateFilesToPublishDirectory> property set in your csproj project file, so Razor views are always copied to the publish directory. This is required by the CMS to display the contents in the backoffice, for Forms to lookup custom theme views and for Deploy to be able to compare schemas (otherwise you'll get schema mismatches).

Production mode

Use Production mode to ensure your production environment is running optimally by disabling development features and validating whether specific settings are configured to their recommended production values.

This mode disables both in-memory ModelsBuilder generation (see ) and Razor (cshtml) runtime compilation. Production mode requires you to compile your views at build/publish time and enforces the following settings for optimal performance/security:

  • The application is built/published in Release mode (with JIT optimization enabled), e.g. using dotnet publish --configuration Release;

  • Umbraco:CMS:WebRouting:UmbracoApplicationUrl is set to a valid URL;

  • Umbraco:CMS:Global:UseHttps is enabled;

  • Umbraco:CMS:RuntimeMinification:CacheBuster is set to a fixed cache buster like Version or AppDomain;

  • Umbraco:CMS:ModelsBuilder:ModelsMode is set to Nothing.

To compile your views at build/publish time, remove the <RazorCompileOnBuild> and <RazorCompileOnPublish> properties from your project file (see the section). If you don't, Umbraco can't find the templates and will return 404 (Page Not Found) errors.

The recommended approach to enable Production mode is to update the appsettings.Production.json file (or create one) with the following settings:

Although you can still edit document types and views (if not running from the published output), changes won't be picked up until you've rebuilt your project or republished the application.

Models won't be generated by ModelsBuilder (because the mode is set to Nothing), requiring you to do all your changes while in Development mode. As Models Builder is set to Nothing, the Models Builder dashboard is disabled in the backoffice of live environment.

Also, templates cannot be edited on live environment as runtime compilation is not enabled and is set to Production.

Also ensure the UmbracoApplicationUrl is updated to the primary URL of your production environment, as this is used when sending emails (password reset, notifications, health check results, etc.) and the keep-alive task.

Static web assets are disabled when using Production mode, following . If you are running a non-Development environment using the Production runtime mode from source (non-published output), you will need to explicitly enable this. You can add the following line of code to your Program.cs file:

This should not be used in a more typical production environment where you are hosting your application from published output.

Customize/extend runtime mode validation

Validation of the above-mentioned settings is done when determining the runtime level during startup using the new IRuntimeModeValidationService and when it fails, causes a BootFailedException to be thrown. The default implementation gets all registered IRuntimeModeValidators to do the validation, making it possible to remove default checks and/or add your own (inherit from RuntimeModeProductionValidatorBase, if you only want to validate against the production runtime mode). The following validators are added by default:

  • JITOptimizerValidator - Ensure the application is built/published in Release mode (with JIT optimization enabled) when in production runtime mode, e.g. using dotnet publish --configuration Release;

  • UmbracoApplicationUrlValidator - ensure Umbraco:CMS:WebRouting:UmbracoApplicationUrl is configured when in production runtime mode;

  • UseHttpsValidator - ensure Umbraco:CMS:Global:UseHttps is enabled when in production runtime mode;

  • RuntimeMinificationValidator - ensure Umbraco:CMS:RuntimeMinification:CacheBuster is set to a fixed cache buster like Version or AppDomain when in production runtime mode;

  • ModelsBuilderModeValidator - ensure Umbraco:CMS:ModelsBuilder:ModelsMode is not set to InMemoryAuto when in development runtime mode and set to Nothing when in production runtime mode.

The following example removes the default UmbracoApplicationUrlValidator and adds a new custom DisableElectionForSingleServerValidator:

{
    "Umbraco": {
        "CMS": {
            "Runtime": {
                "Mode" : "Development"
            },
            "ModelsBuilder":{
                "ModelsMode": "SourceCodeAuto"
            }
        }
    }
}
<RazorCompileOnBuild>false</RazorCompileOnBuild>
<RazorCompileOnPublish>false</RazorCompileOnPublish>
{
  "Umbraco": {
    "CMS": {
      "Runtime": {
        "Mode": "Production"
      },
      "Global": {
        "UseHttps": true
      },
      "ModelsBuilder": {
        "ModelsMode": "Nothing"
      },
      "WebRouting": {
        "UmbracoApplicationUrl": "https://<REPLACE_WITH_YOUR_PRIMARY_DOMAIN>/"
      }
    }
  }
}
builder.WebHost.UseStaticWebAssets();
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Infrastructure.Runtime;
using Umbraco.Cms.Infrastructure.Runtime.RuntimeModeValidators;

public class RuntimeModeValidatorComposer : IComposer
{
    public void Compose(IUmbracoBuilder builder)
        => builder.RuntimeModeValidators()
            .Remove<UmbracoApplicationUrlValidator>()
            .Add<DisableElectionForSingleServerValidator>();
}

public class DisableElectionForSingleServerValidator : IRuntimeModeValidator
{
    private readonly IOptionsMonitor<GlobalSettings> _globalSettings;

    public DisableElectionForSingleServerValidator(IOptionsMonitor<GlobalSettings> globalSettings) => _globalSettings = globalSettings;

    public bool Validate(RuntimeMode runtimeMode, [NotNullWhen(false)] out string? validationErrorMessage)
    {
        if (runtimeMode == RuntimeMode.Production && _globalSettings.CurrentValue.DisableElectionForSingleServer == false)
        {
            validationErrorMessage = "Disable primary server election (and support for load balancing) to improve startup performance.";
            return false;
        }

        validationErrorMessage = null;
        return true;
    }
}
Development mode
Development mode
Microsoft guidance