Fly.io
Fly.io is a platform for running containerized apps and microservices on servers around the world. It makes deploying and managing your apps straightforward with minimal setup.
Prerequisites
To deploy to Fly.io using Wasp CLI:
-
Create a Fly.io account
-
Fly requires you to add a payment method before you can deploy more than two Fly apps. To deploy a Wasp app, you need two Fly apps: your app and its database.
-
Install the
flyCLI on your machine.
Deploying
Using the Wasp CLI, you can easily deploy a new app to Fly.io with just a single command:
wasp deploy fly launch my-wasp-app dfw
Please do not CTRL-C or exit your terminal while the commands are running.
Two things to keep in mind:
-
Your app name (for example
my-wasp-app) must be unique across all of Fly or deployment will fail. -
If your account is a member of more than one organization on Fly.io, you will need to specify under which one you want to execute the command. To do that, provide an additional
--org <org-slug>option. You can find out the names (slugs) of your organizations by runningfly orgs list.
The launch command uses the app basename my-wasp-app and deploy it to the dfw region (dfw is short for Dallas, Texas (US)). Read more about Fly.io regions here.
The basename is used to name your app and its database, resulting in two apps in your Fly dashboard:
my-wasp-app-servermy-wasp-app-db
Your app keeps the -server suffix for historical reasons: it used to be one
of two apps, the one serving your API. It now serves your whole app, pages
included.
You'll notice that Wasp creates a new file in your project root directory:
fly-server.toml
You should include this file in your version control so that you can deploy your app with a single command in the future.
Wasp used to deploy your pages as a Fly app of their own, called my-wasp-app-client. Your app now serves its own pages, so nothing is deployed to that app anymore.
Once your users are on your app's URL, you can destroy it and delete its TOML file:
fly apps destroy my-wasp-app-client
rm fly-client.toml
Wasp reminds you about this whenever it finds a fly-client.toml in your project.
When you run the launch command, Wasp CLI knows what your Wasp app needs to run, so it sets up the required environment variables for it:
WASP_SERVER_URLandWASP_WEB_CLIENT_URL, both set to your app's own URL, since one app serves both your pages and your API.DATABASE_URLwhich is required to connect your app to the database.JWT_SECRETwhich is required for authentication to work.
If your app requires any additional environment variables, use the wasp deploy fly cmd secrets set command. Read more in the API Reference section.
If you want to automate the deployment process, check out the CI/CD Deployment page to re-deploy your app on each commit as part of your CI/CD pipeline.
Using a Custom Domain For Your App
Setting up a custom domain is a three-step process:
- You need to add your domain to your Fly app. You can do this by running:
wasp deploy fly cmd --context server certs create mycoolapp.com
Make sure to replace mycoolapp.com with your domain in all of the commands mentioned in this section.
The server context is your app. Read more about it in the cmd API
reference.
This command will output the instructions to add the DNS records to your domain. It will look something like this:
You can direct traffic to mycoolapp.com by:
1: Adding an A record to your DNS service which reads
A @ 66.241.1XX.154
You can validate your ownership of mycoolapp.com by:
2: Adding an AAAA record to your DNS service which reads:
AAAA @ 2a09:82XX:1::1:ff40
-
You need to add the DNS records for your domain:
This will depend on your domain provider, but it should be a matter of adding an A record for
@and an AAAA record for@with the values provided by the previous command. -
You need to tell your app about its new URL, by setting it as the
WASP_SERVER_URLandWASP_WEB_CLIENT_URLenvironment variables:
wasp deploy fly cmd --context server secrets set WASP_SERVER_URL=https://mycoolapp.com WASP_WEB_CLIENT_URL=https://mycoolapp.com
Wasp builds links from these: the ones in the emails your app sends, and the
ones it redirects OAuth logins to. WASP_WEB_CLIENT_URL defaults to
WASP_SERVER_URL, but setup sets both, so you update both.
That's it, your app should be available at https://mycoolapp.com!
Adding a www Subdomain
If you'd also like to access your app at https://www.mycoolapp.com, you can generate certificates for the www subdomain.
wasp deploy fly cmd --context server certs create www.mycoolapp.com
Once you do that, you will need to add another DNS record for your domain. It should be a CNAME record for www with the value of your root domain.
Here's an example:
| Type | Name | Value | TTL |
|---|---|---|---|
| CNAME | www | mycoolapp.com | 3600 |
With the CNAME record (Canonical name), you are assigning the www subdomain as an alias to the root domain.
Your app should now be available both at the root domain https://mycoolapp.com and the www sub-domain https://www.mycoolapp.com.
Your app serves its pages and its API on the same origin, so serving it on both the www and the non-www domain needs no extra configuration.
Keep in mind that the links Wasp builds (the ones in your app's emails, and the ones it redirects OAuth logins to) always use WASP_SERVER_URL, so they point at whichever of the two domains you set there.
Environment Variables
Server Secrets
If your app requires any other server-side environment variables (like social auth secrets), you can set them:
-
Initially, in the
launchorsetupcommands with the--server-secretoption -
After the app has already been deployed by using the
secrets setcommand:wasp deploy fly cmd secrets set GOOGLE_CLIENT_ID=<...> GOOGLE_CLIENT_SECRET=<...> --context=server
Client Environment Variables
Your client-side environment variables end up inside your app's pages and assets, so they have to be there when your app's image is built, not when it runs. Fly builds that image for you, and wasp deploy has no way of passing them to that build yet.
Until it does, if your app needs any REACT_APP_* variable, build the image yourself with the WASP_CLIENT_ENV build argument and deploy it as described on the Cloud Providers page:
docker build \
--build-arg WASP_CLIENT_ENV="REACT_APP_ANOTHER_VAR='somevalue'" \
-t my-wasp-app \
.wasp/out
Fly.io Regions
Fly.io runs applications physically close to users: in datacenters around the world, on servers we run ourselves. You can currently deploy your apps in 34 regions, connected to a global Anycast network that makes sure your users hit our nearest server, whether they’re in Tokyo, São Paolo, or Frankfurt.
Read more on Fly regions here.
You can find the list of all available Fly regions by running:
fly platform regions
Multiple Fly.io Organizations
If you have multiple organizations, you can specify a --org option. For example:
wasp deploy fly launch my-wasp-app dfw --org hive
Building Locally
Fly.io offers support for both locally built Docker containers and remotely built ones. However, for simplicity and reproducibility, the CLI defaults to the use of a remote Fly.io builder.
If you want to build locally, supply the --build-locally option to wasp deploy fly launch or wasp deploy fly deploy.
Using a custom PostgreSQL database
By default, Wasp uses the standard PostgreSQL Docker image provided by Fly.io when creating a new database for your app. However, if you have a need for a custom Docker image, e.g., your application requires specific PostgreSQL extensions (e.g., PostGIS), you can specify a Docker image with a custom PostgreSQL installation, with the --db-image <docker-image> flag.
Your custom PostgreSQL image must be compatible with Fly.io, as their platform has some requirements to work properly. Since these requirements are not readily documented, an easy way to ensure compatibility is to base your custom image off the official Fly.io PostgreSQL image: flyio/postgres-flex.
We have crafted a small guide on how to create a custom Docker image with PostGIS or pgvector for Fly.io. You can also use it as a starting point to create your own images with other extensions.
You only need to specify the Docker image once, when first creating the app with any of these commands:
wasp deploy fly create-db <region> --db-image <custom-postgres-image>
wasp deploy fly setup <app-name> <region> --db-image <custom-postgres-image>
wasp deploy fly launch <app-name> <region> --db-image <custom-postgres-image>
API Reference
launch
launch is a convenience command that runs setup, create-db, and deploy in sequence.
wasp deploy fly launch <app-name> <region>
It accepts the following arguments:
-
<app-name>requiredThe name of your app.
-
<region>requiredThe region where your app will be deployed. Read how to find the available regions here.
Running wasp deploy fly launch is the same as running the following commands:
wasp deploy fly setup <app-name> <region>
wasp deploy fly create-db <region>
wasp deploy fly deploy
Environment Variables
Server
If you are deploying an app that requires any other environment variables (like social auth secrets), you can set them with the --server-secret option:
wasp deploy fly launch my-wasp-app dfw --server-secret GOOGLE_CLIENT_ID=<...> --server-secret GOOGLE_CLIENT_SECRET=<...>
Client
Client-side environment variables are part of your app's pages and assets, so they can't be set on the deployed app. Read more about it in the Client Environment Variables section.
Custom Server URL
One app serves both your pages and your API, so your pages look for the API on their own origin. There is nothing to point anywhere, not even when you use a custom domain.
The --custom-server-url option is left over from when the client and the server were deployed as two separate apps. It no longer has any effect, so you can drop it from your deployment scripts:
# The option is ignored:
wasp deploy fly launch my-wasp-app dfw --custom-server-url https://api.myapp.com
If you really do serve your API from another origin, that's the REACT_APP_API_URL client environment variable, which is baked into your pages when they are built.
setup
The setup command registers your app on Fly, and sets up needed environment variables.
It only needs to be run once, when initially creating the app. It does not trigger a deploy.
wasp deploy fly setup <app-name> <region>
It accepts the following arguments:
-
<app-name>requiredThe name of your app.
-
<region>requiredThe region where your app will be deployed. Read how to find the available regions here.
After running setup, Wasp creates a new file in your project root directory: fly-server.toml.
You should include this file in your version control.
You can edit the fly-server.toml file to further configure your Fly deployment. Wasp will use the TOML file when you run deploy.
If you want to maintain multiple apps, you can add the --fly-toml-dir <abs-path> option to point to different directories, like "dev" or "staging".
You should only run setup once per app. Wasp skips it when it finds a fly-server.toml file, but if that file is missing, running setup again creates another app on Fly.
create-db
The create-db command creates a new database for your app.
wasp deploy fly create-db <region>
It accepts the following arguments:
-
<region>requiredThe region where your app will be deployed. Read how to find the available regions here.
You should only run create-db once per app. If you run it multiple times, it creates multiple databases, but your app needs only one.
deploy
wasp deploy fly deploy
The deploy command pushes your built app live.
Run this command whenever you want to update your deployed app with the latest changes:
wasp deploy fly deploy
If you've added any client-side environment variables to your app, this command can't get them into your app's pages and assets. Read more about it in the Client Environment Variables section.
Custom Server URL
One app serves both your pages and your API, so your pages look for the API on their own origin. There is nothing to point anywhere, not even when you use a custom domain.
The --custom-server-url option is left over from when the client and the server were deployed as two separate apps. It no longer has any effect, so you can drop it from your deployment scripts:
# The option is ignored:
wasp deploy fly deploy --custom-server-url https://api.myapp.com
If you really do serve your API from another origin, that's the REACT_APP_API_URL client environment variable, which is baked into your pages when they are built.
cmd
If you want to run arbitrary Fly commands (for example fly secrets list for your app), here's how to do it:
wasp deploy fly cmd secrets list --context server
The server context is your app, named that way back when your pages and your API were two separate Fly apps. If you still have the client app from such an older project, --context client runs the command against it.