podfly 0.1.0
podfly: ^0.1.0 copied to clipboard
Deploy Serverpod apps on Fly.io, Railway, and more via existing cloud CLIs. Thin orchestrator (not a host): podfly.yaml, Dockerfile/fly/railway quirks, Flutter web packaging, Postgres wiring, smoke checks.
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 | |
| Repo | github.com/127thousand/podfly |
Official recommendation #
Out of respect for the Serverpod team: the officially recommended hosting path is Serverpod Cloud — managed infrastructure built for Serverpod (API, web, Insights, and the rest of the product surface).
podfly is for teams that want to stay on their own infra (Fly, Railway, big clouds, etc.) and still avoid hand-rolling every CLI and config quirk. It complements Serverpod Cloud; it does not replace it.
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, …) |
Only for the host: you chose (wizard asks) |
| Railway CLI | host: railway (often ~/.railway/bin) |
| 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
Typical automation (Fly today):
- Doctor tools + auth
- Init
podfly.yamlif missing (--yes= non-interactive) - Detect web vs API-only (e.g. mobile without
web/) - Ensure API app exists (needed before Postgres attach)
- Database ensure (
fly_postgres/railway_postgres/ neon / none) - Write
fly.toml/railway.tomlif missing; Serverpod-style Dockerfile only if missing - Patch production
publicHost - 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 or 🚂 Railway static (host: railway) |
🟣 Fly.io or 🚂 Railway |
🪰 fly |
Optional static on Fly | 🟣 Fly.io |
| 📱 API-only | — (mobile / other clients) | 🟣 Fly.io or 🚂 Railway |
| 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) |
🟢 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 | — | ✅ | ✅ | ✅ | Officially recommended managed option |
| 🟣 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 |
🗺️ | ✅ | ✅ | 🟡 | Simple PaaS |
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 |
🗺️ | Simple managed PG |
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
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: fly
name: my-api
server: my_app_server
web:
enabled: false
database:
provider: railway_postgres
railway_postgres:
create: 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