Ror Deployment
title: Ruby on Rails Deployment — Complete Guide to Production Deployment description: 'Learn Ruby on Rails deployment: VPS with Capistrano, Heroku, Docker, environment configuration, database setup, asset precompilation, SSL, and monitoring.' date: 2026-06-28 lastmod: 2026-06-28 weight: 33 tags: [backend, ror]
Rails deployment involves configuring the production environment, setting up a database server, precompiling assets, configuring a web server (Puma + Nginx), and managing environment secrets.
## What You'll Learn
By the end of this tutorial, you'll deploy Rails to a VPS with Nginx and Puma, deploy to Heroku, configure environment variables, set up PostgreSQL, enable SSL, and monitor production.
## Real-World Use
A Rails app is deployed on a $20/month VPS with Nginx reverse proxy, Puma app server, PostgreSQL database, and Let's Encrypt SSL. Capistrano automates zero-downtime deployments.
## Deployment Learning Path
```mermaid
flowchart LR
A[Docker] --> B[Deployment]
B --> C[Reference]
B --> D{You Are Here}
style D fill:#f90,color:#fff
Puma Configuration
# 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
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
preload_app!
port ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "production" }
on_worker_boot do
ActiveRecord::Base.establish_connection
end
plugin :tmp_restart
Nginx Configuration
upstream rails_app {
server unix:///home/deploy/myapp/shared/tmp/sockets/puma.sock;
}
server {
listen 80;
server_name myapp.com www.myapp.com;
root /home/deploy/myapp/current/public;
location / {
try_files $uri @rails;
}
location @rails {
proxy_pass http://rails_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /assets {
expires max;
add_header Cache-Control public;
}
location ~ ^/assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
}
Capistrano Setup
# Gemfile
gem "capistrano", require: false
gem "capistrano-rails", require: false
gem "capistrano-rbenv", require: false
gem "capistrano3-puma", require: false
bundle install
cap install
# Capfile
require "capistrano/setup"
require "capistrano/deploy"
require "capistrano/rbenv"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require "capistrano/puma"
# config/deploy.rb
set :application, "myapp"
set :repo_url, "git@github.com:username/myapp.git"
set :deploy_to, "/home/deploy/myapp"
set :rbenv_ruby, "3.3.0"
set :linked_files, %w[config/master.key config/database.yml]
set :linked_dirs, %w[log tmp/pids tmp/cache tmp/sockets vendor/bundle storage]
Environment Variables
# Production .env or config/credentials.yml.enc
SECRET_KEY_BASE=rails secret # Generate with: rails secret
DATABASE_URL=postgres://user:password@localhost:5432/myapp_production
RAILS_MASTER_KEY=your-master-key # For credentials
# Set on server
export RAILS_ENV=production
export SECRET_KEY_BASE=xxxx
export DATABASE_URL=postgres://...
Heroku Deployment
# Install Heroku CLI
heroku login
heroku create myapp-production
# Add buildpacks
heroku buildpacks:add heroku/ruby
# Set environment
heroku config:set RAILS_MASTER_KEY=your-key
heroku addons:create heroku-postgresql
heroku addons:create heroku-redis
# Deploy
git push heroku main
# Run migrations
heroku run rails db:migrate
# Open app
heroku open
Common Mistakes
1. Forgetting to Precompile Assets
Without precompilation, CSS/JS are missing. Run rails assets:precompile before deploy.
2. Not Setting RAILS_MASTER_KEY
Rails credentials can't be read without the master key. Set it as an environment variable or in config/master.key.
3. Running Migrations During Traffic
Long migrations lock tables. Run them during maintenance windows or use zero-downtime migration strategies.
4. Missing Log Rotation
Without log rotation, production.log grows unbounded. Use logrotate or Heroku's log management.
5. Not Monitoring
Without error tracking (Sentry, Rollbar) and performance monitoring (Scout, Skylight), issues go unnoticed.
Practice Questions
1. What web server does Rails use in production?
Puma (default). Runs behind Nginx as a reverse proxy. Puma handles Rails requests, Nginx serves static files.
2. How do you deploy Rails with zero downtime?
Use Capistrano with symlink-based deployments. The current symlink points to the new release. Puma restarts gracefully.
3. What is the role of the master key in production?
The master key (config/master.key or RAILS_MASTER_KEY env var) decrypts credentials.yml.enc containing API keys.
4. How do you handle database migrations in production?
Run before deploy or as a separate step. Use a maintenance page during long migrations. Test on a staging copy first.
5. Challenge: Deploy a Rails app to a VPS with Puma, Nginx, PostgreSQL, and Let's Encrypt.
# 1. Provision server, install Ruby/PostgreSQL/Nginx
# 2. Clone app, bundle install, precompile assets
# 3. Create database, run migrations
# 4. Configure Nginx reverse proxy
# 5. Set up systemd for Puma
# 6. Enable HTTPS with certbot
FAQ
Mini Project: Deploy to Heroku
Deploy a Rails app to Heroku with PostgreSQL.
heroku create myapp
git push heroku main
heroku run rails db:migrate
heroku open
What's Next
Ruby on Rails Reference Backend Overview
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro