Host a Ghost blog on Fly.io for free
On this post, I’ll show you how to host a Ghost instance on Fly.io for free. If you don’t know yet, Fly.io is an application distribution platform that makes it super easy to deploy and scaling your application on multiple regions. Their free plan includes 3 VMs with 256MB RAM and 3GB of persistent storage, which is more than enough for hosting small blog, like the one you are reading right now.
Launching a new application
The first step is signup for a Fly.io account. After that we will need to install flyctl cli program.
Following commands are all the steps necessary for launching a new Ghost blog. We will use the official Ghost Docker image, that uses SQlite3 as database sytem.
$ flyctl auth login
Launch a new Fly.io application. We use
--no-deploy as we want to change some configurations before deploying.
$ mkdir my-blog $ cd my-blog $ flyctl launch --image=ghost:4.36.3-alpine --no-deploy
The previous command will generate the
fly.toml file. In the example, the application name is
red-sun-2406, your application name will be diferrent.
# fly.toml file generated for red-sun-2406 on 2022-02-28T20:21:37+07:00 app = "red-sun-2406" kill_signal = "SIGINT" kill_timeout = 5 processes =  [build] image = "ghost:4.36.3-alpine" [env] [experimental] allowed_public_ports =  auto_rollback = true [[services]] http_checks =  internal_port = 8080 processes = ["app"] protocol = "tcp" script_checks =  [services.concurrency] hard_limit = 25 soft_limit = 20 type = "connections" [[services.ports]] handlers = ["http"] port = 80 [[services.ports]] handlers = ["tls", "http"] port = 443 [[services.tcp_checks]] grace_period = "1s" interval = "15s" restart_limit = 0 timeout = "2s"
Create a volume to store the SQlite3 database. We set to volume size to 3 to stay within the free plan.
flyctl volumes create data --size 3
- set the URL of the blog to
- change internal service port to
2386(Ghost default port)
- mount the data volume
... [env] url = "https://red-sun-2406.fly.dev" ... [[services]] http_checks =  internal_port = 2368 ... [mounts] source="data" destination="/var/lib/ghost/content"
Everything is ready! Time to launch:
flyctl deploy ==> Verifying app config --> Verified app config ==> Building image Searching for image 'ghost:4.36.3-alpine' remotely... image found: img_nk3yvlndg29pome7 ==> Creating release --> release v2 created --> You can detach the terminal anytime without stopping the deployment ==> Monitoring deployment 1 desired, 1 placed, 1 healthy, 0 unhealthy --> v0 deployed successfully
Your Ghost blog is now live at
- Go to
https://<application-name>.fly.dev/ghostand register the admin account
- Fly.io supports custom domain, and it is free!