Complete Beginner’s Guide to Passenger + Rails on Apache
Learn how to deploy Ruby on Rails with Passenger and Apache β from setup to advanced production tips.
π Table of Contents
- Key Terms & Concepts
- What is Passenger?
- Why Use Passenger with Rails?
- Puma vs Passenger: Comparison
- Pros & Cons: Passenger vs Puma
- Why Use Passenger Over Puma?
- How to Install Passenger & Rails
- Basic Configuration
- Rails Application Settings for Passenger
- Full Implementation Example: Rails + Passenger + Apache + SSL
- Passenger with Nginx
- Passenger with Docker
- Best Settings for Large Scale Applications
- Real-World Case Study
- Common Error Messages Table
- .htaccess and Nginx Equivalent
- Troubleshooting
- Performance Tuning
- Security Best Practices
- Automation
- Monitoring
- Cheat Sheet
- FAQ
- External Resources
- Conclusion
ποΈ Key Terms & Concepts
Term | Description |
---|---|
Passenger | Application server for Ruby, Node.js, and Python apps, integrates with Apache/Nginx. |
Puma | Multi-threaded Ruby/Rails application server, often used with Nginx or Apache as a reverse proxy. |
Rails | Popular web application framework written in Ruby. |
Virtual Host | Apache config to host multiple sites on one server. |
mod_passenger | Apache module that runs Passenger apps. |
Gemfile | File listing Ruby gems (dependencies) for a Rails app. |
Environment Variables | Variables for secrets/config, set outside code for security. |
SSL/TLS | Encryption for secure HTTP (HTTPS). |
Systemd | Linux service manager, used for process control. |
Reverse Proxy | Server that forwards requests to backend apps. |
Assets | Static files (JS, CSS, images) served by Rails. |
Docker | Containerization platform for packaging and running applications in isolated environments. |
Thread | Lightweight process for handling multiple requests concurrently. |
Worker | Separate process for handling requests; more workers = more concurrency. |
Pool | Group of worker processes managed by Passenger or Puma. |
π What is Passenger?
Passenger (also known as Phusion Passenger) is an application server that makes it easy to deploy Ruby, Node.js, and Python web apps. It integrates directly with Apache (or Nginx), handling process management, scaling, and more.
Simple Analogy: Passenger is like a smart traffic controller for your Rails app, making sure requests are handled efficiently and reliably.
β Why Use Passenger with Rails?
Feature | Benefit |
---|---|
Easy Integration | Works out-of-the-box with Apache and Rails |
Process Management | Handles app restarts, scaling, and memory automatically |
Performance | Efficient, supports multiple concurrent requests |
Security | Runs apps as non-root users, supports SSL |
Monitoring | Built-in status and monitoring tools |
π¦ Puma vs Passenger: Comparison
Feature | Passenger | Puma |
---|---|---|
Integration | Direct with Apache/Nginx (module) | Reverse proxy via Apache/Nginx |
Process Model | Multi-process, can be multi-threaded | Multi-threaded, multi-worker |
Zero-downtime Deploys | Yes (built-in) | Yes (with phased restart) |
Monitoring Tools | passenger-status, passenger-memory-stats | pumactl, systemd, external tools |
Ease of Use | Very easy, auto-detects Rails app | Requires manual config, more control |
Docker Support | Official images, but less common | Very common, official images |
Scaling | Automatic process management | Manual tuning of workers/threads |
Memory Usage | Efficient, but more overhead than Puma for small apps | Very efficient for threaded workloads |
Best For | Simple, stable, production Rails hosting | High concurrency, API, microservices |
Summary:
Passenger is best for easy, stable, and secure Rails hosting with Apache/Nginx, especially for traditional web apps and teams who want less manual tuning.
Puma is best for high-concurrency, API-heavy, or microservice Rails apps, and is the default for new Rails projects.
π Pros & Cons: Passenger vs Puma
Passenger | Puma | |
---|---|---|
Pros |
|
|
Cons |
|
|
β Why Use Passenger Over Puma?
- Seamless Apache/Nginx integration (no reverse proxy config needed)
- Automatic process management and scaling
- Zero-downtime deploys out of the box
- Great for teams who want stability and less manual tuning
- Easy to monitor and debug with built-in tools
- Ideal for shared hosting and traditional web apps
When to choose Passenger: If you want a “just works” Rails deployment with Apache or Nginx, especially for monolithic or traditional web apps, Passenger is a great choice.
π οΈ How to Install Passenger & Rails
Install on Ubuntu/Debian
# Install dependencies
sudo apt update
sudo apt install -y dirmngr gnupg apt-transport-https ca-certificates
sudo apt install -y curl
# Add Passenger APT repo
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger $(lsb_release -cs) main > /etc/apt/sources.list.d/passenger.list'
sudo apt update
# Install Passenger + Apache module
sudo apt install -y libapache2-mod-passenger
sudo apt install -y apache2
# Install Ruby, Rails, Bundler
sudo apt install -y ruby-full build-essential zlib1g-dev
sudo gem install rails bundler
Install on CentOS/RHEL
# See official docs for latest steps: https://www.phusionpassenger.com/library/install/apache/install/oss/el7/
βοΈ Basic Configuration
Create a Rails App
# Create a new Rails app (or clone your repo)
cd /var/www
rails new myapp -d postgresql
cd myapp
bundle install
RAILS_ENV=production rails db:setup
RAILS_ENV=production rails assets:precompile
Apache VirtualHost Example
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/myapp/public
Allow from all
Options -MultiViews
Require all granted
ErrorLog ${APACHE_LOG_DIR}/myapp_error.log
CustomLog ${APACHE_LOG_DIR}/myapp_access.log combined
Note: Passenger automatically detects and runs your Rails app from the public directory. No need to run rails server or puma manually.
βοΈ Rails Application Settings for Passenger
- Set RAILS_ENV=production for production deployments
- Precompile assets: RAILS_ENV=production rails assets:precompile
- Use config.force_ssl = true in config/environments/production.rb for HTTPS
- Set secrets and DB credentials via environment variables or config/credentials.yml.enc
- For large apps, tune config.threadsafe! and config.eager_load = true
- Use SetEnv in Apache config to pass ENV vars to Rails
# Example: config/environments/production.rb
Rails.application.configure do
config.cache_classes = true
config.eager_load = true
config.force_ssl = true
config.log_level = :info
# ...other production settings...
end
π Full Implementation Example: Rails + Passenger + Apache + SSL
Step-by-Step Production Deployment
- Install all dependencies (see above)
- Clone/setup your Rails app:
cd /var/www git clone https://github.com/youruser/myapp.git cd myapp bundle install RAILS_ENV=production rails db:setup RAILS_ENV=production rails assets:precompile
- Set permissions:
sudo chown -R www-data:www-data /var/www/myapp sudo chmod -R 755 /var/www/myapp
- Configure Apache VirtualHost (HTTP & HTTPS):
<VirtualHost *:80> ServerName example.com ServerAlias www.example.com RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] </VirtualHost> <VirtualHost *:443> ServerName example.com ServerAlias www.example.com SSLEngine on SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf DocumentRoot /var/www/myapp/public
Allow from all Options -MultiViews Require all granted ErrorLog ${APACHE_LOG_DIR}/myapp_ssl_error.log CustomLog ${APACHE_LOG_DIR}/myapp_ssl_access.log combined </VirtualHost> - Enable required modules and site:
sudo a2enmod passenger rewrite ssl headers sudo a2ensite myapp.conf sudo systemctl reload apache2
- Obtain SSL certificate (Letβs Encrypt):
sudo apt install certbot python3-certbot-apache sudo certbot --apache -d example.com -d www.example.com
- Set environment variables (production):
# In /var/www/myapp/.env or via Apache config: export RAILS_ENV=production export SECRET_KEY_BASE=your_secret export DATABASE_URL=postgres://user:pass@localhost/dbname
- Test:
- Visit https://example.com (should load your Rails app)
- All HTTP is redirected to HTTPS
Troubleshooting Tips:
- App not loading? Check /var/log/apache2/ error.log and log/production.log
- Permission denied? Ensure public/ and tmp/ are writable by Apache
- Assets not loading? Run RAILS_ENV=production rails assets:precompile
- SSL not working? Check /etc/letsencrypt/ and run sudo certbot renew –dry-run
- Environment variables? Use .env or set in Apache config with SetEnv
π Passenger with Nginx
Passenger can also be used with Nginx instead of Apache. This is a popular choice for high-performance Rails deployments, as Nginx is lightweight and efficient for serving static files and handling concurrent connections.
Why use Passenger + Nginx? Nginx is known for its speed and low memory usage. Combined with Passenger, it provides a robust, production-ready platform for Rails apps, especially for high-traffic or API-heavy workloads.
Install Passenger + Nginx (Ubuntu/Debian)
# Add Passenger APT repo
sudo apt update
sudo apt install -y dirmngr gnupg apt-transport-https ca-certificates
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger $(lsb_release -cs) main > /etc/apt/sources.list.d/passenger.list'
sudo apt update
# Install Passenger + Nginx module
sudo apt install -y libnginx-mod-http-passenger nginx
Sample Nginx Config for Rails + Passenger
server {
listen 80;
server_name example.com;
root /var/www/myapp/public;
passenger_enabled on;
passenger_app_env production;
# Static file serving
location ~ ^/(assets|packs|uploads)/ {
expires max;
add_header Cache-Control public;
}
# Rails error pages
error_page 500 502 503 504 /500.html;
client_max_body_size 20M;
keepalive_timeout 10;
}
SSL with Nginx + Passenger
server {
listen 443 ssl;
server_name example.com;
root /var/www/myapp/public;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
passenger_enabled on;
passenger_app_env production;
# ...rest as above...
}
Environment Variables in Nginx + Passenger
passenger_env_var SECRET_KEY_BASE your_secret;
passenger_env_var DATABASE_URL postgres://user:pass@localhost/dbname;
Troubleshooting Tips:
- App not loading? Check /var/log/nginx/ error.log and log/production.log
- Permission denied? Ensure public/ and tmp/ are writable by the Nginx user (usually www-data).
- Assets not loading? Check root path and precompile assets.
- SSL not working? Check certificate paths and run sudo certbot renew –dry-run.
- Environment variables? Use passenger_env_var in your Nginx config.
π³ Passenger with Docker
Passenger can be run inside Docker containers for modern, containerized Rails deployments. Official images are available, but Puma is more common in the Docker world. Hereβs a basic example:
# Dockerfile for Rails + Passenger + Apache
FROM phusion/passenger-ruby31:latest
# Install dependencies
RUN apt-get update && apt-get install -y nodejs yarn
# Set working directory
WORKDIR /app
# Copy app files
COPY . /app
# Install gems
RUN bundle install
# Precompile assets
RUN bundle exec rake assets:precompile
# Expose port 80
EXPOSE 80
# Start Apache + Passenger
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
Tip: For production, use multi-stage builds and set environment variables securely. See Passenger Docker docs for more.
π’ Best Settings for Large Scale Applications
- Increase PassengerMaxPoolSize for more concurrent processes
- Use PassengerMinInstances to keep workers warm
- Enable config.cache_store with Memcached or Redis
- Use a CDN for static assets
- Enable Gzip compression (mod_deflate)
- Monitor with passenger-status and external tools (New Relic, Datadog)
- Set config.active_record.database_selector for DB load balancing (Rails 6+)
- Use config.active_job.queue_adapter for background jobs (Sidekiq, Resque)
# Example: Apache Passenger tuning
PassengerMaxPoolSize 12
PassengerMinInstances 4
PassengerPoolIdleTime 300
Tip: For very large scale, consider horizontal scaling (multiple servers/load balancer) and database replication.
π Real-World Case Study: Rails + Passenger Deployment
Company: Startup SaaS Platform
Stack: Rails 7 + Passenger + Apache + PostgreSQL + Redis + Sidekiq
Deployment: Ubuntu 22.04 VPS, Passenger as Apache module, SSL via Letβs Encrypt, assets on CDN, background jobs with Sidekiq.
Challenges: Needed zero-downtime deploys, easy scaling, and simple monitoring for a small team.
Solution: Used Passenger for process management and zero-downtime deploys, Apache for SSL and static files, passenger-status for monitoring, and capistrano for automated deploys. Switched to Redis cache store and CDN for assets as traffic grew.
Result: 99.99% uptime, easy deploys, and simple scaling as the team grew. Minimal manual tuning required.
π¨ Common Error Messages Table
Error Message | Where | What it Means / How to Fix |
---|---|---|
Could not spawn process for application | Passenger/Apache/Nginx | Check permissions, Ruby version, and Gemfile.lock. Ensure all gems are installed and public/ is readable. |
App 123 stdout: Missing secret_key_base | Passenger/Rails | Set SECRET_KEY_BASE in ENV or credentials. |
Permission denied @ dir_s_mkdir | Rails | Ensure tmp/ and public/ are writable by web server user. |
502 Bad Gateway | Nginx/Browser | Passenger or Rails app crashed or not starting. Check logs and restart. |
503 Service Temporarily Unavailable | Apache/Nginx | App is restarting or overloaded. Check passenger-status and logs. |
Assets not loading (404) | Browser | Run RAILS_ENV=production rails assets:precompile and check root path. |
Database connection refused | Rails | Check DATABASE_URL and DB server status. |
SSL certificate error | Browser/Apache/Nginx | Check certificate paths and renewal. Use sudo certbot renew –dry-run. |
π .htaccess and Nginx Equivalent
.htaccess Rule | Nginx Equivalent |
---|---|
RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] | if ($scheme = http) { return 301 https://$host$request_uri; } |
ErrorDocument 404 /404.html | error_page 404 /404.html; |
AuthType Basic AuthName "Restricted" AuthUserFile /path/to/.htpasswd Require valid-user | auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; |
Header set Access-Control-Allow-Origin "*" | add_header Access-Control-Allow-Origin *; |
Options -Indexes | autoindex off; |
π§ Troubleshooting
- Check /var/log/apache2/ error.log for Passenger and Rails errors
- Check log/production.log in your Rails app
- Use passenger-status and passenger-memory-stats for diagnostics
- Restart Apache after config changes: sudo systemctl reload apache2
- Check permissions on public/ and tmp/
β‘ Performance Tuning
- Use PassengerMaxPoolSize to control max app processes
- Enable caching in Rails (config/environments/production.rb)
- Use a CDN for static assets
- Enable Gzip compression (mod_deflate)
- Monitor memory usage with passenger-memory-stats
π Security Best Practices
- Always use HTTPS (SSL/TLS)
- Hide Apache version (ServerTokens Prod, ServerSignature Off)
- Set proper file permissions (never run as root)
- Use strong secrets and environment variables
- Keep Rails, Passenger, and Apache updated
- Enable firewalls and restrict SSH access
π€ Automation
- Automate deployment with Capistrano or Ansible
- Use bash scripts for backups and log rotation
- Automate SSL renewal with Certbot cron job
# Example: Capistrano deploy
bundle exec cap production deploy
π Monitoring
- Use passenger-status and passenger-memory-stats
- Monitor Apache logs and Rails logs
- Integrate with external tools (New Relic, Datadog, etc.)
π Passenger + Rails Cheat Sheet
Task | Command/Config |
---|---|
Restart Apache | sudo systemctl restart apache2 |
Reload Apache | sudo systemctl reload apache2 |
Check Passenger status | passenger-status |
Check memory usage | passenger-memory-stats |
Precompile Rails assets | RAILS_ENV=production rails assets:precompile |
Set environment variable | export VAR=value or SetEnv VAR value in Apache config |
View Rails logs | tail -f log/production.log |
β FAQ
Question | Answer |
---|---|
What is Passenger? | An application server for Ruby, Node.js, and Python that integrates with Apache/Nginx. |
How do I restart my Rails app? | Touch tmp/restart.txt in your app directory or reload Apache. |
How do I set environment variables? | Use SetEnv in Apache config or .env files. |
How do I enable SSL? | Use certbot to get a certificate and configure your VirtualHost for port 443. |
How do I debug Passenger issues? | Check /var/log/apache2/ error.log and use passenger-status. |
How do I scale my app? | Increase PassengerMaxPoolSize and use a load balancer if needed. |
π External Resources
- Official Passenger Documentation
- Rails Deployment Guide
- DigitalOcean: Deploy Rails with Apache & Passenger
β Conclusion
Passenger + Apache is a powerful, production-ready way to deploy Ruby on Rails apps. With easy integration, strong security, and robust performance, itβs a top choice for Rails hosting.
- Easy to set up and manage
- Handles process management and scaling
- Works seamlessly with Apache and SSL
- Great for both beginners and advanced users
For more advanced Rails optimization, see Randomize Blog.
https://shorturl.fm/1rWpm
https://shorturl.fm/KyP1o
https://shorturl.fm/71rJp
https://shorturl.fm/XhEi4
https://shorturl.fm/WV4ud
https://shorturl.fm/tw1Yz
https://shorturl.fm/DZSiz
https://shorturl.fm/fivUQ
https://shorturl.fm/o3Vmv
https://shorturl.fm/GV5vY
https://shorturl.fm/dpUCK
https://shorturl.fm/Uyr3k
https://shorturl.fm/JmqMB
https://shorturl.fm/r0WKG
https://shorturl.fm/Mj63n
https://shorturl.fm/4Hiud
https://shorturl.fm/2mF35
https://shorturl.fm/axH9n
https://shorturl.fm/LWJPj
https://shorturl.fm/wwZFI
https://shorturl.fm/zqqh2
https://shorturl.fm/pD51u
https://shorturl.fm/wmeri
https://shorturl.fm/M171F
https://shorturl.fm/ONh5n
https://shorturl.fm/9wIIr
https://shorturl.fm/HRhiX
https://shorturl.fm/KWBzb
https://shorturl.fm/RmN1g
https://shorturl.fm/r4zeB
https://shorturl.fm/YIKIl
https://shorturl.fm/TuAk3
https://shorturl.fm/meREs
https://shorturl.fm/iicvO
https://shorturl.fm/5YXBo
https://shorturl.fm/UvYq0
https://shorturl.fm/D4Dfj
https://shorturl.fm/uLOve
https://shorturl.fm/sVeLF
https://shorturl.fm/rw5X4
https://shorturl.fm/Kttqw
https://shorturl.fm/pZMFt
https://shorturl.fm/RbCjb
https://shorturl.fm/opYsI
https://shorturl.fm/62CsW