Rails setup and deployment with Capistrano 2.0 on Ubuntu 7.04 (Feisty)

A very specific post here to serve as a reminder the next time I have to do this: Setting up Ubuntu 7.04 with rails, Apache 2.2, mongrel (clustered), MySQL5, subversion, and deploying with capistrano 2.0. So bleeding edge!

Set up the server:

ssh into the server as a user with sudo privileges, and get to work...

  1. Make sure the universe repository sources are enabled. Edit /etc/apt/sources.list and make sure the following lines are present and uncommented:

    deb http://archive.ubuntu.com/ubuntu/ feisty main restricted universe
    deb-src http://archive.ubuntu.com/ubuntu/ feisty main restricted universe
    
    
    deb http://archive.ubuntu.com/ubuntu/ feisty-updates main restricted universe
    deb-src http://archive.ubuntu.com/ubuntu/ feisty-updates main restricted universe
    
    
    deb http://security.ubuntu.com/ubuntu feisty-security main restricted universe
    deb-src http://security.ubuntu.com/ubuntu feisty-security main restricted universe
  2. Install everything needed to build software:

    $: sudo apt-get install build-essential
  3. Install subversion:

    $: sudo apt-get install subversion
  4. Install apache:

    $: sudo apt-get install apache2
  5. Enable the necessary apache modules:

    $: sudo a2enmod proxy
    $: sudo a2enmod proxy_balancer
    $: sudo a2enmod proxy_http
    $: sudo a2enmod rewrite
  6. Configure mod_proxy:

    In /etc/apache2/mods-available/proxy.conf, find the block that looks like this:

    <Proxy *>
      AddDefaultCharset off
      Order deny,allow
      Deny from all
      #Allow from .example.com
    </Proxy>

    And change it to look like this:

    <Proxy *>
      AddDefaultCharset off
      Order deny,allow
      Deny from all
      Allow from mysite.com www.mysite.com
    </Proxy>
  7. Install MySQL:

    $: sudo apt-get install mysql-server-5.0
  8. Create the production database:

    $: mysql -u root -e 'create database myapp'
  9. Install ruby:

    $: sudo apt-get install ruby
  10. Install some header files that are need to build the gems we'll install later:

    $: sudo apt-get install ruby1.8-dev
  11. Install rake:

    $: sudo apt-get install rake
  12. Install rdoc:

    $: sudo apt-get install rdoc
  13. Install gem:

    The gem package installed by apt-get is old, so I install from source:

    $: wget http://rubyforge.org/frs/download.php/20989/rubygems-0.9.4.tgz
    $: tar -xzvf rubygems-0.9.4.tgz
    $: cd rubygems-0.9.4/
    $: sudo ruby setup.rb
    $: sudo gem update
  14. Install rails (assuming the app uses the latest version):

    $: sudo gem install rails -y
  15. Install mongrel:

    $: sudo gem install mongrel -y

    This command might ask to choose a version for some of the gems. I always pick the ruby version with the highest version number.

  16. Install mongrel cluster:

    $: sudo gem install mongrel_cluster -y
  17. Set up the app root:

    In this example, I'm deploying an app called "myapp" to /var/www/apps/myapp as the user "justin". Adjust paths and usernames as needed.

    $: cd /var/www
    $: sudo mkdir apps
    $: cd apps
    $: sudo mkdir myapp
    $: sudo chown justin myapp
  18. Set up a repository:

    $: cd myapp
    $: svnadmin create repos
  19. Set up the virtual host:

    Assuming there's a domain ("myapp.com" in this example) that points to the server, here's an example of the virtual host entry:

    <VirtualHost *:80>
      ServerName myapp.com
      ServerAlias www.myapp.com
      DocumentRoot /var/www/apps/myapp/current/public
    
    
      <Directory /var/www/apps/myapp/current/public>
        Options FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all
      </Directory>
    
    
      # Configure mongrel_cluster with 3 instances starting on port 8000
      <Proxy balancer://myapp_cluster>
        BalancerMember http://127.0.0.1:8000
        BalancerMember http://127.0.0.1:8001
        BalancerMember http://127.0.0.1:8002
      </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://myapp_cluster%{REQUEST_URI} [P,QSA,L]
    
    
      # Deflate
      AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/x-javascript
      BrowserMatch ^Mozilla/4 gzip-only-text/html
      BrowserMatch ^Mozilla/4.0[678] no-gzip
      BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
    
    
      ErrorLog /var/www/apps/myapp/shared/log/apache2-error_log
      CustomLog /var/www/apps/myapp/shared/log/apache2-access_log combined
    </VirtualHost>

    Save that to /etc/apache2/sites-available/myapp.conf, then run:

    $: sudo a2ensite myapp.conf

