A full guide for installing, configuring and running Ghost on your AWS EC2 Ubuntu 18.04 server, for use in production.


  • 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)
  • Systemd
  • 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.

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.

Click the "Launch Button" to launch an EC2 instance.

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.

Click on the "Select" button for that Ubuntu 18.04 instance.

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.

Choose t2.micro if you want stay free of cost.

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.

Make sure to add HTTPS port for our NGINX SSL setup

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.

Setup AWS RDS MySQL 5.7

Create a AWS RDS database using MySQL 5.7 engine.

Create RDS Use Case

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

Choose Dev/Test - MySQL option for AWS Free Tier account.

Specify DB Details

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.

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" ubuntu@ec2-3-112-67-64.ap-northeast-1.compute.amazonaws.com

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'
"sudo ufw allow 'Nginx Full'" - Make sure the firewall allows HTTP(S) connections:

Install NVM for Node.js

Next, we will install NVM so we can easily change our Node.js version in the future.

ghost-cms:~$ wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
ghost-cms:~$ exit

ubuntu:~$ su - ghost-cms
ghost-cms:~$ command -v nvm
"exit" to ghost-cms to fully activate the command of 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  \
--dbhost=ghost-blog.c5ll9wq6fpis.ap-northeast-1.rds.amazonaws.com \
--dbuser=ghost_blog \
--dbpass=unEEQR2fPVxfu3- \
example ghost install with RDS MySQL credential
? 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)? ghostcmsblog@rommelporras.com
? Do you wish to set up Systemd? Yes
? Do you want to start Ghost? Yes
Enter the "https" link of your blog if you already link this to your DNS (ex: NameCheap)

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!

Guides - Commands that I use in installing Ghost

Configure NGINX SSL -  https:// (SSL) -> 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 http://example.com to https://www.example.com - 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 https://example.com 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 https://example.com

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 https://www.example.com

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/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. example.com.conf 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 https://www.your-primary-domain.com$request_uri;

Don't do this for files with "-ssl.conf"

Save and close the file, and repeat this task for example.com-ssl.conf and www.example.com.conf, but do not do this for www.example.com-ssl.conf and example.com-ssl.conf.

Now do this again your www conf file. DON'T apply the 301 redirect code to your config files with "-ssl.conf" extension.

location / {
return 301 https://www.your-primary-domain.com$request_uri;

Restart NGINX After Applying 301 redirect code

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

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 http://example.com, http://www.example.com or https://example.com, they'll be redirected to https://www.example.com instead.

Happy blogging!

Check Ghost & Gatsby on Netlify - JAMStack guide to know how to host your Ghost blog for FREE.