In this article i will show you how to host a static website almost for free on Azure Storage and Microsoft CDN. You can host any static web pages and take advantage of javascript and CSS but not from any back-end language. Good example of a more advanced static content that you can host on the Azure Storage is Jekyll.

Table of Contents

Requirements

What do you need to have in order to complete the guide:

  • An active Azure subscription - Free/Pay as you go/Visual Studio/Partnership/EA/CSS
  • Custom domain hosted on Azure DNS (optional)

TLDR

Here is the short version:

  • Create a storage account general purpose v2
    • Enable static website
  • Create a CDN profile
  • Host your custom domain's DNS on Azure (unless you already host it in Azure)
  • Add 2x records (@ and www) type Alias pointing to the CDN profile
  • Add the naked and www as custom domains on the CDn profile
  • Provision a free SSL certificate from Let's Encrypt (unless you already have an SSL)
  • Upload the SSL to Key Vault, provision access for the CDN to Key Vault
  • Add the SSL certificate on the custom domains in the CDN profile
  • Redirect http to https and naked to www
  • Upload content
  • Test

Storage Account

Let's start by creating the storage account.

Use this link - https://portal.azure.com/#create/Microsoft.StorageAccount-ARM

Let it be general purpose v2

Azure storage account creation

Once the storage account is created navigate to it and look for the "Static Website" blade. You can only have 1 static website per storage account.

Static website

Click Enabled to enable the functionality and then give it a default document or an index page. Usually index.html. For a Error document path you can give it error.html or 404.html

Click Save when ready

Save static website settings

You are basically ready to serve content now.

CDN profile and endpoint

We need a CDN profile for two reasons.

  1. Azure storage can't serve content over https without a CDN
  2. We can benefit from CDN in optimized delivery and assigning hostnames and SSL certificates

Let's go and create a CDN profile - https://portal.azure.com/#create/Microsoft.CDN

Give it a name, choose subscription and resouce group.

Pricing tier: Standard Microsoft

Do not select Create a new CDN endpoint now

Create the CDN profile

!If you receive this error:

CDN profile creation error

Go to your Subscription -> Resouce Provider -> search for cdn and select it -> click Register. Refersh in a few seconds until it goes green and in Registered state.

Retry creating the CDN profile

Once the CDN profile is created, let's create a CDN enpoint. Go your CDN profile and click + Endpoint.

new cdn enpoint

This is how your CDN enpoint creation should look like:

Create CDN endpoint

For Origin Hostname -> Custom. Use the URL of your storage account static website. You can find it under Storage Account - Static website blade

storage url for static website

Create the CDN endpoint

Custom Domain for CDN

Now let's add custom domains to the CDN profile. We want to add naked + www. Officially, CDN does not support apex (naked) domains by default but there is one workaround to that rule - Using Azure DNS for our custom domain. Why? Because of the "Alias" option which is only exclusive to Azure DNS. And a prerequisite for adding a custom domain to a CDN endpoint is to have the DNS records set before you attempt to add the custom domains

If your custom domain is already on Azure DNS you are ready to go and proceed further. If not, you might want to move your custom domain's DNS to Azure DNS. You are only forced to do that if you are using a naked domain. If you are using a subdomain you can complete this article without moving to Azure DNS.

How to move your domain DNS to Azure DNS? Create an Azure DNS zone with the name of your domain. Notice the Name Servers there. Go to your domain administration and change your existing name servers to the Azure ones. That's it.

Go to your Azure DNS zone for that domain and let's create two records.

First our naked (apex) domain

Name: @

type: A

Alias record set: Yes

Alias type: Azure resouce

Point to the CDN endpoint we just created

Create alias record for apex domain

Now let's repeat the same for www

Name: www

Type: CNAME

Alias record set: Yes

Alias type: Azure resouce

Point to the CDN endpoint we just created

Create alias record for www domain

Notice that there are two additional records created. They will be used for verification in the next step when we add those custom domains to our CDN endpoint

