Tutorial

How To Deploy a Rails App with Unicorn and Nginx on Ubuntu 14.04

How To Deploy a Rails App with Unicorn and Nginx on Ubuntu 14.04

Introduction

When you are ready to deploy your Ruby on Rails application, there are many valid setups to consider. This tutorial will help you deploy the production environment of your Ruby on Rails application, with PostgreSQL as the database, using Unicorn and Nginx on Ubuntu 14.04.

Unicorn is an application server, like Passenger or Puma, that enables your Rails application to process requests concurrently. As Unicorn is not designed to be accessed by users directly, we will use Nginx as a reverse proxy that will buffer requests and responses between users and your Rails application.

Prerequisites

This tutorial assumes that you have an Ubuntu 14.04 server with the following software installed, on the user that will deploy the application:

If you do not have that set up already, follow the tutorials that are linked above. We will assume that your user is called deploy.

Also, this tutorial does not cover how to set up your development or test environments. If you need help with that, follow the example in the PostgreSQL with Rails tutorial.

Create Rails Application

Ideally, you already have a Rails application that you want to deploy. If this is the case, you may skip this section, and make the appropriate substitutions while following along. If not, the first step is to create a new Rails application that uses PostgreSQL as its database.

This command will create a new Rails application, named “appname” that will use PostgreSQL as the database. Feel free to substitute the highlighted “appname” with something else:

  1. rails new appname -d postgresql

Then change into the application directory:

  1. cd appname

Let’s take a moment to create the PostgreSQL user that will be used by the production environment of your Rails application.

Create Production Database User

To keep things simple, let’s name the production database user the same as your application name. For example, if your application is called “appname”, you should create a PostgreSQL user like this:

  1. sudo -u postgres createuser -s appname

We want to set the database user’s password, so enter the PostgreSQL console like this:

  1. sudo -u postgres psql

Then set the password for the database user, “appname” in the example, like this:

  1. \password appname

Enter your desired password and confirm it.

Exit the PostgreSQL console with this command:

  1. \q

Now we’re ready to configure the your application with the proper database connection information.

Configure Database Connection

Ensure that you are in your application’s root directory (cd ~/appname).

Open your application’s database configuration file in your favorite text editor. We’ll use vi:

  1. vi config/database.yml

Under the default section, find the line that says “pool: 5” and add the following line under it (if it doesn’t already exist):

  host: localhost

If you scroll to the bottom of the file, you will notice that the production section is set the following:

  username: appname
  password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>

If your production username doesn’t match the database user that you created earlier, set it now.

Note that the database password is configured to be read by an environment variable, APPNAME_DATABASE_PASSWORD. It is considered best practice to keep production passwords and secrets outside of your application codebase, as they can easily be exposed if you are using a distributed version control system such as Git. We will go over how to set up the database authentication with environment variables next.

Install rbenv-vars Plugin

Before deploying a production Rails application, you should set the production secret key and database password using environment variables. An easy way to manage environment variables, which we can use to load passwords and secrets into our application at runtime, is to use the rbenv-vars plugin.

To install the rbenv-vars plugin, simply change to the .rbenv/plugins directory and clone it from GitHub. For example, if rbenv is installed in your home directory, run these commands:

  1. cd ~/.rbenv/plugins
  2. git clone https://github.com/sstephenson/rbenv-vars.git

Set Environment Variables

Now that the rbenv-vars plugin is installed, let’s set up the required environment variables.

First, generate the secret key, which will be used to verify the integrity of signed cookies:

  1. cd ~/appname
  2. rake secret

Copy the secret key that is generated, then open the .rbenv-vars file with your favorite editor. We will use vi:

  1. vi .rbenv-vars

Any environment variables that you set here can be read by your Rails application.

First, set the SECRET_KEY_BASE variable like this (replace the highlighted text with the secret that you just generated and copied):

SECRET_KEY_BASE=your_generated_secret

Next, set the APPNAME_DATABASE_PASSWORD variable like this (replace the highlighted “APPNAME” with your your application name, and “prod_db_pass” with your production database user password):

APPNAME_DATABASE_PASSWORD=prod_db_pass

Save and exit.

You may view which environment variables are set for your application with the rbenv-vars plugin by running this command:

  1. rbenv vars

If you change your secret or database password, update your .rbenv-vars file. Be careful to keep this file private, and don’t include it any public code repositories.

Create Production Database

Now that your application is configured to talk to your PostgreSQL database, let’s create the production database:

  1. RAILS_ENV=production rake db:create

Generate a Controller

If you are following along with the example, we will generate a scaffold controller so our application will have something to look at:

  1. rails generate scaffold Task title:string note:text

Now run this command to update the production database:

  1. RAILS_ENV=production rake db:migrate

Precompile Assets

At this point, the application should work but you will need to precompile its assets so that any images, CSS, and scripts will load. To do so, run this command:

  1. RAILS_ENV=production rake assets:precompile

Test Application

To test out if your application works, you can run the production environment, and bind it to the public IP address of your server (substitute your server’s public IP address):

  1. RAILS_ENV=production rails server --binding=server_public_IP

