Deploy Rails Apps for $5/Month: Vultr VPS Hosting Guide

Moving from a Platform-as-a-Service (PaaS) like Heroku to a Virtual Private Server (VPS) is a rite of passage for many Ruby developers. While PaaS offers convenience, the cost scales aggressively. If you are looking to deploy Rails apps with full control over your infrastructure, low latency, and predictable pricing, a $5/month VPS from a provider like Vultr is an unbeatable solution.

However, with great power comes great responsibility. You are no longer just an application developer; you are now the system administrator. This guide will walk you through setting up a production-hardened Linux environment, tuning PostgreSQL for low-memory servers, and configuring the classic Nginx/Puma stack for maximum performance.

Why Choose a VPS for Rails Deployment?

Before diving into the terminal, it is essential to understand the architectural trade-offs. When you deploy Rails apps on a raw VPS, you gain:

  • Cost Efficiency: A $5 Vultr instance (usually 1 vCPU, 1GB RAM) can easily handle hundreds of requests per minute if optimized correctly.
  • No “Sleeping” Dynos: Unlike free or cheap PaaS tiers, your VPS is always on. Background jobs (Sidekiq/Resque) run without needing expensive add-ons.
  • Environment Control: You choose the specific version of Linux, the database configuration, and the system libraries (e.g., ImageMagick, libvips).

Pro-Tip: Managing Resources
A 1GB RAM server is tight for modern Rails apps. The secret to stability on a $5 VPS is Swap Memory. Without it, your server will crash during memory-intensive tasks like bundle install or Webpacker compilation. We will cover this in step 2.

πŸš€ Prerequisite: Get Your Server

To follow this guide, you need a fresh Ubuntu VPS. We recommend Vultr for its high-performance SSDs and global locations.

Deploy Instance on Vultr →

(New users often receive free credits via this link)

Step 1: Server Provisioning and Initial Security

Assuming you have spun up a fresh Ubuntu 22.04 or 24.04 LTS instance on Vultr, the first step is to secure it. Do not deploy as root.

1.1 Create a Deploy User

Log in as root and create a user with sudo privileges. We will name ours deploy.

adduser deploy
usermod -aG sudo deploy
# Switch to the new user
su - deploy

1.2 SSH Hardening

Password authentication is a security risk. Copy your local SSH public key to the server (ssh-copy-id deploy@your_server_ip), then disable password login.

sudo nano /etc/ssh/sshd_config

# Change these lines:
PermitRootLogin no
PasswordAuthentication no

Restart SSH: sudo service ssh restart.

1.3 Firewall Configuration (UFW)

Setup a basic firewall to only allow SSH, HTTP, and HTTPS connections.

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Step 2: Performance Tuning (Crucial for $5 Instances)

Rails is memory hungry. To successfully deploy Rails apps on limited hardware, you must set up a Swap file. This acts as “virtual RAM” on your SSD.

# Allocate 1GB or 2GB of swap
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# Make it permanent
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Adjust the “Swappiness” value to 10 (default is 60) to tell the OS to prefer RAM over Swap unless absolutely necessary.

sudo sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf

Step 3: Installing the Stack (Ruby, Node, Postgres, Redis)

3.1 Dependencies

Update your system and install the build tools required for compiling Ruby.

sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl libssl-dev libreadline-dev zlib1g-dev \
autoconf bison build-essential libyaml-dev libreadline-dev \
libncurses5-dev libffi-dev libgdbm-dev

3.2 Ruby (via rbenv)

We recommend rbenv over RVM for production environments due to its lightweight nature.

# Install rbenv
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL

# Install ruby-build
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

# Install Ruby (Replace 3.3.0 with your project version)
rbenv install 3.3.0
rbenv global 3.3.0

3.3 Database: PostgreSQL

Install PostgreSQL and creating a database user.

sudo apt install -y postgresql postgresql-contrib libpq-dev

# Create a postgres user matching your system user
sudo -u postgres createuser -s deploy

