Production Configuration for Rails 6 with Unicorn and Nginx on Ubuntu 18.04
Tags: ruby, unicorn, nginx, webdev
Published: 2020-06-15 08:44:39

---
title: Production Configuration for Rails 6 with Unicorn and Nginx on Ubuntu 18.04
published: true
date: 15/06/2020
tags: ruby, unicorn, nginx, webdev
canonical_url: https://pikseladam.com/production-configuration-for-rails-6-with-unicorn-and-nginx-on-ubuntu
---

[![Rails 6 production environment server setup](https://pikseladam.com/static/4fd0272eda5ae4d746e356474e4444dd/935bc/main.jpg "Rails 6 production environment server setup")](/static/4fd0272eda5ae4d746e356474e4444dd/4b190/main.jpg)

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. Let's start.

### Check your server

First update your server.

```bash
sudo apt-get update && apt-get upgrade
```

Check your rails with

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

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

# Install Unicorn

```bash
sudo gem install unicorn
```

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

```ruby
# 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.

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

## Install Nginx

```shell
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.

```xml
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 serve 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.

```config
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.

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

Ok. That should be it. 🤞

### Start the servers

Start nginx server.

```bash
# 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.

```shell
# 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.