Two years back I have blogged about migrating from BlogEngine to Ghost. In short, I have archived my old blog and started this blog afresh. I have used this Ghost-Azure repository as my source to do a one-click deploy to Azure. I had my ghost blog up and running and it appeared that all my blogging platform issues have been sorted out.

Two years passed by, I was blogging intermittently about my talks and I barely focused on updating my blog. Since I have setup a sync between my Azure website and my source repo using Azure app service deployment center, I was assuming that my blogging platform will be updated with the latest ghost releases. I was correct technically, except that the source Ghost-Azure repo stopped receiving updates and my ghost version was stuck at 0.11.11. Nevertheless, I thought it is just a  matter of upgrading to the latest version, exporting older posts and importing them back to the latest deployment.

A painful migration from Ghost 0.x to 2.0

I thought of attempting a manual deployment of Ghost on Azure to avoid future upgrade problems, but my hectic work schedule didn't encourage me much. I did a quick search to find out what the community is doing and I came across Radoslav Gatev's Ghost-Azure repository with a true one-click deployment of Ghost 2.0 on Azure. If you are starting a new blog and want to deploy on Azure, you should perhaps start here.

My excitement of finding a new and latest one-click deployment was short-lived though, as I quickly found that I was unable to import my blog posts from Ghost 0.11.11 to Ghost 2.0. As per Ghost's official documentation and discussions in forums, I should:

  1. Upgrade Ghost from 0.x to 1.0
  2. Import the 0.x posts to Ghost 1.0 and export them from 1.0
  3. Upgrade Ghost from 1.0 to 2.0
  4. Import the 1.0 posts to Ghost 2.0.

Phew! While I can understand that breaking changes are common across versions, it would have definitely been a great help had Ghost team released a 0.x to 2.0 content migration utility. Given the exciting features in Ghost 2.0, it seemed that it is totally worth taking the pain in migrating to Ghost 2.0 instead of switching to another blogging platform.

So to start my migration process, I  have deployed Ghost 1.0 following Corey Smith's blog post, except that I have used Radoslav Gatev's repo as my Ghost source. I have cloned the source from the tag 1.16.0, used it as a local git repository and pushed it to Azure. I had to use Kudu console to trigger npm install and node db.js to get dependencies and database setup right. Once I have deployed Ghost 1.x, I have imported my posts from Ghost 0.x and it was smooth. Now I exported the posts from 1.x and saved locally. To install Ghost 2.0 on Azure, I used the latest code from Gatev's repo (branch Azure, tag 2.1.0) and the one-click deployment was super smooth. I then imported all my posts that I saved previously from 1.x and all my posts are back in Ghost 2.0!

Lets Encrypt!

Let me be honest, every time I shared my blog post on Twitter, I always had a feeling of guilt as the blog is served on plain HTTP. Moving to HTTPS using LetsEncrypt was always in my TODO list but I kept procrastinating.

To all those wondering why a static site requires HTTPS, read "Here's Why Your Static Website Needs HTTPS" by Troy Hunt.

My site's homepage ( was on http and very recently it automatically got HTTPS love without my effort! It is hosted on Github pages as a sub domain, and recently Github subdomains gained HTTPS support. However, this blog's sub domain ( does not inherit the HTTPS love and I have to explicitly configure HTTPS on this subdomain. Given that this blog is hosted on Azure, first I had to migrate from Shared plan to Basic plan (Shared plan only supports custom domains but does not support enabling TLS for custom domains).

To configure Lets Encrypt on Azure App Service, the process is really, really simple. To all the Azure App Service consumers out there procrastinating to move to HTTPS, delay no further and just install Lets Encrypt Site Extension. There are several blog posts detailing all the steps. I followed CodeHollow's blog post and I had HTTPS configured in less than 20 minutes! Finally, no more guilt!

Future upgrades

Well, this will be a continuous process, but hopefully less painful in the future. I liked the upgrading plan outlined by OnCodeDesign. I have forked Gatev's Ghost-Azure repo on Github and deployed this blog from my forked repo. The plan for now is to sync the fork periodically and keep updating this blog. This will work as long as Gatev's repo gets the latest updates (I trust the community!). If this doesn't work in the long term, may be I will deploy Ghost on my Azure App service manually, as outlined in "Hosting Ghost on Azure — The Definitive Guide".

Why did I blog about this?

Firstly, the references in this post will serve as a quick start when I plan for future upgrades. More importantly, like all the good blog posts that helped me setup this blog, this post might help someone who is facing similar challenges in upgrading Ghost on Azure. Always good to give it back to the community!