Setting up a Rails Server and Deploying with Capistrano on Fedora from Scratch


This article and video tutorial will teach you how to setup a basic Fedora server for Rails and PostgreSQL deployments. First, we'll setup Apache and PostgreSQL. Then, we'll use phpPgAdmin to create our application's user and databases. After that, we'll setup the Ruby platform using Passenger to run our application. Once all the components are installed, we'll prep our application for deployment using Capistrano.

I'll show you how to use Capistrano to automate remote tasks and take advantage of other features.

On With The Show

Understanding the Deployment Process

There is always a lot of confusion around deploying Rails applications. This tutorial hopes to sort some of that out. Most people know LAMP: Linux, Apache, MySQL, and PHP. We will setup LAPR: Linux, Apache, PostgreSQL, and Ruby. Setting up a LAPR server is very similar to setting up a LAMP server. The only wrinkle is getting Rails to talk to Apache. Thankfully, there is Passenger aka mod\_rails. Passenger is like mod\_php. It makes running Rails applications easy as pie. In order to run a Rails application through Apache, create a virtual host pointing the document root to the applications public directory and you'll be riding on rails.

Capistrano is another part that people may not be familiar with. Capistrano is a Ruby gem designed to execute tasks on one or more remote machines. You'll need SSH access to use Capistrano. Capistrano, affectionately known as Cap, automates the deploy process. We can use cap to take our code from some a repo and push it to the server, stop/start/restart the server, write custom tasks required by our application (think install required gems), or disable/enable a maintenance page. Using cap is not required but it sure beats using FTP to copy all the files around! Cap's real power comes from the ability to write custom tasks in Ruby to manipulate the server. I've written a lot of applications that allow user file uploads. Then on the server side, some directory needs to be created with proper permissions for the uploads to succeed. It's easy enough to write a cap task to create the directory and set the permissions. Then, if you ever change servers, you can simply run the cap task to setup the server again. There are many things you can do with Capistrano. You could even automate this entire tutorial to set up any number of machines at once!

Tutorial Sandbox

In order to complete this tutorial, you'll need SSH + sudo access. If you don't have a spare server sitting around, you can create one in VirtualBox. You can easily create a new VM and network it with your host system. I did this for the tutorial. When you start your virtual machine, make sure you use a bridged adapter so your VM gets an IP on the same subnet. I started with a fresh install without any customization. If you have access to a VPS like SliceHost, you can use these instructions as well.

Be sure to view the screencast before analyzing the code below.

Creating The Deployer

    $ sudo adduser -m deployer
    $ sudo passwd deployer
    $ sudo visudo deployer ALL=(ALL) NOPASSWD: ALL
    $ su deployer
    $ mkdir ~/.ssh
    $ touch ~/.ssh/authorized_keys2
    $ chmod -R 0700 ~/.ssh
    # copy your public key and paste it into the authorized_keys2 file
    $ service sshd start

Setting Up Postgres

    $ sudo yum groupinstall "PostgreSQL Database"
    $ sudo service postgresql initdb
    $ sudo service postgresql start
    $ su - postgres
    $ psql -d template1
    $ alter user postgres with password 'yourpostgresuserpassword';
    $ \q
    # Replace ident in /var/usr/lib/pgsql/data/pg_hba.conf with md5
    $ passwd postgres
    # set extra security in /etc/phpPgAdmin/ to false
    # add 'Allow from YOUR_IP_HERE' to vhost in /etc/httpd/conf.d/phpPgAdmin.conf
    # enable http in the firewall
    $ sudo yum install httpd
    $ sudo service httpd start
    $ sudo service postgresql restart

Configuring Ruby, RubyGems, and Passenger

    $ sudo yum groupinstall Ruby
    $ sudo yum install rubygems
    $ sudo gem install gemcutter
    $ sudo yum install postgresql-devel
    $ sudo gem install pg
    $ sudo gem install passenger
    $ yum install gcc-c++ httpd-devel apr-devel
    $ sudo passenger-install-apache2-module
    # create this file /etc/http/conf.d/passenger.conf with these contents:
      LoadModule passenger_module     /usr/lib/ruby/gems/1.8/gems/passenger-2.2.9/ext/apache2/
      PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.9
      PassengerRuby /usr/bin/ruby

    $ sudo setenforce 0
    $ sudo service httpd restart

