How to create a secure self-hosted ghost blog (for free)
Introduction
This week I will walk you through how to create a blog using the open-source CMS called Ghost. Ghost is more modern than WordPress and is much easier to manage. It comes with inbuilt support for newsletters and paid subscribers and is supported by robust documentation to help you in almost every way.
With a basic understanding of HTML, CSS and some javascript based handlebars, you can customise your ghost site to its entirety.
Here I will be showing you how to create a ghost blog using your own hosting. While it is much cheaper, you do have to get your hands dirty by setting up a server and configuring the setup.
If you are not up for that, you can check out ghost pro, which is a monthly paid service from the ghost team where they manage every aspect of the setup for you.
Now let's look at how we can build a free self-hosted ghost blog in 2021.
Prerequisites:
1. A server to host our site
You will need a server to host your blog. To make this an ultra-low-cost affair we will be using a free tier instance from GCP. Ghost documentation suggests that we use Ubuntu 16.04, 18.04 or 20.04 as the OS for our server. Here is my post on how you can set up your own free google cloud server.
2. Your own domain
You will need your own domain to have a place for the blog to exist. This is the major investment you will need in this process. Make sure that you have created an "A" record that points your domain to your server IP.
If you don't have a domain name of your own, you can purchase it from any of the following sites:
Name Cheap
Go Daddy
Google Domains
3. A Cloud Flare account
Finally, you need to have a cloud flare account setup. It is free and once you create an account you should connect your domain's name servers with Cloudflare's name servers. Here is how you do it.
We will be using Cloudflare for three things:
1. Our free server from GCP is not by any means a beast, Cloudflare will keep a cached version of your blog ready all time reducing the real-time load on your server.
2. It enhances security by masking the IP of our origin server.
3. It will also let us create a self-signed security certificate so that our blog will have SSL enabled (SSL are now mandatory on most modern websites)
Let us begin
Note: A ghost blog requires NGINX, MySQL, and a separate user for its functioning. We will be setting these up in the following steps before we install the Ghost platform on our server.
Step 1: Access your Server
Enter your GCP server (Virtual Instance) by SSHing into it.

