# Fly.io

> Container-based Django deployment to Fly.io with PostgreSQL, Upstash Redis, and automated database migrations using Docker and flyctl CLI.

Pegasus supports container-based deployment to [Fly.io](https://fly.io/).

### Prerequisites

[Section titled “Prerequisites”](#prerequisites)

If you haven’t already, install the [flyctl CLI](https://fly.io/docs/hands-on/install-flyctl/).

The create an account with `fly auth signup` or login with `fly auth login`.

### Setup

[Section titled “Setup”](#setup)

Once you have logged in via the CLI you can create your app and the services it will need. For each of the commands below follow the prompts given.

In the example below the “Chicago, Illinois (US) (ord)” region is selected. You may change the region to suit your needs, but it should be consistent throughout the commands.

**Create your app in Fly.io**

```bash
$ fly launch --dockerfile Dockerfile.web \
      --dockerignore-from-gitignore \
      --no-deploy \
      --name {app-name} \
      --region ord
```

After running that, answer ‘yes’ to the first question:

```plaintext
An existing fly.toml file was found for app {app-name}
? Would you like to copy its configuration to the new app? Yes
```

Fly will output some details, then ask another question about customizing. Answer ‘yes’ to that as well:

```plaintext
Using dockerfile Dockerfile.web
Creating app in /path/to/app/source


We're about to launch your app on Fly.io. Here's what you're getting:


Organization: Your Name              (fly launch defaults to the personal org)
Name:         {app-name}             (specified on the command line)
Region:       Chicago, Illinois (US) (specified on the command line)
App Machines: shared-cpu-1x, 1GB RAM (most apps need about 1GB of RAM)
Postgres:     <none>                 (not requested)
Redis:        <none>                 (not requested)


? Do you want to tweak these settings before proceeding? (y/N) Yes
```

A browser tab should open where you should add a Fly Postgres database called {app-name}-db, and an Upstash Redis server. You can leave the other defaults or change the machine size as you see fit. It should look something like this:

![Fly DB config](/_astro/fly-db-config.BD0z3j2A_cySWr.webp)

Click “Confirm Settings” and then close the tab. Back on the command line, Fly will output some more things and should eventually end with a message like this:

```plaintext
✓ Configuration is valid
Your app is ready! Deploy with `flyctl deploy`
```

If you see these two lines you are ready to deploy! If not, see the “Troubleshooting” section below.

<!----
2. Create the app database

    ```bash
    $ fly postgres create --name {app-name}-db --region ord

    # ? Select Organization: My Org
    # ? Select configuration: Development - Single node, 1x shared CPU, 256MB RAM, 1GB disk
    ```

3. Attach the DB to your app

    ```bash
    $ fly postgres attach {app-name}-db -a {app-name}

    Postgres cluster {app-name}-db is now attached to {app-name}
    The following secret was added to <app name>:
      DATABASE_URL=postgres://.....
    ```

4. Create the Redis instance

    ```bash
    $ fly redis create --name {app-name}-redis --region ord

    ? Select Organization: My Org (my_org)
    ? Would you like to enable eviction? Yes
    ? Select an Upstash Redis plan Free: 100 MB Max Data Size
    Your Upstash Redis database {app-name}-redis is ready.
    Apps in the personal org can connect to at redis://.....

    ```

5. Set the `REDIS_URL` secret

    Using the Redis URL from the command above run:

    ```bash
    $ fly secrets set REDIS_URL={url}
    ```

--->

### Deploying

[Section titled “Deploying”](#deploying)

You are now ready to deploy your app. You can do this by running:

```bash
$ fly deploy
```

In a few minutes your app should be live! **After deploying, review the [production checklist](/deployment/production-checklist) for a list of common next steps**.

In particular, make sure add your app URL to the `ALLOWED_HOSTS` variable in your environment/settings as well as in the `http_service.checks` section of `fly.toml`.

### Running Database Migrations

[Section titled “Running Database Migrations”](#running-database-migrations)

Database migrations are applied in the release command during deploy. This is configured in the `fly.toml` file.

### Settings and Secrets

[Section titled “Settings and Secrets”](#settings-and-secrets)

Fly.io builds use the `settings_production.py` file. You can add settings here or in the base `settings.py` file, and use environment variables to manage any secrets, following the examples in these files.

Secrets are managed in Fly.io via the web UI or on the command line using the CLI:

```bash
$ fly secrets set MY_VAR=secret_value
```

### Running One-Off Commands

[Section titled “Running One-Off Commands”](#running-one-off-commands)

You can one-off commands via a shell:

```bash
$ fly ssh console


app $ ./code/manage.py [command]
```

### Celery Support

[Section titled “Celery Support”](#celery-support)

Out of the box, Pegasus is configured to run Celery using the [multiprocess support](https://fly.io/docs/reference/configuration/#the-processes-section) provided by Fly.io.

For alternatives see <https://fly.io/docs/app-guides/multiple-processes/>

### Troubleshooting

[Section titled “Troubleshooting”](#troubleshooting)

**My release / migrate command is failing.**

If you get an error like the following when running `fly deploy`

```plaintext
  django.db.utils.OperationalError: connection to server at "localhost" (127.0.0.1), port 5432 failed: Connection refused
    Is the server running on that host and accepting TCP/IP connections?
```

it is likely that your Database is not set up properly. You can confirm if this is the case by running `fly secrets list` and making sure that you see a `DATABASE_URL` variable. If you do not see one, it is not properly connected/attach.

If you need to create a new database, you can run:

```bash
fly postgres create --name {your-app-db}
```

And you can (re-)attach a database to an app by running:

```bash
fly postgres attach {your-app-db} -a {your-app-name}
```

**My deploy keeps timing out.**

If you keep getting an error like the following:

```plaintext
Error: timeout reached waiting for health checks to pass for machine 28749e0b443558
```

You can try re-deploying with a higher timeout. For example, try running:

```bash
flyctl deploy --wait-timeout 5m
```