Getting Started
Getting an application running on Fly.io is essentially working out how to package it as a deployable image and attach it to a database. Once packaged it can be deployed to the Fly.io global application platform.
In this guide we’ll learn how to deploy an Elixir Phoenix application on Fly.io and connect it to a PostgreSQL database.
NOTE: This guide is for apps generated on Phoenix 1.6.3 or later, where deployment is streamlined significantly. If you’re on an earlier version and can’t upgrade, check out our legacy deployment guide.
We’ll be using the standard web application generated by the Elixir Phoenix Framework.
Preparation
If you don’t already have Elixir and Phoenix installed, get them set up before starting this guide. When you install Elixir, the Mix build tool ships with it.
You can install the Phoenix project generator phx.new
from a Hex package as follows:
mix archive.install hex phx_new
Generate the app and deploy with Postgres
If you just want to see how Fly.io deployment works, this is the section to focus on. Here we’ll bootstrap the app and deploy it with a Postgres database.
First, install flyctl, your Fly app command center, and sign up to Fly if you haven’t already.
Now let’s generate a shiny, new Phoenix app:
mix phx.new hello_elixir
The output ends with instructions for configuring the database and starting the app manually. The Fly.io launcher is going to take care of this, so we can ignore them.
When we run fly launch
from the newly-created project directory, the launcher will:
- Ask you to select a deployment region
- Set secrets required by Phoenix (
SECRET_KEY_BASE
, for example) - Run the Phoenix deployment setup task
- Optionally setup a Postgres instance in your selected region
- Deploy the application in your selected region
cd hello_elixir
fly launch
Creating app in /Users/me/hello_elixir
Scanning source code
Detected a Phoenix app
? App Name (leave blank to use an auto-generated name): hello_elixir
? Select organization: flyio (flyio)
? Select region: mad (Madrid, Spain)
Created app hello_elixir in organization soupedup
Set secrets on hello_elixir: SECRET_KEY_BASE
Installing dependencies
Running Docker release generator
Wrote config file fly.toml
? Would you like to setup a Postgres database now? Yes
Postgres cluster hello_elixir-db created
Username: postgres
Password: <password>
Hostname: hello_elixir-db.internal
Proxy Port: 5432
PG Port: 5433
Save your credentials in a secure place, you will not be able to see them again!
Monitoring Deployment
1 desired, 1 placed, 1 healthy, 0 unhealthy [health checks: 2 total, 2 passing]
--> v0 deployed successfully
Connect to postgres
Any app within the flyio organization can connect to postgres using the above credentials and the hostname "hello_elixir-db.internal."
For example: postgres://postgres:password@hello_elixir-db.internal:5432
See the postgres docs for more information on next steps, managing postgres, connecting from outside fly: https://fly.io/docs/reference/postgres/
Postgres cluster hello_elixir-db is now attached to hello_elixir
Would you like to deploy now? Yes
Deploying hello_elixir
==> Validating app configuration
--> Validating app configuration done
Services
TCP 80/443 ⇢ 8080
Remote builder fly-builder-little-glitter-8329 ready
...
That’s it! Run fly apps open
to see your deployed app in action.
Try a few other commands:
fly logs
- Tail your application logsfly status
- App deployment detailsfly status -a hello_elixir-db
- Database deployment detailsfly deploy
- Deploy the application after making changes
To recap the fly launch
command detected that we are using Phoenix, setup a Fly app, created a Postgres instance and configured it for us, updated our Dockerfile, and created special modules and scripts to run ecto migrations for us!
Storing secrets on Fly.io
You may also have some secrets you’d like set on your app.
Use fly secrets
to configure those.
fly secrets set MY_SECRET_KEY=my_secret_value
Deploying again
When you want to deploy changes to your application, use fly deploy
.
fly deploy
Note: On Apple Silicon (M1) computers, docker runs cross platform builds using qemu which might not always work. If you get a segmentation fault error like the following:
=> [build 7/17] RUN mix deps.get --only
=> => # qemu: uncaught target signal 11 (Segmentation fault) - core dumped
You can use fly’s remote builder by adding the --remote-only
flag:
fly deploy --remote-only
You can always check on the status of a deploy
fly status
Check your app logs
fly logs
If everything looks good, open your app on Fly.io!
fly apps open
Important IPv6 settings
The flyctl
command attempts to modify your project’s Dockerfile and append the following lines:
# Appended by flyctl
ENV ECTO_IPV6 true
ENV ERL_AFLAGS "-proto_dist inet6_tcp"
If you customized your Dockerfile or launched without the Dockerfile, this setting may not have been set for you. These values are important and enable your Elixir app to work smoothly in Fly’s private IPv6 network.
Check for this If you encounter network related errors like this:
Could not contact remote node my-app@fdaa:0:31d4:a5b:9d36:7c1e:f284:2, reason: :nodedown. Aborting...
What’s Next?
Next up, IEx into Your Running App!
Additional resources