Tutorial: Rubystack Deployment Alternatives

BitNami RubyStack provides different deployment options. This article explains the different steps to follow in order to get your application running on top of RubyStack.

We will describe the settings to use:

  • Apache or Nginx as web server.
  • Mongrel, Thin or Phussion Passenger as the engine for Ruby web applications.

1. Initial steps

Some steps are common across all deployment approaches for Rails applications:

  • Extract the application files to a specific directory. For example, inside ${installdir}/apps/app_name
  • Setup the database in ${rails_application_dir}/config/database.yml to use the bundled RubyStack MySQL. Here is an example:
    production:
      adapter: mysql 
      database: rails_app_production 
      host: 127.0.0.1
      username: ${mysql_user}
      password: ${mysql_password}
      port: ${mysql_port}
    

    In Linux and OS X you should use the socket instead of “port”, adding:

      socket: ${installdir}/mysql/tmp/mysql.sock
    
  • Install any additional gems required by the application. This can be usually done by running:
    cd ${rails_application_dir}
    rake gems:install
    
  • Create the database and perform migrations:
    cd ${rails_application_dir}
    rake db:create  RAILS_ENV=production
    rake db:migrate RAILS_ENV=production
    
  • Perform any application-specific configuration steps. For instance, some applications may require you to add smtp parameters in config/email.yml.

    If the application is correctly configured, you should be able to access it at http://127.0.0.1:3000/ after running:

    cd ${rails_application_dir}
    ruby script/server -p 3000 -e production
    

    Once the application is ready, we must set up Apache or Nginx to serve it.

  • 2. Based on Mongrels

    Mongrel is a fast HTTP library and server for Ruby that is intended for hosting Ruby web applications. You can learn more about Mongrel at http://mongrel.rubyforge.org.

    In this case, we are going to configure a group of Mongrel processes that will be running in different ports. Once they are set up, we configure Apache or Nginx as a proxy balancer. All the Rails requests coming to the server will be redirected to the different ports.

    This solution is available in all supported platforms and is the default approach followed by Rails BitNami Modules.

    In order to set up the group of Mongrels, you can configure a mongrel cluster or generate a Windows service for each of them.

    On Linux and OS X, you can use mongrel_cluster gem to configure/start/restart/stop a group of mongrels easily. You can create a mongrel cluster configuration file by running:

    mongrel_rails cluster::configure -e production -p 3001 -N 5
      -C ${rails_application_dir}/config/mongrel_cluster.yml --prefix appname
    

    This will create a cluster with 5 mongrels starting at port 3001 and ending at 3005. The option prefix is added in order to deploy the application inside a sub URI. These settings will be stored in mongrel_cluster.yml :

    prefix: /appname
    log_file: log/mongrel.log
    port: "3001"
    environment: production
    pid_file: tmp/pids/mongrel.pid
    servers: 5
    

    Then, to start the cluster, type:

    cd ${rails_application_dir}
    mongrel_rails cluster::start
    

    On Windows, you must install the mongrels as individual services. In other words, for each mongrel you should use an unique service name and port, calling mongrel_rails gem for each as follows:

    mongrel_rails service::install -N "service_name_1" -p "3001" -c "application_directory" --prefix appname
    mongrel_rails service::install -N "service_name_2" -p "3002" -c "application_directory" --prefix appname
    ...
    

    To start the service you can use theWindows service tool or you type:

    net start "service_name"
    

    To uninstall the service:

    mongrel_rails service::remove -N "service_name"
    

    or

    sc delete "service_name"
    

    The number of Mongrels to be usedshould be decided according to the traffic that must be supported and the machine resources.

    2.1 Using Apache

    These are the steps to follow if you want to use Apache as the main server. You must include a new configuration file at ${rails_application_dir}/conf/http.conf containing something similar to:

    Alias /appname "${rails_application_dir}/public"
    <Directory "${rails_application_dir}/public">
      AllowOverride None
      Order allow,deny
      Allow from all
    </Directory>
    
    # Paths inside public directory that can be served directly by Apache
    ProxyPass /appname/stylesheets !
    ProxyPass /appname/javascripts !
    ProxyPass /appname/images !
    # ...
    
    ProxyPass /appname balancer://appcluster
    ProxyPassReverse /appname balancer://appcluster
    
    <Proxy balancer://appcluster>
      # Proxy entries for each mongrel
      BalancerMember http://127.0.0.1:3001/appname
      BalancerMember http://127.0.0.1:3002/appname
      # ...
    </Proxy>
    

    With a BalancerMember entry for each mongrel. Then, include the file from the main apache configuration ${installdir}/apache2/conf/httpd.conf:

    Include "${rails_application_dir}/conf/http.conf"
    

    That way, each time a Rails request is received, it will be redirected to the mongrels running in ports 3001, 3002...

    After restarting Apache the application should be accessible at http://:/appname.

    2.2. Using Nginx

    You can use the nginx web server instead of Apache. Nginx is designed to be a high-performance server with low resource requirements. You can learn more about nginx at http://nginx.org

    In Linux and OS X, it can be easily started instead of apache through ctlscript.sh by modifying the following line:

    APACHE_SCRIPT=$INSTALLDIR/nginx/scripts/ctl.sh
    

    To make nginx serve the application, you must include a new file nginx/conf/vhosts/railsapp.conf with the contents:

    upstream backend  {
      server 127.0.0.1:3001/appname;
      server 127.0.0.1:3002/appname;
      ...
    }
    
    server {
      location /appname {
        proxy_redirect off;
        port_in_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
        if (-f $request_filename) {
          break;
        }
    
        if (!-f $request_filename) {
          proxy_pass  http://backend;
          break;
        }
      }
    }
    

    That way, each time a Rails request is received, it will be sent to the mongrels defined inside the upstream backend section. This setup also makes ngingx serve static files located in public directory directly.

    Finally, start nginx:

    <installation directory>/nginx/sbin/nginx (linux, osx)
    <installation directory>\nginx\nginx.exe  (windows)
    

    The application should be accessible at http://domain:nginx_port/appname. You may modify the port were nginx is listening adding a "listen" parameter to the server definition. By default, port 1234 is used.

    RubyStack nginx was compiled with the Upstream Fair Module, which will send the incoming requests to the least busy backend server. In order to use it, modify the upstream backend element as follows:

    upstream backend {
      : server 127.0.0.1:3001/appname;
      : server 127.0.0.1:3002/appname;
            ...
      : fair;
    }
    

    You can learn more about this module at: http://wiki.nginx.org/NginxHttpUpstreamFairModule

    3. Based on Thin

    Thin is another ruby web server which can be used to deploy your application. It is based in Mongrel parser, Event Machine and Rack. You can learn more about it at http://code.macournoyer.com/thin.

    The steps to use it are similar to the ones described in the Mongrel approach: you will have a group of processes listening in different ports.

    In Linux and OS X, you can store the configuration in a yml file and use it to start and stop the group easily. For example:

    cd ${rails_application_dir}
    thin -s 5 -p 3000 -e production --prefix /appname -C config/thin.yml config
    

    Which will configure 5 processes in ports 3000 to 3004, running in a production environment and using prefix /appname. Once the configuration file has been generated, you can start, stop or restart the by running:

    thin -C ${rails_application_dir}/config/thin.yml start/stop/restart
    

    If you are using RubyStack on Windows, you can't start multiple servers using '.-s' option. You will need to call a command for each instance:

    cd ${rails_application_dir}
    thin -p 3000 -e production --prefix /appname start
    thin -p 3001 -e production --prefix /appname start
    ...
    

    In order to configure Apache or Nginx, you can follow the steps described in the previous section, using the ports where thin processes are listening.

    4. Based on Phusion Passenger

    If you are using Linux or OS X, you can deploy the application with Phusion Passenger. This approach simplifies the development of Ruby web applications because it is not necessary to configure any additional Mongrel or Thin processes. Furthermore, it allows Ruby on Rails applications to use about 33% less memory in some scenarios.

    You can find more information about Phusion Passenger at http://www.modrails.com/.

    4.2. Using Apache

    To use this method, you just need to include a virtual host which DocumentRoot points to 'public' directory in Rails application.

    <VirtualHost *:80>
      ServerName myapplication.com
      DocumentRoot ${rails_app_dir}/public
      <Directory ${rails_app_dir}/public>
        Allow from all
        Options -MultiViews
      </Directory>
    </VirtualHost>
    

    You should make sure that the 'public' and 'config' application folders and their parent directories are readable and executable by Apache. After restarting Apache, the applications will be accessible at: http://:/

    It is also possible to deploy a set of applications to different sub URIs. In order to do so, create a root directory which contains links to each of the application's public paths. For example, you can do something like:

    mkdir ${installdir}/webapps
    ln -s ${installdir}/app/railsapp1/public ${installdir}/webapps/railsapp1
    ln -s ${installdir}/app/railsapp2/public ${installdir}/webapps/railsapp2
    ...
    

    Once the links are created, configure Apache using a RailsBaseURI entry for each application to be deployed:

    <VirtualHost *:80>
      ServerName myapplication.com 
      DocumentRoot ${installdir}/webapps
      <Directory ${installdir}/webapps> 
        Allow from all 
        Options -MultiViews
      </Directory> 
    
      RailsBaseURI /railsapp1
      RailsBaseURI /railsapp2
      ...
    </VirtualHost>
    

    After restarting Apache, the applications will be accessible at:

      http://<domain>:<port>/railsapp1/
      http://<domain>:<port>/railsapp2/
      ...
    

    4.3 Using Nginx

    Nginx has been compiled with the Phusion Passenger module in Linux and OS X systems. In order to use it, include the options "passenger_enabled" and specify the root path and rails environment.

    You can do this by adding a new file in nginx/conf/vhosts/appname.conf containing:

    server  {
      ...
      root ${rails_appdir}/public; # Path to rails application public dir
      passenger_enabled on;
      rails_env production;
      ...
    }
    

    In this case, it is not necessary to start additional processes apart from Nginx. After restarting the web server, the application will be accessible at http://domain:nginx_port/.

    You can also deploy multiple applications following similar steps to the ones described for Apache using passenger_base_uri option. First, create a common directory containing links to public directories:

    mkdir ${installdir}/webapps
    ln -s ${installdir}/app/railsapp1/public ${installdir}/webapps/railsapp1
    ln -s ${installdir}/app/railsapp2/public ${installdir}/webapps/railsapp2
    ...
    

    Then, add a passenger_base_uri option for each of them inside the server element:

    server  {
      ...
      root /websites/phusion;
      passenger_enabled on;
      passenger_base_uri /railsapp;
      passenger_base_uri /railsapp2;
      ...
    }
    

    After restarting Nginx, the applications will be accessible at:

      http://domain:nginx_port/railsapp/
      http://domain:nginx_port/railsapps2/
      ...
    

Dec 14, 2009 | Tags: Portal Server, Other Category, Ruby on Rails

Comments

no comments

Digg-icon Digg This Story    Reddit-icon Reddit!    Facebook-icon Join Our BitNami Group

Twitter-16x16 Follow Us On Twitter    Add to delicious    Stumbleupon-icon Stumble It!