Fly.io
Sync KeyEnv secrets to Fly.io applications.
Fly.io Integration
Sync secrets from KeyEnv to your Fly.io applications.
Prerequisites
- Fly.io account with an application deployed
- flyctl CLI installed
- KeyEnv service token with read access
Quick Sync
The simplest way to sync secrets:
export KEYENV_TOKEN=your-service-token
keyenv export -p YOUR_PROJECT_ID -e production --format shell | fly secrets importThis exports all secrets from KeyEnv and imports them directly into your Fly.io app.
Sync Script
Create a reusable sync script:
#!/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:
chmod +x sync-to-fly.sh
KEYENV_TOKEN=xxx ./sync-to-fly.shCI/CD Integration
GitHub Actions
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
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:
- mainSelective Sync
Sync only specific secrets:
# 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 importMulti-App Deployment
Sync to multiple Fly.io apps:
#!/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]}"
doneEnvironment-Based Sync
Sync different environments:
#!/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:
# List Fly.io secrets
fly secrets list
# Compare with KeyEnv
keyenv list -p YOUR_PROJECT_ID -e productionRemove Secrets
Remove a secret from Fly.io:
fly secrets unset SECRET_NAMERemove all secrets and re-sync:
# 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 importfly.toml Configuration
While secrets are managed via fly secrets, you can set non-sensitive config in fly.toml:
[env]
LOG_LEVEL = "info"
NODE_ENV = "production"
# Sensitive values come from fly secrets (synced from KeyEnv)
# DATABASE_URL, API_KEY, etc.Best Practices
- Automate in CI/CD - Don't manually sync secrets
- Use separate environments - Don't mix production and staging secrets
- Audit changes - Fly.io tracks secret changes in activity logs
- 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:
fly status
fly logsFormat Issues
Ensure the export format is correct:
# Debug the export
keyenv export -p YOUR_PROJECT_ID -e production --format shell
# Should output:
# KEY1=value1
# KEY2=value2Permission Denied
Verify your Fly.io token:
fly auth whoamiAnd your KeyEnv token:
keyenv whoami