# flyctl — Fly.io CLI `flyctl` is the official command-line interface for Fly.io. Use it to deploy and manage apps, Machines, Postgres clusters, secrets, and more on the Fly.io platform. ## Installation | Platform | Command | |---|---| | macOS | `brew install flyctl` | | Linux | `curl -L https://fly.io/install.sh \| sh` | | Windows (PowerShell) | `iwr https://fly.io/install.ps1 -useb \| iex` | Always use `flyctl` (not `fly`) to ensure compatibility. Verify with `flyctl version`. ## Authentication Log in to your Fly.io account: ```sh flyctl auth login ``` This opens a browser window for authentication. Once complete, your credentials are stored locally. To authenticate non-interactively (e.g. in CI or agentic environments), set the `FLY_API_TOKEN` environment variable with a valid Fly.io API token: ```sh export FLY_API_TOKEN= ``` ## Authentication via Stripe Projects (Macaroon Tokens) When an app is provisioned through Stripe Projects, **you do not need to run `flyctl auth login`**. Fly.io issues **macaroon tokens** (`fm2_XXXX` strings) scoped to the provisioned resource. Multiple tokens can be combined comma-separated. To authenticate `flyctl`, set `FLY_API_TOKEN` with the `FlyV1` prefix: ```sh export FLY_API_TOKEN="FlyV1 fm2_XXXX,fm2_YYYY" flyctl auth whoami # returns HASH@tokens.fly.io — expected and correct ``` ### Token types by resource | Resource type | Token in `access_configuration` | Scope | Use for | |---|---|---|---| | `app` | `deploy_token` | App-scoped | `flyctl` commands targeting that app (`-a `) | | `mpg` | `org_token` | Org-scoped | `flyctl mpg` commands and any app command for apps in the same org | **App token** (`FlyV1` prefix required): ```sh export FLY_API_TOKEN="FlyV1 " flyctl status -a my-app flyctl secrets set KEY=value -a my-app ``` **MPG org token** (no `FlyV1` prefix; org-scoped, so it also covers all apps in the org): ```sh export FLY_API_TOKEN="" flyctl mpg status flyctl mpg attach --app my-app ``` Rotate credentials (issues fresh tokens): ```sh stripe projects rotate-credentials ``` ## Specifying the App **Always pass `-a APP_NAME` (or `--app APP_NAME`) explicitly** to every command rather than relying on a `fly.toml` file being present in the working directory. This makes commands unambiguous and is especially important in agentic and CI environments. ```sh # Preferred — explicit app flag flyctl status -a my-app-name flyctl logs -a my-app-name flyctl secrets set KEY=value -a my-app-name ``` All command examples below use `--app ` for clarity; you can always substitute `-a ` as a shorter equivalent. ## Deploying Apps **First-time deploy:** run `flyctl launch`. The interactive wizard detects your framework, generates `fly.toml` and `Dockerfile`, and performs the first build and deploy. Do not hand-write these files — let the wizard scaffold them. Only intervene if `flyctl launch` or the subsequent build/deploy fails. To check whether an app has ever been deployed: ```sh flyctl status -a ``` If `Image` shows `-`, the app exists (e.g. pre-created via Stripe Projects) but was never deployed — use `flyctl launch` with `--name`, `--force-name`, and `--no-create` to reuse the existing app instead of creating a new one: ```sh flyctl launch --name --force-name --no-create ``` **Updating a live app:** if a `fly.toml` exists, use `flyctl deploy -c fly.toml`. Without a config file, use `flyctl deploy -a `. When passing `-c`, the full toml configuration is applied as part of the deploy. **Cloning a repo that already has a `fly.toml`:** use `flyctl launch --copy-config` to reuse the existing config as a starting point while assigning a new app name and ownership. ## Setting Up an App — Operational Checklist Follow this checklist whenever you are about to work with a Fly.io app, especially in agentic or CI environments. 1. **Look for a `fly.toml`** (or variant like `fly.production.toml`). If found, read the `app` field and run `flyctl status -c fly.toml`: - Success + `Image` is `-` → first deploy; the app already exists, so run `flyctl launch --name --force-name --no-create` to scaffold `Dockerfile` and perform the first deploy without creating a duplicate app. - Success + `Image` has a value → live app; use `flyctl deploy -c fly.toml` for subsequent deploys. - 401/not found → wrong token or app doesn't exist; run `stripe projects status` to disambiguate (matching resource but 401 = wrong token; no matching resource = app not created yet). 2. **No config file** → run `flyctl launch` to generate `fly.toml`, `Dockerfile`, and perform the first deploy. Do not create these files manually. 3. **Config file exists but app is missing on Fly.io** → run `flyctl launch --copy-config -c fly.toml --no-deploy` to register the app and scaffold a `Dockerfile` if needed. Review any generated `Dockerfile` before deploying. 4. **Provisioning app + MPG together — always follow this order:** 1. Create the app first (via `stripe projects create` or `flyctl launch --no-deploy`). 2. Create the MPG cluster. 3. Attach the cluster: `flyctl mpg attach --app ` (injects `DATABASE_URL` automatically). 4. Set remaining secrets: `flyctl secrets set KEY=value --app `. 5. Deploy: `flyctl deploy -c fly.toml`. **Never set secrets on an app that doesn't exist yet** — `flyctl secrets set` will fail with a 404. ## Common Commands ### Apps | Command | Description | |---|---| | `flyctl apps list` | List all apps in your organization | | `flyctl apps create ` | Create a new app | | `flyctl apps destroy ` | Destroy an app (**see note below**) | | `flyctl status --app ` | Show app status and running Machines | | `flyctl logs --app ` | Stream live logs for an app | > **Note on app deletion:** If the app was provisioned through Stripe Projects, **do not use `flyctl apps destroy`**. Use the Stripe Projects CLI instead: > ```sh > stripe projects remove --no-interactive --yes > ``` > This keeps Stripe Projects state consistent. Use `stripe projects status` to find the resource name. ### Deploy | Command | Description | |---|---| | `flyctl deploy` | Build and deploy the current directory | | `flyctl deploy --image ` | Deploy a pre-built Docker image | | `flyctl deploy --remote-only` | Build remotely on Fly.io builders | ### Useful subcommands Machines are low-level VMs you can run directly. Use `flyctl machine --help` for full options. Key subcommands: `list`, `run`, `start`, `stop`, `destroy`, `status`, `update`, `clone`, `exec`, `leases`. Secrets are encrypted environment variables injected into your app's Machines at runtime. Use `flyctl secrets --help` for full options. Key subcommands: `set`, `unset`, `list`, `import`. Scaling controls the number of Machines, their CPU/memory size, and per-region counts. Use `flyctl scale --help` for full options. Key subcommands: `count`, `memory`, `vm`, `show`. ### Managed Postgres (MPG) > **Note:** `flyctl postgres` manages self-hosted (unmanaged) Postgres apps running on Fly Machines — **not** Managed Postgres. Always use `flyctl mpg` for Fly's fully-managed Postgres service. > > If the cluster was provisioned through **Stripe Projects**, prefer the Stripe Projects CLI for lifecycle operations (create, plan changes, credential rotation, destroy) so that Stripe state stays consistent. Use `flyctl mpg` for day-to-day operations (connect, databases, users, backups, etc.). Managed Postgres clusters are fully managed PostgreSQL instances. Use `flyctl mpg --help` for full options. Key subcommands: - **Lifecycle**: `list`, `create`, `status`, `destroy` - **Connectivity**: `attach` (sets `DATABASE_URL` secret on an app), `detach`, `connect` (psql shell), `proxy` (local tunnel) - **Databases**: `databases list`, `databases create` - **Users**: `users list`, `users create`, `users set-role`, `users delete` - **Backups**: `backup list`, `backup create`, `restore` ### Networking & Certificates | Command | Description | |---|---| | `flyctl ips list --app ` | List allocated IP addresses | | `flyctl ips allocate-v4 --app ` | Allocate a dedicated IPv4 address | | `flyctl ips allocate-v6 --app ` | Allocate an IPv6 address | | `flyctl certs add --app ` | Add a TLS certificate for a custom domain | | `flyctl certs check --app ` | Check certificate status | ### SSH & Console | Command | Description | |---|---| | `flyctl ssh console --app ` | Open an interactive SSH shell into a Machine | | `flyctl ssh console -s --app ` | Select a specific Machine to SSH into | ## Regions Fly.io runs Machines in regions around the world. **Region codes are IATA airport codes** (e.g. `iad` = Dulles, `lhr` = Heathrow). To list available regions: ```sh flyctl platform regions # full names + region codes flyctl platform regions --json # also includes latitude/longitude coordinates ``` Specify a region when creating resources with `--region ` (e.g. `--region iad` for Northern Virginia). When you need to pick a region closest to a specific place in the world, or when the user asks to deploy to a particular country or city, use `flyctl platform regions --json` to get coordinates and calculate proximity manually. ### Managed Postgres (MPG) regions MPG clusters are only available in a subset of regions. **Always pick from this list** when provisioning an MPG cluster: | Code | Location | |-------|---------------------------------| | `ams` | Amsterdam, Netherlands | | `fra` | Frankfurt, Germany | | `gru` | São Paulo, Brazil | | `iad` | Ashburn, Virginia (US) | | `lax` | Los Angeles, California (US) | | `lhr` | London, United Kingdom | | `nrt` | Tokyo, Japan | | `ord` | Chicago, Illinois (US) | | `sin` | Singapore | | `sjc` | San Jose, California (US) | | `syd` | Sydney, Australia | | `yyz` | Toronto, Canada | When provisioning an MPG cluster alongside an app, **prefer the same region as the app's `primary_region`** if that region appears in the list above. This minimises latency between the app and the database. If the app's primary region is not in the list, pick the geographically closest one. ## flyctl.toml — App Configuration Most apps include a `fly.toml` file in the project root that defines app settings. Key sections: ```toml app = "my-app-name" [build] dockerfile = "Dockerfile" [http_service] internal_port = 8080 force_https = true [[vm]] memory = "1gb" cpu_kind = "shared" cpus = 1 ``` Run `flyctl config validate` to check your `fly.toml` for errors. ### `primary_region` — let Fly.io choose on first deploy **Do not set `primary_region` in a generated `fly.toml` before running `flyctl launch` or performing the very first deployment.** When the field is absent, Fly.io automatically selects the region closest to the user triggering the deploy, giving them the best possible latency out of the box. Only add `primary_region` explicitly after the first deploy if you have a specific reason to pin the app to a particular region (e.g. data-residency requirements or co-location with another resource). ## Managed Postgres (MPG) — Full Reference Fly.io's **Managed Postgres** (MPG) is a fully-managed database service. Fly handles provisioning, failover, backups, and upgrades. It is distinct from `flyctl postgres`, which creates self-hosted Postgres apps running on Fly Machines and requires manual management. ### Stripe Projects and MPG lifecycle When an MPG cluster is provisioned through **Stripe Projects**, use the Stripe Projects CLI for core lifecycle operations so that billing and resource state stay in sync: - **Create a cluster** → `stripe projects create` - **Change the plan** → `stripe projects update` - **Rotate credentials** → `stripe projects rotate-credentials` - **Destroy a cluster** → `stripe projects remove --no-interactive --yes` For everything else (connecting, managing databases and users, inspecting status, backups), use `flyctl mpg` directly. ### Credentials returned by Stripe Projects for an MPG cluster When an MPG cluster reaches `complete` status, Stripe Projects returns an `access_configuration` with three fields: | Field | Description | |---|---| | `connection_url` | The default PostgreSQL connection string via PgBouncer (fly-user / fly-db) | | `cluster_id` | The MPG cluster ID (hashid) — **required for every `flyctl mpg` command** | | `org_token` | An org-scoped macaroon token to authenticate `flyctl mpg` commands — also covers all apps in the same organization | The token is named `"Stripe Projects MPG "` in the Fly.io dashboard so it is easy to identify and revoke manually if needed. **Always store both `cluster_id` and `org_token`** from the provisioning response — they are needed to operate the cluster via `flyctl mpg`. Example workflow: ```sh # No FlyV1 prefix needed for org tokens export FLY_API_TOKEN="" flyctl mpg status flyctl mpg attach --app my-app # injects DATABASE_URL secret flyctl mpg databases create --name myapp_production flyctl mpg users create --username myapp --role writer flyctl mpg connect # interactive psql shell ``` Rotating credentials via `stripe projects rotate-credentials` revokes the old `org_token` and issues a new one. Update `FLY_API_TOKEN` (and any stored secrets) with the fresh token after rotation. For all other operations (proxy, multiple databases, user roles, backups, destroy), run `flyctl mpg --help`. ## Sprites **Sprites** is a managed browser sandbox service. Use the `sprite` CLI to manage and interact with sprites. ### Installation ```sh # macOS / Linux curl https://sprites.dev/install.sh | bash # Windows (PowerShell) iwr https://sprites.dev/install.ps1 -useb | iex ``` ### Authentication Export `SPRITE_TOKEN` with the token obtained from the `flyio/sprite` resource — this logs you in automatically without needing to run `sprite login`: ```sh export SPRITE_TOKEN="" # Confirm you're logged in sprite org list ``` ### Key commands ```sh # Create a new sprite (first run drops you straight into the console) sprite create SPRITE_NAME # Run a command inside a sprite sprite exec -s SPRITE_NAME ls -la # Connect to an existing sprite's console sprite console -s SPRITE_NAME ``` **Always pass `-s SPRITE_NAME`** with the sprite name the user asked for. ### Reference - User docs: https://docs.sprites.dev/ - API reference: https://sprites.dev/api ## Further Help - Full documentation: https://fly.io/docs/ - Machines API reference: https://api.machines.dev/ - Community forum: https://community.fly.io/ For any `flyctl` command, append `--help` to see usage details: ```sh flyctl --help ```