Now visit this URL in a web browser:

http://server_public_IP:3000/tasks

If it’s working properly, you should see this page:

Tasks controller

Go back to your Rails server, and press Ctrl-c to stop the application.

Install Unicorn

Now we are ready to install Unicorn.

An easy way to do this is to add it to your application’s Gemfile. Open the Gemfile in your favorite editor (make sure you are in your application’s root directory):

  1. vi Gemfile

At the end of the file, add the Unicorn gem with this line:

gem 'unicorn'

Save and exit.

To install Unicorn, and any outstanding dependencies, run Bundler:

  1. bundle

Unicorn is now installed, but we need to configure it.

Configure Unicorn

Let’s add our Unicorn configuration to config/unicorn.rb. Open the file in a text editor:

  1. vi config/unicorn.rb

Copy and paste this configuration into the file:

# set path to 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

# Set up socket location
listen "#{shared_dir}/sockets/unicorn.sock", :backlog => 64

# Logging
stderr_path "#{shared_dir}/log/unicorn.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.stdout.log"

# Set master PID location
pid "#{shared_dir}/pids/unicorn.pid"

Save and exit. This configures Unicorn with the location of your application, and the location of its socket, logs, and PIDs. Feel free to modify the file, or add any other options that you require.

Now create the directories that were referred to in the configuration file:

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

Create Unicorn Init Script

Let’s create an init script so we can easily start and stop Unicorn, and ensure that it will start on boot.

Create a script and open it for editing with this command (replace the highlighted part with your application name, if you wish):

  1. sudo vi /etc/init.d/unicorn_appname

Copy and paste the following code block into it, and be sure to substitute USER and APP_NAME (highlighted) with the appropriate values:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          unicorn
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the unicorn app server
# Description:       starts unicorn using start-stop-daemon
### END INIT INFO

set -e

USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>"

# app settings
USER="deploy"
APP_NAME="appname"
APP_ROOT="/home/$USER/$APP_NAME"
ENV="production"

# environment settings
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH"
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
PID="$APP_ROOT/shared/pids/unicorn.pid"
OLD_PID="$PID.oldbin"

# make sure the app exists
cd $APP_ROOT || exit 1

sig () {
  test -s "$PID" && kill -$1 `cat $PID`
}

oldsig () {
  test -s $OLD_PID && kill -$1 `cat $OLD_PID`
}

case $1 in
  start)
    sig 0 && echo >&2 "Already running" && exit 0
    echo "Starting $APP_NAME"
    su - $USER -c "$CMD"
    ;;
  stop)
    echo "Stopping $APP_NAME"
    sig QUIT && exit 0
    echo >&2 "Not running"
    ;;
  force-stop)
    echo "Force stopping $APP_NAME"
    sig TERM && exit 0
    echo >&2 "Not running"
    ;;
  restart|reload|upgrade)
    sig USR2 && echo "reloaded $APP_NAME" && exit 0
    echo >&2 "Couldn't reload, starting '$CMD' instead"
    $CMD
    ;;
  rotate)
    sig USR1 && echo rotated logs OK && exit 0
    echo >&2 "Couldn't rotate logs" && exit 1
    ;;
  *)
    echo >&2 $USAGE
    exit 1
    ;;
esac

Save and exit. This will allow you to use service unicorn_appname to start and stop your Unicorn and your Rails application.

Update the script’s permissions and enable Unicorn to start on boot:

  1. sudo chmod 755 /etc/init.d/unicorn_appname
  2. sudo update-rc.d unicorn_appname defaults

Let’s start it now:

  1. sudo service unicorn_appname start

Now your Rails application’s production environment is running under Unicorn, and it’s listening on the shared/sockets/unicorn.sock socket. Before your application will be accessible to an outside user, you must set up the Nginx reverse proxy.

Install and Configure Nginx

Install Nginx using apt-get:

  1. sudo apt-get install nginx

Now open the default server block with a text editor:

  1. sudo vi /etc/nginx/sites-available/default

Replace the contents of the file with the following code block. Be sure to replace the the highlighted parts with the appropriate username and application name:

upstream app {
    # Path to Unicorn SOCK file, as defined previously
    server unix:/home/deploy/appname/shared/sockets/unicorn.sock fail_timeout=0;
}

server {
    listen 80;
    server_name localhost;

    root /home/deploy/appname/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 4G;
    keepalive_timeout 10;
}

Save and exit. This configures Nginx as a reverse proxy, so HTTP requests get forwarded to the Unicorn application server via a Unix socket. Feel free to make any changes as you see fit.

Restart Nginx to put the changes into effect:

  1. sudo service nginx restart

Now the production environment of your Rails application is accessible via your server’s public IP address or FQDN. To access the Tasks controller that we created earlier, visit your application server in a web browser:

http://server_public_IP/tasks

You should see the same page that you saw the first time you tested your application, but now it’s being served through Nginx and Unicorn.

Conclusion

Congratulations! You have deployed the production environment of your Ruby on Rails application using Nginx and Unicorn.

