Deploying Rails apps using Capistrano

Capistrano Logo Deploying your application to the web is not a one-time thing. There will be changes to the application code, new assets to include, database updates, and so on. Applying these changes to your web server includes a list of commands that we need to do every time we need to deploy.

Capistrano solves this problem by automating the deploy process so you can execute all of the steps in a single command. Automation prevents user errors while deploying like forgetting the precompile task when assets have changed, missing database migrations, and remembering the sequence of commands. Automation also enables your infrastructure to scale so that your code is automatically deployed to all application servers without logging in to each one to manually deploy your code.

In order to use Capistrano, you need to set up your web server first (we will use Nginx in this article). If you have already done this, please skip the first section of the article and proceed to installing and setting up Capistrano.

Note: This article assumes that you have already set up your server and are using Ruby on Rails as your application framework.

Nginx

Installation

We will install Nginx via the Passenger gem.

In order to do this, we need root privileges. If you are using RVM, it already provides a sudo command called rvmsudo, but if you are using rbenv, you need to install the rbenv-sudo plugin first:

git clone git://github.com/dcarley/rbenv-sudo.git ~/.rbenv/plugins/rbenv-sudo

We then install the passenger gem by adding this line to our Gemfile:

gem 'passenger'

Then install the gem and its binaries:

bundle install

And if you are using rbenv, update with the newly installed binaries:

rbenv rehash

We are now ready to install Nginx via Passenger:

If you are using RVM:

rvmsudo passenger-install-nginx-module

If you are using rbenv:

rbenv sudo passenger-install-nginx-module

Compared to installing Nginx via the Ubuntu package manager (sudo apt-get install nginx) this method of installing Nginx does not provide the start and stop scripts so we can conveniently control the web server process. Thus we need to manually provide this init script in our system:

wget -O init-deb.sh https://raw.github.com/JasonGiedymin/nginx-init-ubuntu/master/nginx
sudo mv init-deb.sh /etc/init.d/nginx

There is a small change that needs to be done in our init script, which is to specify the location of the Nginx install. By default this is located at /opt/nginx, so we set it accordingly:

sudo nano /etc/init.d/nginx

NGINXPATH=${NGINXPATH:-/opt/nginx}      # root path where installed

We make our init script executable:

sudo chmod +x /etc/init.d/nginx

Then we also set it so that Nginx runs automatically when you reboot the system:

sudo /usr/sbin/update-rc.d -f nginx defaults

Rails application server block

We will place all our application code in /var/www/. Make sure that the deploy user that we created has read and write access to this directory.

Next we need to configure Nginx so that it runs our code in /var/www/. Nginx provides a simple way to organize our server configuration in server “blocks” which is very useful especially if we are running multiple applications in the same server. It will look for additonal configuration in the /etc/nginx/sites-enabled directory and includes it when running the web processes.

However, we will not be putting our configuration directly in /etc/nginx/sites-enabled, instead we will create them in the /etc/nginx/sites-available directory. In this example, we assume we have a Rails application called myrailsapp.

Create and edit a new file called myrailsapp.conf in the sites-available directory:

sudo nano /etc/nginx/sites-available/myrailsapp.conf

In the empty file, put in the following:

server {
  listen       80;
  server_name  mydomain.com www.mydomain.com;
  root /var/www/myrailsapp/current/public;
  # passenger_min_instances 4;

  location / {
    passenger_enabled on;
  }
}

If you are using SSL certificates for your domain, place the certificate/certificate bundle and the key file in the /etc/nginx/ssl directory, then add the following as well in the myrailsapp.conf file:

server { listen 443; server_name mydomain.com www.mydomain.com; root /var/www/myrailsapp/current/public; # passenger_min_instances 4; ssl on; ssl_certificate /etc/nginx/ssl/mydomain_bundle.crt; ssl_certificate_key /etc/nginx/ssl/mydomain.com.key; # Forward secrecy settings ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS +RC4 RC4"; location / { passenger_enabled on; } } read more