3 min read

Guide: Self hosting a Ghost blog on Fly.io (Part 1)

Create a Ghost blog on Fly.io, backed by SQLite
Guide: Self hosting a Ghost blog on Fly.io (Part 1)
Ghost Blog on Fly.io

This post explains how to get a Ghost blog set up on Fly.io using SQLite as the database. Ghost is a blog platform that is also available open source and can be self hosted. Out of the box you get a full CMS, themes, and other goodies.

User-uploaded Image
Ghost Blog on Fly.io editor

Ghost on Fly with SQLite

Ghost actually uses a MySQL database by default. It used to be SQLite, but it's no longer maintained. That's okay though because SQLite still works! The choice to use SQLite is for the simplicity of getting up and running.

Note: I'll be following up with posts regarding using MySQL and adding a S3-based CDN with Tigris Global Object Storage.

By the end of this post we'll have a Ghost blog running on a Fly Machine:

  • a Ghost Blog server (nodejs server)
  • a Volume attached to our machine for persisting files between deploys

Here's what that looks like:

Fly Machine (VM) running a Ghost Blog

Deploying Ghost on Fly

Deploying a Ghost Blog on Fly is easy. I'm going to assume that you've signed up, installed the CLI, and are ready to go.

  1. Create an empty folder for your project
mkdir my_app
cd my_app
  1. Create an app

Create an app using:

fly apps create --name <app-name>
  1. Create a Volume

We'll create a volume so that we have persistent storage between deploys.

fly volume create <volume_name> -a <app-name>
Remember the region you create a volume in. When you deploy a machine, it will need to be in the same region as your volume. This is a requirement to use volumes.

Here's an example:

fly volume create nathan_tester_volume -a nathan-tester



Warning! Every volume is pinned to a specific physical host. You should create two or more volumes per application to avoid downtime. Learn more at https://fly.io/docs/reference/volumes/
? Do you still want to use the volumes feature? Yes
Some regions require a Launch plan or higher (bom, fra).
See https://fly.io/plans to set up a plan.

? Select region: Hong Kong, Hong Kong (hkg)
                  ID: vol_vppw2zm8kwz3xzkv
                Name: nathan_tester_volume
                 App: nathan-tester
              Region: hkg
                Zone: 644c
             Size GB: 1
           Encrypted: true
          Created at: 14 Jul 24 09:30 UTC
  Snapshot retention: 5
 Scheduled snapshots: true
💡
If you skipped this step, but still remembered to set a "mount" section in your fly.toml (next step), then fly deploy will detect the mount and create a volume for you automatically.
  1. Create a fly.toml file

You can either run fly launch --no-deploy, which should generate a fly.toml file or just make one yourself:

# fly.toml app configuration file generated for my-ghost-blog
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = '<app name>'
primary_region = 'hkg'

[build]
  image = 'ghost:5.81.0'

[env]
  database__client = 'sqlite3'
  database__connection__filename = 'content/data/ghost.db'
  database__debug = 'false'
  database__useNullAsDefault = 'true'
  url = 'https://<app name>.fly.dev'

[[mounts]]
  source = '<volume name>'
  destination = '/var/lib/ghost/content'

[http_service]
  internal_port = 2368
  force_https = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

[[vm]]
  memory = '1gb'
  cpu_kind = 'shared'
  cpus = 1

👋 There are couple things you'll want to change here:

  • app name: the app name should be what you set in the step #1, but if you skipped that step then you can set it here and fly launch will pick it up anyways.
  • url: likewise the url needs to have the format https://[[app name]].fly.dev so make sure they match
  • vm memory: the above configuration assumes VM memory of 1GB, but you can adjust it accordingly
  • mounts: don't forget to set the mount source to the name of your volume from step #3.
  1. Run fly launch or fly deploy

At this point you should be set and running fly deploy will simply deploy your app.

Alternatively, running fly launch --no-deploy will give you a chance to adjust some of the parameters before deploying.

  1. Start blogging!

At this point you can visit https://[app name]].fly.dev/ghost to get started.

Good luck!

Tips if something isn't working

If you're not able to deploy correctly, it's likely that something is going wrong at the database layer. Using fly logs is your best bet to double check.