If you are looking to improve your production Rails application deployment, you should check out our tutorial series on How To Use Capistrano to Automate Deployments. The series is based on CentOS, but it should still be helpful in automating your deployments.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Mitchell Anicas
Mitchell Anicas
See author profile

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
50 Comments
Leave a comment...

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

I’ve set the environment variables following the steps above and when I try to connect to the production database I keep getting this error:

" Missing secret_token and secret_key_base for ‘production’ environment, set these values in config/secrets.yml "

I’ve tried to google an answer but am running around in circles! Here is what I have in my secrets.yml file:

development: secret_key_base: (mysecretkey)

test: secret_key_base: (mysecretkey)

Do not keep production secrets in the repository,

instead read values from the environment.

production: secret_key_base: <%= ENV[“SECRET_KEY_BASE”] %>

And here is the .rbenv-vars file:

SECRET_KEY_BASE=‘mysecretkey’ export YAMAMA_DATABASE_PASSWORD=‘mydatabasepassword’

Any thoughts would be greatly appreciated!

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
April 16, 2015

The location of your .rbenv-vars file matters. Make sure when you run rbenv vars in the directory that you are running your Rails app from shows the environment variables that you set.

Thanks for the quick response! When I run rbenv vars from the home directory of my Rails app I get

SECRET_KEY_BASE=‘my secret key’ export YAMAMA_DATABASE_PASSWORD=‘my database password’

So I am assuming the file is in the correct location. Still can’t get it working.

I’m not sure if it matters or not, but it’s worth noting that the development environment will run - I only get this message when running RAILS_ENV=production --binding=MyIPAddress

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
April 16, 2015

Did you install Rails with rbenv, like in the prerequisites? If not, try setting the environment variables manually. e.g. run

export YAMAHA_DATABASE_PASSWORD=mysecretkey
export SECRET_KEY_BASE=mysecretkey

before RAILS_ENV=production rails server --binding=ip_address.

If that doesn’t work, your database.yml could be misconfigured (or your PostgreSQL user isn’t set up).

You can check the log at log/production.log for errors about the database connection.

You know (and I believe this is where my general knowledge is showing itself even more) I’m pretty sure that I used the tutorial on how to install with RVM and then jumped over to this one…I have about a million tabs open and wasn’t being careful.

https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-on-ubuntu-14-04-using-rvm

In any event, setting the variables manually did the trick! I can now see the scaffolded page I made on the server.

Is there something I can do so that I don’t have to manually do this each time now that we’ve established I didn’t do something correctly with regard to rbenv (I’d like to continue with your tutorial but want to make sure I’m not setting myself up for even more problems with subsequent steps)?

Thanks for your patience and help!

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
April 16, 2015

The easiest thing to do is to start from scratch (create a new droplet, if you’re using DigitalOcean), then start with the prerequisite tutorials that install RoR with rbenv and PostgreSQL. If you don’t have that option, I believe RVM can be removed by using rvm implode (I’ve never used this), then you can install rbenv/RoR.

The rbenv-vars variables only get loaded if you used rbenv to install Ruby.

Ok, I’ve made it to the end and want to see if I can get this working before I scrap it and start over - Unicorn and Nginx are both up and running. But when I connect to http://my_public_IP/tasks the browser displays that it can’t establish a connection to the server. I know there are a million things that could’ve gone wrong, but anything off the top of your head I should check to see why it’s not seeing my app?

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
April 17, 2015

Is Nginx listening on port 80? Sometimes you’ll run into this issue if some other software is using the port.

sudo netstat -nap | grep :80

Did code sudo netstat -nap | grep :80 but nothing happened. Where should I start looking from what is wrong with my setup?

Thanks for the great tutorial. Took me about a day and a half and rebuilding my server 4 times(plain ubuntu and unicorn+nginx). But finally got it to work. from plain ubuntu. I would suggest adding to your prerequisite postgreSQL tutorial the issues that might arise if locales aren’t set correctly before installing postgresql(fought with that for quite some time until I finally figured what the problem was),

But otherwise great tutorial.

When I get to the part where I install unicorn and try to start it, using:

sudo service unicorn_appname start

I get this error:

Starting appname
-su: bundle: command not found

(I literally named the app “appname”, just for testing purposes, fyi) I’m certain that all users can bundle. I’m lost and this error makes no sense to me. If anybody else has run into this error, I would appreciate your insight. Thanks.

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
April 23, 2015

Did you set USER variable in the init script?

Yes, I set the USER variable in the init script, there was only one user for the system and the database. I destroyed and rebuilt my droplet and tried again and got the exact same error. I’m going to try one more time.

I solved the problem, in case anyone else runs into this. This first tutorial in this series, where I installed rbenv, I strayed from the tutorial and used .bashrc instead of .bash_profile. The reason I did this was because using “exec $SHELL” doesn’t work. The trick is at the bottom of that particular page in that article. One commenter said to use .bashrc (which works and makes you feel awesome till you get to a point…it fails at the point where I had the problem…hence my roadblock, su can’t read .bashrc, so it’s basically lost). The other commenter said to use “source ~/.bash_profile” instead of “exec $SHELL”…This is what I was doing wrong…Summary: if anyone else tried doing .bashrc in the first of these tutorials it’s the wrong choice, use .bash_profile and “source ~/.bash_profile”.

