Ghost CMS

Easy, right? Just spin this thing up, do some basic configuration (DNS, SSL, mail delivery, theme, etc), and I'm set?

Ghost CMS
Photo by Tandem X Visuals / Unsplash

Talking about the CMS used to make this website might sound boring, but I'd like to quickly go over what I had to do in order to get this blog functioning. It turned out to be a bit more complicated than I anticipated.

Ghost?

If you're somehow entirely unaware of what Ghost is- it's a Content Management System. It powers this website and gives me a variety of easy to use editing/publication tools. I chose it because it's nice looking, straightforward to use, relatively few frills, and is not WordPress. Having dealt with the aftermath of outdated/unmaintained WordPress plugins in a professional capacity, I'd rather not invite that into my life.

Initial Setup

Because I'm lazy and don't feel like searching "cheapest cloud providers 2025", I've generally stuck with AWS. Yes, there are providers out there with much more intuitive interfaces, and yes, far cheaper ones- but Lightsail is a pretty handy way to stand up simple stuff like this, so that's what I went with. There's even a handy preconfigured image for Ghost!

So that's what I went with. Easy, right? Just spin this thing up, do some basic configuration (DNS, SSL, mail delivery, theme, etc), and I'm set?

What I ran into

As it turns out, the preconfigured image that AWS allows you to select is, like most others in AWS, a Bitnami stack. This complicates things, since it's a hardened image with some extra tools and a semi-contrived configuration. Somehow, in all of this, I managed to break the "Design and branding" preview iframe. This meant that I wouldn't be able to preview edits I make to this site before publishing them.

The first thing that I did to diagnose this issue was good ol' inspect element. I checked the console, and immediately saw "mixed content" warnings. Turns out, the preview was trying to load assets over http instead of https- which my browser rightfully refused to load. After reading through some bitnami and ghost documentation I eventually managed to hunt down where the problem is- ghost-https-vhost.conf. As it turns out, Ghost wasn't actually configured to serve my domain. I only determined this after wrestling a bit with Apache reverse-proxy settings.

More specifically, this file was located at /opt/bitnami/apache/conf/vhosts/ghost-https-vhost.conf, at least in this case. The first few lines, before I edited them, were configured as follows:
<VirtualHost 127.0.0.1:443 _default_:443>
ServerName www.example.com
ServerAlias *

Which, as you may have noticed, are a little generic. Turns out, it was as simple as actually configuring it:
<VirtualHost *:443>
ServerName zachmorse.com
ServerAlias www.zachmorse.com

I'm not entirely certain what caused this, but I suspect it's because I decided to use the bncert-tool and edit ghost's canonical URL manually instead of using ghost config url . I cannot be bothered to test that, because my stuff's working.

Hopefully if someone in the future runs into this issue, they'll find this. I'd also like to point out that updating ghost without spinning up a new VM and migrating over is not simple when utilizing this bitnami stack. All told, I may ditch this bitnami and go with a plain Ubuntu instance when it's time to upgrade. We'll see.