Fly.io deployment
Deploy the API to Fly.io with the Bun + Turbo Docker image.
What gets deployed
Fly.io is used to run the API service (apps/api) as a container built from the monorepo.
The deployment uses Turbo prune to keep the image lean while still including shared packages.
Files to know
apps/api/fly.toml— Fly app configuration (region, port, health checks, scaling).apps/api/Dockerfile— multi-stage Bun build usingturbo prune @plop/api --docker.apps/api/.dockerignore— trims the build context.
Prerequisites
- Install the Fly CLI (
flyctl) and log in. - Confirm you have all required API secrets (see
env-and-secrets).
Configure the Fly app
Update apps/api/fly.toml before the first deploy:
app— set this to your Fly app name.primary_region— pick the region closest to your database or users.min_machines_running/[[vm]]— adjust for your availability + budget.PORT/internal_port— keep this aligned with the API port (defaults to3003).
Set required secrets
From the repo root, set the API environment variables on Fly. Replace the values below with your production secrets (for local dev, use the .env examples in env-and-secrets).
fly secrets set --config apps/api/fly.toml \
APP_URL=https://app.plop.email \
NEXT_PUBLIC_SUPABASE_URL=... \
SUPABASE_SECRET_KEY=... \
DATABASE_PRIMARY_URL=... \
DATABASE_LHR_URL=... \
DATABASE_SESSION_POOLER=... \
UPSTASH_REDIS_REST_URL=... \
UPSTASH_REDIS_REST_TOKEN=... \
INBOX_ROOT_DOMAIN=in.plop.email \
INBOX_WEBHOOK_SECRET=... \
ALLOWED_API_ORIGINS=https://app.plop.emailOptional billing variables (only if Polar billing is enabled):
fly secrets set --config apps/api/fly.toml \
POLAR_ACCESS_TOKEN=... \
POLAR_ENVIRONMENT=production \
POLAR_WEBHOOK_SECRET=... \
POLAR_STARTER_MONTHLY_PRODUCT_ID=... \
POLAR_STARTER_YEARLY_PRODUCT_ID=... \
POLAR_PRO_MONTHLY_PRODUCT_ID=... \
POLAR_PRO_YEARLY_PRODUCT_ID=... \
POLAR_ENTERPRISE_MONTHLY_PRODUCT_ID=... \
POLAR_ENTERPRISE_YEARLY_PRODUCT_ID=...Fly automatically injects FLY_REGION at runtime. The API uses this to route reads to a nearby replica when available.
Deploy
Run the deploy from the repo root:
fly deploy --config apps/api/fly.tomlThe Dockerfile sets NODE_ENV=production and runs the API with Bun.
Verify
fly status --config apps/api/fly.toml
fly logs --config apps/api/fly.toml
curl https://<your-app>.fly.dev/healthScaling and regions
Common operations:
fly scale count 2 --config apps/api/fly.toml
fly scale memory 1024 --config apps/api/fly.toml
fly regions add lhr --config apps/api/fly.tomlIf you add regions, ensure your read replica URLs (DATABASE_LHR_URL, DATABASE_SESSION_POOLER) are set appropriately.
Keep INBOX_WEBHOOK_SECRET and the worker WEBHOOK_AUTH_TOKEN identical, or webhook delivery will return 401s.