Host Ghost on AWS without breaking the bank

Host Ghost on AWS without breaking the bank

This guide presents a self-hosted, AWS-based option to run a Ghost website. The objective is to minimize cost while providing the required resources to run the application and its dependencies. It leverages services including compute, storage, and DNS available within the AWS Free Tier and is suitable for enthusiasts evaluating the Ghost platform.

Operational Costs

Start by creating a free AWS account to access the 12-month Free Tier offer. Provided you follow the steps in this guide and remain within the AWS Free Tier constraints the only operational cost applicable is the registration of your domain, which is billed per domain per year. The AWS Free Tier service is available for 12 months - after which we can explore alternative hosting and migration options.

Prerequisites

(1) Register a domain

A domain is required to configure SSL for your blog. Exercise caution when registering a domain - the cost is not refundable and can range from a few dollars to hundreds of dollars. The instructions to register a domain using AWS Route 53 can be found here.

(2) Provision a server

The Ghost application components and dependencies will be installed on a single server. Refer to the Launch a Linux instance in AWS Free Tier how-to-guide for details on how to provision a suitable instance within the free tier constraints.

(3) Create a DNS Record

A DNS record is required to return the IP address of the ghost application server when a user navigates to your domain. The IP address in question is the public IPv4 address of the server provisioned in Step (2) - the same address that is used to connect to instance using SSH.

Open the Route53 console at https://console.aws.amazon.com/route53. Navigate to the Hosted Zones and select the Public hosted zone for your domain.

Press the Create record button and an A Record for the domain apex with the value set to the public IPv4 address of the server (example below) and press the Create records button.

Install Ghost

This section extends the official guide on How to install Ghost on Ubuntu.

The commands listed below must be executed in the order they are listed. Where applicable the sample input that was used to configure this blog with the inspired-solutions-lab.com domain is displayed inline.

Update Packages
sudo apt-get update
sudo apt-get upgrade
Install NGINX
sudo apt-get install nginx
Install MySQL
sudo apt-get install mysql-server
Configure MySQL (N.B. replace <your-new-root-password>)
sudo mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY '<your-new-root-password>';
FLUSH PRIVILEGES;
exit
Install Node.js
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
NODE_MAJOR=20 # 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
sudo apt-get update
sudo apt-get install nodejs -y
Install Ghost-CLI
sudo npm install ghost-cli@latest -g
Create a directory
sudo mkdir -p /var/www/ghost-blog
sudo chown ubuntu:ubuntu /var/www/ghost-blog
sudo chmod 775 /var/www/ghost-blog
cd /var/www/ghost-blog
Install Ghost
ghost install
Install Input/Output Sample
Love open source? We’re hiring JavaScript Engineers to work on Ghost full-time.
https://careers.ghost.org



✔ Checking system Node.js version - found v20.18.1
✔ Checking current folder permissions
✔ Checking memory availability
✔ Checking free space
✔ Checking for latest Ghost version
✔ Setting up install directory
✔ Downloading and installing Ghost v5.106.1
✔ Finishing install process
? Enter your blog URL: https://inspired-solutions-lab.com
? Enter your MySQL hostname: 127.0.0.1
? Enter your MySQL username: root
? Enter your MySQL password: [hidden]
? Enter your Ghost database name: ghost_db
✔ Configuring Ghost
✔ Setting up instance
+ sudo chown -R ghost:ghost /var/www/ghost-blog/content
✔ Setting up "ghost" system user
? Do you wish to set up "ghost" mysql user? Yes
✔ Setting up "ghost" mysql user
? Do you wish to set up Nginx? Yes
+ sudo mv /tmp/inspired-solutions-lab-com/inspired-solutions-lab.com.conf /etc/nginx/sites-available/inspired-solutions-lab.com.conf
+ sudo ln -sf /etc/nginx/sites-available/inspired-solutions-lab.com.conf /etc/nginx/sites-enabled/inspired-solutions-lab.com.conf
+ sudo nginx -s reload
✔ Setting up Nginx
? Do you wish to set up SSL? Yes
? Enter your email (For SSL Certificate) your@email.com
+ sudo /etc/letsencrypt/acme.sh --upgrade --home /etc/letsencrypt
+ sudo /etc/letsencrypt/acme.sh --issue --home /etc/letsencrypt --server letsencrypt --domain inspired-solutions-lab.com --webroot /var/www/ghost-blog/system/nginx-root --reloadcmd "nginx -s reload" --accountemail your@email.com --keylength 2048
+ sudo openssl dhparam -dsaparam -out /etc/nginx/snippets/dhparam.pem 2048
+ sudo mv /tmp/ssl-params.conf /etc/nginx/snippets/ssl-params.conf
+ sudo mv /tmp/inspired-solutions-lab-com/inspired-solutions-lab.com-ssl.conf /etc/nginx/sites-available/inspired-solutions-lab.com-ssl.conf
+ sudo ln -sf /etc/nginx/sites-available/inspired-solutions-lab.com-ssl.conf /etc/nginx/sites-enabled/inspired-solutions-lab.com-ssl.conf
+ sudo nginx -s reload
✔ Setting up SSL
? Do you wish to set up Systemd? Yes
+ sudo mv /tmp/inspired-solutions-lab-com/ghost_inspired-solutions-lab-com.service /lib/systemd/system/ghost_inspired-solutions-lab-com.service
+ sudo systemctl daemon-reload
✔ Setting up Systemd
+ sudo systemctl is-active ghost_inspired-solutions-lab-com
? Do you want to start Ghost? Yes
+ sudo systemctl start ghost_inspired-solutions-lab-com
+ sudo systemctl is-enabled ghost_inspired-solutions-lab-com
+ sudo systemctl enable ghost_inspired-solutions-lab-com --quiet
✔ Starting Ghost

Ghost uses direct mail by default. To set up an alternative email method read our docs at https://ghost.org/docs/config/#mail

------------------------------------------------------------------------------

Ghost was installed successfully! To complete setup of your publication, visit:

    https://inspired-solutions-lab.com/ghost/

Visit your blog

Navigate to the URL of your blog that was setup in the previous step - the result will look like the image below if the installation was successful.

Add the /ghost to your URL to access Ghost admin. Initially you will need to configure the blog name, admin user and password after which you will have access to the Ghost Admin pages - and finally start publishing your content!

Maintenance

A post that covers common maintenance activities including application and dependency upgrades, email, backups, and AWS configuration updates will be coming soon!

Final Thoughts

I hope this helps others who wish to explore self-hosting a Ghost website. Feel free to post any comments, questions, suggestions.