Deploying a React Ruby app on Fly.io if you’ve never deployed a thing in your life

After this, you’ll be deploying all over the place

We’re starting a fun little project with some friends, and we want it to be available for people to check out when we’re done. With Heroku retiring their free tier, we went looking for a good alternative in 2023. Since our project will be in React.js , Ruby on Rails, and Postgres, we wanted a solution that would explicitly support these technologies out of the box.

Fly is a platform for running full stack apps and databases close to your users. We’ve been hammering on this thing since 2017, and we think it’s pretty great. 

Fly.io fits the bill, and has some helpful documentation. I found that I relied on outside knowledge and experience at a couple of key points, so if you’ve never done deployments before feel free to check here to keep things moving smoothly.

Signing up for an account

SSO

Fly.io supports single sign-on with Github, which is convenient because then it will also offer to inhale your app from one of your repositories. I created an organization to go with the GitHub organization our group has, and will be assigning the app to the organization.

Payment info

Even though there is a free tier, they do require a payment card on file because payment is calculated based on usage. If your app stays within the free tier, you shouldn’t be charged, according to their documentation. If your app gets a lot of traffic or uses a lot of resources, it will then automatically be treated as a paid app and you should start getting charged. I thought their pricing was pretty fair for what you get, so I signed up.

Install flyctl

Their new web terminal is pretty cool, but I found I was more comfortable using their tried and true flyctl (fly control) command line tool. I know that new developers are sometimes less comfortable with the command line, so please take a deep breath and tell yourself that you can do this. Deployment is a lot of command line, and fly.io is pretty hands-off as far as tasks go. A significant portion of steps are automated for you with this tool.

Our entire team is using Mac, so we will all simply brew install flyctl. There are instructions for installing flyctl on the platform of your preference in their documentation.

Now that you have it installed, we’ll get back to this.

Git init, create-react-app, and however you’re starting your app

Flatiron School, where my friends and I went to programming class last year, has a walkthrough we like to follow for setting up React-Rails apps.

Once you have your empty app ready to go and your repository is synced up, we can come back to fly and get deploying.

Deploying

Their documentation on deploying is fairly comprehensive, but there were two main gotchas that I will point out that I think are most likely to trip up new devs as they take their forays into devops.

Start by fly auth login if you haven’t yet, so that flyctl is authorized and logged in with your account.

Next, run fly launch . This is a script that will ask you some basic questions about your deployment. If you have a personal and organization, you can use the arrow keys to choose where the app lives. You may also choose which region’s datacenter to host (I chose Virginia as I am in the United States). The first gotcha is, if fly launch doesn’t work, chances are you need to bundle install.

10:43 plant-watering-app % fly launch
Creating app in /Users/ashton/Development/plant-watering-app
Scanning source code
Detected a Rails app
? Choose an app name (leave blank to generate one): 
? Select Organization:  [Use arrows to move, type to filter]
  Ashton MacKenzie (personal)
> bromeliad-studios (bromeliad-studios)
10:44 plant-watering-app % fly launch
Creating app in /Users/ashton/Development/plant-watering-app
Scanning source code
Detected a Rails app
? Choose an app name (leave blank to generate one): plant-watering
? Select Organization: bromeliad-studios (bromeliad-studios)
? Choose a region for deployment: Ashburn, Virginia (US) (iad)
Created app plant-watering in organization bromeliad-studios
Admin URL: https://fly.io/apps/plant-watering
Hostname: plant-watering.fly.dev
Set secrets on plant-watering: SECRET_KEY_BASE
? Would you like to set up a Postgresql database now? Yes
? Select configuration: Development - Single node, 1x shared CPU, 256MB RAM, 1GB disk
Creating postgres cluster in organization bromeliad-studios
Creating app...
Setting secrets on app plant-watering-db...
Provisioning 1 of 1 machines with image flyio/postgres:14.6@sha256:9cfb3fafcc1b9bc2df7c901d2ae4a81e83ba224bfe79b11e4dc11bb1838db46e
Waiting for machine to start...
Machine 6e82279c241587 is created
==> Monitoring health checks
  Waiting for 6e82279c241587 to become healthy (started, 3/3)

Postgres cluster plant-watering-db created
{...}
Save your credentials in a secure place -- you won't be able to see them again!

Connect to postgres
Any app within the bromeliad-studios organization can connect to this Postgres using the above connection string

Now that you've set up Postgres, here's what you need to understand: https://fly.io/docs/postgres/getting-started/what-you-should-know/
Checking for existing attachments
Registering attachment
Creating database
Creating user

