Usualmente cuando trabajamos con nuestra aplicación Ruby on Rails en desarrollo usamos WEBrick , sin embargo, cuando toca publicarlo en un servidor de producción con usuarios reales y conexiones concurrentes tenemos que pensar en otras alternativas. Passenger en conjunto con Apache se han convertido en una muy buena opción para desplegar aplicaciones web basadas en Ruby, y si a esto le sumamos la versatilidad de RVM para encapsular gemas (del cual escribí en otro post) tendremos un entorno muy completo para lanzar aplicaciones hechas con Rails. Esta guía pretende abordar los puntos claves para configurar ese entorno, cabe mencionar que la instalación se realizó en un servidor Debian:
1. Instalar Apache
Probablemente esta parte ya la tengas lista. Si no lo instalamos, en Ubuntu o Debian debería ser tan sencillo como:
sudo aptitude install apache2
2. Instalar RVM
RVM servirá para aislar las gemas de la aplicación, además de instar Ruby en caso que aun no lo tengamos. Para su instalación puedes ver la guía en el sitio oficial o seguir esta pequeña guía que escribí. Ten en cuenta las dependencias que necesitarás tener instaladas en tu servidor.
Para comprobar que RVM se ha instalado puede escribir en la consola: type rvm | head -1 si devuelve rvm is a function entonces todo bien, si no revisa un poco aquí los problemas más comunes y sus soluciones.
3. Instalar Ruby a través de RVM
Si ya tienes instalado Ruby no hay problema, puedes usar esa versión, si no igualmente puedes instalar la versión que quieras a través de RVM.
Para ejemplificar instalaremos la versión 1.8.7 de Ruby y lo dejaremos como versión por defecto del sistema, para esto escribimos en la consola:
rvm install 1.8.7 --default
*Al momento de escribir esto aún no hay una solución práctica para que Passenger pueda correr diferentes versiones de Ruby en RVM simultaneamente. Así que deberías usar una misma versión de Ruby para trabajar con todas tus aplicaciones.
4. Instalar gema passenger
En RVM existe un compartimiento global que puede ser usado por todos gemset que creemos. Es decir, todas las gemas puestas ahí estarán disponibles por cada gemset. Este gemset existe por defecto, y siguiendo con el ejemplo anterior (Ruby 1.8.7) podemos acceder a el de la siguiente forma:
rvm 1.8.7@global
y una vez dentro de ese contenedor, procedemos a instalar Passenger como gema global
gem install passenger
5. Instalar Passenger como módulo de Apache
Passenger está disponible tanto para Apache, como para Ngix. En este caso para instalarlo sobre Apache usaremos:
passenger-install-apache2-module
Una vez ejecutado el comando, nos aparecerá un asistente para guiarnos en la revisión de dependencias ,instalación y configuración de Passenger.
Para más información aquí la documentación oficial.
6. Configurar Apache para que corra Ruby y Passenger a través de RVM
Una vez finalizada la instalación anterior (passenger-install-apache2-module), luego de varias lineas de compilación e instalación, la consola imprimirá 3 lineas necesarias para la configuración de Apache:
Copiar esas líneas y ponerlas en el archivo de configuración de Apache. En Ubuntu/Debian el archivo está en /etc/apache2/apache2.conf
Solo resta reiniciar Apache y ya tendrá soporte para Passenger :)
7. Instalar Rails
A este punto, el servidor está listo para la implementación de las aplicaciones en Rails, de esta forma el siguiente paso es configurar el sitio/proyecto bajo todo el entorno que previamente hicimos. La idea base es que cada aplicación corra dentro de su propio contenedor de gemas.
7.1. Crear el contendor:
rvm gemset create contenedor
7.2. Iniciar en el intérprete y contenedor de gemas
rvm 1.8.7@contenedor
7.3. Instalar Rails
gem install rails
*Lo más seguro es que no te interese instalar la documentación de las gemas, así que te recomiendo instalar rails con los parámetros no-rdoc , no-ri
8. Configurar Aplicación
8.1 Crear/Migrar proyecto
En el directorio donde queremos poner nuestra aplicación (por lo general /var/www/ ): Creamos una nueva aplicación Rails con el comando rails new proyecto (en caso de ser Rails 3 lo que hayamos instalado) o copiamos el proyecto que queremos migrar.
8.2 Configurar Virtual Host de Apache
Si vamos a tener varios sitios corriendo en el mismo servidor, es recomendable configurar Virtual Host de Apache. En el caso de Debian/Ubuntu , esas configuraciones están en: /etc/apache2/sites-enabled (pero se habilitan en /etc/apache2/apache2.conf ). Podemos configurar la entrada por defecto 000-default o crear una nueva. Básicamente las configuraciones son:
<VirtualHost *:80> ServerName www.nombredelsitio.com DocumentRoot /tu_aplicacion/public # <-- Confirmar que apunte al directorio 'public' <Directory /tu_aplicacion/public> AllowOverride all # <-- Cambiar , por defecto viene en none Options -MultiViews # <-- cambiar, MultiViews deben estar desabilitadas </Directory> </VirtualHost>
8.3 Configurar rutas
Lo siguiente es decirle a tu aplicación como y donde encontrar las gemas y versión de Ruby que usará Passenger ( Esto es necesario por que lo estamos haciendo a través de RVM), la información detallada está en la documentación de RVM > Intergación con Passenger, pero básicamente es:
8.3.1. Crear un archivo .rvmrc
Creamos un archivo llamado “.rvmrc” en la raiz del proyecto, para indicar las rutas de Ruby y contenedor de gemas que utilizamos con RVM, (esto es por cada proyecto). Para esto, corremos en la consola el comando
rvm use 1.8.7@contenedor --rvmrc --create
*Recuerda cambiar la versión del intérprete y contenedor que usas.
8.3.2. Crear archivo setup_load_paths.rb
Finalmente en la carpeta /config/ del proyecto de Rails crear un archivo llamado setup_load_paths.rb, En el caso del ejemplo utilizando Rails 3, el contenido del archivo seria:
if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm') begin rvm_path = File.dirname(File.dirname(ENV['MY_RUBY_HOME'])) rvm_lib_path = File.join(rvm_path, 'lib') $LOAD_PATH.unshift rvm_lib_path require 'rvm' RVM.use_from_path! File.dirname(File.dirname(__FILE__)) rescue LoadError # RVM is unavailable at this point. raise "RVM ruby lib is currently unavailable." end end ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__)) require 'bundler/setup'
En el caso de ser Rails 2, el contenido del archivo sería
if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm') begin rvm_path = File.dirname(File.dirname(ENV['MY_RUBY_HOME'])) rvm_lib_path = File.join(rvm_path, 'lib') $LOAD_PATH.unshift rvm_lib_path require 'rvm' RVM.use_from_path! File.dirname(File.dirname(__FILE__)) rescue LoadError # RVM is unavailable at this point. raise "RVM ruby lib is currently unavailable." end end
Para más información sobre la integración de Passenger con RVM esta la documentación oficial y el artículo The Path to Better RVM & Passenger Integration de donde se tomo parte de las mejoras para RVM y Passenger.