DNS verification for CDN

Next step is to go to your Azure CDN endpoint and add the two custom domains

While in your CDN profile, select your endpoint or if you browse your cdn endpoint directly - Click + Custom domain and just write down the custom domain. Add both naked and www as separate custom domains.

New custom domain for the CDN

Type your naked domain in the Custom hostname field. It should get the green checkmark because of the verify CNAMEs that were automatically created for us in the previous step. If they are not automatically created you might have to manually create them.

Add custom domain CDN

Add another custom domain, this time for your www subdomain

Add custom domain CDN

HTTPS on Custom domains for CDN

In order for https to work we need an SSL Certificate. Azure CDN offers a free Azure-managed SSL but in our scenario with both www + naked domain it will not work. So the option for us is to use our own certificate. We want to keep things free so we will reach out to Let's Encrypt (https://www.sslforfree.com/) to issue us a free certificate covering both naked and www domains. What you need to do is the following:

  • Request a certificate for your custom domain (it will give you naked + www coverage)
  • Choose manual verification
  • Create the two TXT records required by Let's Encrypt
  • Download the certificate zip and unzip it somewhere locally
  • Browse to SSL Shopper's Converter (https://www.sslshopper.com/ssl-converter.html) and follow the instructions to convert your 3 extracted files into a single pfx file with a password (PEM to PFX conversion)
  • You need to have a pfx file in the end

Now that you have the pfx file, you will need to upload it to Key Vault. Go to your Key Vault (or create one if you don't have) go to Certificates and click on Generate/Import.

Give it a Name you can recognize

Choose the .pfx file

type the password for it

Click Create

Import SSL Certificate Key Vault

 

Once the certificate is successfully uploaded, go back to your CDN profile, click on your custom domain

Custom domain CDN click

select HTTPS. Choose use my own certificate.

There is a big chance that you will encounter an error if you do this for the first time. The 

To do this, open your Cloud Shell and switch fo Powershell. Execute the command given in the infotip

New-AzureRmADServicePrincipal -ApplicationId "205478c0-bd83-4e1b-a9d6-db63a3e1e1c8"

If command is successful - close the powershell session. If not, search for possible reason for it to fail. Try Az module command.

Go to your Key Vault and create a new Access Policy. Select Get permissions for Certificate and Get permissions for Secrets. For Service Principal, search for CDN.

Add and Save the Access Policy

Go back to your CDN endpoint -> select one of the two custom domains -> HTTPS -> Use my own certficiate. Choose the Key Vault, Key Vault secret etc.

Add the certificate. You will now have to wait for it to be propagated to the CDN PoPs (Points of Presence)

Add HTTPS CDN

Repeat the same for the other custom domain - www.

Upload Content

Now that we have the usual setup done - let's upload some content on the storage and see if it works fine. Easiest way is to just go to the Blob container and Upload a simple html file.

Another good way is by using Visual Studio Code's Azure Storage extension which allows you to right click and directly upload to your storage static page

https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurestorage

VS Code: Deploy directly to Azure storage static site

Try to browse it using your custom domains. Is it working? Try https:// too. Should all be wokring

Setting up redirections

Let's do some quality of life redirections now. The two very common ones - redirect http to https and naked domain to www

Redirect rules on the CDN profile are controlled in the Rules Enginer blade

Rules Engine CDN blade

Our first rule will be to redirect http to https traffic. This is a mandatory step really as http:// requests will end up in 400 errors.

So the rule should look like this:

HTTP to HTTPS rule - CDN Rules Engine

Now, the second rule (currently not working, not sure why so this step might not actually do it for you) is optional really ... to redirect to www is just a trend. So if you want to be part of the trend. Create a second rule which should look like this:

Naked to www recirect -CDN Rules Engine 

So now you you have the following logic - a request to http://domain.com should first redirect (302) https:// then another recirect (302) from https://nakeddomain to https://www.domain.com

Look at the F12 Developer tools HAR example of how it should look like for my example