This will open up a bash terminal for us to configure to the VM instance.
Step 2: Create a new user
adduser blogger
Here we are adding the user "blogger" to our instance. You can use any name except "ghost" (using "ghost" will tamper with the ghost CLI) for your instance.
If you are asked to add a password for the user, you can add a password or leave it blank and press enter.
Step 3: Set admin privileges for the new user
Give the new user admin privileges by adding it to the superuser group.
usermod -aG sudo blogger
Step 4: Log in as the new user
su - blogger
If you have added any password for the user you will be asked to enter that to start using the server as "blogger"
Step 5: Update Packages
sudo apt-get update && sudo apt-get upgrade
This command will update all the packages on your server. When the update is completed the CLI will show you a report of the same.
Step 6: Install Nginx
sudo apt-get install nginx
Nginx converts our virtual instance into a server. Ghost also needs it to configure SSL as well.
Step 7: Install the MySql database
sudo apt-get install mysql-server
MySql serves as the database that holds all your blog posts and images to create your blog website.
Step 8: Setup the MySql database
For newer versions of Ubuntu (18.04 and 20.04) for Ghost CLI to work, you need to set a password for the database.
Run sudomysql
The following command will help you update your MySQL user with a password:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
Use any password that you like, but keep the root and localhost variables intact.
Exit MySql using the command quit
Step 9: Install Node.js
Ghost needs a system-wide installation of Node.js to function. Supported Node versions can be found in the Ghost Documentation. We will be using 14.x for our installation.
Use the following commands:
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash
sudo apt-get install -y nodejs
Wait a few seconds for the installation to finish.
Step 10: Setup Swap Memory
Ghost recommends a minimum of 1GB ram for your server. Since we are using a free server from GCP, it is not that powerful to do the consistent heavy lifting. So we will add a swap file to set up additional ram space for smoother operations.
Here is how we do it:
1. Create a swap file (we are allocating 1GB for swapping).
sudo dd if=/dev/zero of=/swapfile bs=1024 count=1048576
sudo fallocate -l 1G /swapfile
2. Set the permissions for the usage of the swap file.
sudo chmod 600 /swapfile
3. Setup the swap area on the file.
sudo mkswap /swapfile
4. Now we activate the swap file and make the change permanent.
sudo swapon /swapfile
sudo sh -c “echo ‘/var/swap swap swap defaults 0 0’ >> /etc/fstab”
This will get your swap file ready. For more information on swap files, visit this website.
Step 11: Install Ghost CLI
The ghost CLI is a tool that is necessary to install a ghost instance into your server through the command line.
sudo npm install ghost-cli@latest -g
Step 12: Create the installation directory for ghost and set the permissions
Before you proceed to install Ghost, you need to create a directory for your ghost installation. Give it any name you want. I will be calling it ghostblog.
sudo mkdir -p /var/www/ghostblog
sudo chown blogger:blogger /var/www/sitename (Don't forget to replace the username blogger with the user name you have chosen)
sudo chmod 775 /var/www/ghostblog
Step 13: Install Ghost, finally!
Navigate to the directory you have created for your installation
cd /var/www/ghostblog
Run the installation by using the ghost install
command
As the installation progresses you will be asked for a series of install questions.
Enter your blog URL: https://example.net
Here enter the domain you have used to connect with your IP. We will be using HTTPS as we will be strictly allowing only HTTPS traffic.
Enter your MySQL hostname: localhost
Enter your MySQL username: root
Enter your MySQL password: password (use the password you had set in step 8)
Enter your Ghost database name: ghost_blog
Do you wish to set up "ghost" mysql user? Yes
Do you wish to set up Nginx? Yes
Do you wish to set up SSL? No
Do you wish to set up Systemd? Yes
Do you want to start Ghost? No
As you might have noticed we are almost ready with our ghost blog. We have skipped the Let's Encrypt SSL setup from ghost because it has to be renewed manually every three months. Instead, we will use self-signed certification from Cloudflare to set up our SSL
Step 14: Create your certificates from Cloudflare
Sign in to your Cloudflare account and go to SSL in the settings dashboard for your website. Now we will set the SSL/TLS encryption mode to full. This makes sure we have end to end encryption for all our website traffic.

The next step is to create a “Cloudflare Origin Certificate”.
This will encrypt the traffic between Cloudflare’s servers and our GCP VM. Navigate to the 'origin server section'

Set hostnames as *.samplesite.net and samplesite.net (this makes the certificates valid for your subdomains as well) and validity to 15 years.

Once you click create, you’ll get two files: a private key and a certificate. Copy the contents of the two files to a secure location. You will need both of them to complete your SSL setup.
Step 15: Adding the certificates to your VM instance
Return to your VM's SSH to copy these certificates. If you had exited the VM's earlier, make sure you log in to the user using su - blogger
command (refer Step 4).
We will be using Nano as the text editor to add these certificates to our host VM.
sudo apt-get install nano
Now, we will install the certificates from Cloudflare to our server.
sudo nano /etc/ssl/certs/cf-cert.pem
# Paste the contents of your Cloudflare certificate into that file then save it using "ctrl + o".
# Use "ctrl + x" to exit Nano
The next step is to install the Private key we got from Cloudflare
sudo nano /etc/ssl/private/cf-key.pem
# Paste the contents of your Cloudflare certificate into that file then save it using "ctrl + o".
# Use "ctrl + x" to exit Nano
If you need help with the nano editor refer here
With that, you have set up your SSL and you are ready to launch your blog.
Step 16: Fixing the Nginx Configuration to add our Certificate files
The Ghost CLI should have set up a config file for us earlier without an SSL server block. We can now access it using the following command (replace example.net with your domain name) :
sudo nano /etc/nginx/sites-available/example.net.conf
Modify it by replacing its content with the following lines using your domain name:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/ssl/certs/cf-cert.pem;
ssl_certificate_key /etc/ssl/private/cf-key.pem;
server_name example.net;
root /var/www/ghostblog/system/nginx-root; # Used for acme.sh SSL verification (https://acme.sh)
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;
proxy_pass http://127.0.0.1:2368;
}
location ~ /.well-known {
allow all;
}
client_max_body_size 50m;
}
With that our server is ready.
Step 17: Fire up Ghost
Now it is time to start our ghost instance using the ghost start
command
If you have done everything while following along your ghost instance should be running successfully at the site address you have given.
Step 18: Configuring your Ghost blog
We have made it. Now that the ghost blog is ready, we can go to https://example.net/ghost (replace with your site URL) and sign to start editing and adding content to our website.
Congrats on making it this far. Hope this post helped you set up your own functioning blog. I built this site using the same exact steps mentioned above. Feel free to contact me if you have any doubts.
There are few other things can do to make the site truly professional, like customising the look and feel of your ghost site, backing up your server and setting up the newsletter. I will write on those soon, meanwhile, you can explore the resources below.
Additional resources you may find helpful
Setting up mail gun for your newsletter
Backing up your ghost server on your Google Drive
Ghost CLI Documentation
Configuring an HTTPS nginx server
Updating Ubuntu
Notes:
Since we are using a self-signed certification from Cloudflare we cannot connect this ghost blog with a stripe account as it does not accept self-signed certificates. What this means is that you can't use the paid subscribers feature that comes with ghost. If you indeed wish to use it, I suggest using the Let's Encrypt certificate that ghost offers. You can set it up using ghost setup ssl
command. Make sure you remove the Cloudflare certificates from your server when doing this as multiple certificates can create trouble for your site.