An Advent series - Building a blog with Jekyll and Azure Blob Static Website

I promised this blog a couple of months back and after a tweet from Gregor Suttie asking about what people were using if not Wordpress, it seems a good time to write this.

The journey to Jekyll

I wrote a blog previously on using the Ghost blog engine on AWS as that is how I had hosted my blog. After my trial year on AWS finished, the costs started creeping up so I flipped over to Google Cloud Engine. Sadly, despite good initial impressions, the free level VM just wasn't enough to run Ghost well and I had quite a few complaints of things not loading. I tried running Ghost on Google App Engine but it was more expensive for the same level of experience.

I had always wanted to run my blog on Azure as that's where I do most of my work but had not found enough options to do that cheaply. That was until the Azure Blob Static Website preview hit and when coupled with Microsoft Cloud Show mentioning Jekyll, the stars had aligned.

What is Jekyll?

Jekyll is a lightweight engine that allows you to write your blog in markdown and then build out your blog as static pages. This makes them lightening fast to load and easy to host as you just need static storage. The getting started guide is simple and you don't need to know any Ruby to get going.

There are two main pain points:

  • You need to compile your posts to deploy them each time
  • There aren't so many templates

However, if you are a bit of a developer, the first point is simple as you can build a CI/CD process and simply check-in your posts to trigger an update - more on this later.

For the template, I had purchased a Ghost template to add a better look than my Delve inspired one previously so I adapted this to work with Jekyll. This was the most complex and onerous step as there were no guides I could find to adapt the syntax directly but running Jekyll locally, it was just a case of iterating through across a couple of evenings. You can also start with one of the base templates and implement your own with basic CSS knowledge too.

Migrating content

One other concern I had was migrating all the content but you could easily extract from Ghost as a large JSON file. There are importers written for most of the main blogging engines such as Wordpress and Ghost listed and this ran quickly and without any issues.

There was some manual formatting needed through some pages although nothing four or five bulk find and replaces couldn't solve. The biggest manual pain was the image assets as some of my earlier posts appear to lose the context but I did not have enough posts for this to be a large problem.

Creating a static website in Azure Storage

Creating a very simple website is not very easy when you create a new Blob Storage account. Under the left menu, there is now a Static Website Preview link. Enabling this, creates a container called $web where you can then upload your static content.

Static Website Preview

Upload an index.html with basic content and you will be able to access the page at the link described on the static website screen, e.g. https://blabla.z6.web.core.windows.net.

Deploying posts

On to the fun part! Running the command:

bundle exec jekyll build

creates the blog in the _site folder. You can then upload these files to the Azure Blob Storage in the $web container and ask your blog with that link. If that is all you are looking for, then you are good to go.

Using custom domain names

A great step with the static website is that you can now use custom domain names and also with https.

There are some details on this mentioned in the Microsoft Docs around static websites but I found myself getting lost in circles around the set-up. So here are my steps:

  • Create a new Azure CDN

Azure CDN Create

  • Configure the CDN Profile choosing whichever CDN you like - I chose the Microsoft one for the pricing

Azure CDN Profile

  • Once created, add an Endpoint to the CDN with the following properties

Azure CDN Endpoint

  • It may take a little time but you should now be able to access your blog via https://mcd79blogdemo.azureedge.net
  • Select custom domain from the left menu
  • In another window, use your domain registrat to set up as per this link
    • below is my example from GoDaddy

GoDaddy www config GoDaddy CDNVerify

  • Add a Custom Domain in the Azure Portal with the CDN endpoint URL and your custom domain
  • Select the Custom Domain and enable HTTPS as below

Azure CDN Custom Domain

It may take a little time for the domain to be validated and the certificate correctly provisioned but after a couple of hours, you should be able to access your blog via the custom domain name.

Deploying with Azure Dev Ops

The steps to build and deploy are relatively simple if a little slow to run due to the requirement to set up Ruby and the Ruby Gems for Jekyll. The first step is to check-in your code to either Git in your Azure Repo or to Github. Then you need a new build pipeline.

  • Connect to the repo you have created
  • Select an empty template
  • Add the "Use Ruby Version" task and configure for version spec ">= 2.4"

Ruby Task

  • Add a command line task to install jekyll bundler using gem install jekyll bundler
  • Add a command line task to install any custom gems using bundle install
  • Add a command line task to build the blog using bundle exec jekyll build
  • Create a Copy Files task to put the _Site directory to a staging area

Copy Files task

  • Add a Publish Artifact task to publish the _site directory

Publish Artifact

I have this build set to Continuous Integration so that it builds on every check-in but it could also be manually triggered.

Next create a new release pipeline with an empty template:

  • Add the defined build as an artifact
  • Add an Azure CLI task with the command az storage blob upload-batch --source _site --destination $(containerName) --account-name $(storageAccount) --output table --no-progress

Dev Ops Release Task

  • You will notice two variables which need to be added to define the storageAccount and containerName (which should be $web)

Dev Ops Variables

Again, you can set this up to release automatically with the build completing but in my case, I decided to allow this to happen manually to control when it took place. The main reason for this is at this stage I do not have an automated way for the CDN to be purged to get the latest home page showing the updated blog posts but I would like to build this in with a script later.

Summary

As you are reading this, you know that a Jekyll based blog hosted in Azure static website can work. I see this as a great option for blogs and other static websites for more technical writers and at a much lower price than many other blog engines that need https and a custom domain. Any questions or thoughts, please do tweet me!