Self Hosting Ghost's Blog Platform in the Cloud
If you'd like to consume this post in video format, it's embedded below:
Overview
I'd been using Wordpress for this blog for around a year but it felt like time for a change. While Wordpress has a plethora of features and an expansive plugin system there was a lot I wasn't taking advantage of. I prefer self-hosting options so that took a few platforms you might have heard of off the table. Ghost recently updated to version 5 and has a self hosted as well as Pro version where they host it for you. The features are tightly focused on blogs, newsletters, podcasts, and the like, so it seemed like an excellent fit. There are also no more plugins to handle with Ghost compared to Wordpress which reduced the admin overhead significantly. If you're just starting out Ghost can easily be hosted on a VPS from the likes of Digital Ocean or my preference: Vultr.
Ghost themselves offers a good breakdown comparing themselves to Wordpress: https://ghost.org/vs/wordpress/
Getting Started
Create a new Ubuntu 20.04 VM or VPS, I used Vultr for my example but you could use your own VM infrastructure or another VPS provider such as Linode or Digital Ocean. I recommend setting it up with an SSH key for better security and easier connection.
I used Vultr's high performance cloud compute option for this, I don't anticipate enough load to require the higher end option that doesn't have "noisy neighbors" (oversubscription of VM CPU cores). Below is pricing for high performance, for a basic site you would likely be fine with their standard offering though.
Once it's created, SSH into the new machine.
The first step is to create a service account for Ghost
sudo adduser ghostblog
Add sudo permissions and log in as Ghost to continue setup with the proper permissions
sudo usermod -aG sudo ghostblog
su - ghostblog
Before we start the Ghost install we need to update our apt repository and make sure Ubuntu is fully up to date, we'll do this with and apt update and apt upgrade
sudo apt update && sudo apt upgrade -y
Ghost uses NGINX as the web server and mysql as the database so we'll install those with apt
sudo apt install -y nginx mysql-server
Since the VPS is exposed to the internet we'll setup Uncomplicated FireWall or UFW to allow only NGINX's ports, 80 and 443 for the web server and 22 for SSH, then enable UFW. This will prevent connections to the VPS over other ports, reducing the attack surface.
sudo ufw allow 'Nginx Full'
sudo ufw allow ssh
sudo ufw enable
Next we need to setup MySQL with a root password that we'll reference later during Ghost's setup, so you will want to note down the password
sudo mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '[your_password]';
quit
su - ghostblog
Ghost is based on nodeJS so we'll add its repository and then install node with apt
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash
sudo apt install -y nodejs
Now that node is installed we'll use NPM to install ghost's Command Line utility
sudo npm install ghost-cli@latest -g
Once the CLI is installed we need to make the folders for our blog and set the permissions for our Ghost service account. Then, change directories into the new folder and install ghost.
sudo mkdir -p /var/www/mawtechblog
sudo chown ghostblog:ghostblog /var/www/mawtechblog
sudo chmod 775 /var/www/mawtechblog
cd /var/www/mawtechblog
ghost install
Ghost will now install, this will take a few minutes. Once it's installed we'll need be prompted with some options:
Enter your blog URL: [FQDN for your blog]
Enter your MySQL hostname: localhost
Enter your MySQL username: root
Enter your MySQL password: [password set previously]
Enter your Ghost database name: [accept default]
Do you wish to set up "ghost" mysql user?: Y
Do you wish to setup Nxinx?: Y
Do you wish to set up SSL?: Yes
Enter your email (For SSL Certificate): [your email]
Do you wish to set up Systemd?: Yes
Do you wish to start Ghost?: Yes
You should be greeted with a success message and the FQDN you supplied for the first step. You will now want to setup DNS to point that URL to the IP address of your server.
Visiting the URL should greet you with a vanilla Ghost install.
The only remaining setup is to setup a mailgun account to use for sending email. You can use the free account without providing payment info for a smaller site. Once you sign up you'll want to get the API token for the subdomain you setup.
Open the configuration file for the ghost instance you just configured with
nano config.production.json
Setup your Mail section to look similar to this:
"mail": {
"transport": "SMTP",
"options": {
"service": "Mailgun",
"host": "smtp.mailgun.org",
"port": 587,
"secureConnection": false,
"auth": {
"user": "[your_mailgun_user]",
"pass": "[mailgun_token]"
}
You should now have a fully functional blog!