Migrated to Hugo
I’ve been thinking about it for a while now, move my blog from Miniblog to a different platform. The most obvious choice would be migrating to Miniblog.Core, however, there are a couple of features missing (like themes) and Open Live Writer isn’t a very modern tool for blogging anymore.
Of course, both of them are open source, so I could spend a lot of time fixing the issues. But as with most of us, our schedule is already packed with a lot of other side-projects.
Static sites
Seeing my blog is rather static, I don’t need the power .NET Framework/Core offers me. A static site generator will suffice. I’ve used such a platform for my Keto site (https://keto.jan-v.nl/), which is generated via Hugo.
Hugo has a steep learning curve, but it does offer a lot of flexibility and features. Being familiar with the product was a nice benefit and the main reason to migrate my blog to Hugo and not some other generator. The migration got kickstarted by one of my 4DotNet colleagues, Eduard Keilholz, who has started blogging some time ago and also decided to use Hugo. Seeing him use Hugo convinced me to migrate ASAP!
The biggest problem I had is moving 13+ years of content to a different format. In the past, I’ve been using several other systems, like SharePoint, Orchard, Miniblog and my custom PHP framework. This means there’s a lot of legacy stuff and the formatting of the posts isn’t in a consistent state. It’s all HTML in the end, but when you take a look at the actual code you’ll get scared pretty quick.
Lucky for me Paweł Hofman has already dealt with a Miniblog to Hugo migration. His guide is pretty good. Because of the different formats of my posts, I still had to tune the convert.py
script to get proper Markdown posts.
It turns out, creating pretty code blocks in a SharePoint page produces a lot of in-line styles. Having spent quite a few hours removing all of the nonsense, I was finally ready to do the ‘fun’ part of this migration, theming the site.
I was able to pick up the hugo-theme-bootstrap4-blog theme, which already looked very familiar. The ‘only’ thing I had to do is implement my custom styles. Integrating these to the new theme was a bit more work than I had expected at first, but it all turned out fine in the end. The site doesn’t look the same when comparing pixels, but it’s not much better/worse compared to the previous version (in my opinion).
The downside of theming this site, I had to override almost every template from the original.
That isn’t bad per se, but when an update happens in the original template, it won’t be reflected on my blog immediately (which can also be a good thing!).
Building & deploying the static site
Hosting a static site is simple. You dump the files on some webserver and it works!
That’s the best part of having a static site. You can even host your site for mere pennies nowadays by using the Static website hosting in Azure Storage.
There are however a couple of things I couldn’t get to work right away (like adding all of my rewrite & redirect rules). That’s why I’ve chosen to stick with an Azure App Service for now. When I solve the issues I’m facing right now, I’ll probably move to the cheaper Storage Account hosting plan.
Adding the Hugo extension
When using Azure DevOps you can add the Hugo extension which will add a build task (HugoTask
) to your environment. This saves you from hosting the hugo.exe
assembly somewhere in your code repository or some external location.
The actual build pipeline
I’ve set my build pipeline to only trigger on the master
branch of my repository.
trigger:
- master
pool:
vmImage: "windows-latest"
steps:
- checkout: self
displayName: "Checkout repository including submodules"
submodules: true
- task: HugoTask@1
inputs:
source:
destination: '$(Build.ArtifactStagingDirectory)/Website'
- task: CopyFiles@2
displayName: Copy scripts
inputs:
contents: |
**\deployment\**
targetFolder: $(Build.ArtifactStagingDirectory)/Deployment
flattenFolders: true
cleanTargetFolder: true
overWrite: true
- task: PublishPipelineArtifact@0
displayName: "Publish deployment artifact"
inputs:
artifactName: "Package"
targetPath: "$(Build.ArtifactStagingDirectory)"
My deployment scripts, like ARM templates and the actual pipeline, are located in the deployment
folder, so I’m copying those in a specific folder. This way, I’m able to use them when doing the actual deployment.
As you can see a fairly straightforward script, thanks to the HugoTask
build task.
Deploying the actual site
This is the easy part, in my opinion.
The first step is to deploy your ARM template to get the Resource Group, Service Plan, App Service & Application Insights instances running.
Note: If you do choose to use a Storage Account to host your website you have to add another step to your release pipeline. By default, the static site hosting isn’t enabled on a Storage Account and you can’t enable this via an ARM template. What you need to do is add an Azure CLI script step where you add the following line:
az storage blob service-properties update --account-name mystorageaccountname --static-website --index-document index.html --404-document 404.html
This script will create the necessary $web
folder and configure the Storage Account to host a website.
The second step is to deploy all of the files in the Website
folder to the App Service.
You can take a look at the steps below to see what I’m doing.
steps:
- task: AzureResourceGroupDeployment@2
displayName: 'Deploy ARM template'
inputs:
azureSubscription: 'mySubscription'
resourceGroupName: 'myResourceGroup'
location: 'West Europe'
csmFile: '$(System.DefaultWorkingDirectory)/Package/Deployment/azuredeploy.json'
- task: AzureRmWebAppDeployment@4
displayName: 'Deploy website'
inputs:
azureSubscription: 'mySubscription'
WebAppName: 'theAppServiceYouWantToDeployTo'
packageForLinux: '$(System.DefaultWorkingDirectory)/Package/Website'
That’s all there is to it, your site now is deployed and static! If you’re deploying to the same App Service as before, you don’t even have to change the DNS records of your site.
I’ll be posting more details & tips on the migration & working with Hugo later on. For now, I’m still busy finetuning the site. If you stumble across an issue, feel free to contact me. Hopefully, I’ll be able to resolve it quite quickly.