Automation: flyctl, the Machines API, tokens and MCP
Fly.io is a CLI-first platform: flyctl does everything, the Machines REST API is the lower-level path for custom orchestration, and tokens are macaroons you can scope down to one app or one command. There is no Terraform provider, and Fly.io says that is intentional (https://docs.fly.io/blueprints/infra-automation-without-terraform/).
This page is drawn from https://docs.fly.io/flyctl/, https://docs.fly.io/flyctl/install/, https://docs.fly.io/flyctl/integrating/, https://docs.fly.io/launch/create/, https://docs.fly.io/launch/deploy/, https://docs.fly.io/launch/continuous-deployment-with-github-actions/, https://docs.fly.io/machines/api/working-with-machines-api/, https://docs.fly.io/security/tokens/, https://docs.fly.io/networking/dynamic-request-routing/, https://docs.fly.io/model-context-protocol/, https://docs.fly.io/model-context-protocol/agent-skills/, https://docs.fly.io/model-context-protocol/setup-agent/ and https://mcp.fly.io/guide.md (fetched 2026-11-04).
flyctl: install, sign in, the core loop
- Install. Homebrew on macOS is
brew install flyctl; the install scriptcurl -L https://fly.io/install.sh | shworks on macOS and Linux; Windows uses a PowerShell script (https://docs.fly.io/flyctl/install/). - Sign in.
fly auth signupandfly auth loginare the two entry points (https://docs.fly.io/flyctl/). Login is browser-based by default, with email/password and one-time-password options (https://docs.fly.io/flyctl/cmd/fly_auth_login/). - The core commands.
fly launchcreates an app,fly deployships it, andfly secrets,fly logs,fly status,fly releases,fly ipsandfly certscover day two (https://docs.fly.io/flyctl/).
fly launch and fly deploy
fly launch is run from the project’s source directory. For most languages and frameworks it generates a Dockerfile and usually a .dockerignore, and you edit and commit that Dockerfile yourself (https://docs.fly.io/launch/create/). Framework scanners are strongest for Elixir/Phoenix, Laravel, Rails and Django (https://docs.fly.io/launch/create/). fly launch --no-deploy creates the app and fly.toml without releasing (https://docs.fly.io/launch/deploy/).
fly deploy builds or fetches the image, then updates Machines as a group using the local fly.toml (https://docs.fly.io/launch/deploy/). Facts a support engineer needs:
| Topic | What the docs say |
|---|---|
| Image choice | --image or [build] in fly.toml wins over any Dockerfile; then the [build] method; then --dockerfile; then a Dockerfile in the working directory (https://docs.fly.io/launch/deploy/) |
| First deploy | With no process groups defined, the first deployment gives two Machines for process groups with services, one Machine when a volume is mounted, and one started plus one stopped standby Machine for groups without services (https://fly.io/docs/launch/deploy/, https://fly.io/docs/apps/app-availability/) |
| Strategies | rolling (default), immediate, canary, bluegreen (https://docs.fly.io/launch/deploy/) |
| Release command | A one-off command in a temporary VM before release, good for migrations, with no access to mounted volumes (https://docs.fly.io/launch/deploy/) |
| Builds | Remote by default; --local-only uses local Docker; --image skips building; --buildkit is experimental (https://docs.fly.io/flyctl/integrating/) |
Say: “Setting a secret restarts your Machines.” The docs state that fly secrets set triggers a new deployment, and --stage defers it (https://docs.fly.io/launch/deploy/, https://docs.fly.io/apps/secrets/).
Tokens and scopes
Fly.io access tokens are macaroons with predefined scopes, from org-wide down to running one command on one app’s Machines (https://docs.fly.io/security/tokens/).
| Command | Scope | Source |
|---|---|---|
fly tokens create deploy | One app; the default for CI | https://docs.fly.io/flyctl/integrating/ |
fly tokens create org | Every app in one organization | https://docs.fly.io/security/tokens/ |
fly tokens create readonly | Read-only across one org | https://docs.fly.io/flyctl/integrating/ |
fly tokens create ssh | SSH to one app (also allowed on the org WireGuard network) | https://docs.fly.io/security/tokens/ |
fly tokens create machine-exec | Only the command you name, via --command | https://docs.fly.io/flyctl/integrating/ |
- Expiry. “Tokens are valid for 20 years (175200h0m0s) by default.” Set
--expiry(or-x) to the shortest duration that works (https://docs.fly.io/security/tokens/). - Do not use the login token in CI. The docs say the
fly auth tokenoutput is “no longer” the right API token for everything, and call it deprecated and hidden (https://docs.fly.io/security/tokens/, https://docs.fly.io/flyctl/integrating/). - Env vars.
FLY_API_TOKENskips interactive auth and beats a saved login;FLY_ACCESS_TOKENis an alternative name that wins if both are set;FLY_APPnames the target app (https://docs.fly.io/flyctl/integrating/). - Machine identity.
POST /v1/tokens/oidcreturns an OpenID Connect JWT for a Machine, with theaudclaim you set (https://docs.fly.io/machines/api/tokens-resource/).
CI/CD with GitHub Actions
The documented path is: create a deploy token, store it as the repository secret FLY_API_TOKEN, and run superfly/flyctl-actions/setup-flyctl then flyctl deploy --remote-only (https://docs.fly.io/launch/continuous-deployment-with-github-actions/). The same flyctl docs show a monorepo matrix using FLY_APP and a staging-on-push, production-on-release pattern (https://docs.fly.io/flyctl/integrating/). For GitLab CI, CircleCI, Jenkins or Buildkite the setup is the same three steps: install flyctl, set FLY_API_TOKEN, run commands (https://docs.fly.io/flyctl/integrating/).
Infrastructure as code
“Fly.io has no Terraform provider” is the blueprint’s own description, and it recommends flyctl plus GitHub Actions for most users (https://docs.fly.io/blueprints/infra-automation-without-terraform/). A 2022 changelog entry says an official Terraform provider was released (https://fly.io/blog/logbook-2022-06-01/); treat the current docs as the answer and the old post as history. Scripts of flyctl commands are “linear and imperative, not declarative or idempotent” (https://docs.fly.io/blueprints/infra-automation-without-terraform/). Pulumi: not in the corpus [verify].
The Machines REST API
- Base URLs. Public
https://api.machines.dev; internalhttp://_api.internal:4280from inside your private WireGuard network (https://docs.fly.io/machines/api/working-with-machines-api/). - Auth.
Authorization: Bearer <fly_api_token>on every request;fly tokens deploymints a token for the app in your current directory (https://docs.fly.io/machines/api/working-with-machines-api/). - Resources. Apps, Machines, Volumes, Certificates and Tokens, plus an OpenAPI 3.0 spec;
fly-gois the Go client flyctl is built on (https://docs.fly.io/machines/api/). - Rate limits. “1 request, per second, per action”, bursting to 3 req/s; Get Machine allows 5 req/s with a burst of 10; app deletions are capped at 100 per minute (https://docs.fly.io/machines/api/working-with-machines-api/).
- Create a Machine.
POST /v1/apps/{app_name}/machinesboots by default;skip_launchcreates without booting. Creation can fail on capacity, so you must handle retry or another region (https://docs.fly.io/machines/api/machines-resource/). - Leases and metadata. A lease nonce goes in the
fly-machine-lease-nonceheader; metadata has its own GET, POST and DELETE endpoints, andGET /machines?metadata.foo=barfilters (https://docs.fly.io/machines/api/machines-resource/). - Fly-Replay. An app answers with a
fly-replayheader and Fly Proxy replays the request to aregion,instance,apporprefer_instance(https://docs.fly.io/networking/dynamic-request-routing/).
MCP and agent skills
- Run MCP servers on Fly.
fly mcp launch "uvx mcp-server-time" --claude --server timedeploys a stdio server to a Machine and configures the client; bearer auth is on by default (https://docs.fly.io/model-context-protocol/launch/). Allfly mcpsubcommands are marked experimental (https://docs.fly.io/flyctl/cmd/fly_mcp/). - flyctl’s local MCP server.
fly mcp server --claude(also Cursor, Neovim, VS Code, Windsurf, Zed) exposes apps, certs, logs, machine, orgs, platform, secrets, status and volumes (https://docs.fly.io/model-context-protocol/flyctl-server/). - Hosted Fly MCP.
https://mcp.fly.iosigns in with browser OAuth; you pick organizations, apps and Sprites permissions on one consent screen, with no pasted token (https://mcp.fly.io/guide.md). Per its tool reference, it covers apps, Machines, volumes, secrets, Managed Postgres and Sprites; deployment workflows, app creation and org administration are not included, and Managed Postgres tools never delete or return passwords (https://mcp.fly.io/guide.md). - Agent skills.
fly skills installwrites theflyandbrandskills from superfly/skills into each detected agent’s skills directory (https://docs.fly.io/model-context-protocol/agent-skills/).fly setup agentinstalls the skills and adds the MCP entry in one step; it needs a flyctl release after v0.5.1 (https://docs.fly.io/model-context-protocol/setup-agent/).
Lead with: “Use a deploy token in CI, a readonly token for dashboards, and the hosted MCP when an agent only needs to look.”