Deploying Ghost Blog to Azure Linux App Service using MySql, SendGrid, Application insights Azure Storage and CloudFlare

Deploying Ghost Blog to Azure Linux App Service using MySql, SendGrid, Application insights Azure Storage and CloudFlare

NOTE: I have made a new post with a much better and complete integration.

Recently I have been looking to further my knowledge in the programming world. I mainly focus on the C# and .NET side. During my time learning the programming language I have come across many problems and solutions which I thought would be useful (and fun) to document because I have come across all sorts of problems.

Firsts things first, finding the blogging platform to use. I spent hours researching what to use. The obvious platforms such as WordPress, Squarespace and Wix all appeared but there is just something about them that doesn't sit right with me. I think it must be all the bloatware attached, especially with WordPress, and I just didn't need all the extra gunk. Anyway, I stumbled upon a platform called Ghost and I saw it was open source which sits nicely with me, its niche to blogging so that sorts out the bloatware problem, it's feature rich, minimal and flexible. So I settled for Ghost . The setup was relatively easy, but it was a bit of a nightmare getting to this point so I've mad a post to make it easy for whoever is reading to setup.

NOTE: There are a few repos out there which deploy Ghost to Azure, however they only work on the Azure Windows instance. I did not want this as that instance costs a lot more than the Linux instance. Hopefully this tutorial solves that issue.


Deployment of Ghost was very easy. I decided to use the Docker image: I used the alpine version as this is the Linux distro and is compatible with the Linux app service that I used. For the database I created a MySQL database in Azure and for the email service I used SendGrid. As far as i am aware you can only bulk send email such as a newsletter via Mailgun. Below are the steps to create the database and the App service.

  1. Create the app service. Make sure this is hosted on the Linux App service plan and NOT windows. Make sure you tick "Docker Container". Depending on the amount of viewers you receive, you can scale your app service plan accordingly.
  2. Select "Docker Hub" for the "Image Source" and the for the image and tag type in "ghost:alpine". This uses the latest version of Ghost with the alpine linux distro. If  you want to use a specific version go to to find the one you need.
  3. Enable Application Insights. Create a new instance if you haven't got one already.
  4. If everything looks ok then go ahead and create your app. Now navigate to your app and test that everything works. Your site will look something like the below. It says "Daniaal Nadir's Blog" as i already signed up (we will get to that).

Note, the app service plan i am using is a Linux B1. This is the cheapest offering available for me and costs around £10 a month.  The MySQL database is a Burstable B1s, 1vcores,8Gib ram. This is the cheapest offering for the MySQL database also.

Create MySQL Database

Now we are going to create our MySQL Database.

1. So, go to Azure, search for "MySQL". You will see "Azure Database for MySQL". Click "Create" on this tile.  Below is an image of what it should look like.

2. Click Flexible Server

3. Now we get to configuring. So select your resource group and enter the server name you would like and then select "Development" for the workload type and then enter your Admin username and password.

4. Next click on "Configure Server". You want your configuration to look like the below.  This is the cheapest configuration although you if your blog receives a lot of viewers, you can scale accordingly.

5. Next click "Networking" and click the checkbox which says "Allow public access from any Azure service within Azure to this server". And then click create and your database should be setup.

Right, not much left now i promise.

Azure Storage

Now we are going to configure Azure Storage so our files are stored off the server and in the cloud. This step will make sure our images are backed up to Azure Storage. Azure app service lets us mount file paths to a file share in the storage account. But first create the Azure Storage Account. Let me show you.

Go to the Azure Portal and go to the Storage Account section and click "Create". Select your Ghost blog resource group or create a new resource group and give your storage account a name.

Now from the portal or Azure Storage explorer, create a new container for you Ghost blog to work with. Give your container a name and select "Blob" for public access level.

Ok so now we have all our resources created finally. Next we need to setup up Application insights.

Application Insights

So to add application insights to my app I went to the app service and clicked "Application Insights". I then clicked enable and create my resource. Note the screenshot below, I had already created my app insights instance. Once you click that and save it will install Application insights into your application.

The disadvantage of this is that we will only get logs from outside of the container such as server error logs. To receive failures from within the app, we need to add the Application Insights library to the node_modules. I will create another blog post on how to do this as i have not got round to this yet.

Application Settings

Ok so now we need to change our application settings. The screenshot below is what your app settings should look like.

Firstly you can see the APPINSIGHTS_INSTRUMENTATION key. This was added when you adding Application insights to your application.

Add the database details exactly how I have added them. The client is MySQL, the host would be something like "".

Add the mail details. In my instance I used SendGrid but I would recommended that you use Mailgun because this is what Ghost support for newsletters so for example if you make a new post and you want to update all your subscribed users, you can only do this via a Mailgun account. So what I have done is used a SendGrid account for one off emails like sign up emails and then I configured Mailgun in the Ghost admin. The pass "mail__options__auth__pass" (double underscore) would be the API key from SendGrid.

And very important, the URL. This is the URL of your website. You will want to configure your custom domain and then set this as the value. So the value for me is "".

Ok now we are so close we just have one more step.

Mount Azure Storage

Now we need to mount our storage account to our App Service. Thankfully App Service introduced this recently.

Go to your App Service and then go to "Configuration" then "Path Mappings". The add a new storage mount. It wants to look like the below. Note the Mount Path, this is important. Once done click save.


And finally we are done. Congratulation if you made it this far. There are some things you can do after. One thing I would recommend is to add a custom domain. The next thing i would recommend to setup is CloudFlare. Add your site and CloudFlare will handle the rest. There are a few benefits to doing this.

  • Your site automatically gets an SSL certificate added to it.
  • Your site is going to load blazing fast because content is disturbed by the nearest node so wherever your readers are, you can be sure page load times are very quick.
  • You can add page rules such as redirects, always use https, auto-minify, always online and much more.

Next Steps

There are some additional things i would like to add to the blog, such as adding a comments section.

  • I am going to use Disqus for this but it requires me to edit the theme. So what i will have to do is download the theme from the Ghost library, edit the .hbs file (handlebars file) and then upload the theme.
  • I do need to sort out the Mailgun account also for the newsletter sending.
  • Add socials

Updating Ghost

If a new version of Ghost has been released, all you have to do is restart the app service and it will deploy the latest version of Ghost . Be careful though, if there are breaking changes it could break your site.