Deploying a Ruby on Rails App on Deployxa
Ruby on Rails is the original full-stack web framework, and it is still a favorite of startups and solo founders for building web apps quickly. It is mature, opinionated, and has a rich ecosystem of gems. But deploying Rails has traditionally required writing a Dockerfile (to install Ruby, install gems, precompile assets, and run the app via Puma), configuring the database, and handling the asset pipeline. Deployxa's zero-config engine eliminates all of that, detecting Rails from your Gemfile and configuring the deployment. Here is how to deploy a Ruby on Rails app on Deployxa.
The direct answer is that Deployxa auto-detects Rails from your Gemfile (which includes rails). It configures the build and start commands: the build command is bundle install && rake assets:precompile, the start command is puma -C config/puma.rb, and the runtime is Ruby 3.3. You do not write a Dockerfile, you do not configure Puma manually, and you do not manage the asset pipeline. The platform handles all of it, just as it does for Laravel and Phoenix apps.
Why Rails Is a Great Choice for Startups
Three reasons explain why Rails is a great choice for startups. First, it is fast to build. Rails's convention-over-configuration approach means you can build a full-stack app in hours, not days. For startups that need to iterate quickly, Rails is hard to beat. Second, it is full-stack. Rails includes everything you need (ORM, routing, views, mailers, jobs, websockets), which means you do not need to assemble a stack from multiple libraries. Third, it has a rich ecosystem. Rails has gems for everything (auth, payments, admin, search), which means you can add features quickly. For more on startup deployment, see our article on why indie hackers are moving their micro-SaaS fleets from AWS to Deployxa.
The Architecture: Rails + Puma + Container
Here is how Deployxa deploys a Rails app.
The Rails container
The ingestion service detects Rails from your Gemfile. It configures the build and start commands:
- Build command: bundle install && rake assets:precompile
- Start command: puma -C config/puma.rb
- Runtime: Ruby 3.3
The Puma configuration
Puma is Rails's default web server, which handles concurrent requests via multiple worker processes and threads. The default configuration (in config/puma.rb) is appropriate for most apps, but you can adjust it based on your container's CPU.
The reverse proxy
Traefik v3 routes traffic from your custom domain to the Rails container, with automatic SSL via Let's Encrypt.
Step-by-Step: Deploying a Rails App
Here is the exact workflow for a typical Cursor-generated Rails app.
Step 1: Create your Rails app
rails new my_app --database=postgresql
cd my_app
bundle installStep 2: Create a controller
rails generate controller Pages index health# app/controllers/pages_controller.rb
class PagesController < ApplicationController
def index
render json: { message: 'Hello, World!' }
end
def health
render json: { status: 'ok' }
end
endStep 3: Configure routes
# config/routes.rb
Rails.application.routes.draw do
root 'pages#index'
get '/health', to: 'pages#health'
endStep 4: Configure database.yml
# config/database.yml
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
url: <%= ENV.fetch("DATABASE_URL") { "postgres://localhost:5432/my_app" } %>
development:
<<: *default
database: my_app_development
test:
<<: *default
database: my_app_test
production:
<<: *defaultStep 5: Configure puma.rb
# config/puma.rb
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
port ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "production" }
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
preload_app!
plugin :tmp_restartStep 6: Push to GitHub
git init
git add .
git commit -m "rails app"
git remote add origin https://github.com/yourname/my_app.git
git push -u origin mainStep 7: Connect to Deployxa
In the Deployxa dashboard, connect your repository. Deployxa auto-detects Rails:
[ingest] Detected Ruby project
[ingest] Framework: rails
[ingest] Runtime: ruby 3.3
[ingest] Build command: bundle install && rake assets:precompile
[ingest] Start command: puma -C config/puma.rb
[ingest] Port: $PORTStep 8: Configure environment variables
In the Deployxa dashboard, add:
- DATABASE_URL: your Postgres connection string (e.g., postgres://user:pass@host:5432/myapp)
- RAILS_MASTER_KEY: your Rails master key (from config/master.key)
- RAILS_ENV: production
- RAILS_SERVE_STATIC_FILES: true
The pre-flight scanner will warn you if any are missing. For more on environment variables, see our article on the vibe coder's guide to environment variables.
Step 9: Deploy
Click Deploy. The build installs gems and precompiles assets, the container starts Puma, and your app is live within 60 to 90 seconds.
Step 10: Run database migrations
After the first deployment, run your database migrations:
rails db:migrate RAILS_ENV=productionYou can do this via the Deployxa CLI or by including the migration command in the build process.
Step 11: Add a custom domain
Add a custom domain in the Deployxa dashboard. SSL is provisioned automatically.
Step 12: Verify with deployxa doctor
Run deployxa doctor to verify health. The 14-point readiness engine checks SSL, DNS, environment variables, health endpoints, and container status.
Common Pitfalls and Troubleshooting
The first pitfall is the PORT environment variable. Rails apps typically listen on port 3000 by default, but Deployxa assigns a dynamic port via the PORT environment variable. The fix is to set port ENV.fetch("PORT") { 3000 } in config/puma.rb. The second pitfall is the RAILS_MASTER_KEY. Rails uses a master key to decrypt credentials, which needs to be set as an environment variable in production. The fix is to set RAILS_MASTER_KEY to the value from your config/master.key file. The third pitfall is the asset pipeline. Rails needs to precompile assets (CSS, JS, images) for production, which is done during the build. The fix is to ensure rake assets:precompile is in the build command. The fourth pitfall is the database connection pool. Rails's default pool size (5) is appropriate for most apps, but for high-traffic apps, you might need to adjust it. The fix is to set RAILS_MAX_THREADS (which controls the pool size) based on your app's needs. The fifth pitfall is static file serving. In production, Rails does not serve static files by default (it expects a reverse proxy to serve them). The fix is to set RAILS_SERVE_STATIC_FILES=true (which tells Rails to serve static files) or to configure Traefik to serve them.
Performance: Rails vs Laravel vs Phoenix
Rails, Laravel, and Phoenix are three leading full-stack frameworks. Rails (Ruby) is the original, with a mature ecosystem and a strong community. Laravel (PHP) is the most popular (by usage), with a larger ecosystem than Rails. Phoenix (Elixir) is the fastest (via the Erlang VM), with excellent realtime support. For startups that want to build quickly, Rails is a great choice. For teams that prefer PHP, Laravel is a great choice. For teams that need realtime and performance, Phoenix is the best choice. Deployxa supports all three equally, with the AutoRepairService and the zero-config engine handling each framework automatically. For more on framework comparisons, see our articles on deploying Laravel with Octane and deploying Phoenix with Elixir.
Advanced Rails Patterns
Beyond the basics, Rails apps benefit from several advanced patterns. The first is Active Record. Active Record is Rails's ORM, which provides a rich DSL for database queries and migrations. The second is Active Job. Active Job handles background jobs (via Sidekiq, Resque, or other backends), which is useful for email sending, report generation, and other asynchronous tasks. The third is Action Cable. Action Cable handles WebSockets, which is useful for realtime features (chat, notifications, live updates). The fourth is Devise. Devise is a popular auth gem that handles user registration, login, password reset, and more. The fifth is testing. Rails has excellent testing support (via rspec-rails or minitest), which makes it easy to write unit and integration tests. For more on testing, see our article on the testing void. For more on Rails deployment, see our articles on deploying a Spring Boot app and deploying an Express app with PM2.
Conclusion: Rails Without the Configuration
Rails is the original full-stack framework, and deploying it should be as simple as pushing to Git. Deployxa's zero-config engine makes it so: no Dockerfile, no Puma configuration, no asset pipeline management. Stop configuring Puma and start shipping.
Ready to deploy your Rails app? Drag your project to Deployxa Drop for an instant live preview, or install the CLI with npm i -g @deployxa/cli and deploy from your terminal. For more on framework deep-dives, see our articles on deploying a Phoenix app with Elixir and deploying a Spring Boot app. Learn about deploying an Express app with PM2 and deploying a Flask app with Gunicorn in our companion articles. Explore our free developer tools to speed up your workflow.