Having the same issue. No solution in sight :/

I know it’s an old post but whoever is stuck on this can try this:

In Unicorn Init Script just replace the CMD line with the following.

GEM_PATH="/home/$USER/.rbenv/shims"
CMD="cd $APP_ROOT && $GEM_PATH/bundle exec unicorn -c config/unicorn.rb -E $ENV -D"

and save and exit

sudo systemctl daemon-reload

Thanks Mitchell. This worked for me (although I did have to use source ~/.bash_profile instead of exec $SHELL)

One thing that’s not working as expected is re-deploying code. When I issue sudo service unicorn_appname restart, it doesn’t reload the new codebase (models, controllers, config, etc.). The Digital Ocean Nginx/Unicorn/Rails image refreshes the code upon a unicorn restart. Is there something I’m missing?

Also, maybe this is a similar problem, but when I issue sudo service unicorn_appname stop, and then sudo service unicorn_appname start the prompt says “Already running”

Thanks for the great tutorial.

Any update on this? Thanks!

When I try …sudo service unicorn_myapp start. I get this message

/etc/init.d/unicorn_myfriendlyroad: 13: /etc/init.d/unicorn_myfriendlyroad: Syntax error: “(” unexpected

I tried setting up a new droplet and starting over and still get the same message.

Help?!

Fixed it, just realized I had a couple of missed line breaks when I copied and pasted. … Now I will figure out my bash issues … got this message

bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell

I have the same issue. what do you mean by “missed line breaks”? My error is : /home/ec2-user/rails_projects/firstapp/config/unicorn.rb: line 1: syntax error near unexpected token (' /home/ec2-user/rails_projects/firstapp/config/unicorn.rb: line 1: app_dir = File.expand_path(“…/…”, FILE)’

Sorry for the late reply on this. What I meant by line breaks was, be careful with copy and paste. It turns out when I pasted, my nano editor added some extra line breaks and did not copy the file correctly. That created this error syntax error near unexpected token `(’ … When I edited my file to make sure it matched the content in the tutorial, the error went away.

I managed to fix the bash issue. However, I can’t get my site to run on port 80. I can see it on http:myapp.com:8080 but not on port 80. The connection is refused. I have a UFW and port 80 is added. I will post a question on the community board, seperately.

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
June 1, 2015

Which port is Nginx configured to listen on? It should have a line like listen 80; in the server block.

My nginx configuration followed the tutorial exactly, when I enter example.com in my browser, I get ERR_CONNECTION_REFUSED. If I add port 8080 example.com:8080, I can see my site. In dev, I was able to get it working on port 3000 using

My nginx configuration follows the configuration in the tutorial. I think it has something to do with the rbenv, or ? When I loaded my production database, I my database.yml would not read my password. By typing rbenv vars in the console, get the exports, but it would not take it when I tried to set up the production database. So, I copied and pasted them in place of the <%=ENV… > in mydatabase.ym. and secrets.yml (not ideal, but wanted to see if it worked). When I run RAILS_ENV=production rails server --binding=my-ip-address I see only HTML When I run sudo service unicorn_myapp start, I get … Starting my app and then bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell I logged a service ticket and they say “something isn’t working as expected in the init script unicorn_app”

I stuck with the config in the tutorial for Unicorn.rb and unicorn_myapp and followed the steps in the tutorial. I also made sure I have unicorn in my gems and did a gem install and bundle update to make sure.

I am able to use the command unicorn. (not unicorn_myapp) … and it gets this result I, [2015-06-01T21:22:52.143309 #22595] INFO – : listening on addr=0.0.0.0:8080 fd=9 I, [2015-06-01T21:22:52.144178 #22595] INFO – : worker=0 spawning… I, [2015-06-01T21:22:52.145277 #22595] INFO – : master process ready I, [2015-06-01T21:22:52.146540 #22639] INFO – : worker=0 spawned pid=22639 I, [2015-06-01T21:22:52.147100 #22639] INFO – : Refreshing Gem list I, [2015-06-01T21:22:54.089793 #22639] INFO – : worker=0 ready

typo above meant to say… when I run sudo service unicorn_myapp, I get the weird bash error …

Hi there, thanks for the tutorial, although, I can’t actually save my unicorn_appname file because it tells me “Unable to save /etc/init.d/unicorn_klein_and_sons - Error: No such file or directory”. I am using Sublime as an editor is that part of the problem?

cd ~/.rbenv/plugins

I am trying to install rbenv-vars by cd-ing into the directory above after I "cd ~"and it doesn’t exist. I tried doing the same thing in my “/home/rails” and it doesn’t exist either. So where is this file or folder? how exactly do i navigate there?

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
June 15, 2015

Did you follow the rbenv tutorial?

ok I will do that

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
June 15, 2015

Are you using the Rails one-click image? If so, you shouldn’t use this tutorial (use this one instead).

I am trying to start service unicorn by using this command.

sudo service unicorn_firstapp start

But, getting the error :

Starting firstapp
/home/ec2-user/rails_projects/firstapp/config/unicorn.rb: line 1: syntax error near unexpected token `('
/home/ec2-user/rails_projects/firstapp/config/unicorn.rb: line 1: `app_dir = File.expand_path("../..", __FILE__)'

Can any one help me please?

Thanks! Your tutorial is awesome. I followed it step by step. Finally, I can access http://server_public_IP/tasks from a browser. But after I added a task, I could not destroy it in the page. It went to the show page of the task. Also, I found in developer tools that http://server_public_IP/stylesheets/application.css and http://server_public_IP/javascripts/application.js are not found. Would you give me any clue?

I checked the directory app_name/public/assets/. The 2 files exist.

application-0723cb9a2dd5a514d954f70e0fe0b89f6f9f1ae3a375c182f43b5f2b57e9c869.css application-a8b5e641d816fad411210989c7f4227a2bfd2ce3f4038925fb02a7864c1fb618.js

Regarding the assets, I have just run into the same issue -try adding this file into the nginx default file:

    location ~* ^.+\.(css|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mp3|flv|mpeg|avi)$ {
                    try_files $uri @app;
            }

when i run the RAILS_ENV=production rails server --binding=myiphere, the webrick client runs normally but i ca’nt acces the page and the webrick wint recive any call what can be that?

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
July 6, 2015

I think you need to bind to an IP address.

what do you mean with bind IP? i’m using my pulic ip served by DigitalOcean 45.55.20.30, so i use RAILS_ENV=production rails server --binding=45.55.20.30

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
July 6, 2015

Yes, that’s correct. So you should be able to access your rails server at the IP address on port 3000 (the default).

in the http://45.55.20.30:3000/ correct? if so i’m doing this and my webrick wont recive any requests and the page wont load =/, i miss something?

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
July 6, 2015

Do you have a firewall that is blocking the incoming requests?

Sorry i made a huge mistake, i cant acces because here in my work port 3000 is bloked so i changed to port 8080 and it Works!!, thanks and sorry 'bout that. But is normal the webrick wont show the requests? before i start to try deploy on digital ocean i’ve used a server wich has a webrick it was show every request on console.

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
July 6, 2015

If a firewall was blocking the requests, webrick can’t show the requests because it never received them in the first place. It sounds like you resolved the issue though.

Thanx for the tutorial! I am using sqlite for production. I was getting 500 error in production and couldn’t find the real reason. First it is a good idea to test in production with WEBrick: rails s -b **droplet_ip** -e production, but you should enable config.serve_static_files = true in config/environments/production.rb temporary in order for webrick to serve static assets. But don’t forget to comment that line when you’ll switch to nginx+unicorn combo. Also log at ~/app_path/log/production.log gave me a hint that something was wrong with database connection, but I did rake db:migrate rails_env=production before. I did it again but again I have got just an empty production.sqlite3 file . cp development.sqlite3 production.sqlite3 did the trick. And I think it would be great to keep all of the config files in ~/app_path/config/ and link to /etc/init.d/unicorn_app_name and /etc/nginx/sites-enabled/app_name. IMHO it would be logical and easier to understand. Two configs for nginx and two for unicorn in different places is confusing to deal with. If you are inexperienced in linux it is a true nightmare as it was for me for last 3 weeks. Here you can simply pull from your git repo.

Hello, i have a question,

I configured the Unicorn and Nginx and when i go to my http://server_public_IP it show me a message that say: Welcome to Nginx.

Then when i run this command: RAILS_ENV=production rails server --binding=server_public_IP

I can see in my Rails app in the http://serve_public_IP:3000, but i want to configure to see my Rails App in http://server_public_IP or something better like http://mydomain.com i have made this before with Passenger and Nginx, it can be do it with Unicorn and Nginx?

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
July 14, 2015

Yes, if you follow this tutorial it should result in a setup like you described.

Ok thanks, i have done everything from the beginning and it works!

Another question,

Why in my domain name there is something called DreamFactory?

My domain is kodfocus.com

Hi, thank you for this great tutorial! I just have a couple of questions.

When I use the unicorn init script to start my unicorn server: sudo service unicorn_app start

I receive an error: Could not find minitest-5.7.0 in any of the sources Run bundle install to install missing gems

Looks like this happens because the script prepends the start command with su - user -c su - user -c “cd /home/user/app && bundle exec unicorn -c config/unicorn.rb -E production -D” #This throws the error cd /home/user/app && bundle exec unicorn -c config/unicorn.rb -E production -D # This works

But I don’t understand why, could it be related to rbenv?

Also, is there a way to make sure unicorn is listening on the specified socket? when I try to access http://server_public_IP/tasks I get a 404 by nginx

Thank you

Hi there! I’ve followed everything as it is in tutorial, there was no errors, notices or warnings during the tutorial setup. When I run rails server everything is okay (I set my ip_address:3000, and I can see actual app in the browser), BUT when I run my app after the last step in this tutorial, just Unable to connect shows up. I’m a bit confused about that. What should I do, where to start looking from? Waiting for you help, people! Thanks in advance.

P.S. When I open firebug, I can see there is GET status ABORTED in Net tab.

Hello Guys,

I recently run into a problem, i can’t start unicorn service, everything was working perfectly i stop unicorn service and want to start it again using the command sudo service unicorn_appname start but it show me this message:

/etc/init.d/unicorn_appname: 33: kill: No such process

Starting appname
master failed to start, check stderr log for details

I Have fixit! It was a environment variable bad declared.

Amazingly detailed and helpful tutorial. Thank you @manicas!

when i run sudo service unicorn_appxyz start it gives me -su: bundle: command not found error

ruby, rail and bundle are installed correctly under the user that owns the rails app.

joe@vps:~$ which ruby
/home/joe/.rbenv/shims/ruby
joe@vps:~$ which rails
/home/joe/.rbenv/shims/rails
joe@vps:~$ which bundle
/home/joe/.rbenv/shims/bundle

If I run bundle exec unicorn -c config/unicorn.rb -E production -D under the app folder as ‘joe’ the server starts fine.

If I run the expanded out bash script under root it does not work and says bundler is not installed please install bundler.

the expanded startup script extracted from the init.d/unicorn_appxyz upstart script’s is the following.

su - joe -c cd /home/joe/appxyz && bundle exec unicorn -c config/unicorn.rb -E production -D

I’m assuming it is root that will run the init.d files when i boot the machine. The above bash should first switch to user joe and run the bundle command under the app folder. However this is not the case for some reason.

My understanding is rbenv is for single user. Shouldn’t everything work even rbenv is not installed for root?

I have posted this on Stackoverflow with full init.d script. http://stackoverflow.com/questions/31971806/unicorn-service-upstart-script-throws-su-bundle-command-not-found

I figured out the issue.

When root excuted su - joe. the login does not run .bashrc file. Since all the path for bundle in include in .bashrc this causes bundle to be not found.

I included the PATH to the .profile file and it works.

When I run this command …

RAILS_ENV=production rake db:create

… I get the message that he can’t create the database. As you can see in the message the password is nil

Couldn't create database for {"adapter"=>"postgresql", "encoding"=>"unicode", "pool"=>5, "host"=>"localhost", "username"=>"USER", "database"=>"NAMEOFTHEPROJECT_production", "password"=>nil}

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
August 13, 2015

Did you follow the steps in Create Production Database User? You need to make sure that the username in database.yml matches the PostgreSQL user that you created (“appname” in the example).

Also, you need to be sure to set the database user’s password in the USER_DATABASE_PASSWORD environment variable. Right now, it’s not set and it shows as “nil”. The tutorial says to use rbenv-vars to set the password, but you can also do something like export USER_DATABASE_PASSWORD=password before running rake.

@manicas I follow the steps and successfully created a user (appname) and added the APPNAME__DATABASE__PASSWORD to the .rbenv-vars file.

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
August 13, 2015

Ok, so now make sure that your database.yml has the proper lines in set. Assuming the username is “appname”:

database.yml — production section
  username: appname
  password: <%= ENV['APPNAME_DATABASE_PASSWORD'] %>

You may also want to check that your APPNAME_DATABASE_PASSWORD env variable is working correctly by running this command in your app’s root directory:

rbenv vars

@manicas when I do export USER_DATABASE_PASSWORD=password it says that theexport command was not found.

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
August 13, 2015

Which shell are you using? I’m assuming you’re using bash.

By the way, you need to make sure that the environment variable name matches whatever you specified in your database.yml file (so the app will know the database password).

@manicas I’m quite sure that I set everything correctly. Created the .rbenv-vars file and I set the variables (as explained in the tutorial in the file). The token and the password from the user that I created in the previous step.

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
August 14, 2015

Are you getting the same error message still?

Followed the instrucitons on this page in setting up unicorn. However, I get this message when I try starting unicorn service:

No passwd entry for user ‘deploy’

Please advice. Thanks.

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
August 24, 2015

The tutorial assumes that you are using a user called deploy. You are probably using a different user. You need to replace “deploy” with your actual username in the following locations:

  • /etc/init.d/unicorn_appname
  • /etc/nginx/sites-available/default

This guide was great until I actually got to deploying the Rails application I was building. Here they just create a dummy application rather than deploy something prebuilt. I put together a git gist explaining the steps I took here

Hey, I have done all this, step by step, and I have almost everything going well. Excepto for the assets, I mean, the images and the CSS files and the JS files are not loaded, my app looks like a simple HTML. in the console these errors are shown:

[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (application.css, line 0)
[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (application.js, line 0)

I’m using VMWare Fusion with a virtual machine with Ubuntu Server 14.04, but I don’t think it is the problem, Isn’t it?

Please help me out and thanks for reading!

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
September 21, 2015

You’ll need to precompile your assets. Use this command in your app’s directory:

  1. RAILS_ENV=production rake assets:precompile

sudo -u postgres createuser -s appname This partiucular command is asking for password and i have no clue what password to enter here.Can I get some help?

Mitchell Anicas
DigitalOcean Employee
DigitalOcean Employee badge
October 5, 2015

It’s asking for your user’s password. sudo asks the system to run the command as a superuser (i.e. same privileges as root), so your user needs to be set up: Initial Server Setup with Ubuntu 14.04.

Just FYI…I may have missed or overlooked something, but I kept getting 502 errors. When I checked the nginx log, it was being denied permission on the socket. I updated the user name on the first line in the /etc/nginx/nginx.conf file (the default was “www-data”) and that solved the problem.

Thanks for a great tutorial!

This comment has been deleted

    Any idea on why am getting blank response here - http://www.practoline.com/ ?

    Am using Rails4, Unicorn and Nginx. No error log in tail “unicorn.log” also app log file is empty, Got no idea where to check the error detail

    Mitchell Anicas
    DigitalOcean Employee
    DigitalOcean Employee badge
    October 25, 2015

    As a user, you are connecting to Nginx, which is a reverse proxy to Unicorn. So you should check your Nginx configuration and logs, then make sure Unicorn is running.

    Great tutorial, thanks! But, how I redirect no-www to www domain?

    I tried this, but unsuccessfully:

    location / { if ($http_host ~* “^seusite.com.br”){ rewrite ^(.*)$ http://www.seusite.com.br/$1 redirect; } }

    Mitchell Anicas
    DigitalOcean Employee
    DigitalOcean Employee badge
    January 19, 2016

    Check out this tutorial (Option 2).

    Great tutorial. I’m still at the middle of it, and just as a reminder, don’t forget if you’re doing things locally and then deploying in a remote server, that just created directories in shared folder, are not going to be included in git unless you explicitly say so (like with an .keep file)

    Unicorn couldn’t start until I realized that.

    Hey but I got a question, is it necessary to start rails server? Or just starting unicorn and nginx should work? I think I’ve gone through but I can’t see anything on the http://public.app.site/

    And no errors on terminal.

    I guess I have to point to port 80, right?

    Mitchell Anicas
    DigitalOcean Employee
    DigitalOcean Employee badge
    February 22, 2016

    Unicorn is the Rails server. So Nginx needs to be configured to connect to the unicorn.sock to work. Nginx should be configured to listen on port 80, so you should be able to access the application as you mentioned if public.app.site resolves to your server’s IP address.

    Hi manicas thanks for your answer. I finally managed to make it work, works great, but I’m facing a problem with unicorn workers.

    It works really fast, but intermittently just freezes, and the workers get killed because of a timeout.

    I’ve been searching how to workaround this, and I found this: http://serverfault.com/questions/655430/unicorn-workers-timing-out-intermittently which explains pretty much the same problem I’m facing. It says

    
    E, [2016-02-23T00:21:16.756224 #62728] ERROR -- : worker=1 PID:63018 timeout (31s > 30s), killing
    E, [2016-02-23T00:21:16.768622 #62728] ERROR -- : reaped #<Process::Status: pid 63018 SIGKILL (signal 9)> worker=1
    I, [2016-02-23T00:21:16.768771 #62728]  INFO -- : worker=1 spawning...
    I, [2016-02-23T00:21:16.770521 #63198]  INFO -- : worker=1 spawned pid=63198
    I, [2016-02-23T00:21:16.770710 #63198]  INFO -- : worker=1 ready
    E, [2016-02-23T00:21:49.803418 #62728] ERROR -- : worker=0 PID:63010 timeout (31s > 30s), killing
    E, [2016-02-23T00:21:49.810124 #62728] ERROR -- : reaped #<Process::Status: pid 63010 SIGKILL (signal 9)> worker=0
    I, [2016-02-23T00:21:49.810298 #62728]  INFO -- : worker=0 spawning...
    I, [2016-02-23T00:21:49.818175 #63202]  INFO -- : worker=0 spawned pid=63202
    I, [2016-02-23T00:21:49.818423 #63202]  INFO -- : worker=0 ready
    

    Once in every 10 minutes or so. And after refreshing twice, page works fine again.

    I’m not using any middleware software, just rails+unicorn+nginx, and my postgres db is in other machine.

    In ngnix log got error, unix:/home/azureuser/lovebeer_dev/shared/sockets/unicorn.sock failed (13: Permission denied) while connecting to upstream, Dont understand what happen the permission of my file socket are ‘srwxrwxrwx. 1 azureuser azureuser 0 Feb 24 14:21 unicorn.sock’

    When i try to run

    sudo service unicorn start

    I get the following error message any ideas?

    Job for unicorn.service failed. See “systemctl status unicorn.service” and “journalctl -xe” for details.

    and this is from inside systemctl status unicorn.service

    ● unicorn.service - LSB: starts the unicorn app server Loaded: loaded (/etc/init.d/unicorn) Active: failed (Result: exit-code) since Tue 2016-03-01 02:01:15 UTC; 57s ago Docs: man:systemd-sysv-generator(8) Process: 14941 ExecStart=/etc/init.d/unicorn start (code=exited, status=127)

    Mitchell Anicas
    DigitalOcean Employee
    DigitalOcean Employee badge
    March 1, 2016

    Which distribution of linux are you using?

    I am running on Ubuntu 15.04 x64

    This comment has been deleted

      I followed this tutorial using the sample app (I called it appname) except I edited routes.rb for the root to direct to tasks#index. When I got to the end I was able to see a ‘welcome to nginx’ message at the ip address, and I had to add /tasks to get to the sample app page. I realized that I had made a typo on my routes.rb file, so I corrected it, tried restarting the unicorn and nginx services, and failed. The app works perfectly when I test it with ‘RAILS_ENV=production rails server --binding=server_public_IP’, but no matter how many times and ways I try to restart the other services nothing works. Can you help me?

      nevermind - it turns out an extra bracket had found it’s way into /etc/nginx/sites-enabled/default . I hadn’t noticed that nginx was sending me a fail message when I tried to restart it.

      I have found an issue with the service shell script above.

      The restart command does not kill the old unicorn instance. According to the unicorn manual linked below

      (https://unicorn.bogomips.org/SIGNALS.html)

      “USR2 - reexecute the running binary. A separate QUIT should be sent to the original process once the child is verified to be up and running.”

      Therefore the first line of the restart case should be sig USR2 && oldsig QUIT && echo “reloaded $APP_NAME” && exit 0

      Awesome tutorial! It help a lot.

      Just a minor fix:

      in the text:

      Update the script's permissions and enable Unicorn to start on boot:
      
      $ sudo chmod 755 /etc/init.d/unicorn_appname
      $ sudo update-rc.d unicorn_appname defaults
      

      … you guys forgot to highlight the “appname” to remind the reader to change for his/her application.

      But it is still awesome as I say. Thanks! :D

      after I run sudo service unicorn start I got an error saying:

      /usr/local/rvm/gems/ruby-2.2.1/gems/unicorn-5.1.0/lib/unicorn/configurator.rb:88:in `block in reload': directory for pid=/home/rails/shared/pids/unicorn.pid not writable (ArgumentError)```
      
      Before this i create the shared folders in my app or rails directory but their aren't any file called unicorn.pid in the /shared/pids/ folder .. so I created one using ```touch unicorn.pid``` 
      
      After I got this error I also tried to give it permission to be able to write by going into unicorn.pid directory and type ```chmod u+w unicorn.pid```
      
      So far nothing work and I have no idea what I need to do. Please help!

      When I run

      sudo service unicorn_appname start
      
      

      after following the tutorial to the section on creating the init unicorn file I get this error…

      Starting rails
      /usr/local/rvm/gems/ruby-2.2.1/gems/unicorn-5.1.0/lib/unicorn/configurator.rb:88:in `block in reload': directory for pid=/home/rails/shared/pids/unicorn.pid not writable (ArgumentError)
      

      It didn’t have unicorn.pid in the rails/shared/pids folder I created in my app/rails directory so I created one using touch unicorn.pid I notice there also isn’t unicorn.sock in the /shared/sockets I also created another one. I tried giving permission by using chmod u+w unicorn.pid but nothing works. I have not sure what I need to do.

      Please help!

      When I run

      sudo service unicorn_appname start
      

      after following the tutorial to the section on creating the init unicorn file I get this error…

      Starting rails
      /usr/local/rvm/gems/ruby-2.2.1/gems/unicorn-5.1.0/lib/unicorn/configurator.rb:88:in `block in reload': directory for pid=/home/rails/shared/pids/unicorn.pid not writable (ArgumentError)
      

      It didn’t have unicorn.pid in the rails/shared/pids folder I created in my app/rails directory so I created one using touch unicorn.pid I notice there also isn’t unicorn.sock in the /shared/sockets I also created another one. I tried giving permission by using chmod u+w unicorn.pid but nothing works. I have not sure what I need to do.

      Please help!

      Sorry for multiple posts, I couldn’t see my answer when refreshed so I thought it didn’t work.

      How is nobody pointing out the fact that SSL is not being forced?

      Great tutorial. I ended up using most of your steps, but used Passenger instead. I’ve created a mini tutorial here for those interested: https://neeto.io/b69AwLSK

      Need your help, Ruby on Rails, Nginx, Unicorn I followed same blog but don’t know where I’m missing.

      Please have a look to my question and please suggest me for right way to do that.

      http://stackoverflow.com/questions/43393960/deploy-rails-app-with-nginx-and-unicorn-not-opening-application-home-page

      Hi! How can i change de Database Manager to MySql?

      Try DigitalOcean for free

      Click below to sign up and get $200 of credit to try our products over 60 days!

      Sign up

      Join the Tech Talk
      Success! Thank you! Please check your email for further details.

      Please complete your information!

      Become a contributor for community

      Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

      DigitalOcean Documentation

      Full documentation for every DigitalOcean product.

      Resources for startups and SMBs

      The Wave has everything you need to know about building a business, from raising funding to marketing your product.

      Get our newsletter

      Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

      New accounts only. By submitting your email you agree to our Privacy Policy

      The developer cloud

      Scale up as you grow — whether you're running one virtual machine or ten thousand.

      Get started for free

      Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

      *This promotional offer applies to new accounts only.