Ruby on Rails
Rails on CentOS 4.3 with Apache and FastCGI Simply

These instructions have been tested twice with a clean minimal install of CentOS 4.3 after a yum update running under VMWare.

Note: I couldn’t make it run with my CentOS 4.3, I was getting this in my Apache error logs:
server /home/myuser/public_html/rubytest/dispatch.fcgi(26580) started
[Fri Oct 27 12:07:31 2006] [notice] mod_fcgid: process /home/myuser/public_html/rubytest/dispatch.fcgi(26580) exit(communication error), terminated by calling exit(), return code: 114

I tried with mod_fastcgi-2.4.2-3.fc4.i386.rpm and the other instructions in Rail on Fedora and worked fine.

Note: WikiGardening is in process – Brazen… actually I’ve pretty much abandoned this page as it’s too much work when people change things and introduce typos or just plain wrong information. It would also be better IMO if any questions for added to the very end. So if anyone else wants to double check it’s current state and clean things up (including removing my discussion comments, or move them to the end) then knock yourself out :D

Optional: Remove some unnecessary cruft.
(Beware of removing dependencies with this command, especially for up2date, it can remove a lot more than you want (such as gcc, bin/cp, etc).richard@d2p.us){color:blue} gcc is not part of a minimal install. If you want gcc, you’ll have to install it later anyway, however, you only need the steps in this document to get ruby on rails working.

  1. yum remove stunnel up2date cups gpm system-config-mouse pcmcia-cs isdn4k-utils NetworkManager

Install Dependencies

  1. yum update
  2. chkconfig yum on && service yum start
    If you want automatic updates. You should also restart (shutdown -r now) to load any updated kernel.
  3. yum install httpd-devel httpd apr apr-devel apr-util-devel emacs-common mysql-devel

Optional: If using a local mysql server as opposed to a (recommended) external mysql server.

  1. yum install mysql-server
  2. vi /etc/my.cnf
    Change this line
    old_passwords=1
    to this
    old_passwords=0

Install FastCGI

  1. wget http://www.fastcgi.com/dist/fcgi-2.4.0.tar.gz
  2. tar -xzf fcgi-2.4.0.tar.gz
  3. cd fcgi-2.4.0
  4. ./configure
  5. make
  6. make install
  7. cd ../

Install mod_fcgid

  1. cd ~
  2. wget http://fastcgi.coremail.cn/mod_fcgid.1.09.tar.gz
  3. tar -xzf mod_fcgid.1.09.tar.gz
  4. cd mod_fcgid.1.09
  5. vi Makefile
    Change top_dir to: <pre>top_dir = /usr/lib/httpd</pre> Uncomment #INCLUDES and change to <pre>INCLUDES=-I /usr/include/httpd -I /usr/include/apr-0 </pre>
  6. make
  7. make install
  8. cd ../

Install Ruby

  1. cd /etc/yum.repos.d/
  2. wget http://dev.centos.org/centos/4/CentOS-Testing.repo
  3. yum --enablerepo=c4-testing install ruby ruby-docs ri ruby-libs ruby-mode ruby-tcltk irb rdoc ruby-devel

Note: you may need to install ruby-irb instead of irb from the testing repo if version numbers do not match up

Install Ruby Gems

  1. wget http://rubyforge.org/frs/download.php/11289/rubygems-0.9.0.tgz
  2. tar -xzf rubygems-0.9.0.tgz
  3. cd rubygems-0.9.0
  4. ruby setup.rb
  5. cd ../
  6. gem update

Install Rails, FastCGI, and Mysql

  1. gem install rails --include-dependencies
  2. gem install fcgi
  3. gem install mysql -- --with-mysql-config=/usr/bin/mysql_config
    1. Select option – mysql 2.7 (ruby)
  4. vi /etc/ld.so.conf
    Add line: <pre>/usr/local/lib </pre>
  5. /sbin/ldconfig

Create Test Application – this will get you started on the popular “cookbook” tutorial from OnLamp.

  1. mkdir /var/www/rails
  2. cd /var/www/rails/
  3. rails cookbook

