How to host Ghost CMS on AWS (EC2 + EFS + RDS)
Tags: aws, ghostcms, amazonwebservices, community
Published: 2024-07-04 18:42:17

This article will dive into hosting Ghost CMS (open source) in AWS using EC2 + EFS + RDS services.

During the weekend I did a small project to host my blog site created using ghost CMS and hosted in AWS using (EC2 + EFS + RDS) services. Now I want to share my experience with you.

If you’re looking to run your own Blog, Media, or Publishing site Ghost CMS is a powerful open source app developed by John O’ Nolan (former Head of Design at WordPress). We will not talk about the Ghost CMS in depth in this article but if you are into blog writing and media publishing you should definitely check out Ghost CMS. It offers top-notch features for publishing your articles and hosting them free of cost through an open-source license. Ghost CMS also has a paid offering but it comes with a cost for taking the hosting troubles away from you and you can just focus on writing and publishing the best content. In this article, we will explore how you can self-host the ghost cms for yourself in AWS.

## The Services
We chose to run with AWS (EC2 + EFS + RDS) services, for a few reasons.

**EC2** -> because I tried to host it in ECS (Fargate) my preferred way but failed, so I resorted to Good Old EC2. If you want to try hosting using containers there is a community-supported docker image and guidance available here. Let me know in the comments if you figure it out.

**EFS** -> For persistent storage of media, so that we do not lose our content if our EC2 instance happens to get terminated accidentally.

**RDS** -> For database needs, storing user and other content-related data.

## Network Setup
First, select the region you want to host your server (ex: us-east-1, N. Virginia).

- Create VPC
- Choose the number of AZs — 2.
- One subnet for each public and private. (Our web server EC2 will be in the public subnet and RDS in the private subnet)
- 1 NAT Gateway in 1 AZ for making internet access available for resources and restricting access the other way around.
- Go with the default settings for the rest of the fields.
- Once you are ready click “Create VPC”, and you should have the VPC in a few minutes.
- When a VPC is created, AWS does the configuration between the Internet and your network space and internally via the Subnets, Route Table Configuration, and Internet Gateway. Unless you want to change your network setup there is no need to modify them for this demo.

## RDS Setup (Database)

- Go to the RDS page, and select Create RDS.
- In the RDS creation page, select the stand create option and choose MySQL Community edition as our DB engine.
- Select the MySQL version greater than 8 (8.0.35).
- Go with the free tier template in the next section unless you are following this article for your production setup then select the Production template which means RDS selects the best default configuration recommended for the production workload.
- Give the DB instance a name and a user name for login access.
- In the credentials management select self-managed credentials and auto-generated password unless you have a preferred password you want to use.
- In the instance configuration section, I chose t3.micro for this demo.
- In storage select GP3 cause it comes with the best and general purpose is all we need for this demo with a 20GB allocated storage. (in the storage autoscaling, de-select the autoscaling option)
- In the connectivity section, select don’t connect to an EC2 option as we don’t have the instance yet and we are going to connect them later.
- Select the VPC we created and Create a new DB subnet group option.
- Do not enable public access to RDS and select Create a new security group for DB.
- In the AZ, select the same zone in which you want to deploy your EC2 for faster connectivity though it would be hard to notice as they are in the same region anyway.
- NOTE: Give your db an initial name under Additional Configuration. If you do not RDS will not create a db for us and only an instance will be created.
- Leave the rest of the options as default.
- Once you are ready click Create database. After the DB is created you will find the pop-up with credentials information (password) copy and save them somewhere secure.

## EFS Setup
Go to the EFS page, and click Create File System.

- Give the file system a name and choose the VPC you are using for this demo.
- Click Create and EFS is created.
- For now, that’s it, folks. We will come back during EC2 setup to enable connectivity between our web server and filesystem and also mount it on the EC2.

## EC2 Setup
- Go to the EC2 page and select Launch instance.
- Give your EC2 a name and select the Ubuntu (22.04) version as Ghost CMS supports only 16.04, 18.04, 20.4, and 22.04 versions of Ubuntu currently.
- Select an instance type that works for you, at least t2.medium.
- Create a new key pair if you want to SSH to your instance from local.
- In the VPC settings, select the VPC we created for this Demo and public subnet.
- Select “Create Security Group” and select all three rules to allow SSH, HTTP, and HTTPS traffic from the internet. Do not worry we will remove the SSH access once we set up the ghost configuration.
- Under the storage configuration, select an 8 GB gp3 as root volume.
- In the same section click edit to add the file system we selected earlier.
- De-select the automount option and select the automatic security group attachment. This way AWS creates the inbound rules to EFS only from the EC2 security group. We can do it manually too but why go the hard way?
- That’s it, when you are ready create your instance.
- Once your instance is ready go to Elastic IP under the network and security section.
- Click Allocate Elastic IP and once the IP is allocated, associate it to the instance we created just now.
- It helps in two ways, one we now have a static IP at which our site can be accessed. Two we can use this elastic IP to map our DNS (your site address) to the server so that people can reach your site using the site address.

