AWS DevOps Blog

Run Umbraco CMS with Flexible Load Balancing on AWS

In version 7.3, Umbraco CMS the popular open source CMS introduced the flexible load balancing feature, which makes the setup of load-balanced applications a lot easier. In this blog post, we’ll follow the guidelines in the Umbraco documentation to set up a load-balanced Umbraco application on AWS. We’ll let AWS Elastic Beanstalk manage the deployments, load balancing, auto scaling, and health monitoring for us.

Application Architecture

When you use the flexible load balancing feature, any updates to Umbraco content will be stored in a queue in the master database. Each server in the load-balanced environment will automatically download, process, and cache the updates from the queue, so no matter which server is selected by the Elastic Load Balancing to handle the request, the user will always receive the same content. Umbraco administration doesn’t work correctly if accessed from a load-balanced server. For this reason, we’ll set up a non-balanced environment to be accessed only by the administrators and editors.

Create Elastic Beanstalk Environments

We’ll start by creating a single instance environment for administrators and editors. This environment will have the master database server as an RDS instance. In the Elastic Beanstalk console, choose Create New Application. Type a name for the application, and then choose Create. When you see the message “No environments currently exist for this application”, choose Create one now. Select Web server environment for the environment tier.

On the Create a new environment page, choose .NET for Platform, and then choose Configure more options.

On the next page, under Capacity, set the Environment type to Single instance. Under Database, for Engine, choose sqlserver. Set the Storage field to, at minimum, 20 GB, review the information, and then choose Create environment.

Next, we’ll create a load-balanced environment for the front-end users. Follow the steps you used to create the first Elastic Beanstalk environment. When you reach the configuration page, select High availability, and then choose Create environment.

Configure RDS Database Server Security Groups

When we created the RDS DB instance through the first environment, Elastic Beanstalk automatically configured the security to allow the servers in this environment to access the database. We’ll configure the security for the second environment manually. By following these steps, the front-end servers will be able to connect to the database:

  1. In the Elastic Beanstalk console, copy the name of the security group for the front-end environment. You will need this for step 7 of this procedure.
  2. In the admin environment, choose Configuration, and then choose RDS.
  3. Choose the View in RDS Console link.
  4. On the Details tab in the RDS console, in the Security and Network section, choose Security Groups.
  5. Choose the name of the active security group to open it in the EC2 console.
  6. In the EC2 console, you should see that Elastic Beanstalk has already added a rule for the admin environment.
  7. Choose Edit, and then choose Add Rule. For Type, choose MS SQL. For Source, paste the name of the security group for the front-end environment.

Handle Session State in a Load Balanced Environment

By default, ASP.NET stores the user’s session in memory. This means the user will lose session information if the next request goes to a different server. To prevent this from happening while keeping the default session provider, configure sticky sessions for your load balancer.

In the Elastic Beanstalk console, navigate to the front-end environment configuration. You can use the Sessions section under the Load Balancing settings to specify whether the load balancer for the application will allow session stickiness. Select the Enable Session Stickiness check box.

When you enable session stickiness, ELB will send all requests for a specific user to the same back-end web server. This can result in an imbalance of requests across all back ends, with some servers having more load than others. When you scale down, the termination of an instance can result in a loss of sessions assigned to it. For this reason, consider storing the sessions in a central location like a SQL Server database and use the SqlSessionStateStore provider.

AWS offers other options, for example, storing the sessions in a NoSQL database using the DynamoDBSessionStore provider or using the Amazon ElastiCache to store the sessions in the cloud as in-memory cache. For information, see the ElastiCache as an ASP.NET Session Store blog post.

A One-Step Alternative: CloudFormation Template

You can download and use this CloudFormation template to create resources similar to those created in the preceding steps. If you use the template, you will still have to prepare and publish your own version of Umbraco from a local machine. We’ll do that next.

The template is written to create the RDS database as a separate resource from the environments. You’ll see in the previous steps the DB is tied to the admin environment (for example, if you delete the environment, the DB will be deleted, too). This works well during development or testing, but is not ideal for production. If you should accidentally delete your database, by default, Elastic Beanstalk creates a snapshot on environment termination so it can be recovered. For information about how to decouple the DB from your environment, see Using Elastic Beanstalk with Amazon RDS in the Elastic Beanstalk Developer Guide.

Prepare the Umbraco CMS Locally

To keep things simple, we’ll download Umbraco from our.umbraco.org/download. As of this writing, the current version is v7.5.

From IIS on the local machine, add a new website with the following settings:

File and Folder Permissions

To ensure the Umbraco installation will run smoothly, grant the read and write permissions to the application pool user for Umbraco’s files and folders. In IIS, right-click the UmbracoApp website, and then click Edit Permissions. Grant modify or full-control permissions to IIS_IUSRS. For information, see File and folder permissions in the Umbraco documentation.

When we deploy the application to AWS, we need to update the permissions for IIS_IUSRS, too. It isn’t easy to access and grant permissions to each Windows server in the environment. If we create an .ebextension, Elastic Beanstalk can automate the permissions process. It can also allow us to run extra commands during the application deployment:

commands:
  create_default_website_folder:
    command: if not exist "C:\inetpub\wwwroot" mkdir "C:\inetpub\wwwroot"
  update_iis_user_permissions:
    command: Icacls.exe "C:\inetpub\wwwroot" /grant IIS_IUSRS:(OI)(CI)F

Here is the .ebextension saved as a .config file:

C:\inetpub\wwwroot\UmbracoCms\App_Data\.ebextensions\update_iis_permissions.config

Although this one is written in YAML, you can write .ebextensions in JSON, too. You can extend the .ebextension by writing a test to ensure the commands run on the first deployment only and not on redeployments. For more information, see the Configuring Advanced Logging on AWS Elastic Beanstalk blog post or the .ebextensions documentation.

Custom Machine Key

By default, ASP.NET generates a unique machine key for each server. In a load-balanced environment, this will cause validation errors and invalid view state. To fix this issue, make sure the machine key is the same on all servers. One of the simplest ways to generate a custom key is from IIS.

In IIS, on the Machine Key page, click Generate Keys. Change the settings as follows, and click Apply.

Create an Empty Database

Before running the CMS installation, we’ll create an empty database in our RDS DB server. Open AWS Explorer in Visual Studio, right-click the DB instance we created in the first step, and then select Create SQL Server Database.

If you encounter any problems connecting to the RDS server, add the IP address of the development machine to the RDS DB security group. Make sure your Windows Firewall allows outbound access for 1433 port.

Run the Umbraco CMS Installation

In IIS, click Browse. The Umbraco installation should start. Enter the required information and use the RDS DB information to complete the fields for the database configuration step.

Publish Umbraco CMS to AWS

Finally, open the UmbracoApp folder in Visual Studio. From the File menu, click Open. Click Web site, click File system, and then navigate to C:\inetpub\wwwroot\UmbracoCms. Right-click the project, and then select Publish to AWS to deploy to the admin environment and then deploy again to the front-end environment.

The EBS volumes attached to the instances in the environments are isolated and not shared. When compared to other load-balanced solutions that use shared storage, there is no extra work required to separate Umbraco logging file paths, change XML cache content settings, or update the configuration for Lucene/Examine indexes.

Conclusion

You now have an Umbraco application that is ready to scale up or down on AWS, and you can take this further using Elastic Beanstalk, there are many options to customize your environments, for example, associating a custom domain name or enabling HTTPS.

We hope you found the information in this post helpful. If you have questions or other feedback, please leave it in the comments below.