Optimization Note: On a 1GB server, PostgreSQL default settings are too aggressive. Edit /etc/postgresql/14/main/postgresql.conf (version may vary) and reduce shared_buffers to 128MB to leave room for your Rails application.

Step 4: The Application Server (Puma & Systemd)

You shouldn’t run Rails using rails server in production. We use Puma managed by Systemd. This ensures your app restarts automatically if it crashes or the server reboots.

First, clone your Rails app into /var/www/my_app and run bundle install. Then, create a systemd service file.

File: /etc/systemd/system/my_app.service

[Unit]
Description=Puma HTTP Server
After=network.target

[Service]
# Foreground process (do not use --daemon in ExecStart or config.rb)
Type=simple

# User and Group the process will run as
User=deploy
Group=deploy

# Working Directory
WorkingDirectory=/var/www/my_app/current

# Environment Variables
Environment=RAILS_ENV=production

# ExecStart command
ExecStart=/home/deploy/.rbenv/shims/bundle exec puma -C /var/www/my_app/shared/puma.rb

Restart=always
KillSignal=SIGTERM

[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl enable my_app
sudo systemctl start my_app

Step 5: The Web Server (Nginx Reverse Proxy)

Nginx sits in front of Puma. It handles SSL, serves static files (assets), and acts as a buffer for slow clients. This prevents the “Slowloris” attack from tying up your Ruby threads.

Install Nginx: sudo apt install nginx.

Create a configuration block at /etc/nginx/sites-available/my_app:

upstream app {
    # Path to Puma UNIX socket
    server unix:/var/www/my_app/shared/tmp/sockets/puma.sock fail_timeout=0;
}

server {
    listen 80;
    server_name example.com www.example.com;

    root /var/www/my_app/current/public;

    try_files $uri/index.html $uri @app;

    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 10M;
    keepalive_timeout 10;
}

Link it and restart Nginx:

sudo ln -s /etc/nginx/sites-available/my_app /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo service nginx restart

Step 6: SSL Certificates with Let’s Encrypt

Never deploy Rails apps without HTTPS. Certbot makes this free and automatic.

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

Certbot will automatically modify your Nginx config to redirect HTTP to HTTPS and configure SSL parameters.

Frequently Asked Questions (FAQ)

Is a $5/month VPS really enough for production?

Yes, for many use cases. A $5 Vultr or DigitalOcean droplet is perfect for portfolios, MVPs, and small business apps. However, if you have heavy image processing or hundreds of concurrent users, you should upgrade to a $10 or $20 plan with 2GB+ RAM.

Why use Nginx with Puma? Can’t Puma serve web requests?

Puma is an application server, not a web server. While it can serve requests directly, Nginx is significantly faster at serving static assets (images, CSS, JS) and managing SSL connections. Using Nginx frees up your expensive Ruby workers to do what they do best: process application logic.

How do I automate deployments?

Once the server is set up as above, you should not be manually copying files. The industry standard tool is Capistrano. Alternatively, for a more Docker-centric approach (similar to Heroku), look into Kamal (formerly MRSK), which is gaining massive popularity in the Rails community.

Deploy Rails Apps for $5/Month: Vultr VPS Hosting Guide

Conclusion

You have successfully configured a robust, production-ready environment to deploy Rails apps on a budget. By managing your own Vultr VPS, you have cut costs and gained valuable systems knowledge.

Your stack now includes:

  • OS: Ubuntu LTS (Hardened)
  • Web Server: Nginx (Reverse Proxy & SSL)
  • App Server: Puma (Managed by Systemd)
  • Database: PostgreSQL (Tuned)

The next step in your journey is automating this process. I recommend setting up a GitHub Action or a Capistrano script to push code changes to your new server with a single command. Thank you for reading theΒ DevopsRolesΒ page!

,

About HuuPV

My name is Huu. I love technology, especially Devops Skill such as Docker, vagrant, git, and so forth. I like open-sources, so I created DevopsRoles.com to share the knowledge I have acquired. My Job: IT system administrator. Hobbies: summoners war game, gossip.
View all posts by HuuPV →

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.