# Fly.io

Sync KeyEnv secrets to Fly.io applications.

Source: https://keyenv.dev/docs/guides/flyio/

Sync secrets from KeyEnv to your Fly.io applications.

## Prerequisites

- Fly.io account with an application deployed
- [flyctl](https://fly.io/docs/hands-on/install-flyctl/) CLI installed
- KeyEnv service token with read access

## Quick Sync

The simplest way to sync secrets:

```bash
export KEYENV_TOKEN=your-service-token
keyenv export -p YOUR_PROJECT_ID -e production --format shell | fly secrets import
```

This exports all secrets from KeyEnv and imports them directly into your Fly.io app.

## Sync Script

Create a reusable sync script:

```bash
#!/bin/bash
# sync-to-fly.sh

set -euo pipefail

PROJECT_ID="${KEYENV_PROJECT:-YOUR_PROJECT_ID}"
ENVIRONMENT="${KEYENV_ENV:-production}"

# Sync secrets
echo "Syncing secrets from KeyEnv ($ENVIRONMENT) to Fly.io..."
keyenv export -p "$PROJECT_ID" -e "$ENVIRONMENT" --format shell | fly secrets import

echo "Done! Fly.io will automatically redeploy."
```

Run it:

```bash
chmod +x sync-to-fly.sh
KEYENV_TOKEN=xxx ./sync-to-fly.sh
```

## CI/CD Integration

### GitHub Actions

```yaml
name: Deploy to Fly.io

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install KeyEnv CLI
        run: curl -fsSL https://keyenv.dev/install.sh | bash

      - name: Setup Fly.io
        uses: superfly/flyctl-actions/setup-flyctl@master

      - name: Sync secrets
        run: |
          export PATH="$HOME/.keyenv/bin:$PATH"
          keyenv export -p ${{ vars.KEYENV_PROJECT }} -e production --format shell | fly secrets import
        env:
          KEYENV_TOKEN: ${{ secrets.KEYENV_TOKEN }}
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

      - name: Deploy
        run: fly deploy
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
```

### GitLab CI

```yaml
deploy:
  stage: deploy
  image: ubuntu:latest
  before_script:
    - apt-get update && apt-get install -y curl
    - curl -fsSL https://keyenv.dev/install.sh | bash
    - curl -L https://fly.io/install.sh | sh
    - export PATH="$HOME/.keyenv/bin:$HOME/.fly/bin:$PATH"
  script:
    - keyenv export -p $KEYENV_PROJECT -e production --format shell | fly secrets import
    - fly deploy
  only:
    - main
```

## Selective Sync

Sync only specific secrets:

```bash
# Export all secrets
secrets=$(keyenv export -p YOUR_PROJECT_ID -e production --format json)

# Filter and sync specific ones
echo "$secrets" | jq -r '.secrets[] | select(.key | startswith("FLY_")) | "\(.key)=\(.value)"' | fly secrets import
```

## Multi-App Deployment

Sync to multiple Fly.io apps:

```bash
#!/bin/bash
# sync-all-apps.sh

APPS=("app-web" "app-api" "app-worker")
ENVIRONMENTS=("production" "production" "production")

for i in "${!APPS[@]}"; do
  echo "Syncing to ${APPS[$i]}..."
  keyenv export -p YOUR_PROJECT_ID -e "${ENVIRONMENTS[$i]}" --format shell | \
    fly secrets import -a "${APPS[$i]}"
done
```

## Environment-Based Sync

Sync different environments:

```bash
#!/bin/bash
# sync-env.sh

ENV=${1:-production}
APP=${2:-my-app}

case "$ENV" in
  production)
    APP_NAME="$APP"
    ;;
  staging)
    APP_NAME="$APP-staging"
    ;;
  *)
    echo "Unknown environment: $ENV"
    exit 1
    ;;
esac

keyenv export -p YOUR_PROJECT_ID -e "$ENV" --format shell | fly secrets import -a "$APP_NAME"
```

## Verify Secrets

Check what secrets are currently set:

```bash
# List Fly.io secrets
fly secrets list

# Compare with KeyEnv
keyenv list -p YOUR_PROJECT_ID -e production
```

## Remove Secrets

Remove a secret from Fly.io:

```bash
fly secrets unset SECRET_NAME
```

Remove all secrets and re-sync:

```bash
# Get current secret names
fly secrets list | tail -n +2 | awk '{print $1}' | xargs fly secrets unset

# Re-sync from KeyEnv
keyenv export -p YOUR_PROJECT_ID -e production --format shell | fly secrets import
```

## fly.toml Configuration

While secrets are managed via `fly secrets`, you can set non-sensitive config in `fly.toml`:

```toml
[env]
  LOG_LEVEL = "info"
  NODE_ENV = "production"

# Sensitive values come from fly secrets (synced from KeyEnv)
# DATABASE_URL, API_KEY, etc.
```

## Best Practices

1. **Automate in CI/CD** - Don't manually sync secrets
2. **Use separate environments** - Don't mix production and staging secrets
3. **Audit changes** - Fly.io tracks secret changes in activity logs
4. **Don't commit tokens** - Use CI/CD secrets for KEYENV_TOKEN and FLY_API_TOKEN

## Troubleshooting

### Secrets Not Updating

Fly.io redeploys automatically when secrets change. Check the deployment:

```bash
fly status
fly logs
```

### Format Issues

Ensure the export format is correct:

```bash
# Debug the export
keyenv export -p YOUR_PROJECT_ID -e production --format shell

# Should output:
# KEY1=value1
# KEY2=value2
```

### Permission Denied

Verify your Fly.io token:

```bash
fly auth whoami
```

And your KeyEnv token:

```bash
keyenv whoami
```
