Skip to main content
The server interface is in private early access. Contact bryan@qlty.sh if you’re interested in trying it.
Fly.io can host the Fabro server by pulling the pre-built image published to GHCR. The repo ships a fly.toml that points Fly directly at the image — no build step on Fly’s builders, no Dockerfile evaluation — and declares a Volume mount at /storage so your runs, checkpoints, and sessions survive redeploys. Fly.io is CLI-first; there is no one-click deploy button. The workflow below uses flyctl.

First-deploy checklist

1. Adopt fly.toml in a new app

git clone https://github.com/fabro-sh/fabro
cd fabro
fly launch --copy-config --no-deploy
fly launch --copy-config keeps the repo’s fly.toml instead of generating a new one; --no-deploy lets you finish wiring secrets and volumes before the first deploy. You’ll be prompted for an app name (must be globally unique on Fly) and a primary region — update fly.toml in place if you change the defaults.

2. Create the persistent Volume

Fabro writes all persistent state — run history, checkpoints, sessions, the default token, and JWT keys — under /storage. Fly containers have ephemeral filesystems, so without a Volume that directory is wiped on every redeploy. fly.toml declares the mount but cannot create the volume itself — provision it with flyctl:
fly volumes create storage --size 1 --region <your-primary-region>
Grow later with fly volumes extend if needed. The volume name (storage) must match [[mounts]].source in fly.toml.

3. Set required environment variables

Fly stores env vars as encrypted secrets:
fly secrets set \
  ANTHROPIC_API_KEY=... \
  SESSION_SECRET=...
The Server Configuration reference has the full list; the minimum useful set:
VariablePurpose
ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY / …At least one LLM provider key for the models you’ll run
FABRO_DEV_TOKENOptional — pre-set the dev token instead of reading the one written to /storage on first boot
SESSION_SECRET64-character hex string; required when the web UI is enabled
GITHUB_APP_CLIENT_SECRET, GITHUB_APP_WEBHOOK_SECRET, GITHUB_APP_PRIVATE_KEYOnly if you enable GitHub OAuth or the GitHub App integration

4. Deploy

fly deploy
Fly pulls ghcr.io/fabro-sh/fabro:nightly, attaches the volume, and starts the Machine. The health check on /health must pass before traffic is routed.

Accessing your Fabro server

Once the deploy is healthy, Fly exposes a <app>.fly.dev URL (or your custom domain). Two things to grab:
  1. The dev token — on first boot, Fabro writes one to /var/fabro/dev-token and logs it. Read it via the Machine’s shell:
    fly ssh console -C "cat /var/fabro/dev-token"
    
    Or tail the startup logs with fly logs.
  2. Point your local CLI at the server — add the Fly URL to ~/.fabro/settings.toml:
    ~/.fabro/settings.toml
    [cli.target]
    type = "http"
    url = "https://<your-app>.fly.dev/api/v1"
    
    Then commands like fabro model list --server <url> will hit your Fly instance.
See Running the Fabro Server for the full auth and CLI-pointing story.

Redeploys and updates

fly deploy re-pulls the GHCR image on every run. fly.toml references the :nightly tag by default, so redeploying picks up the latest nightly automatically. To pin a specific version, edit fly.toml to reference ghcr.io/fabro-sh/fabro:<version> and redeploy. The /storage Volume survives redeploys, so runs and checkpoints persist.

Caveats

  • $PORT is not injected. Unlike Railway and Render, Fly does not set a PORT environment variable. The Fabro image binds to $PORT if set, otherwise 32276fly.toml pins internal_port = 32276 so the default works. If you change internal_port, also fly secrets set PORT=<n> to match.
  • Volume is load-bearing and not replicated. Fly’s docs recommend at least two Volumes per app for redundancy, but Fabro’s server is single-replica by design — one Machine owns /storage. Treat this like a traditional VPS: hardware failure means restoring from Fly’s volume snapshots or a backup you manage.
  • Single Machine. Don’t fly scale count above 1 — a second Machine can’t mount the same Volume, and the server assumes a single writer.
  • Architecture. Fly Machines run x86_64 (amd64) by default. The :nightly tag is multi-arch, but the arm64 variant is not currently usable — stay on amd64.
  • Autostop is disabled. fly.toml sets auto_stop_machines = "off" so the Machine stays up for the run queue. Leaving autostop enabled would pause Fabro when there’s no HTTP traffic, stalling any in-flight runs.

Next steps

Running the Fabro Server

Auth, dev tokens, submitting runs, and pointing the CLI at your deployment.

Server Configuration

Full settings.toml reference — TLS, auth methods, concurrency, and more.