Migrating WordPress to an Azure Static Site

Ever since Microsoft announced its Static Site option on Azure I have been hoping to try it. Luckily I finally found some time to dive into it. This post contains a write up on how to set-up an Azure Static Site and then migrate your WordPress content into it.

Azure Static Site

A static site consists of HTML, CSS, JavaScript, and images. They can be hosted directly from an Azure storage account with a special $web container. You can read all the basics on Static website hosting in Azure Storage.

I ended up using an Azure CDN as well as that allows for a custom domain including an SSL certificate. There is a nice video walkthrough by Scott Hanselman that contains all the steps in setting it up.

I ended up with the following configuration:

  • A resource group called weblog
  • Storage account with the static site option enabled
  • The CDN profile with a CDN endpoint. The endpoint has a custom domain and a default SSL certificate

Remark: When deploying the SSL certificate it can take up to six to eight hours. I had to wait for the full eight hours before it worked. So when you expect it to take just two hours as in the video you might be thrown off by the actual wait time.

Static Site generator

While you could write your HTML and JavaScript that might be time-consuming. To speed up things you can find several static site generators. They will generate static output based on configuration and content. There are several options out there like Gatsby, Hugo and Jekyll. For more details check out a comparison blog article. I mainly focused on speed and learning curve and ended up picking Hugo.

Local dev

To play around you will have to prepare your machine. Hugo can be downloaded as a compiled binary. To install all you need to do is to set it as a path variable. A how-to is available in the Getting Started section: Download the latest release from Hugo Releases. Extract all the contents to the desired location. Rename the downloaded executable to hugo.exe. Edit your path variable and add the location where hugo.exe is stored to use it from your command prompt. Once it is available as a path variable you can start using it. To create your very first site follow the quick start to set-up.

hugo new site quickstart
hugo new posts/my-first-post.md
hugo server -D

To make your site look good you might want to browse for a theme for inspiration. The theme gallery provides an overview of available themes. Once you have picked the one you can install it and recompile your site.

WordPress export

As I was already running a WordPress site I had to migrate some content. For the comments, I decided to switch to Disqus. They provide a WordPress plugin as well. If you install the plugin you can import existing WordPress comments. Making it easy to migrate. Installing the plugin and importing your comments takes five minutes. As comments are stored using the ‘slug’ of the page migration is easy. Just keep the same slug for your static site.

For the actual content, there is some additional work. The plugin WordPress-to-Hugo-exporter will help you to export your content. It generates a zip that you can download. The zip contains all your posts and metadata as MD files. These MD files can be used by Hugo to generate your site. Based on your choice of the theme you will have to change your config file. As your download will put all pages in a folder called ‘posts’. So either you have to rename that folder or edit the config file to watch the post folder.

Azure Pipelines

So Hugo is running locally. Your content is done and you have a nice design. That means you can get your content live. I created a repo in Azure DevOps and pushed my content there. Once the content is in Azure DevOps you can create a pipeline. My pipeline consists of two steps: Generate the output and publish them as artifacts. To generate the output you can add the Hugo.exe to your repository. Or you can use an extension. I used the Hugo VSTS extension. I use the following settings:

pool:
  name: Hosted
steps:
- task: giuliovdev.hugo-extension.hugo-build-task.HugoTask@1
  displayName: 'Generate blog output'
  inputs:
    source: '$(Build.SourcesDirectory)'
    destination: '$(Build.ArtifactStagingDirectory)'
    baseURL: 'https://www.cloudappie.nl/'

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact: drop'

After that build publishes the ArtifactStagingDirectory so that I can use them in my release. The release itself uses the Azure file copy to publish to my storage account:

steps:
- task: AzureFileCopy@2
  displayName: 'AzureBlob File Copy'
  inputs:
    SourcePath: '$(System.DefaultWorkingDirectory)/_Weblog-CI/drop'
    azureSubscription: 'subscriptionid'
    Destination: AzureBlob
    storage: mycloudstorage
    ContainerName: '$web'

Potentially you can also automatically purge your CDN endpoint using an extension. If you do not do that your post won’t show up as the CDN is caching everything for you. So for that, I used another extension with the following config:

steps:
- task: fabienlavocat.FabienLavocat-PurgeAzureCDNEndpoint.PurgeAzureCDNEndpoint.PurgeAzureCDNEndpoint@2
  displayName: 'Purge Azure CDN Endpoint'
  inputs:
    ConnectedServiceNameSelector: ConnectedServiceNameARM
    ConnectedServiceNameARM: 'connectionID'
    ResourceGroupName: 'myresourcegroup'
    EndpointName: myendpoint
    ProfileName: 'myprofile'

If you feel installing extensions is not an option. You can achieve the same things with PowerShell that you can execute as well as part of your release pipeline.

Easy blogging

Because the release pipeline takes any commit as a trigger. All I have to do is to write a blogpost in VSCode. Once I am finished and I push to my repository the pipeline will make sure to generate the updated version of my site. And it will be automatically be pushed. All in all, it is a pretty easy way to blog. I already spend a large part of my day in VSCode so blogging is easy. I estimate that it takes me a few bucks a month to run my blog like this. So it is definitely cheaper than running WordPress. The only downside so far is that I like to use Grammarly. As that doesn’t work to good with MD files yet it takes some copy paste magic to work with that…

A final remark is that Hugo uses UTC time when publishing your post. So if you write a new blog from scratch make sure to set the proper date. My first blog didn’t show up due to setting the local time. Felt a bit like a rookie mistake.