Fly.io is a cloud platform for hosting and deploying applications. Its simplicity, performance and affordable pricing make it a no-brainer choice for startups and works very well as a replacement for Heroku. In this post we will show how to deploy a Buffalo application to Fly.io.

Initializing the Buffalo application

Initializing a Buffalo application implies running the new command on the Buffalo cli. To make things simpler we will create a SQLite application

> buffalo new --db-type sqlite3 flyapp

Which will generate the base source for our application in the flyapp folder.

DEBU[2022-06-11T10:27:23-05:00] Step: 5d32fdc6
DEBU[2022-06-11T10:27:23-05:00] Chdir: /Users/users/code/wawandco/flyapp
...

INFO[2022-06-11T10:28:05-05:00] Congratulations! Your application, flyapp, has been successfully generated!
INFO[2022-06-11T10:28:05-05:00] You can find your new application at: /Users/user/code/wawandco/flyapp
INFO[2022-06-11T10:28:05-05:00] Please read the README.md file in your new application for next steps on running your application.

From this point we can start our application locally with the buffalo dev command. Which is ok but we talked about deploying our application to Fly.io, So let’s do that.

Configuring Fly.io

Now that our application has been created we should setup a few things to run our application on Fly.io.

As we mentioned before, we have taken the route of deploying a SQLite application to Fly.io. Which means that our database will live in a file. To keep that file (and our application data) safe across deployments we will need to use a volume that will be mounted to the Fly.io container.

Installing the CLI

First step is to install the Fly.io CLI. If (like me) you’re on a Mac you can use Homebrew to install it with the following command:

> brew install flyctl

Other than that you can use the install script on the Fly.io website.

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

Or just refer to the Fly.io documentation for more information.

Authenticating

Once you have the CLI installed you can authenticate to Fly.io. This is done by running the following command:

> fly auth login

Which will open a browser window and ask you to authenticate to Fly.io. With that we should be all-set to deploy our application.

Initializing the Fly.io application

Creating the Application

After all of the configuration steps we can initialize our application. This is done by running the following command:

> fly create flyapp-demo
New app created: flyapp-demo

Which will create the application in our Fly.io personal organization.

Creating the volume

As we mentioned we need to create a volume that will store our data. This is done by running the following command:

> fly volumes create flyappdata -a flyapp-demo

It will ask for the region where that volume should live. In this case we will use the same region as the application: Miami, Florida (US) (mia).

Adding fly.toml

In our repository we will need to have a file (fly.toml) which will contain the configuration for our application, the Fly.io platform will read this file for instructions.

In our codebase we should create a fly.toml file with the following content:

app = "flyapp-demo"

kill_signal = "SIGINT"
kill_timeout = 1
processes = []

[deploy]
  strategy = "rolling"

[env]
  GO_ENV = "production"

[experimental]
  allowed_public_ports = []
  auto_rollback = true

[mounts]
  source = "flyappdata"
  destination = "/data"

[[services]]
  http_checks = []
  internal_port = 3000
  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 = 6
    timeout = "2s"

Which establishes that how our application will be deployed and how the volume will be mounted.

Secrets

Buffalo applications require one secret: SESSION_SECRET when running in production mode. While we could have added this to the fly.toml file we will instead create a secret in our Fly.io account.

> fly secrets set SESSION_SECRET=[our secret] -a flyapp-demo

That way our app will have SESSION_SECRET set in the environment. The secrets space can be used for other things such as API keys or credentials that we don’t want to put in our git repository.

Configuring the Buffalo application

Now that the Fly.io application is created we need to tweak our database configuration to store our data in the volume.

We should set the database.yml file to the following content:

---
...

production:
  dialect: "sqlite3"
  database: /data/database.db

Remember we set our volume to /data so we need to make sure that the database.db file is created/read from the volume.

Deploying

Once this is set we can run the fly deploy command to deploy our application.

> fly deploy -a flyapp-demo
...
--> v1 deployed successfully

This command will build an image from the Dockerfile and deploy that image to the Fly.io platform. One important thing to mention is that Fly.io does not exactly deploy Docker images but micro-vms, that said, it seems to be able to receive Docker images and deploy these.

Wrapping up

After the deploy command finished we should be able to see our application running in the https://flyapp-demo.fly.dev URL. There are a couple of topics we didn’t cover in this tutorial like CI and data management for SQLite databases. we could cover topics like Litestream in future posts but for now we will just leave that as an exercise for the reader.