In this tutorial, you will learn how to host your Umbraco media folder within an AWS S3 bucket.  The benefit is using S3 to host your static files within the media/templates/stylesheets within the cloud.  Hosting files within the cloud instead of on a file-server can be hugely beneficial.   For example, within a load-balanced configuration, you can easily sync media between different servers.

In the first half of the tutorial, I will walk you through how to create an account in AWS and configure your S3 bucket successfully. In the second part, we will focus on configuring Umbraco.

Creating an S3 Account

To host your media within AWS you will need to create an S3 bucket. You can do this from Amazon AWS. Create a new account and follow the steps to create an S3 bucket.

As the media within the bucket will need to be accessible front-end website, you will need to allow Umbraco and the world to access your media, so you will need to ensure that you do not block public access, by making sure the 'block public access' is not ticked:

You will also need to configure a user account so you can upload files to S3. To create a user token within AWS go to the 'My Security Credentials':

When you're creating the user you will use for Umbraco to access AWS, you will need to ensure the user has the 'AmazonS3FullAccess' permission:



After creating a user, you will need to get the access id and token to use within your website.  You will put these two things within an app setting within the web.config later.  To get a key within the security credentials section, like the 'create access key'.  Copy the details from the pop-up:

Managing Your Media

The easiest way to manage and upload files from your PC into S3 is to use S3 Browser. From here you just need your access ID and secret code.

Configuring Umbraco

First, we will need to configure Umbraco to use some new packages, the main one being the Umbraco S3 Provider. Within Visual Studio, open the package manager console:

Tools > NuGet package manager

Run these commands:

Install-Package Umbraco.Storage.S3

And

Install-Package ImageProcessor.Web.Config

After installing those packages, we will need to update some config files.

~/config/filesystemprovider.config

The fileSystemProviders.config contains all the configurations that tell Umbraco how to interact with file systems. If you want to read a little more about this you can view the official Umbraco documentation here. You can find this file within the 'config' -> 'filesystemprovider.config'. If you open up a default Umbraco local storage, you should see something similar to this:

<FileSystemProviders>
  
  <!-- Media -->
  <Provider alias="media" type="Umbraco.Core.IO.PhysicalFileSystem, Umbraco.Core">
    <Parameters>
      <add key="virtualRoot" value="~/media/" />
    </Parameters>
  </Provider>
   
</FileSystemProviders>

To configure Azure you will need to update/add containerName, rootUrl and connection string values. You can find the connectionString details within the Azure portal.

<?xml version="1.0" encoding="UTF-8"?>
<FileSystemProviders>
    <Provider alias="media" type="Umbraco.Storage.S3.BucketFileSystem, Umbraco.Storage.S3">
        <Parameters>
            <add key="bucketName" value="<<BUCKET-NAME>>"/>
            <add key="bucketHostName" value=""/>
            <add key="bucketKeyPrefix" value="media"/>
            <add key="region" value="<<YOUR-REGION>>"/>
        </Parameters>
    </Provider>
</FileSystemProviders>

I encountered a massive issue that took me a lot of head-scratching. When I looked in the log files, this exception was being thrown:

'Exception of type 'Amazon.Runtime.Internal.HttpErrorResponseException'

With an inner exception of:

'Error making request with Error Code MovedPermanently and Http Status Code MovedPermanently' 

This error happened as I had the region wrong. Within the region, I had the region eu-west-1, instead of, eu-central-1.  Simply having the wrong region code resulted in all images throwing a 500.  Finding the cause of this error took me ages to figure out as the documentation online was pretty limited, so I hope this helps someone.

~/config/imageprocessor/security.config

When you have ImageProcessor.Web.Config installed, you will need to update your security.config file like so.  Replacing the <<BUCKET-NAME>> with your bucket name:

<?xml version="1.0" encoding="utf-8"?>
<security>
  <services>
    <service prefix="media/" name="CloudImageService" type="ImageProcessor.Web.Services.CloudImageService, ImageProcessor.Web">
      <settings>
        <setting key="MaxBytes" value="8194304"/>
        <setting key="Timeout" value="30000"/>
        <setting key="Host" value="http://<<BUCKET-NAME>>.s3.amazonaws.com/media/"/>
      </settings>
    </service>
  </services>
</security>

~/media/web.config

Within the media folder, you should have a web.config file.  If not, create one and replace the file with this config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <clear/>
      <add name="StaticFileHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.StaticFileHandler"/>
      <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read"/>
    </handlers>
  </system.webServer>
</configuration>

~/global.ascx

Next, update the OnApplicationStarting() method within your global.ascx like so:

using Umbraco.Storage.S3;

public class Global : UmbracoApplication
{
   protected override void OnApplicationStarting(object sender, EventArgs e)
   {
      FileSystemVirtualPathProvider.ConfigureMedia();
      base.OnApplicationStarting(sender, e);
   }
}

~/web.config

Finally, you will need to add your access key and secret within your web.config, like so:

<add key="AWSAccessKey" value="publicKey" />
<add key="AWSSecretKey" value="secretKey" />

If you configure everything above then your media should now be hosted within AWS. Configuring AWS is definitely a little trickier than Azure.