Now the server should be ready to roll (pending starting up the mongrels and restarting apache, which we'll do from the local machine).

Set up the local machine:

  1. On the local machine, I need to install most of the same things I did on the server, plus capistrano. Assuming I've got ruby and rails installed already (hence my existing app), installing the rest will vary depending on OS. Here's how I do it on OS X with macports:

    $: sudo port install subversion
    $: sudo port install mysql5 +server
    $: sudo gem install mongrel
    $: sudo gem install mongrel_cluster
    $: sudo gem install capistrano
  2. Configure mongrel:

    Assuming I want 3 mongrel instances starting on port 8000 (adjust the Proxy balancer section of the virtual host if that's not the case):

    $: cd /path/to/myapp
    $: mongrel_rails cluster::configure -e production -p 8000 -a 127.0.0.1 -N 3 -c /var/www/apps/myapp/current
  3. Make sure the production: section of config/database.yml has the proper settings for the database created in step 4 of the server setup.

    Mine looks like this:

    production:
      adapter: mysql
      database: myapp
      username: root
      password: 
      socket: /var/run/mysqld/mysqld.sock
  4. Create the proper svn layout:

    For subversion, I like to have the typical myapp/trunk|branches|tags directory structure.

    $: cd ..
    $: mkdir myapp.temp
    $: mv myapp myapp.temp/trunk
    $: mkdir myapp.temp/branches
    $: mkdir myapp.temp/tags
  5. Remove files that shouldn't be under version control:

    $: rm myapp.temp/trunk/log/*
    $: rm myapp.temp/trunk/db/schema.rb
    $: rm myapp.temp/trunk/tmp/sessions/*
    $: rm myapp.temp/trunk/tmp/cache/*
  6. Import into svn:

    $: svn import myapp.temp svn+ssh://myapp.com/var/www/apps/myapp/repos -m "Initial import"
  7. Check out a working copy:

    We're done with myapp.temp. Check out the trunk as myapp and start using that.

    $: svn co svn+ssh://myapp.com/var/www/apps/myapp/repos/trunk myapp
    $: cd myapp
  8. Set svn:ignore where appropriate:

    $: svn propset svn:ignore "*.log" log
    $: svn propset svn:ignore "schema.rb" db
    $: svn propset svn:ignore "*" tmp/sessions
    $: svn propset svn:ignore "*" tmp/cache
    $: svn commit -m "Setting svn:ignore"
  9. Configure capistrano:

    $: capify .
  10. Edit config/deploy.rb to look like this:

    set :application, "myapp"
    set :domain, "myapp.com"
    
    
    set :repository,  "svn+ssh://#{domain}/var/www/apps/#{application}/repos/trunk"
    
    
    set :deploy_to, "/var/www/apps/#{application}"
    
    
    role :app, domain
    role :web, domain
    role :db,  domain, :primary => true
    
    
    set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml"
    
    
    desc "Restart apache"
    task :restart_apache, :roles => :app do
      sudo "/etc/init.d/apache2 reload"
    end
    
    
    # Capistrano 2.0 doesn't work with the mongrel recipes, so we need to override the defaults ourselves.
    # Thanks to http://thinedgeofthewedge.blogspot.com/2007/08/mongrel-and-capistrano-20.html for these tasks.
    namespace :deploy do
      namespace :mongrel do
        [ :stop, :start, :restart ].each do |t|
          desc "#{t.to_s.capitalize} the mongrel appserver"
          task t, :roles => :app do
            #invoke_command checks the use_sudo variable to determine how to run the mongrel_rails command
            invoke_command "mongrel_rails cluster::#{t.to_s} -C #{mongrel_conf}", :via => run_method
          end
        end
      end
    
    
      desc "Custom restart task for mongrel cluster"
      task :restart, :roles => :app, :except => { :no_release => true } do
        deploy.mongrel.restart
      end
    
    
      desc "Custom start task for mongrel cluster"
      task :start, :roles => :app do
        deploy.mongrel.start
      end
    
    
      desc "Custom stop task for mongrel cluster"
      task :stop, :roles => :app do
        deploy.mongrel.stop
      end
    end

    Update: You may have to add this if you're running Capistrano 2.1:

    default_run_options[:pty] = true

    Explanation here.

  11. Run the capistrano setup:

    $: cap deploy:setup
  12. Make sure capistrano is happy:

    $: cap -q deploy:check

    You should see: "You appear to have all necessary dependencies installed"

  13. Do a cold deploy:

    $: cap deploy:cold

    Note: You only need to do a cold deploy the first time. Subsequent deploys can be done with cap deploy

  14. Restart apache:

    $: cap restart_apache

    Note: You do not need to restart apache after every deploy. We're only doing it here because we modified the apache config earlier.

Give the server a minute or so to "warm up", then hit http://myapp.com/ and you should have a working site. You can go ahead and commit the new files capistrano created in your app:

$: svn add Capfile
$: svn add config/deploy.rb
$: svn commit -m "Adding capistrano files"

That should be it.

Tags: apache capistrano deployment mongrel rails subversion ubuntu  Meta: 5 comments, permalink

Comments

Leave a response

  1. ThomasNovember 21, 2007 @ 07:23 AM
    Nice tutorial. Don't forget to check your enabled repository sources. (make sure universe is enabled)
  2. JustinNovember 21, 2007 @ 11:42 AM
    Thanks, Thomas. I've added that step.
  3. kadDecember 05, 2007 @ 05:59 AM
    thanks , I found teh answer to one of my problem... do u know why we must write the BalancerMember as local, 127.0.0.1 ? BalancerMember http://127.0.0.1:8000 and not BalancerMember http://mydomain:8000
  4. JustinDecember 05, 2007 @ 07:27 AM
    Kad, the mongrel instances are running on the same server as apache, which is why you're proxying to localhost. If mydomain points to the server where your mongrels are running, you'd use that instead.
  5. kihjsoagpApril 18, 2008 @ 10:46 PM
    w6ZjZo cgfogqszmgbe, [url=http://hsykkkxzhdkg.com/]hsykkkxzhdkg[/url], [link=http://kxybzywmtnzx.com/]kxybzywmtnzx[/link], http://mtmlzguiyufg.com/
Comment