Ghost's DevOps Experience is Ghosting Me

I've been looking to release some more writing lately, and Ghost is definitely top-of-the-line experience for making that happen and distributing that writing to the places I want it. Where Ghost ghosting me is the operations side of things. I've self-hosted a ton of services in my 20 years on the internet, so I'm no stranger to figuring out complicated issues related to all sorts of technology platforms.

At the moment, I keep most of my personally managed infrastructure on Digital Ocean. One of my goals this year was to both reduce my costs and move away from VPS systems as much as possible. It's gone really well. I've managed to move almost everything to the App platform, cutting down a lot of my costs.

There are two holdouts though:

  1. Ghost (my blog)
  2. Cockpit (a headless CMS that runs my personal website)

I have accepted that my Cockpit installation will persist until something more ideal comes along, but I really wanted to get rid of my Ghost VPS. How hard could it be?

What issues am I running into?

Given that Ghost runs on Node, I presumed it would be straightforward to migrate. Move the DB to a managed cluster I already own, move the files to object storage, spin up the app on the App Platform with the official Docker image. Whambo, bambo! The VPS is dead, but the blog lives! I was wrong.

Ghost is not built to scale. Unlike many modern SaaS apps that can have multiple instances running behind a load balancer, Ghost is built to run behind a caching layer. They even admit this in the documentation, but there's nothing inherently wrong with this design choice. If anything, it's the correct design choice for a content management system like Ghost. This does presents some challenges when, say, you want to deploy it to function in more of a headless manner and have no desire to use any of the caching or other.

Database issues. One of the key reasons to migrating my Ghost blog off droplets is that I can reduce my own risk of shit going wrong. I've crashed (and lost) a lot of content over the years because I have a lovely ignore Linux for a long time and then try to update Linux and everything goes to hell. So, I want to use Digital Ocean's managed MySQL database and Spaces (object storage) products for Ghost, but DO (in good practice) requires primary keys for all rows to be declared. Ghost's migration setup currently does not set primary keys for many of its tables. Ghost v3, for example, doesn't set primary keys for its own migrations and migrations_lock tables. I have to modify the table declaration in a SQL dump in order to get this imported into DO's MySQL. While it seemed to work for V3, I was still unable to upgrade to V4 with the ghost-cli because further migrations tried to create tables without primary keys.

This is a mess. What's worse? One issue opened in the Ghost repo suggests that this might be completely resolved by updating their severely outdated query builder dependency, Knex.

Changing image storage to S3 requires filesystem persistence. Ghost requires the use of a storage adapter in order to tell Ghost to not save things in the local file system. And while I have no doubt the two S3 adapters listed on their site will work since S3's API doesn't change much, but both have gone two years without any updates.

Why not use Ghost(Pro)?

In order to have "custom integrations" which is what Ghost calls access to API keys, I'd have to shell out for the $36/mo plan. Also, "Views per month" pricing quantifiers have never sat well with me.

The goal was to save money and reduce risk. Using Ghost(Pro) only provides a semblance of reduced risk, and it doesn't justify the increased expense.

I think it's also important to note that Ghost--despite being a non-profit org--has an incentive not to improve their self-hosting/dev-ops experience. I'm not saying they have nefarious intentions, but making it too easy to deploy Ghost in a reliable, separated way is introducing competition to their own product.

VPS it is, I guess.

I'm really tired of WordPress, but I have no problem using it. Surprisingly, I can more easily reach my ideal infra setup using WordPress than I can with Ghost. Which is too bad because Ghost's writing experience is much better.

I'd love to see a mainstream content management system come along that really embraces headless delivery in its core. WordPress and Ghost don't even fit this bill. They have "design" and "themes" ingrained into their systems. Imagine deploying "Ghost(lite)," a core piece of the Ghost application that delivers only the admin interface and APIs?

Here's to hoping Ghost gets things updated and makes their project easier to deploy. I'd love to not keep getting ghosted.