Fly.io

Complete Fly.io Deployment Guide for Rails App

A beginner-friendly, step-by-step guide to deploying Ruby on Rails applications to Fly.io with Supabase database, custom domain, and email setup.

Table of Contents

Prerequisites


This content originally appeared on DEV Community and was authored by Quinterabok

Complete Fly.io Deployment Guide for Rails App

A beginner-friendly, step-by-step guide to deploying Ruby on Rails applications to Fly.io with Supabase database, custom domain, and email setup.

Table of Contents

  1. Prerequisites
  2. Part 1: Install Fly CLI
  3. Part 2: Set Up Supabase Database
  4. Part 3: Deploy to Fly.io (Testing)
  5. Part 4: Create Admin User
  6. Part 5: Deploy to Production
  7. Part 6: Buy and Connect Domain
  8. Part 7: Set Up Email Forwarding
  9. Part 8: Managing Your App
  10. Troubleshooting

Prerequisites

Before starting, ensure you have:

  • ✅ A Rails application ready to deploy
  • ✅ Git installed and your code committed
  • ✅ AWS S3 bucket set up for file storage (or similar)
  • ✅ Terminal/Command line access
  • ✅ Credit/debit card for domain purchase (~$10/year)

Cost Estimate:

  • Fly.io hosting: $5-10/month
  • Supabase database: FREE
  • Domain name: ~$10/year
  • Email: FREE (forwarding)
  • Total: ~$70-130/year

Part 1: Install Fly CLI

Step 1: Install Fly.io Command Line Tool

For macOS/Linux:

curl -L https://fly.io/install.sh | sh

For Windows (PowerShell):

powershell -Command "iwr https://fly.io/install.ps1 -useb | iex"

Step 2: Sign Up / Login

# Sign up for new account
fly auth signup

# Or login if you have an account
fly auth login

Follow the browser prompts to complete authentication.

Step 3: Verify Installation

fly version

You should see the Fly CLI version number.

Part 2: Set Up Supabase Database

Why Supabase?

  • ✅ FREE tier (500MB database)
  • ✅ Automatic backups
  • ✅ Great dashboard
  • ✅ Saves $38/month vs Fly Postgres

Step 1: Create Supabase Account

  1. Go to: https://supabase.com
  2. Click "Start your project"
  3. Sign up with GitHub, Google, or Email

Step 2: Create Organization (First Time)

  1. Enter organization name (e.g., "My Company")
  2. Click "Create organization"

Step 3: Create New Project

Fill in the form:

  • Name: your-app-name-prod (e.g., name-website-prod)
  • Database Password: Click refresh icon to generate
    • IMPORTANT: Copy and save this password!
    • Example: Kx9mP#vL2nQ8wR5t
  • Region: Choose closest to your users
    • Southeast Asia (Singapore)
    • West EU (Ireland)
    • East US (North Virginia)
  • Pricing Plan: FREE (already selected)

Click "Create new project" and wait 1-2 minutes.

Step 4: Get Database Connection String

  1. Click ⚙️ Settings (left sidebar)
  2. Click "Database"
  3. Scroll to "Connection string"
  4. Click "URI" tab
  5. Copy the connection string
  6. Replace [YOUR-PASSWORD] with your actual password from Step 3

Example final URL:

postgresql://postgres.abcdefghijklmno:Kx9mP#vL2nQ8wR5t@aws-0-ap-southeast-1.pooler.supabase.com:6543/postgres

Save this URL - you'll need it soon!

Part 3: Deploy to Fly.io (Testing)

Step 1: Navigate to Your Project

cd /path/to/your-rails-app

Step 2: Initialize Fly.io App

fly launch --no-deploy

You'll be asked several questions:

Question 1: Copy existing fly.toml?

Answer: N (No) - Start fresh

Question 2: App name

Enter: your-app-test (e.g., name-website-test)

Question 3: Organization

Select: Personal (or your organization)

Question 4: Region

Select: Closest to you or your users (e.g., sin for Singapore)

Question 5: Tweak settings?

Answer: Y (Yes)

Step 3: Configure Settings in Browser

A browser window opens with configuration form:

