• Ubuntu 18.04 EC2 image
  • NGINX (minimum of 1.9.5 for SSL)
  • Node Version Manager to install latest Node.js LTS version (currently at Node.js v10.16.0)
  • AWS RDS MySQL 5.7 or below (not >= 8.0)
  • A server with at least 1GB memory
  • A registered domain name (ex: in Namecheap)

Tip: Check the images for more detailed info in configuring EC2, RDS, NGINX, and SSL.

Setup AWS Infrastructure

AWS EC2 Instance Configuration

I assume that you already have account on AWS / Amazon Web Services. There is an free tiers offer for new AWS customer. You can set up your account here.

The first thing we need to do is configure an EC2 instance. In case you’re not familiar to AWS EC2, Amazon Elastic Compute Cloud (Amazon EC2) is a web service that provides secure, resizable compute capacity in the cloud. It is designed to make web-scale cloud computing easier for developers.

Launch EC2 Instance

After you’d logged into AWS and you’re on the landing page, select the EC2 service. You will arrive at the EC2 Dashboard. Click that blue Launch Instance button.

AWS EC2 Dashboard
AWS EC2 Dashboard

Choose an Amazon Machine Image (AMI)

First, you need to decide on the machine image you want.

You can choose this images for your Ghost project:

  • Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
  • Ubuntu Server 16.04 LTS (HVM), SSD Volume Type instance.

We’re going to use the Ubuntu Server 18.04 LTS (HVM), SSD Volume Type instance, because Ubuntu 18.04 LTS is latest LTS version of Ubuntu and officially supported by Ghost.

EC2 Amazon Machine Image (AMI)
EC2 Amazon Machine Image (AMI)

Choose an Instance Type

We will pick our EC2 instance type, our server specs. You can use t2.micro type instance if you want to use your AWS Free Tier account and not getting bill for your dev/test server.

If you’re new in AWS and just trying it out, choose t2.micro. It has 1 GB of memory and 1 vCPU, the minimum required to run Ghost.

EC2 Step 3 to 5

We will skip to detailed this out, because the use case of this is different from each users. If you want to see what I choose, see the images below.

Configure the Security Group

We will define what kind of connections we will allow to our instance. AWS will block everything by default, so you’ll need to enable the specific traffic you want to allow. In the default configuration, AWS will allow SSH over port 22 from your current IP address.

We will add public connection to our HTTP and HTTPS port from our security group, click Review and Launch button.

Review Instance Configuration

Go ahead and review everything and make sure nothing sticks out as odd. Here’s my options:

  1. AMI is Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
  2. Instance type is t2.micro for AWS Free Tier users (you can choose other instance type)
  3. Allowing SSH port 22 on your own IP address
  4. Allowing HTTP port 80 to the public
  5. Allowing HTTPS port 443 to the public

Key Pair Setup

When you click Launch button, AWS will show a popup asking you to either select an existing key pair, or create a new one. Create a new one if needed, download the key, and click Launch Instances.

Make sure to don’t lose the .pem keys, you need this to SSH in your EC2 instance. Wait for a few minutes, your EC2 instance will get ready.

Create/Use EC2 Key Pair
Create/Use EC2 Key Pair

Setup AWS RDS MySQL 5.7

Create a AWS RDS database using MySQL 5.7 engine. Launch Ghost database using AWS RDS MySQL 5.7

Create RDS Use Case & Specify DB Details

If you are using this in your AWS Free Tier account, choose Dev/Test - MySQL, else choose others for your production environment Ghost project.

RDS Use Case page

*Be careful in choosing DB Instance class, other options have costing and not covered in AWS Free Tier.

Configure Advance Settings

Make sure to select Yes in Public accessibility, so our EC2 instance can connect to it. If you are not familiar in configuring AWS RDS, you can check my selected options so you can have an idea in what to choose.

Click Create database button to finish configuring AWS RDS.

AWS RDS MySQL 5.7 created

Wait for few minutes for your database to get ready.

Setup RDS’s Security Group for EC2 connection

  • Click RDS’s VPC security group under Security column.
  • Edit Inbound rules.
  • Add type MySQL/Aurora, TCP protocol, port 3306, source WebDMZ (that we create in EC2 instance installation step).

WebDMZ is the security group of our EC2 instance, we need this so our EC2 instance can connect to our RDS MySQL. Get the RDS endpoint in “Connectivity & security” tab of RDS.

Congratulation! We are finish in configuring AWS RDS MySQL database for our Ghost project.

SSH to EC2 Instance

Before getting started you should set an A record from the domain (ex: Namecheap) you plan to use, pointing at the EC2 server’s IP address and ensure that it’s resolving correctly. This must be done in advance so that SSL can be properly configured during setup.

To connect to our instance, we need to SSH to it.

cd <directory-of-your-pem-key>
sudo chmod 400 ghost-publishing-platform-cms.pem
ssh -i "ghost-publishing-platform-cms.pem"

You should be prompted on whether or not you want to continue, as the authenticity of the host cannot be established. Continue through this and you should successfully access your EC2 instance:


Installing Ghost in AWS EC2 Ubuntu Image

