Hosting a Ghost blog on Fly.io

Fly.io is a platform as a service (PaaS) provider. I discovered it after the Heroku hack earlier this year precipitated many discussions on Hacker News about suitable alternatives.

Among them, I found Render.com and Fly.io to be most suitable (no affiliate links). Railway.app didn’t make the cut because it doesn’t have persistent storage, which imposed certain limitations on how much Ghost could simplify your blogging workflow, e.g. changing themes. I’m sure there are other PaaS cos but these appeared to be the most popular alternatives.

Between Fly.io and Render.com, the former seemed better because it has more locations and has a generous free tier. This said, you’ll find that hosting on either can be much cheaper and come with more peace of mind than with many other options.

So without further ado, here’s a noob’s guide to hosting your Ghost blog on Fly.io.

Install the Fly.io command line interface

Open the Terminal app on your Mac or its counterpart on Windows/Linux. There…

On MacOS

brew install flyctl

On Windows

iwr https://fly.io/install.ps1 -useb | iex

On Linux

curl -L https://fly.io/install.sh | sh

Create a folder for your blog and then move into it

Within the Terminal itself, type:

mkdir <name-of-your-blog>

cd <name-of-your-blog>

Sign up for a Fly.io account

flyctl auth signup

This will open a tab in your default browser and start the sign-up process. Fly.io will ask for your card details. You won’t be charged unless you exceed the limits of the free plan; it requires your card to prevent people from abusing the resources in its free plan. Once you’re done signing up, check your Terminal (or its counterpart), where it should say something like “you’re signed from <your-email-ID>”. If you see it, good.

Launch a Ghost site

flyctl launch --image=ghost:5-alpine --no-deploy

You’ll be asked to choose a region at which to situate your site. Use up and down arrows on your keyboard select your region of choice and hit enter.

This step will generate a TOML file in the folder you’re in, called fly.toml. The contents of this file will dictate what Fly.io needs to do the next time you deploy your site. Become able to edit the file with this command:

nano fly.toml

Some checks

The first line will say app = "<your-app-name>". The name will be something like fiery-shadow-1234. Make sure the url environment variable is equal to "fiery-shadow-1234.fly.dev". Also make sure that internal_port value, under [[services]], is 2368.

One addition

In a new line after the one that reads port = 443, add the following:

 [[services.ports]]
handlers = ["http"]
port = 80

Once you’re done, you can exit with ctrl + x.

Create a volume that will store your site’s database

Fly.io offers up to 3 GB of storage on its free plan. This proved more than sufficient for my blog, which has 10 years’ worth of posts and images. Going ahead, you could host images on Flickr or Cloudinary (both offer sufficiently ample free plans).

flyctl volumes create data --size 2

(‘2’ here refers to the volume’s size in GB.)

You will be asked to choose a region in which to deploy the volume – choose the same one as for your site.

Mount the volume

Open the fly.toml file and check for a section called [mounts]. If there isn’t one, add it.

 [mounts]
source = "data"
destination = "/var/lib/ghost/content"

Exit with ctrl + x.

You’re ready to fly.

Launch

Type the following command and hit enter:

flyctl deploy

The Terminal will show you the progress of your deployment. You can also view it on your new Fly.io dashboard, under ‘Monitoring’ on the left sidebar. Your site will be ready if you see a line that says “1 desired, 1 placed, 1 healthy, 0 unhealthy”. If you see it, open a tab on your browser and navigate to fiery-shadow-1234.fly.dev to see your Ghost site.

If, however, you run into trouble, check out Fly.io’s troubleshooting guide.

Custom domain

To use a custom domain for your site, navigate to ‘Certificates’ on the left sidebar on your Fly.io dashboard and click ‘Add certificate’. Follow the instructions that appear on screen to, first, verify that you own the domain you’re using and, second, add the A and AAAA records – both with your domain registrar.

Say your domain is example.com. Once Fly.io verifies the records, open the fly.toml file and edit the url thus:

url = "example.com"

Exit and redeploy your site:

flyctl deploy

Importing posts

If you, have a sizeable JSON file of your exported Ghost posts, the CMS may fail repeatedly to import them. To get around this, go to ‘Scale’ on your dashboard sidebar and set the “Size name” to shared-cpu-1x and “Memory” to 1GB. You should be able to import the JSON file now.

Once the import is done, you can reset the “Memory” to 256MB, which the free plan offers. You might incur a small charge for this short-lived change (the billing is per-second). You can check Fly.io’s prices on this page. In any case, you should expect to pay lower than if you were to host with Ghost(Pro) or self-host on Digital Ocean. Ghost(Pro) also offers to manage the setup so you can focus on your site, but that’s also the purpose of PaaS.

To have your (forthcoming) posts backed up, you could set up a Zapier integration that copies the contents of each new post – taken from the RSS feed – into a Doc file in a folder in your Google Drive account. Again, Zapier offers this for free (as long as you’re not the sort of furious blogger who publishes three posts a day every day).

A final note

Peace of mind is important, especially if you’re not familiar with the tools you’re using to set up your site. Launching your blog based on instructions from the internet is one thing; putting out a fire when something goes wrong will be something else entirely.

With PaaS, this worry is lower, but providers like Fly.io, Render.com and Railway.app are still oriented at developers, and so is their support team and documentation. This is to say that even if they help you, they will expect some level of technical chops from you.

If you’re confident that you can manage, go ahead because there are significant advantages. One of them, for me personally, is that with regular backups I have a relatively risk-free environment in which to learn these things, and I believe that this knowledge will serve me well in the longer term.

Root Privileges itself will continue to be a WordPress site hosted in a more ‘conventional’ way because it’s too important for me to be experimenting with at this point. But I’ll be changing my publishing workflow to be Fly + Ghost first, meaning I’ll be publishing posts there first and, more importantly, regularly thinking about how I can improve my experience there.

Sources

I compiled this guide based on instructions on the following pages:

The authors of the latter two guides have put together nearly complete instructions. But each of their guides taken separately didn’t work for me whereas a combination did. If my guide didn’t work for you, you can also check out their guides and where they’ve deviated.

I should also mention that I discovered that a Ghost blog could be hosted on Fly.io after finding that Anil Dash’s blog is.