Fill in:

  1. App name: your-app-test (already filled)
  2. Organization: Personal (already selected)
  3. Region: Keep your selection
  4. Internal port: 8080
  5. VM Memory: 2GB (select from dropdown)
  6. Postgres Provider: Select none (we're using Supabase)
  7. Tigris Object Storage: Select Disabled (using S3)
  8. Redis: Keep none
  9. Sentry: Keep Disabled

Click "Confirm Settings"

Step 4: Set Environment Secrets

Back in your terminal, set your secrets:

Generate SECRET_KEY_BASE:

rails secret

Copy the output.

Set Database URL (from Supabase):

fly secrets set DATABASE_URL="postgresql://postgres.abc:yourpassword@aws-0-region.pooler.supabase.com:6543/postgres" --app your-app-test

Set Rails Secret:

fly secrets set SECRET_KEY_BASE="paste-secret-from-rails-secret-command" --app your-app-test

Set AWS S3 Credentials (if using S3):

fly secrets set AWS_ACCESS_KEY_ID="your-aws-key" --app your-app-test
fly secrets set AWS_SECRET_ACCESS_KEY="your-aws-secret" --app your-app-test
fly secrets set AWS_REGION="your-region" --app your-app-test
fly secrets set BUCKET_NAME="your-bucket-name" --app your-app-test
fly secrets set AWS_ENDPOINT_URL_S3="your-s3-endpoint" --app your-app-test

Verify All Secrets:

fly secrets list --app your-app-test

You should see all your secrets listed (shows digests, not actual values).

Step 5: Update fly.toml Configuration

Open fly.toml in your editor and ensure it looks like this:

app = 'your-app-test'
primary_region = 'sin'
console_command = '/rails/bin/rails console'

[build]

[env]
  PORT = '8080'
  RAILS_ENV = 'production'
  RAILS_LOG_TO_STDOUT = 'true'

[processes]
  app = './bin/rake litestream:run ./bin/rails server'

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = 'stop'
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

  [[http_service.checks]]
    interval = '10s'
    timeout = '2s'
    grace_period = '5s'
    method = 'GET'
    path = '/up'
    protocol = 'http'
    tls_skip_verify = false
    [http_service.checks.headers]
      X-Forwarded-Proto = 'https'

[[vm]]
  memory = '2gb'
  cpu_kind = 'shared'
  cpus = 1

Step 6: Deploy Your App

fly deploy --app your-app-test

Wait 3-5 minutes for the build and deployment to complete.

Watch logs in another terminal:

fly logs --app your-app-test

Step 7: Run Database Migrations

fly ssh console --app your-app-test -C "rails db:migrate"

Step 8: Test Your App

fly open --app your-app-test

Your app opens at: https://your-app-test.fly.dev

✅ Test Environment is Live!

Part 4: Create Admin User

Step 1: SSH into Your App

fly ssh console --app your-app-test

Step 2: Start Rails Console

./bin/rails console

Or:

bundle exec rails console

Step 3: Create Admin

Admin.create!(
  email: 'admin@example.com',
  password: 'TestPassword123!',
  password_confirmation: 'TestPassword123!'
)

Note: Replace Admin with User if your model is called User. Adjust fields based on your model.

Step 4: Verify Admin Created

Admin.last

Should show your newly created admin.

Step 5: Exit

exit  # Exit Rails console
exit  # Exit SSH

Alternative: One-Line Command

From your local terminal:

fly ssh console --app your-app-test -C "./bin/rails runner \"Admin.create!(email: 'admin@example.com', password: 'TestPassword123!', password_confirmation: 'TestPassword123!')\""

Step 6: Test Admin Login

  1. Visit your app: https://your-app-test.fly.dev/admin
  2. Login with credentials you just created
  3. Verify everything works ✅

Part 5: Deploy to Production

Now that testing works, let's create a production environment.

Step 1: Create Production App

fly launch --no-deploy

Configuration:

  • App name: your-app-prod
  • Region: Same as test or closer to users
  • Tweak settings: Y (Yes)

Step 2: Configure Production Settings

In the browser form:

  • App name: your-app-prod
  • Region: Choose production region
  • Internal port: 8080
  • VM Memory: 2GB (more for production)
  • Postgres: none (using Supabase)
  • Tigris: Disabled

Click "Confirm Settings"

Step 3: Create Production Supabase Database

Option A: Use Same Database

  • Use the same Supabase database for production
  • Good for small projects
  • Cost: FREE

Option B: Create Separate Database (Recommended)

  1. Go to Supabase dashboard
  2. Create new project: your-app-prod
  3. Get new DATABASE_URL
  4. Keep test and production data separate ✅

Step 4: Set Production Secrets

# Generate NEW secret for production
rails secret

# Set database URL
fly secrets set DATABASE_URL="your-production-supabase-url" --app your-app-prod

# Set NEW secret key base
fly secrets set SECRET_KEY_BASE="new-secret-from-rails-secret" --app your-app-prod

# Copy AWS credentials (or use different production bucket)
fly secrets set AWS_ACCESS_KEY_ID="your-aws-key" --app your-app-prod
fly secrets set AWS_SECRET_ACCESS_KEY="your-aws-secret" --app your-app-prod
fly secrets set AWS_REGION="your-region" --app your-app-prod
fly secrets set BUCKET_NAME="your-production-bucket" --app your-app-prod
fly secrets set AWS_ENDPOINT_URL_S3="your-s3-endpoint" --app your-app-prod

# Verify
fly secrets list --app your-app-prod

Step 5: Update Production fly.toml

Open fly.toml and update:

app = 'your-app-prod'
primary_region = 'sin'

[env]
  PORT = '8080'
  RAILS_ENV = 'production'

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = 'suspend'
  auto_start_machines = true
  min_machines_running = 1  # Keep 1 always running in production

[[vm]]
  memory = '2gb'
  cpu_kind = 'shared'
  cpus = 2  # More CPU for production

Step 6: Deploy Production

fly deploy --app your-app-prod

Wait for deployment to complete.

Step 7: Run Migrations

fly ssh console --app your-app-prod -C "rails db:migrate"

Step 8: Create Production Admin

fly ssh console --app your-app-prod -C "./bin/rails runner \"Admin.create!(email: 'admin@yourdomain.com', password: 'StrongProductionPassword123!', password_confirmation: 'StrongProductionPassword123!')\""

Save these credentials securely!

Step 9: Test Production App

fly open --app your-app-prod

Visit: https://your-app-prod.fly.dev

✅ Production is Live!

Part 6: Buy and Connect Domain

Step 1: Buy Domain from Namecheap

Why Namecheap?

  • ✅ Cheapest overall (~$10/year)
  • ✅ FREE privacy protection forever
  • ✅ FREE email forwarding
  • ✅ Easy DNS management
  • ✅ Great support

Purchase Process:

  1. Go to: https://www.namecheap.com
  2. Search for your desired domain
  3. Add to cart
  4. At checkout:
    • ✅ Check: WhoisGuard (Privacy Protection) - FREE
    • ❌ Uncheck: PremiumDNS
    • ❌ Uncheck: Email hosting
    • ❌ Uncheck: Website builder
    • ❌ Uncheck: SSL certificate
  5. Complete purchase (~$10-13)

Step 2: Get Fly.io IP Addresses

# Get your production app's IPs
fly ips list --app your-app-prod

Output shows:

VERSION  IP                      TYPE    REGION
v4       66.241.125.202         public  global
v6       2a09:8280:1::a0:a7a4:0 public  global

Copy both IPs - you'll need them next!

Step 3: Add Domain to Fly.io

# Add main domain
fly certs add yourdomain.com --app your-app-prod

# Add www subdomain
fly certs add www.yourdomain.com --app your-app-prod

Example:

fly certs add name.com --app name-website-prod
fly certs add www.noblmed.com --app name-website-prod

Step 4: Configure DNS in Namecheap

Login to Namecheap:

  1. Go to: https://www.namecheap.com
  2. Click "Sign In"
  3. Enter credentials

Go to Domain Management:

  1. Click "Domain List" (left sidebar)
  2. Find your domain
  3. Click "Manage" button

Open Advanced DNS:

  1. Click "Advanced DNS" tab

Delete Old Records:

Look for and DELETE any existing:

  • A Records with @ or blank host
  • CNAME Records with @ or blank host
  • Parking page records

Add New DNS Records:

Record 1 - A Record (IPv4):

Type: A Record
Host: @
Value: 66.241.125.202  (your IPv4 from Step 2)
TTL: Automatic

Click ✅ to save.

Record 2 - AAAA Record (IPv6):

Type: AAAA Record
Host: @
Value: 2a09:8280:1::a0:a7a4:0  (your IPv6 from Step 2)
TTL: Automatic

Click ✅ to save.

Record 3 - CNAME Record (WWW):

Type: CNAME Record
Host: www
Target: your-app-prod.fly.dev.  (note the dot at end!)
TTL: Automatic

Click ✅ to save.

Save All Changes:

Scroll to bottom and click "SAVE ALL CHANGES"

Step 5: Wait for DNS Propagation

Wait 10-30 minutes for DNS changes to spread worldwide.

Check DNS Status:

# Check main domain
dig yourdomain.com

# Check www subdomain
dig www.yourdomain.com

Or check online: https://www.whatsmydns.net/

Step 6: Verify SSL Certificates

After 15-20 minutes:

# Check main domain certificate
fly certs show yourdomain.com --app your-app-prod

# Check www certificate
fly certs show www.yourdomain.com --app your-app-prod

When ready, you'll see:

The certificate for yourdomain.com has been issued.
Status: Ready ✅

Step 7: Test Your Domain

Open browser and visit:

Both should:

  • ✅ Load your website
  • ✅ Show 🔒 padlock (secure HTTPS)
  • ✅ Work perfectly!

🎉 Your Custom Domain is Live!

Part 7: Set Up Email Forwarding

Step 1: Enable Email Forwarding

In Namecheap (still on your domain's management page):

  1. Look for "Mail Settings" or "Email Forwarding" section
  2. Click "Add Forwarder" or "Enable Email Forwarding"

Step 2: Add Email Forwards

Create forwarding rules:

Example forwards:

How to add each:

  1. Click "Add Forwarder"
  2. Alias: Enter admin (without @domain)
  3. Forward to: Enter your Gmail
  4. Click "Add" or ✅
  5. Repeat for other addresses

Step 3: Save Email Settings

Click "Save Changes"

Step 4: Test Email Forwarding

  1. Send test email to: admin@yourdomain.com
  2. Check your Gmail inbox
  3. Should receive within 1-2 minutes ✅

Step 5: Set Up Gmail "Send As" (Optional)

To reply from admin@yourdomain.com:

  1. Open Gmail
  2. Click ⚙️ Settings"See all settings"
  3. Click "Accounts and Import" tab
  4. Find "Send mail as:"
  5. Click "Add another email address"
  6. Enter:
  7. Click "Next Step"
  8. For SMTP, you need paid email service (Google Workspace, Zoho, etc.)

Note: Free forwarding only receives emails. To send, you need:

  • Google Workspace ($6/month)
  • Zoho Mail (free for up to 5 users)
  • Or reply from your Gmail (recipient sees Gmail address)

Part 8: Managing Your App

View App Status

# Check if app is running
fly status --app your-app-prod

# List all machines
fly machine list --app your-app-prod

# View recent logs
fly logs --app your-app-prod

Stop App (When Not in Use)

To save costs when not needed:

# Stop all machines
fly scale count 0 --app your-app-prod

What happens:

  • ✅ App stops completely
  • ✅ No compute charges (only storage)
  • ✅ Visitors see "503 Service Unavailable"
  • ✅ Database and files remain safe

Start App Again

# Start 1 machine
fly scale count 1 --app your-app-prod

What happens:

  • ✅ App starts in 10-30 seconds
  • ✅ Website works normally
  • ✅ Everything restored

Auto-Stop Configuration

Edit fly.toml to automatically stop when idle:

[http_service]
  auto_stop_machines = 'stop'      # Auto-stop when no traffic
  auto_start_machines = true       # Auto-start when visitor arrives
  min_machines_running = 0         # Allow stopping completely

Benefits:

  • ✅ Automatically stops after 5 minutes of no traffic
  • ✅ Automatically starts when someone visits
  • ✅ Saves money on low-traffic sites
  • ⚠️ First visitor waits ~10 seconds for startup

For always-on production:

[http_service]
  auto_stop_machines = false
  auto_start_machines = true
  min_machines_running = 1  # Always keep 1 running

Restart App

fly apps restart your-app-prod

View Dashboard

fly dashboard --app your-app-prod

Opens web dashboard in browser.

SSH into App

fly ssh console --app your-app-prod

Run Rails Console

fly ssh console --app your-app-prod -C "./bin/rails console"

Update App

After making code changes:

# Commit changes to git
git add .
git commit -m "Your changes"

# Deploy update
fly deploy --app your-app-prod

# Watch deployment
fly logs --app your-app-prod

Scale Resources

# Add more memory
fly scale memory 4096 --app your-app-prod

# Add more machines
fly scale count 2 --app your-app-prod

# Change VM type
fly scale vm shared-cpu-2x --app your-app-prod

View Costs

fly orgs show

Shows your current usage and estimated costs.

Troubleshooting

Issue: "Database connection failed"

Solution:

# Verify DATABASE_URL is set
fly secrets list --app your-app-prod

# Re-set if needed
fly secrets set DATABASE_URL="your-correct-url" --app your-app-prod

# Restart app
fly apps restart your-app-prod

Issue: "DNS not resolving"

Solution:

  1. Check DNS records in Namecheap
  2. Verify IPs match: fly ips list --app your-app-prod
  3. Wait 30 more minutes for propagation
  4. Clear browser cache or try incognito

Issue: "SSL certificate not issued"

Solution:

# Check certificate status
fly certs show yourdomain.com --app your-app-prod

# If stuck, remove and re-add
fly certs remove yourdomain.com --app your-app-prod
fly certs add yourdomain.com --app your-app-prod

# Wait 15 minutes

Issue: "App not starting"

Solution:

# Check logs for errors
fly logs --app your-app-prod

# Common issues:
# - Missing SECRET_KEY_BASE
# - Wrong DATABASE_URL
# - Port configuration (should be 8080)

# Verify secrets
fly secrets list --app your-app-prod

# Check fly.toml port settings
cat fly.toml | grep port

Issue: "Can't create admin"

Solution:

# SSH into app
fly ssh console --app your-app-prod

# Check your model name
./bin/rails runner "puts User.column_names"
# or
./bin/rails runner "puts Admin.column_names"

# Create with correct fields
./bin/rails console
Admin.create!(email: 'test@example.com', password: 'password123', password_confirmation: 'password123')

Issue: "File uploads not working"

Solution:

# Verify S3 credentials are set
fly secrets list --app your-app-prod

# Should see:
# - AWS_ACCESS_KEY_ID
# - AWS_SECRET_ACCESS_KEY
# - AWS_REGION
# - BUCKET_NAME
# - AWS_ENDPOINT_URL_S3

# Test S3 connection in Rails console
fly ssh console --app your-app-prod -C "./bin/rails console"
# Then test upload

Issue: "Out of memory errors"

Solution:

# Check current memory
fly status --app your-app-prod

# Increase memory
fly scale memory 4096 --app your-app-prod

# Or reduce memory if overprovisioned
fly scale memory 1024 --app your-app-prod

Issue: "Emails not forwarding"

Solution:

  1. Check Namecheap email forwarding settings
  2. Verify Gmail isn't marking as spam
  3. Wait 30 minutes for DNS changes
  4. Test with different email provider

Get Help

# Fly.io community forum
# https://community.fly.io

# Fly.io documentation
# https://fly.io/docs

# View all Fly commands
fly help

# Get help for specific command
fly help deploy

Quick Command Reference

Deployment

# Initialize app
fly launch --no-deploy

# Deploy app
fly deploy --app your-app-name

# Deploy with specific fly.toml
fly deploy --app your-app-name --config fly.toml

App Management

# View status
fly status --app your-app-name

# View logs
fly logs --app your-app-name

# Restart app
fly apps restart your-app-name

# Stop app
fly scale count 0 --app your-app-name

# Start app
fly scale count 1 --app your-app-name

# Open app in browser
fly open --app your-app-name

SSH & Console

# SSH into app
fly ssh console --app your-app-name

# Run Rails console
fly ssh console --app your-app-name -C "./bin/rails console"

# Run one-off command
fly ssh console --app your-app-name -C "rails db:migrate"

Secrets

# List secrets
fly secrets list --app your-app-name

# Set secret
fly secrets set KEY="value" --app your-app-name

# Unset secret
fly secrets unset KEY --app your-app-name

Domain & SSL

# Add domain
fly certs add yourdomain.com --app your-app-name

# Check certificate
fly certs show yourdomain.com --app your-app-name

# List all certificates
fly certs list --app your-app-name

# Remove certificate
fly certs remove yourdomain.com --app your-app-name

Scaling

# Scale number of machines
fly scale count 2 --app your-app-name

# Scale memory
fly scale memory 2048 --app your-app-name

# Change VM type
fly scale vm shared-cpu-2x --app your-app-name

Database

# Run migrations
fly ssh console --app your-app-name -C "rails db:migrate"

# Create database
fly ssh console --app your-app-name -C "rails db:create"

# Seed database
fly ssh console --app your-app-name -C "rails db:seed"

# Reset database (CAREFUL!)
fly ssh console --app your-app-name -C "rails db:reset"

Cost Breakdown

Monthly Costs

Service Cost Notes
Fly.io Compute $5-10/month Depends on usage
Supabase Database FREE Up to 500MB
AWS S3 Storage $1-5/month Depends on files
Domain Name ~$1/month $10-13/year
Email Forwarding FREE Via Namecheap
SSL Certificates FREE Via Let's Encrypt
Total $7-16/month $84-192/year

Ways to Save

  1. Use auto-stop: App stops when not in use
  2. Use free tier Supabase: Instead of paid Postgres
  3. Share S3 bucket: Use same bucket for test/prod
  4. Buy domain for multiple years: Slight discount
  5. Use email forwarding: Instead of Google Workspace

Next Steps

After completing this guide, you can:

  1. Add monitoring: Set up Sentry or error tracking
  2. Add analytics: Google Analytics, Plausible, etc.
  3. Set up CI/CD: GitHub Actions for auto-deploy
  4. Add custom email: Google Workspace or Zoho
  5. Scale up: Add more machines, memory, regions
  6. Add CDN: Cloudflare for better performance
  7. Set up backups: Automate database backups
  8. Add staging: Create staging environment

Summary

You've learned how to:

✅ Install Fly CLI and set up account
✅ Create FREE Supabase database
✅ Deploy Rails app to Fly.io (test and production)
✅ Create admin users
✅ Buy and connect custom domain
✅ Set up FREE email forwarding
✅ Manage, stop, and start your app
✅ Troubleshoot common issues

Your app is now live with:

  • Custom domain with SSL
  • Professional email addresses
  • Free database
  • Scalable hosting
  • All for ~$7-16/month!

Congratulations! 🎉

Support & Resources

Made with ❤️ for beginners


This content originally appeared on DEV Community and was authored by Quinterabok


Print Share Comment Cite Upload Translate Updates
APA

Quinterabok | Sciencx (2025-10-07T20:39:43+00:00) Fly.io. Retrieved from https://www.scien.cx/2025/10/07/fly-io/

MLA
" » Fly.io." Quinterabok | Sciencx - Tuesday October 7, 2025, https://www.scien.cx/2025/10/07/fly-io/
HARVARD
Quinterabok | Sciencx Tuesday October 7, 2025 » Fly.io., viewed ,<https://www.scien.cx/2025/10/07/fly-io/>
VANCOUVER
Quinterabok | Sciencx - » Fly.io. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/10/07/fly-io/
CHICAGO
" » Fly.io." Quinterabok | Sciencx - Accessed . https://www.scien.cx/2025/10/07/fly-io/
IEEE
" » Fly.io." Quinterabok | Sciencx [Online]. Available: https://www.scien.cx/2025/10/07/fly-io/. [Accessed: ]
rf:citation
» Fly.io | Quinterabok | Sciencx | https://www.scien.cx/2025/10/07/fly-io/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.