Set Permissions on Test Application

  1. chgrp -R apache cookbook/
  2. chmod -R g+r cookbook/
  3. chmod -R g+w cookbook/log/
  4. chmod -R g+w cookbook/tmp/
  5. find /var/www/rails/cookbook/ -type d -exec chmod g+x {} \;

Configure Apache

  1. vi /etc/httpd/conf.d/fcgid.conf
    Insert the following:
LoadModule fcgid_module /usr/lib/httpd/modules/mod_fcgid.so

<IfModule mod_fcgid.c>
    SocketPath /tmp/fcgid_sock/
    AddHandler fcgid-script .fcgi
</IfModule>


Is the above a typo? where do we load mod_fastcgi?
This setup didn’t work for me until I changed it to
IfModule mod_fcgid.c. You are correct, there was a typo. I fixed it, but there may be others, I’m still revising, updating, proofreading, and testing this document. Thanks for helping out – Brazen. Apache wasn’t setting the
socket path correctly… further, no where in this
howto indicates that you MUST create that directory
/tmp/fcgid_sock/ and you MUST chown apache.apache it.You should NOT have to create this directory or change permissions on it. By default the apache user has permission to create files and folders in the /tmp directory. Apache will automatically create the directory on it’s own and assign it the proper permissions.

  1. vi /etc/httpd/conf.d/hosts.conf
    (Personally, I put all my custom Apache configuration in this file to keep things organized)
    Insert the following: <pre><VirtualHost *:80> SetEnv RAILS_ENV development ServerName dnsnameoripaddress DocumentRoot /var/www/rails/cookbook/public/ ErrorLog /var/www/rails/cookbook/log/apache.log
<Directory /var/www/rails/cookbook/public/> Options ExecCGI FollowSymLinks AddHandler fcgid-script .fcgi AllowOverride all Order allow,deny Allow from all

  1. vi /var/www/rails/cookbook/public/.htaccess
    Change line: <pre>RewriteRule ^(.*)$ dispatch.cgi [QSA,L]</pre> to <pre>RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]</pre> And change: <pre>AddHandler fastcgi-script .fcgi</pre> to <pre>AddHandler fcgid-script .fcgi</pre>do NOT change the _require_ line as other guides tell you to do.

Hello, World!

  1. cd /var/www/rails/cookbook/
  2. ruby script/generate controller MyTest
  3. vi app/controllers/my_test_controller.rb
    Change file to read: <pre>class MyTestController < ApplicationController def index render :text => "Hello World!" end end</pre>
  4. /sbin/service httpd start

Note: There was a typo in this hello world example which I fixed. The : before text was missing.

Note: you’ll need to run system-config-securitylevel-tui and add “www” to open up the firewall (or configure the firewall however you prefer to open tcp port 80).

Access http://dnsnameoripaddress/MyTest, “Hello World” should be displayed.

At this stage Ruby tells me “Recognition failed for MyTest” – yay more digging around looking for fixes!

I believe the URL is incorrect, I got the same error and after a bit of digging it would seem that you get that page for any ‘page not found’ errors if your Ruby server is running in development mode. If you change the url to: http://dnsnameoripaddress/mytest it works. The ONLamp tutorial uses windows, in which the urls are not case sensitive. Even though the app was created with uppercase names, the URL must be lowercase Actually at one point, any of these three URLs would work: MyTest, mytest, or my_test, even on case sensitive OSes. For some reason an update to rails changed this.

I got an error: [error] (13)Permission denied: mod_fcgid: couldn't bind unix domain socket /etc/httpd/logs/fcgidsock/1534.5 and fixed it by executing sudo chmod 555 /etc/httpd/logs/ and going to http://dnsnameoripaddress/my_test

%{color:red}At this point, it.. sort of works.

no route found to match "/MyTest" with {:method=>:get}

I have to browse deeply into my directory structure to even get to the MyTest application.

IE: http://rails.janga.org/janga/public/MyTest – just to get an error to pop in the development.log file.
My presumption is that I’d be able to hit http://rails.janga.org/MyTest/ and see something.%

In order to get /MyTest to work, you have to add a route.

