Skip to content

Install Folio on Fly.io

You already use Fly.io. This is possible but not a one-click: there is no template format that creates an app, a volume and a database together, so it is a short recipe around fly.toml. Treat it as a starting point and tell us what differs.

What you need

  • flyctl installed and signed in.
  • The image ghcr.io/evergreen-it-dev/folio, published and public.
  • A PostgreSQL database: Fly's Managed Postgres, a PostgreSQL of your own, or an external one such as Neon or Supabase.

Before you start

Why it works, and why it is not a kit

Folio needs a disk, and Fly gives one: a volume attaches to one machine only, lives in one region, and is not synchronised between machines. So Folio runs as exactly one machine with one volume, and you cannot scale it out. That fits Folio, which is designed to run as one instance, but it means no zero-downtime deploys. A hardware failure of the host is your backup's problem: Fly takes daily volume snapshots, kept five days by default, and Fly itself says snapshots should not be your only backup.

The database is the other cost. Fly's Managed Postgres starts around $38 a month for its smallest plan, which is more than the rest of the stack. The alternative is to run your own PostgreSQL (a second Fly app with its own volume), or to use an external database such as Neon or Supabase and set DATABASE_URL to its connection string. For a small team, a small VPS is simpler and cheaper.

Steps

  1. Step 1: Save fly.toml, then edit the app name and the region.

    fly.toml
    # Folio on Fly.io. See the steps on this page.
    app = "folio-change-me"        # must be unique across Fly: pick your own
    primary_region = "ams"         # pick the region closest to your people
    
    [build]
      image = "ghcr.io/evergreen-it-dev/folio:latest"
    
    [env]
      NODE_ENV = "production"
      PORT = "4870"
      ASSET_BACKEND = "local"
      # PUBLIC_URL and FOLIO_SECRET are set with `fly secrets set` (see the steps).
    
    # The Git repositories of the spaces. A Fly volume attaches to exactly one machine.
    [mounts]
      source = "folio_data"
      destination = "/app/data"
    
    [http_service]
      internal_port = 4870
      force_https = true
      auto_stop_machines = "off"   # Folio keeps WebSocket connections open: never stop it
      auto_start_machines = true
      min_machines_running = 1
    
      [[http_service.checks]]
        method = "GET"
        path = "/api/health"
        interval = "30s"
        timeout = "5s"
        grace_period = "90s"
    
    [[vm]]
      size = "shared-cpu-1x"
      memory = "2gb"
  2. Step 2: Create the app from it without deploying yet.

    bash
    fly launch --copy-config --no-deploy
  3. Step 3: Create the volume for the Git repositories, in the same region.

    bash
    fly volumes create folio_data --size 10 --region ams
  4. Step 4: Create a PostgreSQL database and attach it to the app. This sets DATABASE_URL.

    bash
    fly mpg create
    fly mpg attach <cluster> --app <your-app>
  5. Step 5: Set the secrets: the address people open, and the encryption key.

    bash
    fly secrets set PUBLIC_URL=https://<your-app>.fly.dev FOLIO_SECRET=$(openssl rand -hex 32)
  6. Step 6: Deploy, then check it on a fresh instance. The smoke test comes from a clone of the repository.

    bash
    fly deploy
    node deploy/smoke.mjs https://<your-app>.fly.dev

Settings

NODE_ENV, PORT and ASSET_BACKEND are set in fly.toml. Redis is optional here: Folio uses it for rate limits and short locks, and degrades without it (in-memory rate limit, unlocked space mutations), which is correct for a single machine. If you want it, create an Upstash Redis with fly redis create and set REDIS_URL.

Environment variables for Folio on Fly.io
VariableDefaultWhat it does
PUBLIC_URLfly secrets setThe address people open, for example https://<your-app>.fly.dev.
FOLIO_SECRETfly secrets setEncrypts saved Git tokens and AI keys. Never change it afterwards.
DATABASE_URLset by fly mpg attachOr the connection string of your own or an external database.
REDIS_URLoptionalAn Upstash Redis created with fly redis create.

Update

Run fly deploy again. The image tag in fly.toml decides what you get; pin a release for control. The database migrates itself on start.

Back up

Snapshot the data volume, and use your database provider's backups (or pg_dump over fly proxy). Keep a copy outside Fly as well.

bash
fly volumes snapshots create <volume-id>

Limits and honest notes

  • One machine with one volume. You cannot scale it out, and deploys are not zero-downtime.
  • auto_stop_machines is off in fly.toml on purpose: Folio keeps WebSocket connections open and must never be stopped.
  • Managed Postgres costs about $38 a month at the smallest plan.

Platform documentation

Check the installation

From a clone of the repository, run the smoke test against a fresh instance. It needs Node 18 or newer. It creates the first account, a space and a page, and opens a WebSocket connection to the page. Delete the instance, or that space, afterwards.

bash
node deploy/smoke.mjs https://wiki.example.com

Other ways to install

Compare all platforms

Not ready to install?

Try the public demo: https://demo.foliowiki.online. Pick Sam on the sign-in screen. The login is shared and the data resets every 24 hours, so don't enter personal data or API keys.

Open the demo