Postgres cluster plant-watering-db is now attached to plant-watering
The following secret was added to plant-watering:
  DATABASE_URL=postgres://plant_watering:RaeBvlef2ND8i72@top2.nearest.of.plant-watering-db.internal:5432/plant_watering?sslmode=disable
Postgres cluster plant-watering-db is now attached to plant-watering
? Would you like to set up an Upstash Redis database now? Yes
? Select an Upstash Redis plan Free: 100 MB Max Data Size

Your Upstash Redis database plant-watering-redis is ready.
Apps in the bromeliad-studios org can connect to at redis://default:a831f64ba41e4e879f7fedc2e70c2bbe@fly-plant-watering-redis.upstash.io
If you have redis-cli installed, use fly redis connect to connect to your database.

Redis database plant-watering-redis is set on plant-watering as the REDIS_URL environment variable
? Create .dockerignore from 2 .gitignore files? Yes
Created /Users/ashton/Development/plant-watering-app/.dockerignore from 2 .gitignore files.
Wrote config file fly.toml

Your Rails app is prepared for deployment.

Before proceeding, please review the posted Rails FAQ:
https://fly.io/docs/rails/getting-started/dockerfiles/.

Once ready: run 'fly deploy' to deploy your Rails app.

The second gotcha is that you can’t just run fly deploy, you need to generate a Dockerfile first. Docker is a whole thing in itself, but the way I’ll summarize it for now is that it’s a lot like a recipe to make a computer. (There’s a lot more to it than that, but….). Developers like it because instead of “works on my machine”, and closing each others’ issues, you can essentially mail them your machine and now they get to look at why it doesn’t work. Or they can mail you the machine it does work on and tell you to just use this.

One of the best things to remember in any operational environment, and that includes devops, is that the chances are very low that you have a truly novel problem. What I’m saying is that there is a generator for docker files.

And in order to get the docker file that we want on Fly, we will want to use the PostgreSQL and redis options as shown:

11:20 plant-watering-app % bin/rails generate dockerfile --postgresql --redis

Once you run this command, your terminal will fill up with a lot of output as the dockerfile is read and a virtual machine is provisioned for your app. If you’re still having trouble, check out their community forums and be prepared to provide versions of the tools you’re using as well as the contents of configuration files. Check out existing posts to get an idea of what people ask for and include that from the beginning, or see if your error has already been posted about and discussed.

When the terminal is done with its output, if everything went well you should be able to navigate to your app on Fly.io and see it in production. Yay!

Here is ours: https://plant-watering.fly.dev/

Deploying an existing app (Updated)

There are some additional gotchas I noticed when I deployed an existing app to Fly.io.

Firstly, I would get annoying error messages like these when trying to generate a Dockerfile:

/Users/ashton/.rvm/gems/ruby-2.7.4/gems/dockerfile-rails-1.2.3/lib/generators/dockerfile_generator.rb:704:in `block in api_client_dir': undefined method `load_file' for JSON:Module (NoMethodError)

I solved this issue by using rvm to change to a later version of Ruby, editing my Gemfile to allow Ruby versions of 2.7.4 or greater, and running bundle update. This allowed me to build my Dockerfile. I also had to edit config/database.yml to provide the new postgres connection information for the production environment, as I had previously had different postgres connection information in production. The logs will not tell you specifically that this is the issue, or they will, but that requires you to understand that the ActiveRecord connection issue is a you problem and not an it problem. Here’s an example of what it’s going to look like:

 2023-03-01T14:38:29.305 app[dddb100b] iad [info] /rails/vendor/bundle/ruby/3.0.0/gems/railties-7.0.4.2/lib/rails/commands.rb:18:in `<main>'

2023-03-01T14:38:29.305 app[dddb100b] iad [info] /rails/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.16.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'

2023-03-01T14:38:29.305 app[dddb100b] iad [info] Caused by:

2023-03-01T14:38:29.305 app[dddb100b] iad [info] PG::ConnectionBad: could not connect to server: No such file or directory

2023-03-01T14:38:29.305 app[dddb100b] iad [info] Is the server running locally and accepting

2023-03-01T14:38:29.305 app[dddb100b] iad [info] connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

2023-03-01T14:38:29.305 app[dddb100b] iad [info] /rails/vendor/bundle/ruby/3.0.0/gems/pg-1.4.6/lib/pg/connection.rb:756:in `connect_start' 

Once I provided it with the Fly.io postgres information, everything was able to finish deploying normally and I now have the pre-alpha version of The Guild of the Magi live for people to play with.

Thank you for reading. Please let me know if there are any clarifications I can make or further questions I can answer either down in the comments, on LinkedIn, or hit me up on Mastodon.

Related Posts