Step by Step Technical guide to Self-hosting your Ghost Blog

Published: Jan 1, 2018
6 min read
Last updated: May 13, 2021

Self-hosting will save you a lot of money. But, initially you have to invest your time to set things up from the scratch like installing database, configuring web server. Don't worry I've got you covered.

So, what sets this guide apart from the official guide provided by Ghost itself? Well, I've included the best practices & certain configurations to save you from possible SEO related and other future problems.


  • Ubuntu 16.04 installed machine (Min: 1GB memory) with SSH access.
  • Domain name

1. Update System Packages

Before installing anything we have to update the repositories and packages to get the latest version of packages when we install them.

sudo apt-get update && apt-get upgrade

2. Install Database

Ghost has out of box support to MySQL. Install MySQL using the following command. While installing you'll be asked password for the root user. Don't skip password as it is mandatory while installing Ghost.

sudo apt install mysql-server

3. Install Nginx

Nginx will be our web server. That is the piece of application that routes web requests to Ghost application. It is not just that we'll be able to do more with Nginx. That I'll explain later in this post.

sudo apt install nginx

4. Install Node.js & Ghost-CLI

As Ghost uses Node as backend, we've to install Node on our machine. Enter the following command one by one on your terminal. These commands install Node and NPM which is a package manager for Node. Using NPM we'll install Ghost-CLI.

curl -sL | sudo -E bash
sudo apt install -y nodejs

Install Ghost-CLI

Ghost-CLI will help us install Ghost.

sudo npm i -g ghost-cli

5. Allow access - Nginx

If the firewall is inactive we are good to go. Else, you have to allow access to Nginx for network connections. Check firewall status.

sudo ufw status

If the above command returns active run the following command.

sudo ufw allow 'Nginx Full'

6. Create user

Though you can skip this step, It's highly recommended to create an user for the installation of Ghost and for the better security of your server. Replace ganapa with the username of your choice.

adduser ganapa
usermod -aG sudo ganapa

Use command su - ganapa to login as user ganapa. Do login as that user for the remainder of the tutorial if you had created one.

7. Configure domain to point to your server

This is one of the crucial steps. On your DNS control panel add an A record to point to the server you're installing Ghost on. Once done make sure your DNS resolves to your server IP using the below command.


Replace with your domain name. You must be seeing your domain name followed by server's IP address. If not go back and make sure it is mapped before proceeding.

8. Install Ghost

We'll use Ghost-CLI to install Ghost. It must be installed inside /var/www/ directory so we'll create a folder ghost within it. If you had created an user run the second command, else skip it. Again don't forget to replace ganapa with your username.

sudo mkdir -p /var/www/ghost
sudo chown ganapa:ganapa /var/www/ghost

Then to install Ghost run the following command. During the installation you'll be prompted for input many times. Follow the guide to know what is what.

cd /var/www/ghost && ghost install
  • Blog URL - It's upto you to decide. You can go with or I recommend using www version. Here's why - www vs non www.
  • MySQL hostname - localhost as our database is in the same server.
  • MySQL username - root
  • MySQL password - password used in step #2
  • Ghost database name - Whatever you want
  • Nginx setup - No. We'll do it later
  • SSL setup - No. Will be explained
  • "ghost" mysql user - Yes (recommended)
  • Systemd setup - Yes. It's an utility that monitors Ghost demon and restarts it automatically if killed.
  • Start Ghost - Yes

9. SSL setup

It's highly advisable to setup SSL, though it is not mandatory. It is said that SSL slightly improves your site ranking. Before setting up SSL, you have to change a configuration of Nginx.

Open this file /etc/nginx/sites-available/default on vi or nano and replace the line root /var/www/html; with root /var/www/ghost/system/nginx-root;. Then, you've to reload Nginx configuration using the command below.

sudo nginx -s reload

Now, run the below commands one by one to install which will help you setup SSL. Replace the mail with your mail.

git clone && cd
sudo ./ --install --home /etc/letsencrypt/ --accountemail

Install SSL

Now we're going to generate SSL certificate for both www and non-www versions of your domain.

sudo mkdir -p /etc/letsencrypt
sudo /etc/letsencrypt/ --issue --home /etc/letsencrypt -d -d -w /var/www/ghost/system/nginx-root --accountemail

Make sure in that command your preferred domain comes first in the command (www or non www). It will take a minute or two to finish. Once done, make a note of the path of your full chain certs and cert key. We'll use it while configuring Nginx.

10. Configure Nginx

As you've installed SSL, now there are four versions for your blog.


However you've to go with any one between 3 and 4 if you've installed SSL 1 and 2 if you haven't. Reason being your blog URL will look consistent and it's good for SEO.

Let's say you've written a post. If it's indexed by search engines for both www and non www versions of your site, your ranking will be diluted. So, it's must to have one version of URL which is called as canonical URL.

We can achieve that by properly configuring Nginx. This can be a bit tricky but it's actually easy. Take a look into the below configuration file.

server {
    listen 80;
    listen 443 ssl http2;

    return 301$request_uri;

server {
    listen 80 default_server;

    return 301$request_uri;

server {
    listen 443 ssl http2 default_server;

    root /var/www/ghost/system/nginx-root;

    ssl_certificate /etc/letsencrypt/;
    ssl_certificate_key /etc/letsencrypt/;
    include /etc/nginx/snippets/ssl-params.conf;

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;

    location ~ /.well-known {
        allow all;

    client_max_body_size 50m;

You can reuse the whole piece of the above code. Just check the lines 5-6, 12-13, 17, 22-23 and replace it with your domain name. If you had opted for non www domain version at step #8, interchange all the www values with non www values and vice versa. Make sure that the values of ssl_certificate and ssl_certificate_key are the one you got at step #9.


If you don't want to get technical, you can skip this section and go on to update the configuration. The ultimate aim is to redirect all other URL to https://www version of the domain.

  • Server Block 1 - Redirects domain version 2 and 3 to 4.
  • Server Block 2 - Redirects domain version 1 to 4.
  • Server Block 3 - All the requests will go through this block so it will have all the configurations. section 1 & 2 are just to port the request to section 3. Hence, your future configurations will come here.

Update configuration

Once you're done with the changes, We've to update this configuration. Change your directory,

cd /etc/nginx/sites-available

Now, create a file with the name <domain name>.conf . For eg: Update the file with your configuration. Then you've to create a symbolic link inside sites-enabled directory.

sudo ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/

Now, We have to restart Nginx.

sudo systemctl restart nginx.service

Once everything is done successfully, check all the 4 versions of your URLs and make sure it is redirecting to the canonical URL.

If you're going for self-hosted blogs, you've to take responsibility for all your data, you can't afford to lose any. Hence, you may like to read - How to Setup Automatic Backup for your Ghost Blog.

I have built an app to check the things that matter to you the most with a single click. If this interests you, you can give it a try on