It has been almost an year since I finished my last project hosted on Azure so I thought it was time to experiment with it a bit and catch-up on “new” services I haven’t yet tried. One of those services was Azure Static Web Apps.

Similar to any other Azure service, this one bundles everything one might need for hosting static web app and a bit more in a single service. This is the pattern we can see in other services within the Azure such as App Services, Function App, etc. They have this tendency to combine multiple things together under one service for easier ClickOps management. If you’re used to AWS or on-premises like I was, it can be odd and off-putting at first, but once you get used to it, I assure you, it is really amazing.

I’ve already written about my static website setup here on the blog, and as you can see in that article, there are some components that you have to set up in order to make the whole thing working. I also had to use Lambda@Edge function (a bit of python) to manipulate requests in order to get the behavior I wanted. With Azure Static Web App service, there’s no need for such thing as there was a simpler way to achieve basic redirects I had to do, more on this later.

Setup

Simply go to the Azure Portal, type in “Static Web Apps” into search bar and there you are.

Select Create button to start creating new app

Fill in the necessary details like the Subscription, Resource Group, name of the app etc. You can also configure pipeline automatically. Automatic configuration works for Github Actions and Azure DevOps which is quite nice, and from the UI you can either authorize automatically, or preview Workflow file to create it manually by yourself later on. For manual creation you’ll need to copy deployment token from the overview page and expose it to the build/deploy process via secrets. At least when using GHA.

After everything is configured, Github Actions will be triggered and perform build and deploy of the website to the new Static Web App. Site can be reached using auto-generated azurestaticapps.net endpoint. This endpoint is also used for temporary environments BTW, it uses slightly different prefix though (eg. AUTOGENERATEDHOSTNAME-ENVNUMBER.azurestaticapps.net).

Configuration

Custom domain

By default Azure provides auto-generated domain for the website which you can use to view the deployed website. Whenever you create PR to the main branch, additional “Preview” environment gets provisioned along with the new DNS domain name under the auto-generated domain. This way it is quite easy to preview changes to the website before making them on the main branch.

You can of course use your own domain name as well (up to 2 in “Free” plan, and up to 5 in “Standard”). Unfortunately, adding a custom domain to a preview environment is not supported, although that would be a nice option for Azure DNS managed sites (idea: use “RANDOMSTRING.preview.CUSTOMDOMAIN” - and point *.preview.CUSTOMDOMAIN via CNAME to some Azure Managed endpoint).

With an intention to migrate my current website to Azure, I have attempted to validate my existing site name (tomica.net and www.tomica.net) as custom domain. After I set up TXT based validation, and waited for almost 24 hours (although it says it might take up to 12h - while in reality it should be almost instant to detect the change). Unfortunately, for some unknown reason, Azure failed to verify my custom domains, they were just stuck in “Validating” phase.

For the record; I configured everything at around 10AM in the morning, and at 7AM the next morning they were still not validated.

I was first reading the documentation very carefully to find out which step did I miss, but whatever I read it was already set up that way, so it would appear I have configured everything correctly the first time (which, if I’m being honest, rarely happens, but here we are).

Then idea popped up in my mind: “I know, I’ll just contact Azure support, it has to be easy to tackle that and check what’s wrong on their end”. Well, for that you have to pay at least Developer level support subscription which costs 29 USD a month. It isn’t so expensive and I understand why they decided to charge the support, otherwise they’d be swamped with bogus support requests all the time. But still, for that amount of money I can pay for a few servers on some random VPS providers and get more value from them overall.

Then I was talking with my friend Vedran (take a look of his amazing blog at blog.thedewa.com, he has quite a few interesting articles on there), and he suggested that recreating the static app might solve the issue (such a Microsoft solution, I know…). Unfortunately, that didn’t work either, so I decided to shelf this project for the time being and cleanup everything from my Azure account.

Few days later, I was talking to my brother over one interesting JS based project which would be ideal fit for this service, so I thought, what the hell, let’s try to configure this thing once again with a calmer mind and see where it went wrong.

Starting away again with my own website, I do exactly the same steps I did the first time, and after few minutes (10 at most), domains were successfully validated. If that doesn’t make you mad I don’t know what will… :-)

But with this, my custom domains were finally set-up and site was ready for deployment.

Also, setting custom domain, you can choose one domain to be the “Default” - which means that all other domains will redirect to that one. To have similar functionality on Cloudfront I had to configure my own redirect rules there or in case of Hugo use baseURL parameter to be hard-coded (eg. https://www.tomica.net). I’m now using relative / as a base URL which also works with preview environments that Azure provides by default.

Authorization and rewrites

When preparing the website I didn’t want search engines to index some random temporary URL, or others to be able to visit the site that way, so I figured I should try out authentication options. I also had the need to rewrite one particular URL (/feed -> /index.xml - legacy from the Wordpress days that looks nice).

Anyhow, configuration of the site can be done using staticwebapps.config.json file.

In order to require login and allow access only to the certain roles, you just declare the route and specify the allowedRoles parameter. Role “anonymous” provides public access, while other roles are according to what you specify/assign your users with under the Role Management page.

In the end, my file looked like the following:

{
    "routes": [
        {
            "route": "/feed",
            "rewrite": "/index.xml",
            "allowedRoles": ["administrator"]
        },
        {
            "route": "/*",
            "allowedRoles": ["administrator"]
        }
    ],
    "responseOverrides": {
        "401": {
            "statusCode": 302,
            "redirect": "/.auth/login/github/"
        }
    },
    "trailingSlash": "always"
}

So if you visited any page, you would get 401 which would in turn redirect you to the Github for authentication. If your user is on the list of my allowed users (has “administrator” role assigned to it) you would get the page after that, if not, 403 would be returned.

This process uses Azure provider Github OAuth app for authentication and authorization, but you can use your own auth mechanism if you pay for the standard plan (9 USD a month).

Once I prepared everything it was time to change the DNS, so those AuthN/Z options quickly became obsolete, for now at least… Here’s how my final config looks now:

{
    "routes": [
        {
            "route": "/feed",
            "rewrite": "/index.xml"
        }
    ],
    "trailingSlash": "always"
}

Summary

Random errors with Azure that I experienced last time I was using it are still present, just in different places, which is apparently just something you have to get accustomed to. It seems they have embraced “move fast and break things mentality” which enables them to push feature after feature (you constantly see new features going into “Preview” phase and quickly maturing to GA) and expand their platform offering. On the other hand that leaves bad taste in practitioners mouth. There are few things worse than platform intermittently failing and sending you on goose chase every so often.

But once you get everything working, things almost never break. That was experience for me back then, and it is still to this day. It is only when you’re configuring things that you uncover wild stuff.

Now, I have my site fully migrated to the Azure Static Web Apps service and will see how that goes for me. I’m still keeping my AWS based setup in place. In case something goes wrong I can just revert the DNS entries and Robert is your father’s brother.