Pro Deploy to Fly.io
Viewing latest docs.
Switch version: v3

Deploy to Fly.io

Ship your Petal Pro app to production on Fly.io.

Before you start

There are a few things to think about before deploying — see Deployment fundamentals for the full checklist.

If you’re using Claude Code, the easiest path is to ask:

help me deploy this app to Fly.io

Claude knows the patterns from the CLAUDE.md files and will walk you through the steps below. The rest of this guide is the same flow, in case you want to do it yourself.

Dev scripts

Petal Pro ships with a few convenience scripts in /scripts/:

shell
sh scripts/server.sh      # Start Phoenix + IEx in a tmux session named petal_pro
sh scripts/reset_db.sh    # Drop, create, migrate, and seed the database
sh scripts/kill_db.sh     # Kill stuck Postgres connections (handy when migrations hang)

Launch on Fly.io

Fly.io is the cheapest, easiest place to host a Phoenix app. Petal Pro is configured to deploy there with minimal fuss.

Install the Fly.io CLI, then sign in.

Create a new app with:

shell
fly launch

ℹ️ Information: Fly will prompt you with default settings and ask if you want to tweak them. Hit Y — it opens a browser configuration UI.

In the configuration UI:

  • Give your app a name (you can’t change it later).
  • Under Database, choose Fly Postgres.
  • Pick the cheapest server size to start.
  • Leave Redis as none.
  • Hit Confirm.

The Dockerfile

Petal Pro v4 ships a production-ready Dockerfile in the repo root — you don’t need to generate one with mix phx.gen.release --docker. It’s a multi-stage build:

  • Builder stage: Elixir 1.17.2 / OTP 27 on Debian Bookworm. Compiles deps, runs the npm asset pipeline, produces an Elixir release.
  • Runner stage: Lean Debian Bookworm slim with only the compiled release — no Elixir or build tools in the production image.

fly launch detects the existing Dockerfile and uses it. If it tries to generate a new one, skip that step — the included Dockerfile already has nodejs and npm for the asset pipeline.

Environment variables

fly launch automatically creates these secrets:

  • SECRET_KEY_BASE
  • DATABASE_URL

The generated fly.toml also sets:

  • PHX_HOST
  • PORT

Required

shell
# Email — required for auth flows (confirmation, password reset, etc.)
fly secrets set RESEND_API_KEY="re_..."

Optional

shell
# Sentry error tracking — auto-activates when set, no code changes needed
fly secrets set SENTRY_DSN="https://..."

# Admin MCP API bearer token (for AI tool access)
fly secrets set MCP_ADMIN_TOKEN="your_secure_token"

# Slack notifications (new signups, billing events, daily digest)
fly secrets set SLACK_OAUTH_TOKEN="xoxb-..."
fly secrets set SLACK_CHANNEL_ID="C0123456789"

Auto-deploy on push to main

Petal Pro v4 includes a GitHub Actions workflow at .github/workflows/fly.yml that auto-deploys on push to main:

yaml
name: Deploy to Fly.io
on:
  push:
    branches:
      - main

concurrency:
  group: fly-deploy
  cancel-in-progress: false

jobs:
  deploy:
    name: Deploy app
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: superfly/flyctl-actions/setup-flyctl@master
      - run: flyctl deploy --remote-only
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

To enable it:

  1. fly tokens create deploy -x 999999h to generate a long-lived token
  2. In your GitHub repo: Settings → Secrets and variables → Actions
  3. Add a secret called FLY_API_TOKEN with the token value

cancel-in-progress: false queues deploys instead of cancelling them — so you don’t end up half-deployed if you push twice in a row.

Manual deploy

You can also deploy at any time with:

shell
fly deploy

ℹ️ Information: If deployment fails, you may need to add a payment method — Fly only allows 1 machine per app on the free tier.

After deploying, run fly open to view it in the browser. You’re live.