podfly 0.2.1 copy "podfly: ^0.2.1" to clipboard
podfly: ^0.2.1 copied to clipboard

Deploy Serverpod apps on Fly.io, Railway, DigitalOcean, and more via existing cloud CLIs. Thin orchestrator (not a host): podfly.yaml, Docker/fly/railway/DO quirks, Flutter web packaging, Postgres wir [...]

podfly #

Deploy Serverpod on real cloud infrastructure without memorizing each provider’s CLI, config, and quirks.

podfly is a thin orchestrator: it shells out to existing tools (fly, railway, wrangler, neonctl, …), generates the right config, and encodes battle-tested defaults (Flutter web packaging, scale-to-zero, DB wiring). It is not a new host — it makes the hosts you already use boring to ship to.

serverpod create …     →  Dockerfile + monorepo (Serverpod)
podfly deploy          →  provider CLIs + configs + quirks (podfly)
pub.dev pub package
Repo github.com/127thousand/podfly

Serverpod Cloud vs podfly #

The Serverpod project’s managed offering is Serverpod Cloud — API, web, Insights, and the rest of the product surface on infrastructure built for Serverpod.

podfly is the path when you want to keep your own infra (Fly, Railway, and similar) and still avoid hand-rolling every CLI and config quirk. Use one or the other; they solve different problems.


Install #

dart pub global activate podfly

Ensure ~/.pub-cache/bin (or your platform’s pub cache bin) is on PATH. Upgrade with the same command.

Contributors / unreleased:

dart pub global activate --source git https://github.com/127thousand/podfly.git
# or: dart pub global activate --source path /path/to/podfly
Tool When
Flutter / Dart Always
Host CLI (fly, railway, doctl, …) Only for the host: you chose (wizard asks)
Railway CLI host: railway (often ~/.railway/bin)
doctl + Docker host: digitalocean (DOCR registry required)
wrangler Flutter web on Cloudflare Pages (mode: split)
neonctl database.neon.provision: true

podfly doctor checks these, can install missing CLIs (TTY or PODFLY_AUTO=1), and can open login flows on a TTY.

CI: see doc/ci.md (FLY_API_TOKEN / RAILWAY_TOKEN + --yes --no-login).


Quick start #

serverpod create my_app --mini -f   # Serverpod: monorepo + Dockerfile
cd my_app
podfly deploy --yes --smoke         # podfly: provider CLIs + config quirks

API-only + GitHub Actions → Fly (every push to main):
see example/mobile_api_only (workflow, podfly.yaml, smoke).

Typical automation (Fly today):

  1. Doctor tools + auth
  2. Init podfly.yaml if missing (--yes = non-interactive)
  3. Detect web vs API-only (e.g. mobile without web/)
  4. Ensure API app exists (needed before Postgres attach)
  5. Database ensure (fly_postgres / railway_postgres / neon / none)
  6. Write fly.toml / railway.toml if missing; Serverpod-style Dockerfile only if missing
  7. Patch production publicHost
  8. Build/deploy + optional smoke
podfly deploy --dry-run
podfly deploy --api
podfly deploy --host railway --api --yes --smoke
podfly deploy --web
podfly doctor
podfly init
podfly smoke

What you get today #

Mode UI API
🔀 split 🟠 Cloudflare Pages (CDN) + API host 🟣 Fly / 🚂 Railway / 🌊 DO
🧱 monolith UI with the API host (or DO native web app) 🟣 Fly / 🚂 Railway / 🌊 DO
📱 API-only — (web.enabled: false; usually mode: monolith) 🟣 Fly / 🚂 Railway / 🌊 DO

mode: fly is still accepted as a legacy alias for monolith.

Database When
🚫 none Stateless
💾 sqlite Single machine + volume (Fly)
🟣 fly_postgres Classic Serverpod on Fly (attach → Serverpod config)
🚂 railway_postgres Railway Postgres plugin (host: railway)
🌊 digitalocean_postgres DO Managed Postgres (host: digitalocean)
🟢 neon Serverless PG

Insights and full managed Serverpod ops: Serverpod Cloud (not podfly).


Provider roadmap #

podfly status = first-class in this tool.
Fit = how well that host matches Serverpod’s process model, independent of whether podfly implements the deploy yet.

Topology keys #

Topology Meaning When it fits
📱 API-only One public API port. Mobile or other clients. Any container/PaaS that runs a single process + port.
🔀 Split Static Flutter web on a CDN; API on an app host. Best of both: CDN for multi‑MB WASM; API can scale to zero.
🧱 All-in-one API + static web on one machine (multi-port / multi-role). Hosts that allow multi-port Machines or a reverse proxy.

