--- title: "Rails production server setup and deployment on Ubuntu/Debian" kind: article slug: rails-production-server-setup-and-deployment-on-ubuntudebian created_at: 2007-06-20 tags: - General - RubyOnRails - Features - Linux - Ubuntu --- Please digg this story to spread the word! Thanks! Okay, this is a big one! This article will show you (and explain to you) how to setup a Ruby on Rails production server with Ubuntu 7.04 or Debian 4.0 and how to deploy your Rails application there. First, what's getting installed:
sudo apt-get update
sudo apt-get dist-upgrade
This probably installs a new kernel (linux-kernel) so a reboot may be in order for optimal performance.
$ sudo apt-get install openssh-server openssh-client
You will now be able to login remotely wiht SSH.
You'll need SSH later if you want to use Capistrano to deploy your Ruby on Rails application. In any case, SSH is a good thing to have around.
$ sudo apt-get install subversion
We only need the client on the production server. We're not going to host Subversion repositories here.
$ sudo apt-get install mysql-server mysql-client libmysqlclient15-dev
Be sure to set a password for the root MySQL user. Failing to do so will leave your database open for anyone who wishes to see.
$ mysqladmin -u root -h localhost password 'secret'
$ mysqladmin -u root -h myhostname password 'secret'
Make sure to replace secret with your actual password.
Try logging in to MySQL with your new password to make sure everything works okay.
$ mysql -u root -p
Enter password:
mysql>
MySQL is in place now, so let's get cracking at Ruby and Rails now.
$ sudo apt-get install ruby
You'll now have Ruby 1.8.5. You will also need to install some other develoment package to help you build native Ruby Gems.
$ sudo apt-get install make autoconf gcc ruby1.8-dev build-essentials
I'll install ruby gems the conventional way (so I'm not going to use Ubuntu's packages here). Download the latest Gems .tgz here.
$ wget http://rubyforge.org/frs/download.php/17190/rubygems-0.9.2.tgz
$ tar xvf rubygems-0.9.2.tgz
$ cd rubygems-0.9.2/
$ sudo ruby setup.rb
$ gem -v
That's it for the gems. Now, install Rails an all it's dependencies:
$ sudo gem install rails --include-dependencies
If you get an error message complaining that the 'rails' gem cannot be found include the --remote option.
$ sudo gem install mysql capistrano mongrel mongrel-cluster --include-dependencies
You'll be asked several times to choose a version for different gems. Always choose the latest available version for 'ruby'. (Don't choose win32. I don't need to explain why.)
$ mysqladmin -u root -p create testapp_development
$ mkdir testapp
$ rails testapp
$ cd testapp
$ vi config/database.yml
$ rake db:migrate
If you get any errors from that last command, check the previous steps. Normally, all should be fine and you can continue safely.
Most people configure a 'socket' in their config/database.yml for MySQL. Note that this socket is in different places for different distribution. Ubuntu and Debian keep it in: /var/run/mysqld/mysqld.sock. You may need to update your configuration in order to connect to the database.
$ sudo apt-get install apache2
Before you continue, enable several modules which we'll be using later on.
$ sudo a2enmod proxy_balancer
$ sudo a2enmod proxy_ftp
$ sudo a2enmod proxy_http
$ sudo a2enmod proxy_connect
$ sudo a2enmod rewrite
That's it for now on Apache. Let's move along.
$ mysql -u root -p
> create database myapp_production;
> grant all privileges on myapp_production.* to 'myapp'@'localhost'
identified by 'secret_password'
The next step is to install capistrano. You can install it on your development machine as a gem, as demonstrated above. Next, apply capistrano to your application:
$ sudo gem install capistrano
$ cap --apply-to myapp
Take a look at myapp/config/deploy.rb. This file contains the configuration for the deployment of your application. Take special care of the following, here's an example for 'myapp':
require 'mongrel_cluster/recipes'
set :application, "myapp"
set :repository, "http://svn.myhost.com/svn/#{application}/trunk"
# We only have one host
role :web, "myapp.com"
role :app, "myapp.com"
role :db, "myapp.com", :primary => true
# Don't forget to change this
set :deploy_to, "/home/ariejan/apps/#{application}"
set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml"
As you can see, I've already included several lines that enable the use of mongrel, we'll get to that next.
Make sure you adapt this file to your own needs. myapp.com is the address of the server you're going to deploy your application to. the mongrel_cluster.yml file will be created in a moment.
On the server, make sure you create the 'apps' directory. You can now setup a basic file structure for the deployment:
$ cd myapp
$ cap setup
On your server, you'll notice that the /home/ariejan/apps/myapp directory was created, including some subdirectories.
If you are annoyed with entering your SSH password every time, create and upload your public SSH key to automate this. (I'll write something up about that later on.)
Now, configure mongrel. For a normal setup, with moderate traffic, you can handle all traffic with two mongrel instances. The mongrel servers will only be accessable through 'localhost' on the server on non-default ports. Apache will do the rest later.
In your rails app, run the following command:
$ mongrel_rails cluster::configure -e production -p 9000 \
-a 127.0.0.1 -N 2 -c /home/ariejan/apps/myapp/current
The configuration file we saw earlier has been created. Check-in all new files in to subversion now, and cold deloy your application!
$ cap cold_deploy
The deployment will checkout the most recent code from Subversion and start the mongrel servers.
After the deployment, migrate your production database and restart the mongrel cluster:
$ cap migrate
$ cap restart
To check that your application is running, issue the following command on your server. It should return you the HTML code from your app:
$ curl -L http://127.0.0.1:9000
BalancerMember http://127.0.0.1:9000
BalancerMember http://127.0.0.1:9001
ServerName myapp.com
ServerAlias www.myapp.com
DocumentRoot /home/ariejan/apps/myapp/current/public
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]
RewriteRule ^/$ /index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://myapps_mongrel_cluster%{REQUEST_URI} [P,QSA,L]
ErrorLog /home/ariejan/apps/myapps/shared/log/tankfactions_errors_log
CustomLog /home/ariejan/apps/myapps/shared/log/tankfactions_log combined
Now enable this new site in apache:
$ sudo a2ensite myapp
$ /etc/init.d/apache2 force-reload
In some cases you may need to make a small change to /etc/apache2/mods-enabled/proxy.conf and swap
Order deny,allow Deny from allfor
Order allow,deny Allow from allThat's all, you can now access your app on myapp.com!
$ cap deploy
If you made changes in the database, you may want to run a long_deploy:
$ cap long_deploy
And if for some reason, your mongrel cluster dies, just restart it.
$ cap restart
That's it! Happy hacking :)
Please digg this story to help spread the word! Thanks a lot!
Comments can be posted here or in my new and shiny Google Group!