Skip to content

Fly.io Notes

Initialization

Debug:

Bash
fly doctor
fly agent restart

App creation

Check existing names then create the fly app with a unique name, we'll use as lawdata.

Bash
fly apps create lawdata

Volume creation

After creating the app, create a volume that will be used by the app for persistent storage.

Note that the app is separate from the volume.

In case it already exists, it might be necessary to destroy the volume first and recreate it in case it has no more space.

Bash
fly vol list
# will display list of vol ids
fly vol destroy <instance-id>
# ? Are you sure you want to destroy this volume? Yes
# Destroyed volume xxx from lawdata -- recall lawdata is the app name

We'll use the db_lawdata as the volume name to create, allocating 7GB as the volume size in the Singapore region with:

Bash
fly vol create db_lawdata --region sin --size 7
fly vol list

Review fly.toml:

  1. source db_lawdata is created via fly vol create db_lawdata;
  2. the destination /data is prospective location of sqlite db; this is a folder of the volume that is described by the Dockerfile:
TOML
# fly.toml
[mounts]
source = "db_lawdata"
destination = "/data"

See the associated Dockerfile:

Docker
# Dockerfile
ENV DB_FILE=/data/x.db

After the app is deployed, can ascertain the folder via

Bash
fly ssh console
# cd data
# ls

The database file referred to is built with corpus-x.

Setup config

Review root fly.toml, specifically app_name, mount.source, and services.internal_port

TOML
app = "lawdata" # this was the name set during creation of the app
[env]
FLY_PRIMARY_REGION = "sin" # this is the region set during creation of the app's volume
[mounts]
source = "db_lawdata" # this was the name set during creation of the app's volume; can verify this with fly volumes list
destination = "/data" # this is the folder to be created in the app for persistent storage, used in the Dockerfile
[[services]]
internal_port = 8080 # will be used in the Dockerfile

Add secrets

Set the environment variables of the app:

Bash
fly --app lawdata secrets import < .env --stage

Set environment vars

See .env.example which outlines 5 variables that serve the following purposes

vars purpose
LITESTREAM_ACCESS_KEY_ID & LITESTREAM_SECRET_ACCESS_KEY aws credentials for litestream.io to restore a replica of previously saved & replicated database to the volume created
LAWSQL_BOT_TOKEN Bearer Token, a user-made credential for datasette (see datasette-auth-tokens plugin), to query the database; see allow list in metadata.yml
DATASETTE_GITHUB_AUTH_CLIENT_ID & DATASETTE_GITHUB_AUTH_CLIENT_SECRET github credentials, see (datasette-auth-github plugin), to login and access datasette via the production url, set the callback url in Github's / Developer Settings / oAuth Apps

build local image then deploy to fly

Use the local Dockerfile to build the image before deploying the same to fly.io

Bash
fly deploy --local-only

This will result in the following lines:

Bash Session
==> Verifying app config
--> Verified app config
==> Building image
==> Creating build context
--> Creating build context done
==> Building image with Docker
--> docker host: 20.10.21 linux aarch64
...

Substantive steps of the Dockerfile to create the Docker image

Step Description Time (seconds)
2 Building python slim with relevant libs ~120
5 Building sqlite with extensions ~420
7 Install requirements.txt ~60

After the image is built, this will push the image to fly:

Bash Session
--> Building image done
==> Pushing image to fly
The push refers to repository [registry.fly.io/corpus-x]
...
deployment-aaa: xxx
--> Pushing image done
image: registry.fly.io/corpus-x:deployment-aaa
image size: 323 MB
==> Creating release
--> release v2 created

--> You can detach the terminal anytime without stopping the deployment

Add certificate to production url

When the app is first created, the following URL will be usable: lawdata.fly.dev

After a certificate is issued, this can become lawdata.xyz.

Bash
fly ips list
fly certs create lawdata.xyz
fly certs create www.lawdata.xyz

Visit the fly.io dashboard and copy the A and AAAA values. These are also the same values reflected in fly ips list.

After running fly certs create www.lawdata.xyz, the following prompt is displayed:

Bash Session
You can configure your DNS for www.lawdata.xyz by:

1: Adding an CNAME record to your DNS service which reads:

    CNAME www. lawdata.fly.dev

Test access on deployed app

Unauthorized

Without token:

Bash
curl -IX get https://lawdata.fly.dev/x

Produces a HTTP/2 403 (FORBIDDEN) http status code:

Bash
HTTP/2 403
date: x x x x
server: Fly/x x x
content-type: text/html; charset=utf-8
via: 2 fly.io
fly-request-id: x x x-sin

Authorized

With the url set at: lawdata.fly.dev, the database file at x.db, and the secret previously set for LAWSQL_BOT_TOKEN, can test a json list of tables with:

Bash
export token=<whatever-value-of-LAWSQL_BOT_TOKEN>
curl -H "Authorization: Bearer ${token}" https://corpus-x.fly.dev/x.json | jq