First, we will need to establish all the prerequisites for installing Ghost-CLI, Ghost’s command line interface tool. Using the command line, setup a new user and log in as the created user (note: everything after # is a comment and should not be included in the command):

ubuntu:~$ sudo adduser ghost-cms          # add new user
ubuntu:~$ sudo usermod -aG sudo ghost-cms # give new user elevated permissions
ubuntu:~$ su - ghost-cms                  # login as new user

Next, update the package list and upgrade the install packages:

ghost-cms:~$ sudo apt-get update && sudo apt-get upgrade

Install NGINX

ghost-cms:~$ sudo apt-get install nginx
ghost-cms:~$ sudo ufw allow 'Nginx Full'

Install NVM for Node.js

Next, we will install NVM so we can easily change our Node.js version in the future. “exit” to ghost-cms to fully activate the command of NVM

ghost-cms:~$ wget -qO- | bash

ghost-cms:~$ exit

ubuntu:~$ su - ghost-cms

ghost-cms:~$ command -v nvm

Install Node.js latest LTS (v10.16.0 at moment) and Ghost CLI

ghost-cms:~$ nvm install --lts
ghost-cms:~$ node -v
ghost-cms:~$ npm i -g ghost-cli

And then verify it installed correctly:

ghost-cms:~$ ghost help

Now create a new folder for Ghost to reside, give your ghost-user ownership of this direction, give the folder the correct permissions, and navigate to the folder:

ghost-cms:~$ sudo mkdir -p /var/www/ghost
ghost-cms:~$ sudo chown ghost-cms:ghost-cms /var/www/ghost
ghost-cms:~$ sudo chmod 775 /var/www/ghost
ghost-cms:~$ cd /var/www/ghost

Run the Ghost Install Process

ghost-cms:/var/www/ghost$ ghost install \
--db=mysql  \ \
--dbuser=ghost_blog \
--dbpass=unEEQR2fPVxfu3- \
ghost-cli install command
? Enter your blog URL: https://<WITHOUT-WWW-paste-your-public-dns-here>
? Do you wish to set up Nginx? Yes
? Do you wish to set up SSL? Yes
? Enter your email (For SSL Certificate)?
? Do you wish to set up Systemd? Yes
? Do you want to start Ghost? Yes
Options in ghost-cli install command

Enter the “https” link of your blog if you already link this to your DNS (ex: NameCheap)

Guides - Commands that I use in installing Ghost

Configure NGINX SSL -  Redirect https:// -> https://www

One of the cool things about Ghost is that it has its own CLI, which makes installing free SSL certificates from Let’s Encrypt even more of a breeze than using a tool like certbot. This is amazingly easy to use if you just plan on using a single domain:

ghost config url https://<your-domain-without-www>.com
ghost setup nginx ssl

Now let’s say you want to redirect to - if you have the knowledge to host your own Apache / Nginx web server, then doing that is pretty straightforward (using a rewrite rule). However, trying to redirect to the www equivalent results in a big red certificate error. Why? Because your web browser tries to validate the certifcate before processing the redirect. Therefore, you need to have a valid SSL certificate for both your non-www and your www domains.

Normally this task is easily handled by fetching a certificate with multiple domain names (also sometimes referred to as a UCC certificate). However, because of the way Ghost handles SEO requests (the proper way), it technically only supports one domain.

Therefore, in order to redirect all non-www versions of your site to the SSL side, you first need to “trick” ghost by temporarily changing the site url (via Ghost knowledgebase).

Since this article setup Ghost on AWS EC2, you should change to the ghost-cms user:

su - ghost-cms

Now change over to your ghost directory. ex: “cd /path/to/your/ghost/install”

cd /var/www/ghost

Temporarily tell ghost to use your non-www url

ghost config url

Now tell Ghost to generate an SSL config for the non-www url

ghost setup nginx ssl

Now change ghost back to the ‘primary url’ for your site

ghost config url

Now tell Ghost to generate an SSL config for the www url

ghost setup nginx ssl

But you’re not done yet! Now you have to tell Nginx to redirect your site. Navigate to /etc/nginx/sites-enabled (these are symbolic links so you shouldn’t have to hunt for your config files). Locate the non-www, non-SSL config file e.g. and open it using your editor of choice.

Next, add the following line at the bottom of the location section:

location / {
a bunch of stuff you should ignore
return 301$request_uri;

Don’t do this for files with “www.-ssl.conf, DON’T apply the 301 redirect code to your config files with “www-ssl.conf” extension.”

Save and close the file, repeat this task for and

location / {
return 301$request_uri;

Restart NGINX After Applying 301 redirect code

ghost-cms:~$ sudo systemctl restart nginx
ghost-cms:~$ sudo service nginx restart

To summarize, what we just did was set up a 301 redirect for each domain that doesn’t match the https version of your primary one. Now, whenever a visitor browses to, or, they’ll be redirected to instead.

Congratulations! You successfully host your Ghost blog in AWS. Go ahead and paste the URL you copied earlier into your favorite web browser and admire your handy work!

Happy blogging! <3