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
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"Step 2: Create the app from it without deploying yet.
bashfly launch --copy-config --no-deployStep 3: Create the volume for the Git repositories, in the same region.
bashfly volumes create folio_data --size 10 --region amsStep 4: Create a PostgreSQL database and attach it to the app. This sets DATABASE_URL.
bashfly mpg create fly mpg attach <cluster> --app <your-app>Step 5: Set the secrets: the address people open, and the encryption key.
bashfly secrets set PUBLIC_URL=https://<your-app>.fly.dev FOLIO_SECRET=$(openssl rand -hex 32)Step 6: Deploy, then check it on a fresh instance. The smoke test comes from a clone of the repository.
bashfly 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.
| Variable | Default | What it does |
|---|---|---|
PUBLIC_URL | fly secrets set | The address people open, for example https://<your-app>.fly.dev. |
FOLIO_SECRET | fly secrets set | Encrypts saved Git tokens and AI keys. Never change it afterwards. |
DATABASE_URL | set by fly mpg attach | Or the connection string of your own or an external database. |
REDIS_URL | optional | An 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.
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.
node deploy/smoke.mjs https://wiki.example.comOther ways to install
Compare all platformsNot 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.