Perfect Rails Stack... part deux
I just picked up a new VPS with Etch (Debian 4.0) and was amazed at how much easier it is build a nice Rails deployment stack as compared to Sarge (Debian 3.1).
Yeh Debian, you've come along way since the Perfect Rails Stack...
Let's take a look at just how easy it is...
Terms and Conventions
The # prompt means we are logged into the Etch server:
# uname -n
etch
The $ prompt means we are logged into our dev machine:
$ uname -n
Darwin
References to yourusername refer to a non-root user on the Etch server and is likely the same username as you use on your development machine.
We will be deploying an app named foobar to a domain example.com. When you see these terms being used, please substitute your own app and domain name.
The Basics
This section is basically ripped straight from the Perfect Rails Stack...
Login for first time
# ssh -l root example.com
Create your user
# adduser yourusername
Get sudo!
# apt-get install sudo
Add user to sudoer list by adding this line to /etc/sudoers
yourusername ALL=(ALL) ALL
Diable ssh login via password for root. Change /etc/ssh/sshd_config to read:
PermitRootLogin without-password
Restart SSH
# /etc/init.d/ssh reload
Ruby and friends
# apt-get -y install ruby ruby1.8 ruby1.8-dev ri ri1.8 rdoc rdoc1.8 irb irb1.8 ruby1.8
That wasn't hard:
# ruby -v
ruby 1.8.5 (2006-08-25) [i486-linux]
Ruby gems
# cd /usr/local/src/
# wget http://rubyforge.iasi.roedu.net/files/rubygems/rubygems-0.9.4.tgz
# tar xzvf rubygems-0.9.4.tgz
# cd rubygems-0.9.4
# ruby setup.rb
# cd ..
# rm rubygems-0.9.4.tgz
Rails
# gem install rails -y
Mongrel
We'll need compilers first...
# apt-get -y install build-essential
# gem install mongrel -y
Mongrel Cluster
We want mongrel_cluster 1.0 which currently is a beta gem so we need to specify the source:
# gem install mongrel_cluster -s http://mongrel.rubyforge.org/releases/
Configure mongrel_cluster to fire up those mongrels on reboot. Update the mongrel_cluster location depending on the gem version.
# cp /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.1.1/resources/mongrel_cluster /etc/init.d/
# chmod +x /etc/init.d/mongrel_cluster
# update-rc.d mongrel_cluster defaults
Add mongrel user
# adduser --system --group --no-create-home mongrel
Create directory for mongrel_cluster config files and set permissions
# mkdir -p /etc/mongrel_cluster
# mkdir -p /var/run/mongrel_cluster
# chown mongrel:www-data /etc/mongrel_cluster
# chown mongrel:www-data /var/run/mongrel_cluster
# chmod g+w /etc/mongrel_cluster
Postfix (optional)
# apt-get -y install postfix
During the install two questions will be asked. Answer:
- Internet site
- example.com
Mysql
# apt-get -y install mysql-server-5.0 mysql-client-5.0 libmysql-ruby libmysql-ruby1.8
# mysqladmin -u root password yourrootsqlpassword
Subversion
# apt-get -y install subversion
Apache 2.2 with proxy balancer
# apt-get -y install apache2
# a2enmod deflate
# a2enmod rewrite
# a2enmod proxy
# a2enmod proxy_balancer
# a2enmod proxy_http
Setup deployment permissions
# adduser yourusername www-data
# chown root:www-data /var/www
# chmod g+w /var/www
Get rid of the default apache site
# a2dissite default
Reload
# /etc/init.d/apache2 force-reload
Almost essential
Your definitely going to want to use public keys with capistrano and ssh and Rails Machine has excellent instructions posted at https://support.railsmachine.com/index.php?pg=kb.page&id=33
You should check out the above link for more details but the basics are:
Create key pair (you probably have done this already)
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa -C "yourusername@devmachine.com"
Copy public key to app:
$ ssh yourusername@example.com 'mkdir ~/.ssh;chmod 700 ~/.ssh'
$ scp ~/.ssh/id_rsa.pub yourusername@example.com:~/.ssh/authorized_keys
$ ssh yourusername@example.com 'chmod 600 ~/.ssh/authorized_keys'
Deployment
Now that your Etch box is ready to rock, it's time to fire up Capistrano and deploy your app!
Let's use Capistrano 2 because it's going to be released very soon and it has some nice new features. Check out the Capistrano tutorial for more info.
CAUTION
Installing Cap2 may break deployment tasks on existing apps. Check the Capistrano upgrade notes before you upgrade.
Cap2
$ gem install net-ssh
$ gem install net-sftp
$ gem install highline
$ gem install -s http://gems.rubyonrails.com capistrano
Capify
From the root of your Rails app:
$ capify .
Setup server
$ cap deploy:setup
Here is a simple little deploy.rb file:
config/deploy.rb
require 'mongrel_cluster/recipes'
set :application, 'foobar'
set :repository, 'svn+ssh://svn.example.com/foobar/trunk'
set :deploy_to, "/var/www/#{application}"
set :domain, 'example.com'
set :mongrel_conf, "/etc/mongrel_cluster/#{application}.yml"
set :mongrel_clean, true
role :app, domain
role :web, domain
role :db, domain, :primary => true
namespace :deploy do
task :cold do
update
migrate
setup_apache
setup_mongrel_cluster
start
end
# until mongrel_cluster updates to cap2...
task :start, :roles => :app do start_mongrel_cluster end
task :stop, :roles => :app do stop_mongrel_cluster end
task :restart, :roles => :app do restart_mongrel_cluster end
task :setup_apache do
sudo "cp #{current_path}/config/apache_vhost.conf /etc/apache2/sites-available/#{application}"
sudo "a2ensite #{application}"
sudo "/etc/init.d/apache2 reload"
end
task :setup_mongrel_cluster do
sudo "cp #{release_path}/config/mongrel_cluster.yml #{mongrel_conf}"
sudo "chown mongrel:www-data #{mongrel_conf}"
sudo "chmod g+w #{mongrel_conf}"
end
end
and here is a nice simple apache config file that you can customize:
config/apache_vhost.conf
<VirtualHost *:80>
ServerName www.example.com
ServerAlias example.com *.example.com
DocumentRoot /var/www/foobar/current/public
<Directory "/var/www/foobar/current/public">
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
# Configure mongrel_cluster
<Proxy balancer://foobar_cluster>
Order allow,deny
Allow from all
BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001
</Proxy>
RewriteEngine On
# Prevent access to .svn directories
RewriteRule ^(.*/)?.svn/ - [F,L]
ErrorDocument 403 "Access Forbidden"
# Check for maintenance file and redirect all requests
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]
# Rewrite index to check for static
RewriteRule ^/$ /index.html [QSA]
# Rewrite to check for Rails cached page
RewriteRule ^([^.]+)$ $1.html [QSA]
# Redirect all non-static requests to cluster
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://foobar_cluster%{REQUEST_URI} [P,QSA,L]
# Deflate
AddOutputFilterByType DEFLATE text/html text/plain text/xml
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
ErrorLog /var/log/apache2/foobar-error_log
CustomLog /var/log/apache2/foobar-access_log combined
</VirtualHost>
Final check
Don't forget to check config/deploy.rb and config/apache_vhost.conf into subversion before you move on!
Setup production database
# mysql -p
mysql> create database foobar_production;
Query OK, 1 row affected (0.00 sec)
Cold Deploy
$ cap deploy:cold
Check mongrels
# mongrel_rails cluster::status -C /etc/mongrel_cluster/foobar.yml
found pid_file: /var/run/mongrel_cluster/foobar.8000.pid
found mongrel_rails: port 8000, pid 4153
found pid_file: /var/run/mongrel_cluster/foobar.8001.pid
found mongrel_rails: port 8001, pid 4156
Parting thoughts
Etch makes deployment simple (at least compared to Sarge) and when mongrel_cluster 1.0 and Cap2 are released from beta captivity it'll be even easier.
Happy deployment!


3 Comments
Commenting is closed for this article.