Production Configuration for Rails 6 with Unicorn and Nginx on Ubuntu 18.04

June 15, 2020

Rails 6 production environment server setup

I was using Puma as an app server and there were no web server for my site. It is not a good thing that you don't have a web server on production environment. Web servers are essential tool for serving assets and process requests to your site. App servers main job is run you rails app. That's why i needed an app server and a web server which works well together for my rails web application. I searched for the best solutions and found out that Unicorn (app server) and Nginx (web server) runs pretty well together. So i have implemented it.

This post is about my server implementation for production. It took my days, i wish it will help you. I also want to add that i tried to work with Puma and Nginx but it was really frustrating for me but Unicorn was really easy. I really recommend Unicorn instead of Puma.

Ok lets start.

Check your server

First update your server.

sudo apt-get update && apt-get upgrade

Check your rails with

nodejs -v
yarn check --integrity
ruby -v
rails -v

If there is a problem, fix it first. Then move on.

Install Unicorn

sudo gem install unicorn

Go to your config folder in your rails app folder and create unicorn.rb file and use this code.

# set path to the application
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
working_directory app_dir

# Set unicorn options
worker_processes 2
preload_app true
timeout 30

# Path for the Unicorn socket
listen "#{shared_dir}/sockets/unicorn.sock", :backlog => 64

# Set path for logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"

# Set proccess id path
pid "#{shared_dir}/pids/unicorn.pid"

Create the required directories for your pids and logs. You can access production errors in this log folders if you face a problem. Please check it time to time.

mkdir -p shared/pids shared/sockets shared/log

Install Nginx

sudo apt-get install nginx

Now go to /etc/nginx/nginx.conf file and define your unicorn socket in for your nginx so it will work as reverse proxy. These log files will store web server errors and access logs. You should also check them regularly.

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

upstream rails {
	# Path to Unicorn socket file
	server unix:/path/to/your/rails-app/shared/sockets/unicorn.sock fail_timeout=0;
}

Now be careful part 🙂

Nginx have 2 folders. One is sites-available the other one is sites-enabled . Nginx will server settings in sites-enabled folder, not in sites-available folder. So you will edit your Nginx settings in available folder and copy them to enabled folder to work.

Go to /etc/nginx/sites-available/domain . 'domain' is a new file you created for your website.

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

root /path/to/your/rails-app;

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

# serve static (compiled) assets directly if they exist (for rails production)
location ~ ^/(assets|packs|images|javascripts|stylesheets|swfs|system)/ {
	try_files $uri @rails;
	access_log off;
	gzip_static on;
	root /path/to/your/rails-app/public;
	
	 # to serve pre-gzipped version
	expires max;
	add_header Cache-Control public;
	
	add_header Last-Modified "";
	add_header ETag "";
	break;
}

# added so i can server html and txt in my public folder. I'm using it for google analytics.
location ~* \.(html|txt) { root /path/to/your/rails-app/public/;  }

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

# to server error pages
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;

}

Now copy this file to sites-enabled folder. Delete the 'default' file in sites-enabled folder.

sudo ln -s /etc/nginx/sites-available/domain /etc/nginx/sites-enabled

Ok. That should be it. 🤞

Start the servers

Start nginx server.

# to start
sudo service nginx restart

# if you want to restart it
systemctl daemon-reload 
systemctl restart nginx

Start unicorn. Go to your rails main folder.

# to start
sudo unicorn -c config/unicorn.rb -E production -D

# to kill unicorn 
sudo pkill unicorn

Thank you. I wish it will help you. Back-end jobs never really finish. Don't stop search for better practices and solutions. Please let me know if i missed anything.

Documented and written by

Tuna Gümüş @tcgms

© 2024, built by boredom.