How to FLY.`io`

Nimish Tolasaria
5 min readJan 20, 2023

--

I am relatively new to the world of software development and at the time of writing this, enrolled in the Core Curriculum of Launch School. Infact, my experience at Launch School is the reason why I am writing rather trying to write this article.

The first time when I could actually develop something interactive beyond the Command Line Interface was indeed an experience that will go down as one of the important `firsts` of my life.

Next step was to deploy it to a platform so that it can exists on the world wide web with the potential to be accessed anywhere across the globe. The common choice here is Heroku. However, due to some technical issues which is beyond the scope of this article It was not possible for me to deploy my educational project to Heroku. I tried out fly.io as an alternative and gave myself a few hours of dedicated time to figure it out. My thought was, if it takes more than the said amount of time, I will move on without deploying and not be trapped in yet another rabbit hole.

To my surprise, the experience was rather breezy and I could manage to do it less than an hour or so. Kudos, to Launch School for not only teaching a new skill but deconstructing and breaking down every step of learning in a meaningful way. Here, again I was encouraged by one of the senior TAs at Launch School to try and write down my experience through this step, i.e deploying a Database Backed Web-Application to fly.io. More specifically a Ruby application connected to a PostgreSQL database. Although, the app being deployed here was a guided one in the Launch School curriculum.

Steps taken to deploy to fly.io :

First, step was to create an account on fly.io and get the command line utility installed and running. For a mac this step is as easy as:

brew install flytcl

Next, up was trying to figure out if the application was ready for deployment. This involved the usual steps:

  • checking if the application is working as desired in the local environment
  • updating the Gemfile appropriately. In this case specifically including the gem "puma" which will be the web server of choice
  • setting the version of Ruby recommended by fly.io which at the time of writing this was 3.1.3
  • committing and pushing all the changes to my github repo

Next, was creating the Procfile just as was done for Heroku. The content of my Procfile looked like below:

web: bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}

Now, comes the actual deployment process.

First, run the following command from the project directory in the command line

flyctl launch
Scanning source code
Detected a Ruby app
Using the following build configuration:
Builder: heroku/buildpacks:20
? Choose an app name (leave blank to generate one): <enter-your-app-name>

Next, is chosing a region for deployment. Here, I chose Singapore, Singapore (sin) as it is close to my location.

Next will come the prompt:

? Would you like to set up a Postgresql database now? (y/N) 

Type y and press return / enter. The prompt for the selecting the configuration of the computer that will run the database will be displayed. Here, I chose Development — Single Node, 1x shared CPU, 256MB RAM, 1GB disk.

This starts creating the postgres cluster and also creating the app. After the setup process is done and the machine is started after passing the checks, a prompt will be displayed showing the credentials of the postgres cluster that has been created. And I followed what they warned me:

Save your credentials in a secure place — you won’t be able to see them again!

Also, you get the message that the following DATABASE_URL has been set to the created postgres cluster . That is, the created postgres cluster is now attached to the application.

Next, will be a prompt asking:

? Would you like to set up an Upstash Redis database now? (y/N) 

I selected the option N here not even knowing what an Upstash Redis database is.

Next is the prompt:

? Would you like to deploy now? (y/N) 

And, here I did enter the option y which started the process of deploying the app with a series of DOWNLOADING / DETECTING / ANALYZING / BUILDING / EXPORTING / PUSHING.

Finally after waiting a few minutes the following message was displayed:

--> v0 deployed successfully

During this process a file called fly.toml is created in the project directory which is a configuration file for fly.io. It contained the following information:

app = <app_name>
kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[build]
builder = "heroku/buildpacks:20"

[env]
PORT = "8080"

[experimental]
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]]
force_https = true
handlers = ["http"]
port = 80

[[services.ports]]
handlers = ["tls", "http"]
port = 443

[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"

Here, I thought, that somehow magically, the app is deployed and running without realising that I am yet to set the database up. The app was running on my local database while in develpoment all this while and I have not yet set up the freshly created postgres cluster.

Excited, I typed in the URL to my freshly deployed app in the browser ony to be greated with a message in bold:

Internal Server Error

That’s when I went through more docs on fly.io and tried to figure out how to go about setting up and connecting to the database. I came across the command flyctl postgres. It can be used as follows to connect to the database:

flyctl postgres connect -a <database_name>

And, finally I was inside an interface, that we were made familiar and comfortable with at Launch School

psql (14.6 (Debian 14.6-1.pgdg110+1))
Type "help" for help.

postgres=#

The psql console. This can be easily used to created the tables required for the application. Though, there is a way to create your schema using an SQL file and which seems like the better way of doing things, it involved some configuration and I took the path of creating the tables manually using the simple DDL statements learnt before the good old CREATE TABLE. Also metacommands like \d , \dt etc. can be used to verify if the schema is created as required by the application.

After creating the tables I tried to access the URL of the application once again and was greeted with the same Internal Server Error.

After some troubleshooting, I finally figured out that the DATABASE_URL needs to be set again using the command flyctl secrets. Probably, the process of setting up the database manually caused this. This can be done easily as follows:

lyctl secrets set DATABASE_URL=<Connection String>

Connection String was provided while the credentials to the created postgres cluster was displayed and and prompted to be saved securely. This starts another round of deployment and in a few moments the following message displayed:

1 desired, 1 placed, 1 healthy, 0 unhealthy [health checks: 1 total, 1 passing]
--> v1 deployed successfully

And just like, that the application is up and running!

And though the title of this article is rather overstated, sometimes small steps can feel rewarding enough. Such is the joy of finding happiness in small things.

--

--