Serverpod Insights is not covered by podfly. For Insights and the full managed product surface, use Serverpod Cloud.

App hosts #

Provider CLI podfly 📱 API-only 🔀 Split UI+API 🧱 All-in-one Notes
💜 Serverpod Cloud Serverpod Cloud Serverpod’s managed host (not via podfly)
🟣 Fly.io fly / flyctl Default podfly path; multi-port Machines OK
🚂 Railway railway 🟡 Separate API + static web services
🟠 Cloudflare Pages wrangler ✅ UI ✅ UI Static Flutter web only; not the API
🟦 Render Render CLI 🗺️ 🟡 Prefer API service + static site
☁️ Google Cloud Run gcloud 🗺️ 🟡 🟡 One public port; cold starts
📦 AWS App Runner / ECS aws 🗺️ 🟡 App Runner ≈ API-only
🔷 Azure Container Apps az 🗺️ 🟡 Similar to other container PaaS
🌊 DigitalOcean App Platform doctl 🟡 DOCR images + App Spec; web = separate app

Fit legend: ✅ natural · 🟡 possible with constraints · ❌ poor fit · 🗺️ podfly not implemented yet · — N/A

Hosted Postgres #

Provider CLI / API podfly Notes
🚫 None Stateless APIs
🟢 Neon neonctl Serverless PG; pairs with sleeping APIs
🟣 Fly Postgres fly postgres Private network; often bills when API is stopped
🚂 Railway Postgres Railway CLI database.provider: railway_postgres
💾 SQLite (+ Fly volume) fly volumes Single-machine only
Supabase CLI / URL 🗺️ Managed PG
🟦 Render Postgres API / dashboard 🗺️ Bundle with Render
📦 AWS RDS aws 🗺️ Enterprise default
☁️ Google Cloud SQL gcloud 🗺️ GCP default
🔷 Azure Database for PostgreSQL az 🗺️ Azure default
🌊 DigitalOcean Managed Postgres doctl digitalocean_postgres + app firewall

podfly legend: ✅ supported today · 🗺️ planned

Want another provider? Open an issue — preference is excellent DX or clouds most teams already pay for.


Example podfly.yaml (split, no database) #

host: fly
mode: split   # or monolith — UI with API host, no Pages
name: sacred-draw
server: tarot_draw_server
flutter: tarot_draw_flutter

fly:
  app: sacred-draw
  region: iad
  config: fly.toml
  scale_to_zero: true
  ha: false

cloudflare:
  project: sacred-draw
  branch: main

database:
  provider: none

web:
  enabled: true
  server_url_define: SERVER_URL
  api_url: https://sacred-draw.fly.dev/
  patch_bootstrap: true
  write_headers: true

smoke:
  api:
    method: POST
    path: /tarot/draw
    body: '{}'
    expect_status: 200
  web:
    path: /
    expect_status: 200

Railway API-only sketch:

host: railway
mode: monolith
name: my-api
server: my_app_server
web:
  enabled: false
database:
  provider: railway_postgres
  railway_postgres:
    create: true

DigitalOcean full stack sketch:

host: digitalocean
mode: monolith
name: my-app
server: my_app_server
flutter: my_app_flutter
digitalocean:
  app: my-app
  region: nyc
database:
  provider: digitalocean_postgres
  digitalocean_postgres:
    create: true
    region: nyc1
web:
  enabled: true

Full field list: doc/podfly.yaml.md.


Documentation #

Doc Contents
User guide Flow, flags, automation, troubleshooting
CI / GitHub Actions Tokens, example workflows, dry-run on PR
Caching & Flutter web WASM, service worker, _headers
Database Providers + detection
Config reference podfly.yaml fields
AGENTS.md Rules for coding agents
llms.txt LLM / doc index
Skill Grok skill (/podfly)
CHANGELOG Release history
Design specs Architecture decisions

License #

MIT

0
likes
0
points
400
downloads

Documentation

Documentation

Publisher

unverified uploader

Weekly Downloads

Deploy Serverpod apps on Fly.io, Railway, DigitalOcean, and more via existing cloud CLIs. Thin orchestrator (not a host): podfly.yaml, Docker/fly/railway/DO quirks, Flutter web packaging, Postgres wiring, smoke checks.

Repository (GitHub)
View/report issues

Topics

#serverpod #deploy #cli #fly #railway

License

unknown (license)

Dependencies

args, io, path, yaml

More

Packages that depend on podfly