Skip to main content

Documentation Index

Fetch the complete documentation index at: https://getfloo.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks a Rails app from local code to a production URL with a database and per-user auth. Every step has runnable Rails code. By the end you have a working app at https://<app>.on.getfloo.com with a Postgres sibling service, signed-in users, and (optionally) your own domain. If you’ve never deployed to floo before, read Golden Path first for the minimal three-command flow. This page is the Rails-specific version.

Before you start

You need:
  • A Rails 7+ project (or a fresh rails new).
  • The project pushed to a GitHub repository (public or private). floo pulls source from GitHub — it does not upload local files.
  • The floo CLI installed and authenticated (curl -fsSL https://getfloo.com/install.sh | bash then floo auth login).
  • The floo GitHub App installed on your repo’s org. The CLI prompts you to install during floo apps github connect.

1. Add a Dockerfile

Rails 7.1+ ships with a production-ready Dockerfile from rails new. If yours doesn’t, generate one:
bin/rails generate dockerfile
Or write a minimal one:
Dockerfile
FROM ruby:3.3-slim

RUN apt-get update -qq && \
    apt-get install -y --no-install-recommends \
      build-essential libpq-dev libyaml-dev && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY Gemfile Gemfile.lock ./
RUN bundle config set --local without 'development test' && \
    bundle install --jobs 4

COPY . .
RUN bundle exec rails assets:precompile

ENV RAILS_ENV=production
ENV RAILS_LOG_TO_STDOUT=1
ENV RAILS_SERVE_STATIC_FILES=1
EXPOSE 3000

CMD ["bin/rails", "server", "-b", "0.0.0.0", "-p", "3000"]
Bind to 0.0.0.0, not localhost. Cloud Run only routes traffic to processes bound to all interfaces.

2. Initialize the floo config

From the repo root:
floo init my-rails-app
This writes floo.app.toml. For a single-service Rails app it looks like:
floo.app.toml
[app]
name = "my-rails-app"

[services.web]
type = "web"
path = "."
port = 3000
ingress = "public"
dev_command = "bin/rails server -p 3000"
migrate_command = "bin/rails db:migrate"
migrate_command runs after every deploy (against the dev schema) and after every promote (against the prod schema). It’s how Rails migrations stay in sync with deploys.

3. Connect the repo and deploy

git add . && git commit -m "feat: floo config + Dockerfile"
git push origin main
floo apps github connect owner/my-rails-app
github connect does three things:
  1. Creates the floo app if it doesn’t exist.
  2. Wires the GitHub repo as the source.
  3. Triggers the first deploy.
Watch the build:
floo deploys watch --app my-rails-app
When it’s done:
floo apps status my-rails-app
Your Rails app is live at https://my-rails-app-dev.on.getfloo.com.Every git push origin main ships to dev. When you’re ready, floo releases promote --app my-rails-app publishes to https://my-rails-app.on.getfloo.com.

4. Local development and one-shot commands

Once your first deploy is up, you don’t need to redeploy to iterate. Two commands cover the daily Rails workflow.

Local dev server with prod-shaped env

floo dev --app my-rails-app --service web
Runs dev_command (the bin/rails server line in floo.app.toml) locally, with DATABASE_URL and other env vars sourced from your dev-environment floo app. You get a real Cloud SQL connection from your laptop without exporting credentials. To test signed-in flows without writing a fixture-user shim in your Rails code, add --fixture-user:
floo dev --app my-rails-app --service web --fixture-user you@example.com
floo dev then starts a small proxy in front of each accounts-mode service that injects the same X-Floo-User-* headers floo’s gateway adds in production. The output table shows both the raw service URL and the auth-proxied URL — hit the auth-proxied one when testing dashboard/profile/etc. paths.

One-shot commands: rake tasks, console, db:seed

floo run executes a single command with the same managed-service env vars floo dev injects — no server, just the command. Pass the command after --:
# Run a rake task against your dev database
floo run --service web -- bundle exec rake my_task

# Seed the dev database
floo run --service web -- bin/rails db:seed

# Open a Rails console connected to dev Postgres
floo run --service web -- bin/rails console

# Run a migration manually (outside the deploy path)
floo run --service web -- bin/rails db:migrate
floo run inherits stdin/stdout/stderr, so interactive commands like bin/rails console and byebug work the same as running them locally — the only difference is your shell sees the floo-injected env vars instead of whatever’s in your local .env.
Migrations run automatically on every deploy via migrate_command in floo.app.toml. Use floo run -- bin/rails db:migrate only for ad-hoc migration work outside the deploy path.

5. Add a Postgres database

floo services add postgres --app my-rails-app
This provisions the database, injects DATABASE_URL plus standard PG* component vars into your app’s runtime, and writes .floo/services.lock. Commit the lock file so PR reviewers see managed-service changes alongside code:
git add .floo/services.lock && git commit -m "feat: add postgres"
git push origin main
Rails reads DATABASE_URL automatically. Confirm config/database.yml has the production block:
config/database.yml
production:
  primary:
    url: <%= ENV["DATABASE_URL"] %>
The next deploy runs your migrate_command against the new database before traffic shifts. Dev and prod each get isolated schemas and credentials — no shared state, no cross-environment leaks. DATABASE_URL is a normal PostgreSQL URI, so Rails/ActiveRecord can parse it directly. You do not need custom Cloud SQL socket parsing in config/database.yml. floo preflight also warns if a local env file still contains the old Cloud SQL socket-style DATABASE_URL shape (postgresql://user:pass@/db?host=/cloudsql/...), which Ruby’s URI parser rejects before Rails can boot.

6. Add per-user auth

floo manages user authentication for you. Set access_mode = "accounts" in floo.app.toml:
floo.app.toml
[app]
name = "my-rails-app"
access_mode = "accounts"
Push and deploy. From the next deploy onward, floo’s gateway sits in front of your app and:
  • Redirects unauthenticated requests to a hosted login page.
  • Validates the session cookie on every request.
  • Injects identity headers into every request that reaches your Rails app.
Your Rails controllers read the headers — no auth code, no callback handlers, no session storage:
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :load_floo_user

  private

  def load_floo_user
    @current_user_email = request.headers["X-Floo-User-Email"]
    @current_user_id    = request.headers["X-Floo-User-Id"]
    @current_user_name  = request.headers["X-Floo-User-Name"]
  end
end
For local development, run floo dev --fixture-user (see section 4) — it injects the same X-Floo-User-* headers floo’s gateway adds in production, so the controller above works locally without any conditional code. For the full reference on access modes and identity headers, see Add User Auth to Your App.

7. Add a custom domain

floo domains add app.example.com --app my-rails-app
The output shows the CNAME record to add at your DNS provider. Once it propagates, click “Verify DNS” in the dashboard or wait for the auto-poll. If your app needs request.host to match the custom domain (for redirects, mailer URLs, etc.), Rails reads it from the Host header automatically — no extra config needed.

Common gotchas

  • /healthz is reserved. Cloud Run’s edge intercepts that exact path. Use /health or /livez for health checks.
  • bind: 0.0.0.0, not localhost. Rails binds to localhost by default in some configs — that won’t accept Cloud Run traffic.
  • Asset compilation. RAILS_SERVE_STATIC_FILES=1 is set in the Dockerfile above so Rails serves precompiled assets directly. For high-traffic apps, push assets to floo’s storage service or a CDN.
  • Force-SSL. Rails 7+ defaults config.force_ssl = true in production. floo’s edge handles TLS termination and forwards X-Forwarded-Proto: https, so this works correctly without extra config.

What’s next

Add User Auth — full reference

Identity headers, access policies, and access modes in detail.

Managed Services

Postgres, Redis, Storage — what they cost and how isolation works.

Custom Domains

DNS, verification, multi-service routing.

Environments

Dev vs prod, promotion, env overrides.