Deploy Ruby on Rails on a VPS
Deploying a Rails application on a Virtual Private Server (VPS) involves configuring various components of the operating system, runtime environment, database, server software, and security measures. This guide explores the essential steps and considerations for setting up a production-ready Rails environment on a VPS.
When deploying Rails on a VPS, it is crucial to begin with a fresh Ubuntu LTS image, such as Ubuntu 24.04. This choice offers wide package support, an extended security window, and comprehensive Rails-specific documentation. Immediately create a dedicated deploy user and avoid running the application as the root user. Copy your SSH public key to this deploy user's home directory and disable password authentication and root login in the SSH configuration file. Restart the SSH service to apply the changes.
Expose only three external ports: the Puma application server listens on a Unix socket, not a public port, so there are no additional ports to open. Set the server's timezone and locale to UTC, ensuring consistent timekeeping for the application. Install the necessary dependencies, including rbenv and ruby-build, which allow for easy Ruby version management. Install the desired Ruby version and verify the installation by running `ruby -v`.
Use peer authentication for database access if the database server is co-located on the same VPS. This approach is simpler and more secure than using password authentication. Configure PostgreSQL settings, such as shared_buffers and work_mem, based on the available memory of the VPS. Avoid applying tuning configurations designed for high-performance servers to a smaller VPS, as it may lead to out-of-memory issues.
For the application server, configure Puma to listen on a Unix socket rather than a TCP port. This approach reduces latency, eliminates the risk of exposing Puma to the internet inadvertently, and ensures proper isolation if the firewall rules are misconfigured. Set the worker count to match the number of CPU cores available on the VPS.
A sensible default for thread count is five for database-intensive applications. Use the `preload_app!` directive to optimize memory usage, but be aware that it requires re-establishing database connections after each fork operation.
Configure Nginx as a reverse proxy to handle static assets directly from the `public/` directory, offloading this task from Puma. This separation improves performance and security by offloading static content handling to Nginx. Obtain an SSL certificate using Certbot, which automates the process of obtaining and renewing HTTPS certificates. Verify the renewal process with a dry-run command to ensure automatic certificate updates are functioning correctly.
Implement TLS security headers, such as Strict-Transport-Security, to enforce HTTPS usage across the application. Redirect HTTP requests to HTTPS at both the Nginx and application levels to ensure comprehensive protection. For background processing, consider integrating Sidekiq, a popular job queuing system. Configure Redis to listen exclusively on `127.0.0.1` and set appropriate memory limits to prevent resource exhaustion.
Create systemd service units for both Puma and Sidekiq, ensuring proper configuration and enabling the services using `systemctl`.
Regularly monitor the server's resource usage, including CPU, memory, and swap, to proactively identify potential issues. Implement monitoring and alerting systems to detect and respond promptly to anomalies, such as sudden spikes in disk usage or memory consumption. While small side projects may not require extensive monitoring, it is prudent to establish monitoring practices early to avoid unexpected disruptions in production.
Although some argue that Docker offers benefits for reproducibility and multi-service orchestration, it may introduce unnecessary complexity for a single Rails application on a VPS. Focus on the essential components and configurations necessary for a stable and secure deployment, prioritizing simplicity and reliability over added abstraction layers.
Written by urgent.news from Lobsters's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.