PreviewDrop for Rails
A live Rails preview for every branch
Rails apps run end-to-end on PreviewDrop: migrations, Active Job workers, Action Cable websockets, Turbo streams. No serverless rewrite, no cold starts, no Edge Runtime compatibility matrix.
TL;DR
Add a Dockerfile, set
RAILS_MASTER_KEY and a DB URL, push. Works with Rails 7.x and 8.x. PG, MySQL, SQLite all supported. Each branch gets its own subdomain — same URL across pushes.Dockerfile
Drop this at the root of your repo. PreviewDrop picks it up on the next push and builds it into a container behind a TLS-terminated subdomain.
DockerfileFROM ruby:3.3-slim RUN apt-get update -qq && apt-get install -y --no-install-recommends \ build-essential libpq-dev libvips nodejs \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY Gemfile Gemfile.lock ./ RUN bundle install --jobs 4 --retry 3 COPY . . RUN SECRET_KEY_BASE=dummy bundle exec rake assets:precompile EXPOSE 3000 CMD ["sh", "-c", "bundle exec rails db:migrate && \ bundle exec rails s -b 0.0.0.0 -p $PORT"]
Environment variables
Set these in the Variables tab of your PreviewDrop project. They're encrypted at rest and injected into every preview container at start.
| Variable | Example value | Note |
|---|---|---|
| RAILS_ENV | production | Use production for previews — closer to real behavior than development. |
| RAILS_MASTER_KEY | <contents of config/master.key> | Required so Rails can decrypt credentials.yml.enc. Never commit the key itself. |
| DATABASE_URL | postgres://user:pass@dev-db.internal/myapp_preview | Point at a shared preview DB, or pair with Neon for per-branch isolation. |
| SECRET_KEY_BASE | <rails secret> | Generate with rails secret. Different from RAILS_MASTER_KEY. |
| RAILS_SERVE_STATIC_FILES | true | Lets Rails serve /assets without nginx in front. |
| RAILS_LOG_TO_STDOUT | true | Streams logs to PreviewDrop’s runtime logs tab. |
Common gotchas
Assets:precompile needs a SECRET_KEY_BASE
Rails 7+ errors on
bundle exec rake assets:precompile if SECRET_KEY_BASEis unset. The Dockerfile above sets a dummy value at build time (it's overridden at runtime by the real value from your Variables tab).force_ssl and redirect loops
PreviewDrop terminates TLS at the edge and proxies HTTP to your container. If your Rails app has
config.force_ssl = true, set config.ssl_options = { redirect: false } or trust the X-Forwarded-Protoheader, otherwise you'll hit a redirect loop.Active Job workers
For Sidekiq or GoodJob workers, create a second PreviewDrop project on the same repo with a worker-specific Dockerfile (
CMD ["bundle", "exec", "sidekiq"]). Both projects share env vars and coordinate via Redis. PreviewDrop won't put the worker behind a public URL — set the Exposed port to a non-HTTP value or leave it unset.ActionMailer in previews
Don't send real email from previews. Set
config.action_mailer.delivery_method = :test or use Mailcatcher / letter_opener_web. Previews are ephemeral — a reviewer opening a preview can accidentally trigger welcome emails to real users if you leave prod SMTP config wired up.Why not Vercel or Netlify?
Vercel doesn't run Rails. You can try
rails-on-lambda-style workarounds, but you lose Sidekiq, ActionCable, long-running uploads, and half your middleware. Rails is a fundamentally stateful framework; PreviewDrop runs it the way it expects — as a persistent process in a container.More Rails patterns
Frameworks & Docker for the full guide;Environment variables for per-branch DB patterns.Preview your Rails app in 5 minutes
Connect a repo, push a branch, get a URL. No credit card, no trial clock.
Start free