Creating the Deployer Folder

    $ sudo mkdir /var/www/html/apps
    $ sudo chown deployer:apache /var/www/html/apps
    $ sudo yum install git
    # at this point, create your databases in phpPgAdmin

Configuring Apache

    # echo "Include vhost.d/*.vhost" >> /etc/httpd/conf/httpd.conf
    $ sudo mkdir /etc/httpd/vhost.d
    $ sudo touch /etc/httpd/vhost.d/nettuts-demo.vhost
    # update that files conttents to:
          DocumentRoot /var/www/html/apps/nettuts-demo/current/public
            Options FollowSymLinks
              Allow from all
              Options -MultiViews
          RewriteEngine On
          RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
          RewriteCond %{SCRIPT_FILENAME} !maintenance.html
          RewriteRule $ /system/maintenance.html [R=302,L]

Complete Cap File

    set :application, "nettuts-demo"
    set :repository,  "git://"

    set :user, :deployer

    set :deploy_to, "/var/www/html/apps/#{application}"

    set :use_sudo, false

    set :scm, :git

    role :web, ""                          # Your HTTP server, Apache/etc
    role :app, ""                          # This may be the same as your `Web` server
    role :db,  "", :primary => true # This is where Rails migrations will run
    role :db,  ""

    default_run_options[:pty] = true

    namespace :deploy do
       task :start do ; end
       task :stop do ; end
       task :restart, :roles => :app, :except => { :no_release => true } do
         run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"

       desc "Installs required gems"
       task :gems, :roles => :app do
         run "cd #{current_path} && sudo rake gems:install RAILS_ENV=production"
       after "deploy:setup", "deploy:gems"   

       before "deploy", "deploy:web:disable"
       after "deploy", "deploy:web:enable"
Related Posts
  • Code
    Web Development
    How to Use New Relic With PHP & WordPressRelic retina preview
    Today we will look at how to monitor a PHP application using New Relic. More specifically we will set up a basic WordPress installation and get some performance data about it, in the New Relic dashboards.Read More…
  • Code
    An Introduction To Deploying WordPress with MinaImage400
    As a PHP application, WordPress is usually deployed by a very old method: uploading files via FTP. We have some deployment tools, but they often requires some type of Ruby skill. For example, one popular, powerful tool is Capistrano, but it's also very heavy with many Ruby/Rails related features. I also think that it's little bit tricky to install Capistrano for a PHP developer without any Ruby knowledge. So what options do we have as WordPress developers? In this tutorial, I will introduce you Mina: A small, light tool aims to fast deployment and server automation.Read More…
  • Computer Skills
    How to Use a Raspberry Pi as a Local Web ServerThumb
    In this tutorial I will show you how to set up a Raspberry Pi to be used as a Local Web Server with SSH and FTP functionality.Read More…
  • Code
    Deploying a Laravel Application Using CapistranoLaravel 4 auth retina preview
    So you've just built a fancy web application and you're planning to put it online. This can be done in many ways. In this article I'd like to cover one approach to deploy your backend system to your production server. We'll go through the following steps by example of a Laravel application but this can be applied to any other language or technology.Read More…
  • Computer Skills
    Take Control of Your Raspberry Pi Using Your Mac, PC, iPad or PhonePi ra400
    In this tutorial I will show you how to setup your Raspberry Pi for remote control on your home network or over an internet connection. This is really useful if you want to run your Pi as a 'headless' machine without the need for its own monitor, mouse and keyboard - instead you can use your home computer, ipad or even mobile phone to access and control your Pi. I'm going to be using two methods to remotely control the Pi -- SSH (Secure SHell) which provides access to the Pi's command line interface, and VNC (Virtual Network Computing) which replicates the graphical desktop. Of the two SSH is much quicker as it's just text based, but VNC is probably easier to use on a tablet or smartphone.Read More…
  • Code
    Setting Up A Staging Environment Staging
    It's common practice to work locally on a project and push revisions to a production server, but the step that people often skip is the staging server. A staging server is a mix between production and development; you get to test your app as if it were in production. Let's review some of the issues that you'll have to consider, as well as the steps needed to replicate a production Platform as a Service (PAAS).Read More…