Complete Beginner’s Guide to Puma + Rails
Learn how to deploy Ruby on Rails with Puma β from setup to advanced production tips.
π Table of Contents
- Key Terms & Concepts
- What is Puma?
- Why Use Puma?
- Puma vs Passenger/Unicorn
- Pros & Cons
- How to Install Puma & Rails
- Basic Configuration
- Rails Application Settings for Puma
- Full Implementation Example
- 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
- External Resources
- Conclusion
ποΈ Key Terms & Concepts
Term | Description |
---|---|
Puma | Multi-threaded, multi-worker Ruby/Rails application server, default for new Rails apps. |
Rails | Popular web application framework written in Ruby. |
Worker | Separate process for handling requests; more workers = more concurrency. |
Thread | Lightweight process for handling multiple requests concurrently within a worker. |
Reverse Proxy | Server (like Apache or Nginx) that forwards requests to Puma. |
Systemd | Linux service manager, used for process control. |
ENV | Environment variables for secrets/configuration. |
SSL/TLS | Encryption for secure HTTP (HTTPS). |
Cluster Mode | Puma mode with multiple workers and threads for high concurrency. |
Preload App | Puma setting to load the app before forking workers (saves memory, faster boot). |
Capistrano | Popular deployment tool for Rails apps. |
Docker | Containerization platform for packaging and running applications in isolated environments. |
π What is Puma?
Puma is a fast, concurrent web server for Ruby and Ruby on Rails applications. It is the default server for new Rails projects and is designed to handle many requests at once using threads and workers.
Simple Analogy: Puma is like a team of waiters (workers), each able to serve multiple tables (threads) at the same time, making your Rails app fast and responsive even under heavy load.
β Why Use Puma?
Puma is a great choice for Rails apps because it is lightweight, easy to configure, and supports high concurrency. It works well with reverse proxies like Nginx and Apache, and is suitable for both small and large-scale deployments.
Feature | Benefit for Beginners |
---|---|
Multi-threaded | Handles many requests at once, making apps faster |
Cluster mode | Multiple workers for better CPU/core usage |
Default for Rails | No extra setup for new Rails apps |
Works with Nginx/Apache | Easy to use behind a reverse proxy for SSL, static files, etc. |
Simple config | Easy to tune for your server size |
Great for APIs | Handles high concurrency, perfect for JSON APIs |
Production ready | Used by many large Rails sites |
βοΈ Puma vs Passenger/Unicorn
Feature | Puma | Passenger | Unicorn |
---|---|---|---|
Threaded | Yes (multi-threaded, multi-worker) | Optional (multi-process, can be multi-threaded) | No (multi-process only) |
Zero-downtime deploys | Yes (phased restart) | Yes (built-in) | Yes (USR2 signal) |
Reverse proxy needed | Yes (Nginx/Apache) | No (integrates as module) | Yes (Nginx/Apache) |
Ease of use | Easy, default for Rails | Very easy, auto-detects Rails app | Manual config, less beginner-friendly |
Best for | APIs, high concurrency, modern Rails | Traditional web apps, shared hosting | Legacy Rails, simple deployments |
Docker support | Excellent | Good | Good |
Monitoring tools | pumactl, systemd, external | passenger-status, passenger-memory-stats | Manual, external |
Summary:
Puma is the default for new Rails apps and is best for high concurrency and APIs. Passenger is great for easy integration with Apache/Nginx and traditional web apps. Unicorn is older, process-based, and best for legacy or simple deployments.
π Pros & Cons
Puma | |
---|---|
Pros |
|
Cons |
|
π οΈ How to Install Puma & Rails
Install on Ubuntu/Debian
# Install Ruby, Rails, and dependencies
sudo apt update
sudo apt install ruby-full build-essential zlib1g-dev
sudo gem install rails bundler
# Add Puma to your Rails app
cd /var/www/myapp
bundle add puma
bundle install
Install on CentOS/RHEL
# Install Ruby, Rails, and dependencies
sudo yum install ruby ruby-devel gcc make
sudo gem install rails bundler
# Add Puma to your Rails app
cd /var/www/myapp
bundle add puma
bundle install
Install on macOS
# Using Homebrew
brew install ruby
sudo gem install rails bundler
# Add Puma to your Rails app
cd /path/to/myapp
bundle add puma
bundle install
Note: Puma is the default server for new Rails apps (Rails 5+), so you may already have it in your Gemfile.
βοΈ Basic Configuration
puma.rb Example (Rails)
# 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") { "development" }
# For production, use workers (cluster mode)
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
preload_app!
plugin :tmp_restart
- threads: Sets min/max threads per worker (concurrency)
- port: Port Puma will listen on (default 3000)
- environment: Rails environment (development, production, etc.)
- workers: Number of worker processes (for cluster mode)
- preload_app!: Loads app before forking workers (saves memory, faster boot)
- plugin :tmp_restart: Allows rails restart to work
Tip: For production, set WEB_CONCURRENCY and RAILS_MAX_THREADS as environment variables for best performance.
βοΈ Rails Application Settings for Puma
- 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.eager_load = true and config.cache_store
- Use WEB_CONCURRENCY and RAILS_MAX_THREADS for scaling
# 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
1. Standalone Puma (for development or simple production)
# Start Puma in your Rails app directory
RAILS_ENV=production bundle exec puma -C config/puma.rb
- App will be available at http://localhost:3000 (or port you set)
- Not recommended to expose Puma directly to the internet in production
Troubleshooting Tips:
- Puma not starting? Check log/production.log and config/puma.rb
- Port in use? Change port in puma.rb or stop other services
2. Puma with Apache Reverse Proxy
# Apache VirtualHost example
ServerName example.com
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
ErrorLog ${APACHE_LOG_DIR}/puma_error.log
CustomLog ${APACHE_LOG_DIR}/puma_access.log combined
- Start Puma on 127.0.0.1:3000
- Apache handles SSL, static files, and proxies requests to Puma
Troubleshooting Tips:
- Proxy errors? Ensure Puma is running and listening on the correct port
- Permission denied? Check Apache and Rails logs
3. Puma with Nginx Reverse Proxy
# Nginx server block example
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
error_log /var/log/nginx/puma_error.log;
access_log /var/log/nginx/puma_access.log;
}
- Start Puma on 127.0.0.1:3000
- Nginx handles SSL, static files, and proxies requests to Puma
Troubleshooting Tips:
- 502 Bad Gateway? Check Puma is running and Nginx proxy_pass is correct
- Permission denied? Check Nginx and Rails logs
4. Puma with Docker
# Dockerfile for Rails + Puma
FROM ruby:3.2
# Install dependencies
RUN apt-get update -qq && apt-get install -y nodejs yarn
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
RUN bundle exec rake assets:precompile
EXPOSE 3000
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
- Set environment variables in your Dockerfile or docker-compose.yml
- Use a reverse proxy (Nginx/Apache) for SSL and static files in production
Troubleshooting Tips:
- Puma not starting? Check container logs and config/puma.rb
- Assets not loading? Ensure assets:precompile ran successfully
π’ Best Settings for Large Scale Applications
- Set WEB_CONCURRENCY to match CPU cores (e.g., 4 for quad-core)
- Set RAILS_MAX_THREADS to 5-16 (tune for your workload)
- Use preload_app! in puma.rb for memory savings
- Enable config.cache_store with Redis or Memcached
- Use a CDN for static assets
- Monitor memory and CPU usage (see Monitoring section)
- Use config.active_job.queue_adapter for background jobs (Sidekiq, Resque)
- Consider horizontal scaling (multiple servers/load balancer) for very high traffic
# Example: config/puma.rb for production
workers ENV.fetch("WEB_CONCURRENCY") { 4 }
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 8 }
threads threads_count, threads_count
preload_app!
Tip: Always test your settings under load (using tools like wrk or ab) before going to production.
π Real-World Case Study: Rails + Puma Deployment
Company: High-Traffic API Platform
Stack: Rails 7 + Puma + Nginx + PostgreSQL + Redis + Sidekiq
Deployment: AWS EC2, Dockerized Rails app, Puma in cluster mode (4 workers, 8 threads), Nginx reverse proxy, SSL via AWS ACM, assets on S3/CloudFront, background jobs with Sidekiq.
Challenges: Needed to handle 1000+ concurrent API requests/sec, minimize latency, and ensure zero-downtime deploys.
Solution: Tuned WEB_CONCURRENCY and RAILS_MAX_THREADS, used preload_app!, enabled caching with Redis, and set up rolling deploys with Capistrano. Used Datadog for monitoring and alerting.
Result: 99.99% uptime, sub-100ms API response times, and seamless scaling during traffic spikes.
π¨ Common Error Messages Table
Error | Cause | Solution |
---|---|---|
Puma not starting | Missing dependencies, incorrect config, port in use | Check log/production.log, config/puma.rb, and stop conflicting services. |
Port in use | Another service is using the port (3000) | Change port in config/puma.rb or stop the conflicting service. |
Permission denied | File permissions, user permissions, or SELinux | Check file/directory permissions, run with sudo, or adjust SELinux. |
502 Bad Gateway | Nginx proxy_pass incorrect, Puma not running, or SSL issue | Check Nginx config, Puma logs, and SSL settings. |
No such file or directory | Missing file, incorrect path, or file permissions | Check file existence, path, and permissions. |
NoMethodError | Missing method, incorrect config, or precompilation issue | Check config/environments/production.rb, log/production.log, and ensure assets are precompiled. |
ActionView::Template::Error | Missing template, incorrect path, or precompilation issue | Check log/production.log, config/environments/production.rb, and ensure assets are precompiled. |
ActiveRecord::ConnectionError | Database connection issues, missing credentials, or config error | Check config/database.yml, config/credentials.yml.enc, and log/production.log. |
ActionController::RoutingError | Incorrect route, missing routes, or precompilation issue | Check config/routes.rb, log/production.log, and ensure assets are precompiled. |
ActionView::MissingTemplate | Missing template, incorrect path, or precompilation issue | Check log/production.log, config/environments/production.rb, and ensure assets are precompiled. |
Tip: Always check your log/production.log for detailed error messages. Use pumactl for Puma-specific monitoring.
π .htaccess and Nginx Equivalent
Below are examples of how to configure Apache’s .htaccess and Nginx for Puma. These are often used in conjunction with a reverse proxy.
Apache .htaccess
# Apache .htaccess for Puma
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/assets/
RewriteCond %{REQUEST_URI} !^/favicon.ico
RewriteCond %{REQUEST_URI} !^/robots.txt
RewriteRule ^(.*)$ http://127.0.0.1:3000/$1 [P,L]
Nginx Server Block
# Nginx server block for Puma
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
error_log /var/log/nginx/puma_error.log;
access_log /var/log/nginx/puma_access.log;
}
Note: The .htaccess example assumes a reverse proxy is in place. The Nginx example is a complete server block.
π§ Troubleshooting
Common issues and how to resolve them:
Puma Not Starting
- Check log/production.log for detailed error messages.
- Ensure all dependencies are installed and up-to-date.
- Verify config/puma.rb is correct and has no syntax errors.
- Check if the port is in use and stop conflicting services.
- Run RAILS_ENV=production bundle exec puma -C config/puma.rb directly to test.
Port in Use
- Use lsof -i :3000 to find which process is using port 3000.
- Stop the process using kill -9 PID (replace PID with the actual process ID).
- Change the port in config/puma.rb to a different one.
Permission Denied
- Check file/directory permissions: chmod 755 /path/to/your_app
- Run with sudo: sudo RAILS_ENV=production bundle exec puma -C config/puma.rb
- Adjust SELinux: chcon -R -t httpd_sys_content_t /path/to/your_app
502 Bad Gateway
- Check log/production.log for Nginx errors.
- Verify config/puma.rb is running on 127.0.0.1:3000 or correct port.
- Check SSL settings in Nginx if using HTTPS.
No Such File or Directory
- Ensure the file/directory exists: ls -la /path/to/your_file
- Check file permissions: chmod 644 /path/to/your_file
- Check path: pwd and cd /path/to/your_file
NoMethodError
- Check log/production.log for the specific error.
- Ensure config/environments/production.rb is correct.
- Check if the method exists in the class: Rails.application.routes.named_routes.helper_names
ActionView::Template::Error
- Check log/production.log for the specific error.
- Ensure config/environments/production.rb is correct.
- Check if the template file exists: ls -la /path/to/your_app/app/views/your_controller/your_action.html.erb
ActiveRecord::ConnectionError
- Check config/database.yml and config/credentials.yml.enc.
- Ensure database credentials are correct and accessible.
- Check log/production.log for connection errors.
ActionController::RoutingError
- Check config/routes.rb and log/production.log.
- Ensure routes are defined and accessible.
- Check if the route name is correct: Rails.application.routes.named_routes.helper_names
ActionView::MissingTemplate
- Check log/production.log for the specific error.
- Ensure config/environments/production.rb is correct.
- Check if the template file exists: ls -la /path/to/your_app/app/views/your_controller/your_action.html.erb
Tip: Always check your log/production.log for detailed error messages. Use pumactl for Puma-specific monitoring.
β‘ Performance Tuning
Optimize Puma for better performance:
Threads and Workers
- Set RAILS_MAX_THREADS and RAILS_MIN_THREADS based on your server’s CPU cores.
- Use WEB_CONCURRENCY for scaling.
- For a 4-core server, set RAILS_MAX_THREADS=4, RAILS_MIN_THREADS=2, WEB_CONCURRENCY=2.
- For a 16-core server, set RAILS_MAX_THREADS=16, RAILS_MIN_THREADS=8, WEB_CONCURRENCY=4.
Preloading and Caching
- Enable config.eager_load = true for production.
- Configure config.cache_store for better performance.
- Precompile assets: RAILS_ENV=production rails assets:precompile.
SSL/TLS
- Configure SSL/TLS for secure connections.
- Use config.force_ssl = true in config/environments/production.rb.
Monitoring
- Use pumactl for Puma-specific monitoring.
- Use external monitoring tools like New Relic, Datadog, or Sentry.
Error Handling
- Implement robust error logging and monitoring.
- Use config.log_level = :info in config/environments/production.rb.
Tip: Always monitor your application’s performance and adjust settings as needed. Use tools like pumactl and external monitoring services.
π Security Best Practices
Ensure your Rails app is secure:
SSL/TLS
- Configure SSL/TLS for secure HTTP (HTTPS).
- Use config.force_ssl = true in config/environments/production.rb.
Environment Variables
- Never commit sensitive credentials to version control.
- Set secrets via config/credentials.yml.enc or environment variables.
- Use RAILS_ENV for different environments.
File Permissions
- Set appropriate file permissions for your application files.
- Use chmod 644 for configuration files.
- Use chmod 755 for application directories.
Authentication
- Use strong authentication mechanisms (e.g., Devise, Auth0).
- Implement secure session management.
- Use HTTPS for all requests.
Input Validation
- Sanitize all user inputs.
- Use strong parameters.
- Validate all inputs.
Error Messages
- Do not expose sensitive error messages to users.
- Log all errors to log/production.log.
Tip: Regularly update your dependencies and Ruby version to ensure security patches are applied.
π€ Automation
Use tools to automate your deployment and management:
Capistrano
- Popular deployment tool for Rails apps.
- Handles zero-downtime deploys.
- Configures environment variables, SSL, and reverse proxies.
Docker
- Containerization platform for packaging and running applications.
- Easy to replicate environments.
- Handles SSL, static files, and reverse proxies.
Systemd
- Linux service manager for managing Puma as a system service.
- Handles process restarts, monitoring, and logging.
pumactl
- Command-line tool for managing Puma processes.
- Provides status, restart, and other management functions.
Tip: Use a combination of tools for optimal automation. For example, Capistrano for deployment, Docker for containerization, and Systemd for service management.
ποΈ Monitoring
Monitor your application’s performance and health:
pumactl
- Command-line tool for Puma monitoring.
- Provides status, stats, and management functions.
Passenger Status
- For Passenger users, use passenger-status and passenger-memory-stats.
External Monitoring
- Use New Relic, Datadog, Sentry, or other external monitoring services.
- Track performance metrics, error rates, and user behavior.
Log Analysis
- Regularly analyze log/production.log for errors and performance issues.
- Use tools like tail -f or grep for quick checks.
Tip: Combine multiple monitoring tools for a comprehensive view of your application’s health.
π Cheat Sheet
Quick reference for common commands and configurations:
Basic Puma Commands
# Start Puma in development
RAILS_ENV=development bundle exec puma -C config/puma.rb
# Start Puma in production
RAILS_ENV=production bundle exec puma -C config/puma.rb
# Restart Puma
RAILS_ENV=production bundle exec puma -C config/puma.rb --restart
# Check Puma status
pumactl status
# Check Puma stats
pumactl stats
# Check Puma logs
tail -f log/puma.log
Common Configurations
- Threads: max_threads_count = ENV.fetch(“RAILS_MAX_THREADS”) { 5 }
- Port: port ENV.fetch(“PORT”) { 3000 }
- Environment: environment ENV.fetch(“RAILS_ENV”) { “development” }
- Workers: workers ENV.fetch(“WEB_CONCURRENCY”) { 2 }
- Preload App: preload_app!
- Plugin: plugin :tmp_restart
Tip: Always refer to the official Puma documentation for the most up-to-date information.
π External Resources
π Conclusion
Puma is a powerful, production-ready application server for Rails, offering high concurrency, performance, and flexibility. With the right configuration, automation, and monitoring, you can deploy robust Rails applications that scale to meet any demand. Use this guide as your reference for deploying, tuning, and securing Puma in real-world scenarios. Happy deploying!
47 thoughts on “Puma for Rails: Full Guide from Start to Scale”
Comments are closed.
https://shorturl.fm/bezzQ
https://shorturl.fm/egZvR
https://shorturl.fm/EETmX
https://shorturl.fm/yGicU
https://shorturl.fm/DQa8b
https://shorturl.fm/3GsON
https://shorturl.fm/xEZCz
https://shorturl.fm/cmre0
https://shorturl.fm/LbsZr
https://shorturl.fm/uC2UP
https://shorturl.fm/mPj4S
https://shorturl.fm/YOZZ7
https://shorturl.fm/up8zO
https://shorturl.fm/RH0d3
https://shorturl.fm/HqPK1
irj617
https://shorturl.fm/DI4w9
https://shorturl.fm/DbXOS
https://shorturl.fm/oAjnc
https://shorturl.fm/QFktx
https://shorturl.fm/HfQhH
https://shorturl.fm/uCMzl
https://shorturl.fm/HDVWg
https://shorturl.fm/MoCl7
https://shorturl.fm/kyE7C
https://shorturl.fm/ODrLk
https://shorturl.fm/7LTy1
https://shorturl.fm/vpqgZ
https://shorturl.fm/GL4EZ
https://shorturl.fm/kBRx7
https://shorturl.fm/nCSaZ
https://shorturl.fm/oC6bG
https://shorturl.fm/1kXTy
https://shorturl.fm/cVnDJ
https://shorturl.fm/Yc9ht
https://shorturl.fm/gtPX7
https://shorturl.fm/8H1T2
https://shorturl.fm/uLOve
https://shorturl.fm/QUF6A
https://shorturl.fm/odedR
https://shorturl.fm/rpqfb
https://shorturl.fm/ibf70
https://shorturl.fm/X7oOJ
https://shorturl.fm/Jr0V7
https://shorturl.fm/3iboY
https://shorturl.fm/iRCWa
https://shorturl.fm/HNY3Y