Login Logout

HowtoRails

Cette page a été importée automatiquement de notre ancien wiki mais n’a pas encore été révisée.

Howto Rails

http://blog.phusion.nl/2012/09/21/the-right-way-to-deal-with-frozen-processes-on-unix/

Mettre en place un environnement de production “Ruby On Rails” exige de trouver les bons compromis entre les composants système - stable et robuste par nature - et l’environnement de développement “Ruby On Rails” très volatile et changeant. Voici comment nous mettons cela en oeuvre.

Cas 1 : utilisation avec Passenger

Installation

On installe d’abord Ruby 1.8 et ses dépendances utiles (irb, rdoc, ri, …).

# aptitude install ruby-full irb rubygems rails libactionpack-ruby1.8 libactionmailer-ruby1.8

Installer les bindings MySQL et OpenSSL (voir [#les-gems Les gems]) :

# aptitude install libmysql-ruby libopenssl-ruby libmysqlclient15-dev

Les gems #les-gems

Les gems sont des paquets contentant des librairies et/ou des applications écrites en Ruby. Elles sont énormément utilisées, notamment dans Rails.

Par défaut, aucune librairie n’est installée sous forme de gem à part les bindings MySQL et Rack (qui est une dépendance de Passenger) Il est préférable d’installer les bindings MySQL à la main (libmysql-ruby) car ils nécessitent la compilation d’extensions en C et risquent d’être utilisés par tous les utilisateurs.

OpenSSL fait normalement partie de la librairie standard Ruby, mais n’est pas inclus dans Debian. Rails en a besoin pour fonctionner, il convient donc d’installer libopenssl-ruby manuellement.

Ruby Enterprise Edition (REE)

REE est une version patchée de Ruby optimisée pour les applications Web et créée par les mêmes développeurs que Passenger. REE est donc censé s’intégrer parfaitement avec Passenger.

Des paquets (ubuntu) existent pour REE, mais le plus simple est de le compiler à la main. Par défaut il s’installera dans le dossier /opt, en totale isolation du reste du système. Rubygems est livré avec REE, et est placé dans le dossier de ce dernier.

Il suffit de récupérer une archive des sources sur le site de REE, de la décompresser et de lancer le script ./installer --no-dev-docs en tant que root. Le reste de la procédure est indiqué par l’installateur.

À noter qu’il faut avoir installé les paquets libreadline-dev, libz-dev, libssl-dev et avoir une suite de compilation fonctionnelle (gcc, g++, make, patch, …)

Utilisation avec Passenger

Passenger est livré avec REE sous forme de gem, on peut donc l’installer juste après REE. Le mode d’installation est alors quelque peu différent :

Avant tout on installe toutes les librairies nécessaires : celles de REE listées précédemment, plus les libs de développement d’Apache

# aptitude install libreadline-dev libz-dev libssl-dev apache2-prefork-dev libcurl4-openssl-dev

On installe ensuite REE selon la procédure définie ci-dessus, et une fois cette installation terminée, on lance la commande :

/opt/ruby-enterprise-<version>/bin/passenger-install-apache2-module

L’installateur nous guide dans la procédure. Dans le cas ou le MPM d’Apache est ITK, il préviendra :

WARNING: Apache doesn't seem to be compiled with the 'prefork' or 'worker' MPM

On peut cependant continuer l’installation en ignorant l’avertissement. Une fois terminée, l’installateur donne la configuration pour Apache

Dans /etc/apache2/mods-available/passenger.load on mettra la ligne :

LoadModule passenger_module /opt/ruby-enterprise-1.8.7-2010.02/lib/ruby/gems/1.8/gems/passenger-3.0.0/ext/apache2/mod_passenger.so

et dans /etc/apache2/mods-available/passenger.conf :

<IfModule passenger_module>
    PassengerRoot /opt/ruby-enterprise-<version>/lib/ruby/gems/1.8/gems/passenger-3.0.0
    PassengerRuby /opt/ruby-enterprise-<version>/bin/ruby  

    PassengerEnabled off
    #RailsAutoDetect off
    #RackAutoDetect off
    PassengerFriendlyErrorPages off

</IfModule>

Puis : a2enmod passenger

Une fois REE installé il reste un dernier soucis, les binaires sont dans /opt/ruby-enterprise-<version>/bin, et pour que les utilisateurs puissent les utiliser il y a deux options possibles :

  1. Rajouter ce chemin dans le PATH par défaut de tous les utilisateurs.
  2. Créer des liens symboliques dans /usr/bin.

Pour la deuxième solution, le script suivant permet d’automatiser la tâche :

#!/bin/bash
cd /usr/bin
for i in `ls -1d /opt/ruby-enterprise-*/bin/*`; do
    ln -s $i
done

Configuration de Passenger/mod_rails

Par défaut, Passenger est activé pour tous les sites d’Apache et propose une auto-détection des environnements Rails et Rack, on commence par désactiver ce comportement dans /etc/apache2/mods-available/passenger.conf :

<IfModule mod_passenger.c>
  PassengerRoot /usr
  PassengerRuby /usr/bin/ruby1.8

  # On ajoute les lignes suivantes:
  PassengerEnabled off
  RailsAutoDetect off
  RackAutoDetect off

  PassengerTempDir /var/tmp/
  PassengerUploadBufferDir /var/tmp
  # S'assurer que les permissions sur le dossier permettent à Apache d'écrire dedans
  # cf. <http://modrails.com/documentation/Users%20guide%20Apache.html#PassengerUploadBufferDir>
  # C'est surtout important avec Apache ITK !
</IfModule>

Exemple de VirtualHost pour Rails

<VirtualHost *:80>
  ServerName redmine.evolix.net
  PassengerEnabled on
  RailsAutoDetect on

  DocumentRoot /home/redmine/www/public
  <Directory /home/redmine/www/public>
    Allow from all
    Options -MultiViews
  </Directory>

  # Pour Apache 2 ITK
  AssignUserID {user} {group}
</VirtualHost>

Trucs, astuces et détails

Apache ITK #apache-itk-users

Passenger détermine sous quel utilisateur il va lancer l’application en se basant sur le propriétaire du fichier config/environment.rb de l’application Rails.

Il faut donc y placer un propriétaire identique à celui utilisé dans AssignUserID

Les environnements de Rails

Rails propose trois environnements d’exécution distincts : production, development et test.

Chacun a un but précis facilement devinable depuis son nom.

Par défaut, Passenger fait tourner l’application en mode production. On peut forcer un certain environnement en plaçant la directive RailsEnv <env> dans le fichier de configuration du VHost.

Pour lancer dans un certain environnement les commandes qui agissent avec l’application (par exemple les tâches Rake), il suffit de définir la variable d’environnement RAILS_ENV, par exemple :

$ RAILS_ENV=production rake db:migrate

Redémarrage de l’application

Pour redémarrer une application Rails, il suffit de créer ou de mettre à jour le timestamp du fichier tmp/restart.txt (avec la commande touch par exemple). À la prochaîne requête, l’application sera redémarrée et tout l’environement chargé de nouveau.

Pour que l’application redémarre à chaque requête on peut aussi créer un fichier tmp/always_restart.txt et le supprimer une fois qu’on ne souhaite plus ce comportement.

umasks spéciaux

Sur certains système, l’umask par défaut rend les fichiers installés par root non lisibles par le commun des utilisateurs. Si celà est une bonne idée, combinée avec Rubygems et Apache ITK, celà devient moins évident, et il faut veiller à chmoder correctement le dossier de Ruby pour que tous les utilisateurs puissent l’utiliser.

Un exemple avec REE :

# chmod -R u=rwX,g=rX,o=rX /opt/ruby-enterprise-1.8.7-2010.02/

Priorités de chargement

Par défaut, même lorsque rubygems est activé, Ruby utilisera en priorité les librairies système (celles installées par les paquets) plutôt que les gems. On peut cependant forcer l’utilisation d’une gem, et même fixer la version désirée (sinon c’est la plus récente qui est automatiquement utilisée).

Cette gestion des versions doit être faite par le développeur, qui peut installer les librairies qu’il souhaite indépendamment du système. L’important est de savoir qu’il y a trois endroits ou on peut trouver une librairie Ruby :

  • Installée par un paquet (/usr/lib/ruby/1.8/)
  • Installée en temps que gem système (/var/lib/gems/1.8/)
  • Installée en temps que gem utilisateur (~/.gem/ruby/1.8/)

Lister les gems

Il n’existe pas de moyen de lister les gems installées uniquement sur le système, la commande gem cherche à la fois dans le dossier .gem de l’utilisateur et le dossier système. La solution est d’utiliser un script spécialisé qui fait cette recherche.

Le script est disponible dans le dépôt Subversion du Pack Web Evolix, dans trunk/scripts/list_gems.

Économiser un peu d’espace

Par défaut, gem installe la documentation aux formats RDoc (documentation html) et RI (documentation console) pour les gems installées. Pour éviter celà, créer un fichier .gemrc dans la $HOME de l’utilisateur avec le contenu suivant :

gem: --no-rdoc --no-ri

À mettre aussi dans la $HOME de root si c’est lui qui installe les gems.

Rails 2.3.2->2.3.5 & Passenger & les logs

Une petite erreur en environnement de production affecte les versions 2.3.2 à 2.3.5 (incluse) de Rails. Les logs de l’application ne sont pas écrits dans le fichier log/production.log. Pour pallier cette erreur, il faut appliquer le patch qu’on trouve ici (deuxième fichier).

Répertoire temporaire de Passenger

Passenger stocke tous ses fichiers temporaires dans le répertoire /tmp/ par défaut. Pour diverses raisons (de place, de droits voire de performance), il peut être intéressant d’en définir un autre. Cela ce fait via la directive Apache du module Passenger PassengerTempDir. Par exemple, nous mettons :

PassengerTempDir /var/tmp/

Mise à jour de Passenger

Passenger est installé en tant que gem dans /opt/ruby-enterprise-/lib/ruby/gems/1.8/gems/. Voici la procédure pour le mettre à jour :

gem update passenger
/opt/ruby-enterprise-<version-ree>/lib/ruby/gems/1.8/gems/passenger-<nouvelle-version-passenger>/bin/passenger-install-apache2-module

Puis modifier les chemins vers mod_passenger dans la conf d’Apache /etc/apache2/mod-available/passenger.{conf,load} pour pointer vers la nouvelle version (notamment les directives LoadModule et PassengerRoot). Enfin, redémarrer Apache pour prendre en compte le nouveau module.

Mise à jour de REE

Pour mettre à jour REE, il suffit de recommencer la procédure d’installation, la nouvelle version sera installé dans /opt/ruby-enterprise- et ne perturbera donc pas la prod existante.

Pour prendre en compte la nouvelle installation de REE, il faut modifier les chemins vers REE dans la configuration d’Apache.

Important : pour la migration de REE 1.8.7-2010.02 vers 1.8.7-2011.01, il faut ajouter cette directive dans la configuration d’Apache :

RackBaseURI /

Et enlever les éventuelles directives RailkBaseURI.

Cas 2 : utilisation avec rbenv + Unicorn

rbenv permet d’avoir un environnement compilé par utilisateur. C’est donc le développeur qui gère sa version de Ruby, ses Gems, etc… on ne lui installe même pas Ruby !

Note préalable : mettre les droits exec sur la partition /home

# aptitude install build-essential curl mg
# aptitude install python-pygments zlib1g-dev libxml2-dev \
 libxslt1-dev libmysqlclient-dev libcurl4-openssl-dev \
 libmagickcore-dev libmagickwand-dev libreadline-dev imagemagick
$ git clone git://github.com/sstephenson/rbenv.git .rbenv
$ git clone git://github.com/sstephenson/ruby-build.git .rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ . .bash_profile
$ rbenv install 1.9.2-p290
$ rbenv global 1.9.2-p290

Astuces diverses :

rails_env = `head -1 $(HOME}/www/current/config/database.yml | tr ':' ' '`