3 min read

Installing Ghost; ft. Ghost Doctor

I decided that Ghost would be the content management system (CMS) I finally settled down with and stuck to for my blog. It was a pretty sudden decision, but I was tired of my website always being empty.

This is my first time using a true web based CMS and not a static site or a flat file CMS. I liked the idea of being able to use a web interface to manage the blog as I feel it will allow me to focus on the content and creativity more rather than webdev. I want this to enable me to share my learning, and Ghost seemed to be a great fit.

It looks like things will be different this time and I will stick with it due to how easy it makes managing the website.

I use Digital Ocean for my blog and so I spun up a new droplet and got to work.

I chose one of the cheaper servers with 2 GB / 1 CPU, 50 GB SSD Disk, 2TB transfer.

This seemed to be the best option to give me some overhead room for growth and ensure any issues I face will not be due to constricted resources.

Ghost has great documentation so this looked to be an easy process that would be done before my coffee ran out. You can follow along at: https://ghost.org/docs/install/ubuntu/

Prerequisites

I got the Ubuntu 22.04 server set up and began to go through the list of prerequisites for Ghost.


"The officially recommended production installation requires the following stack:

  • Ubuntu 20.04 or Ubuntu 22.04
  • NGINX (minimum of 1.9.5 for SSL)
  • A supported version of Node.js
  • MySQL 8
  • Systemd
  • A server with at least 1GB memory
  • A registered domain name

Before getting started you should set up a working DNS A-Record from you domain, pointing to the server’s IP address. This must be done in advance so that SSL can be configured during setup."


OOPS

I don't have my domain name redirected yet. The old DNS records are still hanging around in CloudFlare. I gotta go move those while the updates are running.

Done. Just have to wait for the changes to take effect. I created the user and gave it sudo permissions.

Landing Page

I cloned https://github.com/tmKamal/under-construction-template.git into a directory to have a proper landing page. I don't like only having the default Nginx page.

MySQL

While still waiting on DNS changes to take effect, my next step was running the commands to install MySQL. This was straightforward, just had to update the passwords and flush the privileges.

Node.js

Ghost recommends Node v18 Hydrogen LTS (18.x) , but also supports Node v20 Iron LTS (20.x)

18.x is what they currently use in production on their Pro hosted version of Ghost.

Nodesource GPG Key

We have to add the Nodesource GPG key to a new keyring in /etc/apt/keyrings. Once that is added we create a deb repository specifying the major version to use as NODE_MAJOR=18 to ensure we don't upgrade on accident.

Ghost-CLI

The Ghost-CLI is a command line tool to install and configure ghost. It can be installed via npm with a quick command.

Running this CLI tool configures ghost based off the inputs given and then starts Ghost .

Diagnosing Issues...

So, Ghost did not start cleanly. I was getting a 502 error from Nginx. I assumed it was because I had messed with the Nginx configuration when setting up my landing page.

After about 10 minutes of wondering how I borked configs when I didn't do anything, I realize I hadn't. So I finally decided to do some real troubleshooting but I'll spoil the ending for you now. What I had​ done was miss a step in the Ghost docs. You see above where I mentioned that I had to update the permissions after installing MySQL? Well I didn't.

Ghost is not compatible with the way that MySQL in Ubuntu 22.04 authenticates by default. There is a section in Ghost's docsdocs that goes into more details. Not changing this to use a password will result in auth errors with the database.

Except I didn't realize that at first, because I didn't get auth errors. I got the following: connect ECONNREFUSED ::1:3306. This error meant that 'localhost' is translating to an IPv6 address. Yay. Changing the config file to use 127.0.0.1 instead fixed that issue.

I was glad for a moment it was a quick fix after wasting all that time with Nginx, until I realized that the domain was still presenting a 502 error.

Time for a Doctor!

A ghost doctor​​​ to be specific. This command line tool built into Ghost checks the environment for compatibility issues and common misconfigurations. It pointed me in the right direction, but while all seemed to be okay Ghost still wasn't starting cleanly. It wasn't until I checked the journald logs that the auth error presented itself.

That was super easy to find as well because Ghost provides some helpful commands to remind you which logs to check when the ghost start command fails.

Yeah... Ghost hadn't even been starting cleanly this whole time but I was too distracted by other tasks to notice. Ghost's documentation was great at helping resolve these issues I encountered, but the "Getting Started" section assumes you, well, followed the instructions properly. Oops. Lesson learned. Don't try to multitask while setting up a new stack.