2 min read

Guide: Ghost blog on Fly.io using MySQL (part 2)

Guide: Ghost blog on Fly.io using MySQL (part 2)
Ghost Blog on Fly.io

This part 2 in a series about using Ghost on Fly.io. In part 1, we setup a Ghost blog with SQLite as the database. In this post we'll be setting up a MySQL database and configuring our Ghost app to use it.

By the end we'll have a system that looks like:

Fly Machine running Ghost connected to a Machine running MySQL

Step 1: Create a MySQL database

The details on how to create a MySQL database are here: https://fly.io/docs/app-guides/mysql-on-fly/

There are some things you should keep in mind:

  • The MySQL database will run on a single VM. If that VM crashes then you'll have to start it again.
  • This is NOT managed MySQL. This is a self-hosted MySQL image on a VM. If you need something resilient, then there are plenty of services out there.

Before configuring Ghost, verify that your MySQL database works

The way I do that is to ssh into the machine running the MySQL image, logging into the database and confirming it works:

# SSH into the app
fly ssh console -a <mysql app name>

# From inside the vm run:
mysql <my_database_name> -u root -p
Enter password:

# use the password you set for MYSQL_ROOT_PASSWORD

# run a command like "SHOW DATABASES" just to see that things work
mysql> SHOW DATABASES;

Step 2: Configure Ghost to use MySQL

The next steps are to update you apps fly.toml and set some secrets.

Update the fly.toml with some Ghost config

In the last post we configured the fly.toml to use a SQLite database. We'll modify the env database bit to look like the following:

# fly.toml

app = <ghost app name>
primary_region = 'sea'

[env]
  ##### MYSQL Database
  database__client = 'mysql'
  # database__connection__user = '' # set as secret
  # database__connection__password = '' # set as secret
  database__connection__host = '<mysql app name>.internal'
  database__connection__port = '3306'
  database__connection__database = '<database name>'
  database__connection__useSSL = 'false'
  database__useSSL = 'false'

...
💡
Note: database__connection__host = '<mysql app name>.internal' is using Fly's internal private network. Each app in your organization is visible to each other over a private network (unless you set it otherwise). You can read more about it here: https://fly.io/docs/networking/private-networking/

Set some secrets:

Then we need to set a few secrets on our Ghost app.

fly secrets set --stage database__connection__user=root database__connection__password=[[MYSQL_ROOT_PASSWORD]] -a <ghost app name>

This will set secrets on your app for the next deploy. I'm using the root user and the root password (that's what worked for me).


Final Example:

So for example, let's say I created an app called my-ghost-blog-db and I created a database in it called my_db . Then my fly.toml might look like:

# fly.toml

app = 'my-ghost-blog'
primary_region = 'sea'

[build]
  image = 'ghost:5.81.0'

[env]
  ##### MYSQL Database
  database__client = 'mysql'
  # database__connection__user = '' # set as secret
  # database__connection__password = '' # set as secret
  database__connection__host = 'my-ghost-blog-db.internal'
  database__connection__port = '3306'
  database__connection__database = 'my_db'
  database__connection__useSSL = 'false'
  database__useSSL = 'false'
  url = 'https://my-ghost-blog.fly.dev'

[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

And I'd run something like:

fly secrets set --stage database__connection__user=root database__connection__password=mysecurepassword1234 -a my-ghost-blog

Deploy and check that it works

Run fly deploy for your Ghost app and run fly logs in a separate app to check that it's connecting to the database properly.