Skip to content
Snippets Groups Projects
Select Git revision
  • e3e0dafd83736898dcfeb237b6bc57d0a8efb983
  • main default
  • final_pytorch
  • phase-1-final
4 results

clips

Demo Fly Postgres

This demo shows you how to deploy a website to Fly with a Postgres database.

Make sure to follow all instructions carefully.

Billing

fly.io's pay as you go plan will charge you based on usage, but as of 2024-08-07, they have a secret policy that if your monthly bill is < $5, they'll waive your bill. Most groups will probably qualify for this. If not, I'd expect your bill to be no more than $5, and definitely no more than $10, as long as you select "Development" and not "Production" when deploying. If this is an issue for you, let me know and we can work something out.

Set up web app configuration, deploy Postgres app

  • Follow steps 1 - 3 here if you don't already have a Fly account and to install the fly command line program
  • fly launch will fail if you don't have a credit card on file; see here and above for information on billing
  • Then when running fly launch, when prompted "Do you want to tweak these settings before proceeding?", enter y, will take you to webpage
    • Choose unique app name, can't match any other existing fly apps globally
      • Note that your app name will also have to become your database name; see the creating database tables section below
      • Make your app name a valid variable name, as we'll be using it later on. The default generated names have hyphens in them - don't use any hyphens
    • Check that the port your server.js listens on matches what's on the Fly page, and if not, change either so they match
    • Under database section, select Fly Postgres, give your database its own app name (I did my web app name + -db),
      • Make sure to pick the Development deployment option ; default is production, which costs more
    • Then confirm settings
  • This command will generate credentials for your Postgres cluster — save these somewhere private in case you need them later, as after you close this terminal window you'll never be able to get them again
  • If this worked, it'll create a Dockerfile and a fly.toml with your configuration settings for your web app; you won't need to run fly launch again
  • It will also deploy a Fly app for your Postgres cluster and create a database in your Postgres cluster with the same name as your web app name
    • It will also make an environment variable called DATABASE_URL available to your Fly web app, which we'll use to connect to the Postgres database
  • Both of these apps will be visible on the Fly website on your dashboard

You can also configure your web app and Postgres app separately by running fly launch to create your web app, fly postgres create to create a Postgres app, and fly attach to make the DATABASE_URL available to the web app; see here for more details. I don't recommend doing this, as you have to do a little more work to get your web app and database app talking to each other.

fly launch won't generate a separate fly.toml for the Postgres app; if you want to tweak the Postgres settings, you need to run fly config save --app FLYPOSTGRESAPPNAME (replacing with your DB's app name) to create a fly.toml for the Postgres Fly app (make sure you run this in a different directory as this may overwrite the fly.toml for your web app; not sure, haven't checked).

Also, any fly commands you run for Postgres app specifically will need to provide its app name through the command line, since otherwise fly will use the app name in the fly.toml which is your web app, e.g. fly postgres connect -a APPNAME.

Code changes you'll need to make web app work and connect to Postgres app

Your local and deployed server will need different configurations to run:

  • Fly expects server to listen to host 0.0.0.0, not localhost
  • Port can remain 3000 as long as you've configured Fly to deploy to that (see setup section above, should happen automatically when you run fly launch)
  • Fly will automatically put your DB credentials in the environment variable DATABASE_URL (you can access environment variables in the global Node object process.env); node-postgres can take a connectionString parameter when creating the pool, so we can pass DATABASE_URL to that, e.g. let pool = new Pool({ connectionString: process.env.DATABASE_URL });
    • This means that you don't need to pass Postgres credentials to Fly, so it doesn't need access to your .env to run Postgres
    • If you want to pass API keys to Fly, note that Fly includes .env in the .dockerignore file by default, which means any files named .env will be excluded from your deployed app code base. You can remove the .env line from .dockerignore, or just have a keys.json file that you .gitignore (but don't .dockerignore) and read from it like we've done before. You can also set secret env vars through the command line interface; see here.
  • To make your code work both locally and on Fly, you can do different things if process.env.NODE_ENV === "production", because Fly sets NODE_ENV to production automatically, and otherwise it's the empty string by default; see server.js for details

Using this repo

If you use this repo, make the following changes:

  1. Copy env.sample to .env and replace all variables with your local Postgres credentials
  2. Change .env's database name to match your Fly web app name
    • Your .env is just for running locally, as Fly won't use this for Postgres, if your local database has the same name as your Fly database, it makes it easier to write a setup.sql that works for both; see below
  3. Change setup.sql's database name references to match your Fly web app name (to make it consistent with your local .env)
  4. In package.json, change FLYPOSTGRESAPPNAME to match your Fly Postgres app name

To run your code locally:

  • npm run setup:dev to initialize your DB and tables - you only need to do this once (or whenever you change your schema/want to delete all data and start fresh)
  • npm run start:dev to run your server

To set up your Fly database:

  • npm run setup

Fly will use the npm run start command automatically to start your server when you deploy. You shouldn't run npm run start locally if you're using Postgres, because the start command doesn't inject the Postgres environment variables that server.js expects to connect to the local DB.

Creating your database tables

  • The Postgres Fly app's connection string in the DATABASE_URL assumes you're using a Fly database with the same name as your Fly web app
  • It's easiest to change your local database's name to match your Fly web app name (not your Fly Postgres app name) in your setup.sql, e.g. if you named your Fly app foo and your Fly Postgres app foo-db, you'll run CREATE DATABASE foo
    • You'll need to change the database name in any files that reference it, like .env/env.json, setup.sql, and if package.json uses the database name in any script commands, there as well
  • To run your setup.sql on the deployed Fly Postgres cluster, run fly postgres connect -a FLYPOSTGRESAPPNAME < setup.sql (or if you're using this repo, just run npm run setup), replacing FLYPOSTGRESAPPNAME with the name of your Fly Postgres app (I made mine the same as my webapp + -db); this will feed the SQL commands inside setup.sql to a SQL interpreter running on your Postgres instance, which will create the needed tables in your deployed database
    • FYI, the DROP DATABASE command will probably say it failed with an error saying the database is currently in use, but the CREATE TABLE commands seem to work anyway, so don't worry about this
    • You need to provide an explicit app name when running this command or else it'll use the one in your fly.toml, which is your web app's app name, not your Postgres app's app name
    • You can also run fly postgres connect -a FLYPOSTGRESAPPNAME to open up a psql command line on your deployed DB and copy-paste the SQL commands in setup.sql manually if the above command doesn't work because you're not using a Unix shell; see docs here

Deploy your web app

Your Postgres app is already deployed, but we still need to deploy your web app.

  • Run fly deploy to actually deploy web app to public internet
  • Rerun fly deploy every time you change code to re-deploy it
  • Web app will be available at https://FLYWEBAPPNAME.fly.dev/
  • Can see server logs at https://fly.io/apps/FLYWEBAPPNAME/monitoring or by running fly logs from the command line
  • Can ssh into server with fly ssh console; note that this won't work if no instances of your web app are active, and Fly will automatically autoscale down to 0 instances if the site hasn't been used in a bit, so if this fails, make sure your deployment didn't crash, then visit your site's URL to start one of the machines and then it should work
  • Can run fly postgres connect -a FLYPOSTGRESAPPNAME to connect to your Postgres instance with a psql shell

It seems like sometimes the Fly Postgres app is slow to accept connections, so any code that touches the database might fail at first when you visit your website. Try again after a few seconds if you get a network error to see if it's started.