## Host Server Configuration in EC2
Go to your EC2 page and select the instance you just created. Click Connect using EC2 Instance Connect. You can also find the server setup configuration in ghost docs.

**Update system packages**
Once you log in use the commands to update your packages and install them.

**Update package lists**

> sudo apt-get update

**Update installed packages**

> sudo apt-get upgrade

If you are system is acting up and asking for a restart to load new system packages or libraries. Please go to the instance and reboot the instance using the option available under actions. Reconnect to the system.

**Create a new user for ghost**
Create a new user and follow prompts

> adduser <user>

**Add user to superuser group to unlock admin privileges**

> usermod -aG sudo <user>

**Then log in as the new user**

> su - <user>

## Install Nginx
Ghost CMS uses NGINX server. Install Nginx server and activate ufw for HTTP and HTTPS connect in the firewall.

**Install NGINX**

> sudo apt-get install nginx

**Allow HTTP and HTTPS connections in the firewall**

> sudo ufw allow 'Nginx Full'

## Install MySQL

> sudo apt-get install mysql-server

skip the user creation in the local MySQL setup as we are going to use the RDS for our DB requirement.

## Install Node.js

**Download and import the Nodesource GPG key**

> sudo apt-get update
> sudo apt-get install -y ca-certificates curl gnupg
> sudo mkdir -p /etc/apt/keyrings
> curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg

**Create deb repository**

> NODE_MAJOR=18 # Use a supported version
> echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list

**Run update and install**

> sudo apt-get update
> sudo apt-get install nodejs -y

## Install Ghost CLI

> sudo npm install ghost-cli@latest -g

## Install EFS-UTILS
Since we are going to mount EFS for persistence storage, to do that we have to first install the efs-utils library package. You can also find the instruction here.

First, install rust and cargo through rustup:

> curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
> . "$HOME/.cargo/env"

**To build and install debian package for efs-utils follow these commands.**

> $ sudo apt-get update
> $ sudo apt-get -y install git binutils rustc cargo pkg-config libssl-dev
> $ git clone https://github.com/aws/efs-utils
> $ cd efs-utils
> $ ./build-deb.sh
> $ sudo apt-get -y install ./build/amazon-efs-utils*deb

## Mount EFS
Follow these instructions carefully as we are going to create a directory we are going to mount our efs to this new directory and then install ghost inside the mounted directory.

**Create directory: Change `sitename` to whatever you like**

> sudo mkdir -p /var/www/sitename

**Mount EFS Find your EFS mount details in EFS page and click attach on the EFS created for this demo**

> sudo mount -t nfs4 -o 
nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport <your EFS ID>.efs.us-east-2.amazonaws.com:/ /var/www/sitename

**Set directory owner: Replace <user> with the name of your user**

> sudo chown <user>:<user> /var/www/sitename

**Set the correct permissions**

> sudo chmod 775 /var/www/sitename

**Then navigate into it**

> cd /var/www/sitename
You should be able to find your EFS mount command by going to the EFS page. select the EFS you created for this demo and click attach. You will be able to find the mount command in the pop-up screen.

## Run the install process

> ghost install

During the installation process, Ghost CLI will ask multiple questions to configure the ghost server.

1. Blog URL: Provide your site URL and include the protocol. ex: https://example.com (you might find a challenge with not being able to access your site using www.example.com TLD later if you gave only the example.com as an input. You can use this article to fix that issue after the full site setup)
2. MySQL hostname: Copy the RDS instance endpoint and paste it here.
3. MySQL Username: Type the username you have given during the RDS setup.
4. MySQL Password: The one I asked you to copy and save somewhere safe :).
5. Ghost DB Name: The DB name I asked you to specifically create and not to forget during RDS setup.
6. Set up Nginx: Yes
7. Setup SSL: Yes (it asks for your email for SSL purposes)
8. Setup Systemd: Yes
9. Start Ghost: Yes.
If you followed the instructions closely, you should be able to access your Ghost CMS site at the Public IP/ DNS endpoint of your EC2. To access the admin configuration page just add “/ghost” at the end of your DNS and you should see the site configuration and login page.

## DNS Configuration
If you already have a domain you bought for your site. Go to the DNS provider and add a couple of A records. For this demo I have my domain registered with Route53, so I will configure the records in Route53 hosted zone.

Record 1

Record name: sitename.com,
Record Type: A
Value: <Static IP of your instance> (in our demo we have an elastic IP associated with the instance so add that here and save.

Record 2

Record Name: www.sitename.com,
Record Type: A,
Alias: select alias as yes (alias to another record in this hosted zone since I have the other A record also in here) select the sitename.com record and save.

Save the settings and in a few mins, your site should be served over your DNS name.

Please leave a like if you find this article helpful and add your feedback or ask your queries in the comments.

Thank you!