vi config/routes.rb

and add a line in the body:

map.connect 'MyTest/:id', :controller => 'MyTest', :action => 'index'

Appendix A – using PHP to manage the database

  1. yum -y install php-mysql php-mbstring php-gd php-mbsring
  2. cd ~
  3. wget http://superb-east.dl.sourceforge.net/sourceforge/phpmyadmin/phpMyAdmin-2.8.1.tar.gz
  4. tar -xzf phpMyAdmin-2.8.1.tar.gz
  5. cd phpMyAdmin-2.8.1
  6. mkdir /var/www/phpmyadmin
  7. mv * /var/www/phpmyadmin/
  8. vi /var/www/phpmyadmin/config.inc.php
    Insert the following:
    <?php
    /*
     * Generated configuration file
     * Generated by: phpMyAdmin 2.8.1 setup script by Michal Čihař
     * Version: $Id: setup.php,v 1.23.2.8.2.2 2006/05/15 07:57:09 nijel Exp $
     * Date: Sun, 11 Jun 2006 17:34:57 GMT
     */

/* Servers configuration */
$i = 0;

$i++;
$cfg‘Servers’[$i]‘host’ = ‘sql.svr.ip.addy’;
$cfg‘Servers’[$i]‘extension’ = ‘mysql’;
$cfg‘Servers’[$i]‘connect_type’ = ‘tcp’;
$cfg‘Servers’[$i]‘compress’ = false;
$cfg‘Servers’[$i]‘auth_type’ = ‘config’;
$cfg‘Servers’[$i]‘user’ = ‘mysql-user’;
$cfg‘Servers’[$i]‘password’ = ‘mysql-password’;

/* End of servers configuration */

?>Be sure to change sql.svr.ip.addy, mysql-user, and mysql-password to match your environment. WARNING this will allow any who can access the web page to manage your MySQL server. Change auth_type to ‘http’ and delete the user and password lines, to be prompted every time you access the phpmyadmin page.

  1. vi /etc/httpd/conf.d/hosts.conf
    Add the Alias directive to the VirtualHost:
    <VirtualHost *:80>
       Alias /phpmyadmin /var/www/phpmyadmin
       ...
  2. Browse to http://dnsnameoripaddress/phpmyadmin and have at it.

Appendix B – mod_fcgid notes. This is taken verbatim from the mailing list in an email by Peter Gibbons.

mod_fcgid tips (tested on Apache 2.0.55 and mod_fcgid-1.08 on Debian 
3.1)

Make sure you set IPCCommTimeout to at least 45 to allow enough startup
time.
Set DefaultMaxClassProcessCount to 2 unless your benchmarks tell you to
change.
Set IdleTimeout to 3600 or higher since your only have 2 dispatch.fcgi.
Set ProcessLifeTime to a multiple of IdleTimeout.
Set MaxProcessCount > DefaultMaxClassProcessCount so you can use
mod_fcgid for other things than rails.

mod_fcgid religiously kills idle or old processes so keep IdleTimeout
and ProcessLifeTime to high values.

Here is an example ‘starter’ /etc/apache2/mods-enabled/fcgid.conf

AddHandler fcgid-script .fcgi SocketPath /var/lib/apache2/fcgid/sock IdleTimeout 3600 ProcessLifeTime 7200 MaxProcessCount 8 DefaultMaxClassProcessCount 2 IPCConnectTimeout 8 IPCCommTimeout 60 DefaultInitEnv RAILS_ENV production

If you have plenty of RAM, then increase DefaultMaxClassProcessCount to
about 2*CPU—assume each instance will eat 20-30MB RAM.

Appendix C – Setting up the MySQL server
Do the same kind of “minimal” CentOS server install. You can also remove the packages mentioned in the very first, optional step above.

  1. yum -y install mysql-server
  2. vi /etc/my.cnf
    Change the following:
    old_passwords=01

    to
    old_passwords=0
    ROR has been reported not to work correctly if this is not done.
  3. service mysqld start && chkconfig mysqld on
  4. system-config-security-level-tui
    Add 3306:tcp to the open ports.
  5. mysql

References