Building Ruby on Rails with open-source tools
This guide details the implementation of a production-ready Rails 8 application using the 'No-PaaS' stack. It focuses on replacing Redis-dependent background processing with Solid Queue and deploying to a VPS using Kamal. This architecture minimizes infrastructure complexity while maintaining scalability for full-stack web applications.
Configure Solid Queue for Background Jobs
Rails 8 defaults to Solid Queue for background processing to remove the Redis dependency. Ensure your database configuration supports the queue schema and that the adapter is correctly set for production.
# config/environments/production.rb
config.active_job.queue_adapter = :solid_queue
# config/database.yml
production:
primary:
<<: *default
database: storage/production.sqlite3
queue:
<<: *default
database: storage/production_queue.sqlite3
migrations_paths: db/queue_migrate⚠ Common Pitfalls
- •Failure to run 'bin/rails solid_queue:install' will result in missing migration files for the queue schema.
- •Using a single SQLite database for both data and queueing can lead to lock contention under high write loads; use separate database files as shown.
Initialize Kamal Deployment Configuration
Kamal handles Docker-based deployments to any Linux server. Initialize the configuration to generate the deploy.yml file and the necessary directory structure.
bundle add kamal
kamal init⚠ Common Pitfalls
- •Do not commit the generated .env file to version control; it will contain sensitive registry and server credentials.
Define Infrastructure in deploy.yml
Configure your application name, container registry, and server IP addresses. Specifically, define a separate role for the Solid Queue worker to ensure background tasks do not starve the web server of CPU cycles.
service: my-rails-app
image: username/my-rails-app
servers:
web:
hosts:
- 192.168.1.100
job:
hosts:
- 192.168.1.100
command: bundle exec rake solid_queue:start
registry:
username: [REGISTRY_USERNAME]
password:
- KAMAL_REGISTRY_PASSWORD
env:
secret:
- RAILS_MASTER_KEY⚠ Common Pitfalls
- •Ensure the 'job' role command correctly points to the solid_queue runner; otherwise, jobs will remain in the 'pending' state.
- •Verify that port 80/443 is open on the host firewall for the 'web' role.
Configure Health Checks for Zero-Downtime
Kamal uses a health check endpoint to verify the new container is ready before stopping the old one. Rails 8 includes a built-in health check controller; ensure it is properly mapped in deploy.yml.
proxy:
ssl: true
host: app.example.com
healthcheck:
path: /up
interval: 5s
timeout: 2s⚠ Common Pitfalls
- •If your /up endpoint requires authentication or database connections that are not yet established, the deployment will roll back automatically.
- •Mismatch between the proxy port (default 80) and the Rails Puma port (default 3000) will cause health check failures.
Provision and Deploy
The final step is to prepare the server and push the application. Kamal will install Docker on the remote host, build the image locally (or via builder), push it to the registry, and pull it to the server.
kamal setup⚠ Common Pitfalls
- •First-time setup may fail if the SSH user does not have passwordless sudo access on the target server.
- •Asset compilation failures during the Docker build stage are often caused by missing environment variables required by Tailwind CSS or Propshaft.
What you built
Your Rails 8 application is now configured for modern production standards using Solid Queue for background processing and Kamal for deployment. This setup provides the benefits of a managed PaaS while retaining full control over the underlying hardware. For scaling, you can now add additional IP addresses to the 'web' or 'job' roles in deploy.yml and run 'kamal deploy' to distribute the load.