Setup Rails with nginx + Passenger

Setup Rails with nginx + Passenger

In my previous posts, I had set up Ruby on Rails running with Puma and SQLite. This is a very fast installation of the environment with minimal configuration but it is not meant for production use.

After that, I installed PostgreSQL and configure Rails with PostgreSQL. Now in this post, I’ll be installing nginx with Passenger and configure Rails with it.

These installations are done in AWS EC2 t3.nano. The operating system used is Ubuntu 18.04 with additional 1GB of swap memory.

Install packages

Installing nginx if you do not already have nginx in your Ubuntu and all the required packages for nginx and Passenger.

# Install nginx
sudo apt update
sudo apt install nginx -y

# Install PGP and HTTPS support for APT
sudo apt install dirmngr gnupg -y
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo apt install apt-transport-https ca-certificates -y

# Add Passenger APT repository
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger bionic main > /etc/apt/sources.list.d/passenger.list'
sudo apt update

# Install Passenger and nginx module
sudo apt install libnginx-mod-http-passenger -y

Setup configuration file

Setting up the nginx configuration file. The ls command should yield a file named mod-http-passenger.conf. If it it doesn’t you will encounter errors restarting your nginx service.

# Setup configuration file 
if [ ! -f /etc/nginx/modules-enabled/50-mod-http-passenger.conf ]; then sudo ln -s /usr/share/nginx/modules-available/mod-http-passenger.load /etc/nginx/modules-enabled/50-mod-http-passenger.conf ; fi 
sudo ls /etc/nginx/conf.d/mod-http-passenger.conf 
sudo service nginx restart

Setup virtual host

We will be creating a configuration file to host our rails app in the “sites-available” folder and later enabling it by creating a soft link in “sites-enabled” folder.

# Create the rails app file in sites-available directory
sudo vim /etc/nginx/sites-available/blog

Paste the content below into the file.

server {
  listen 80;
  server_name rails.oofnivek.com;
  passenger_ruby /home/ubuntu/.rbenv/versions/2.5.1/bin/ruby;
  passenger_enabled on;
  passenger_app_env development;
  root /home/ubuntu/ror/blog/public;
}

Replace the server_name value with your domain. Since we are migrating from Puma web server to nginx + Passenger, I left the passenger_app_env set to “development” for testing. Your passenger_ruby value might vary from mine. To find out yours in your environment, run this command.

passenger-config --ruby-command
setup rails with nginx passenger
My passenger_ruby value in my environment.

Enable the site

Enabling your rails site in nginx to test if your migration from Puma to nginx is successful.

sudo ln -s /etc/nginx/sites-available/blog /etc/nginx/sites-enabled/blog
sudo service nginx restart
setup rails with nginx passenger
Successful migration from Puma to nginx + Passenger.

Production mode

To switch it to production mode, replace the value of passenger_app_env from development to production.

You can hardcode your database password in your rails database.yml file if you prefer to skip a few steps and also avoiding rebooting your server.

# Modify app environment to production
sudo sed -i 's/passenger_app_env development/passenger_app_env production/' /etc/nginx/sites-available/blog

# My PostgreSQL blog role is using 'password1' as password
echo "export BLOG_DATABASE_PASSWORD='password1'" >> ~/.bashrc
source ~/.bashrc

# Have to reboot server in order to refresh this value
echo "export BLOG_DATABASE_PASSWORD='password1'" >> ~/.profile

After configuring the production database connection, we create the database and migrate the tables.

# Create blog_production database 
cd ~/ror/blog/ 
RAILS_ENV=production rails db:create 
RAILS_ENV=production rails db:migrate 

# Configure default route 
vim ~/ror/blog/config/routes.rb

Add the line to default root to posts index route like my example below.

Rails.application.routes.draw do
  resources :posts
  root 'posts#index'
end

Finally, speed up your rails by precompiling it and reboot your Ubuntu so that the saved database password in the environment variable will take effect.

# Speed up your rails by precompiling assets
rails secret > ~/ror/blog/config/secrets.yml
cd ~/ror/blog
RAILS_ENV=production rails assets:precompile

# Finally reboot the server to refresh the environment variable
sudo reboot now

That’s all, once rebooted your site will be up and running in production mode.