« September 25, 2011 | Main | October 25, 2011 »

October 2, 2011

Installer Redmine sur Mac OS X 10.6: La façon correcte

Oui, c’est un titre plutôt prétentieux étant donné que c’est la première fois que je réussis à installer une application Rails, et non, cela ne me dérange pas. C’était agréable comme un coup de pied au cul alors je dois documenter la façon dont j’y suis parvenu et cela pourrait rendre service à d’autres, alors si ça vous dérange, lisez-le comme ‘la façon correcte pour moi’.

Redmine (1.2.1 du 2011-07-11 au moment d’écrire ces lignes) est sacrément regardant en ce qui concerne ses prérequis: les gems (et aussi Ruby et RubyGems) ne doivent pas être trop anciens, certains ne peuvent pas être trop récents, et l’un d’eux (i18n) ne peut même pas être d’une version différente que celle spécifiée (0.4.2).

La page d’installation de Redmine indique qu’il nécessite:

  • Ruby 1.8.6 ou 1.8.7, pas 1.9;
  • RubyGems 1.3.7 ou plus récent, mais pas la 1.5.0 ni la 1.7.0 ou supérieure, parce que Rails 2.3.11 ne fonctionne pas avec celles-ci;
  • Rails 2.3.11 (puis plus loin mentionne que la 2.3.14 fonctionne aussi);
  • Rack 1.1.1;
  • Rake 0.8.7 (pas la 0.9.x parce qu’elle n’est pas supportée par Rails);
  • i18n 0.4.2 (la version 0.6.0 actuelle causera une erreur parce que la 0.4.2 est introuvable).

De plus, Redmine est distribué avec Rails 2.3.11 dans le dossier ‘vendor’, et utilisera celui-là à moins que vous ne l’en supprimiez et changiez la version désirée dans config/environment.rb. Ceci est élégamment documenté sur la page d’installation par une phrase très explicative: “read config/environment.rb first”. Simplement changer la version de Rails dans ce fichier n’aidera pas: si Redmine trouve Rails dans son dossier ‘vendor’, il utilisera celui-là.

La réalité des prérequis de Redmine est légèrement différente. Rake 0.9.x est supporté par Rails 2.3.14 (il installe la 0.9.2 avec ses dépendances), mais RubyGems 1.7.0 ou plus récent ne l’est quand-même pas. Alors pour réduire la quantité de software obsolète et buggué que l’installe et les soucis qui s’ensuivent, je vais utiliser Rails 2.3.14.

Utiliser RVM

Ruby Version Manager, ou RVM, permet d’utiliser une version de Ruby et une gamme de gems différents pour des projets différents, sans installer lesdits gems au niveau du système. I est similaire au virtualenv de Python. À mon avis, il est absolument vital de l’employer dès le départ. Vous ne savez pas quels autres programmes vous pourriez vouloir installer, programmes qui pourraient avoir des prérequis aussi délicats que Redmine mais dans des version différentes. 

RVM se trouve à l’adresse http://beginrescueend.com/ et s’installe comme ceci (apparemment il nécessite git, ce qui est un peu gonflant si vous ne vous en servez pas. Mais vous devriez l’essayer, couplé à la version d’évaluation de Tower, c’est fantastique une fois que vous commencez à piger):

$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

Ajoutez ensuite ceci à votre fichier.bash_profile ou .zshrc (vous voulez clairement passer à zsh et utiliser oh-my-zsh, parce qu’ils sont fantastiques également), comme indiqué par le script d’installation (personnalisé pour votre  $HOME):

# This loads RVM into a shell session.
[[ -s "/Users/olivier/.rvm/scripts/rvm" ]] && source "/Users/olivier/.rvm/scripts/rvm"

Ensuite nous devons installer la dernière version de Ruby pré-1.9 pour utiliser avec RVM. RVM le compile depuis les sources, mais cela ne prends pas trop longtemps (et si vous trouvez que si, faites un saut sur 9gag.com). On peut lister les version disponibles de Ruby et ensuite installer celle que l’on veut, c’est à dire la 1.8.7 (qui donnera ruby-1.8.7-p352), comme suit:

$ rvm list known

# MRI Rubies
[ruby-]1.8.6[-p420]
[ruby-]1.8.6-head
[ruby-]1.8.7[-p352]
[ruby-]1.8.7-head
[ruby-]1.9.1-p378
[ruby-]1.9.1[-p431]
[ruby-]1.9.1-head
[ruby-]1.9.2-p180
[ruby-]1.9.2[-p290]
[ruby-]1.9.2-head
[ruby-]1.9.3[-preview1]
[ruby-]1.9.3-head
ruby-head
...

$ rvm install 1.8.7
...
$ rvm use 1.8.7

Une fois fait, nous allon créer un gemset pour Redmine, où RubyGems installera les gems dont nous avons besoin, dans les versions dont nous avons besoin, sans interférer avec l’installation système.

$ rvm gemset create redmine
'redmine' gemset created (/Users/olivier/.rvm/gems/ruby-1.8.7-p352@redmine).
$ rvm gemset use redmine

Notes:

  1. La version de Ruby et le gemset employés sont liés à la session shell, ce qui fait que vous devez les changer à nouveau à chaque nouvelle session. Cela peut être effectué en une étape:

    $ rvm use 1.8.7@redmine
    Using /Users/olivier/.rvm/gems/ruby-1.8.7-p352 with gemset redmine
    
  2. L’environnement en cours d’utilisation peut être vérifié avec rvm-prompt:

    $ rvm-prompt        
    ruby-1.8.7-p352@redmine
    
  3. Vous pouvez repasser au Ruby système avec:

    $ rvm use system
    Now using system ruby.
    
  4. Il n’y a pas besoin de sudo pour installer des gems dans un gemset RVM, parce que tous les fichiers sont contenus dans votre dossier Home.

  5. Quand un gemset est en cours d’utilisation, les commandes Rake doivent être préfixées par rvm:

    $ rvm rake bla bla
    

Installer les gems

Tout d’abord, accélérons l’installation des gems d’un facteur 10, comme suggéré par The Budding Rubbyist. Ajoutez ceci à votre fichier ~/.gemrc, en le créant si nécessaire:

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

Cela ommettra la documentation (que nous ne lirons jamais, étant donné que nous ne sommes intéressés qu’à installer des programmes Ruby, pas à en développer) à l’installation des gems, une étape inexplicablement très lente, puisqu’elle dure généralement plus longtemps que l’étape “Building native extensions. This could take a while…” de certains gems.

Ensuite, assurons-nous que nous utilisons bien le Ruby et le gemset créés précédemment:

$ rvm use 1.8.7@redmine

Installons ensuite Rails 2.3.14 et i18n 0.4.2 (Rails installe i18n 0.6.0 mais souvenez-vous, Redmine ne la verrait pas même si on la bourrait dans son crâne épais avec une [we]brique):

gem install rails -v=2.3.14
gem install i18n -v=0.4.2

Note: pour déterminer que c’était Rails 2.3.14 que je voulais, j’ai listé toutes les versions disponibles et choisi la 2.3.x la plus récente:

$ gem query  --all --remote -n '^rails$'

*** REMOTE GEMS ***

rails (3.1.0, 3.0.10, 3.0.9, 3.0.8, 3.0.7, 3.0.6, 3.0.5, 3.0.4, 3.0.3, 3.0.2, 3.0.1, 3.0.0, 2.3.14, 2.3.12, 2.3.11, 2.3.10, 2.3.9, 2.3.8, 2.3.7, 2.3.6, 2.3.5, 2.3.4, 2.3.3, 2.3.2, 2.2.3, 2.2.2, 2.1.2, 2.1.1, 2.1.0, 2.0.5, 2.0.4, 2.0.2, 2.0.1, 2.0.0, 1.2.6, 1.2.5, 1.2.4, 1.2.3, 1.2.2, 1.2.1, 1.2.0, 1.1.6, 1.1.5, 1.1.4, 1.1.3, 1.1.2, 1.1.1, 1.1.0, 1.0.0, 0.14.4, 0.14.3, 0.14.2, 0.14.1, 0.13.1, 0.13.0, 0.12.1, 0.12.0, 0.11.1, 0.11.0, 0.10.1, 0.10.0, 0.9.5, 0.9.4.1, 0.9.4, 0.9.3, 0.9.2, 0.9.1, 0.9.0, 0.8.5, 0.8.0)

La commande list est plus simple mais affichera tout ce qui commence par rails, ce qui est un peu gênant:

$ gem list --all --remote rails

*** REMOTE GEMS ***

rails (3.1.0, 3.0.10, 3.0.9, 3.0.8, 3.0.7, 3.0.6, 3.0.5, 3.0.4, 3.0.3, 3.0.2, 3.0.1, 3.0.0, 2.3.14, 2.3.12, 2.3.11, 2.3.10, 2.3.9, 2.3.8, 2.3.7, 2.3.6, 2.3.5, 2.3.4, 2.3.3, 2.3.2, 2.2.3, 2.2.2, 2.1.2, 2.1.1, 2.1.0, 2.0.5, 2.0.4, 2.0.2, 2.0.1, 2.0.0, 1.2.6, 1.2.5, 1.2.4, 1.2.3, 1.2.2, 1.2.1, 1.2.0, 1.1.6, 1.1.5, 1.1.4, 1.1.3, 1.1.2, 1.1.1, 1.1.0, 1.0.0, 0.14.4, 0.14.3, 0.14.2, 0.14.1, 0.13.1, 0.13.0, 0.12.1, 0.12.0, 0.11.1, 0.11.0, 0.10.1, 0.10.0, 0.9.5, 0.9.4.1, 0.9.4, 0.9.3, 0.9.2, 0.9.1, 0.9.0, 0.8.5, 0.8.0)
rails-3-settings (0.1.1)
rails-action-args (0.1.1, 0.1.0)
rails-admin (0.0.0)
rails-and-solid (0.9.1, 0.9.0)
...

Je voulais utiliser SQLite (je n’ai pas pu compiler le gem mysql contre le MySQL de Zend Server, et je m’en fiche — oh, c’est notre shortstop), alors j’ai installé le gem sqlite3:

gem install sqlite3

Nous devons aussi downgrader RubyGems depuis la dernière version (1.8.10 au moment d’écrire ces lignes) vers une version qui est au moins la 1.3.7 mais pas la 1.5.0, ni la 1.7.0 ou plus récente. La version que nous voulons peut être déterminée de la même façon que pour Rails, en demandant le gem rubygems-update:

$ gem list --all --remote  rubygems-update

*** REMOTE GEMS ***

rubygems-update (1.8.10, 1.8.9, 1.8.8, 1.8.7, 1.8.6, 1.8.5, 1.8.4, 1.8.3, 1.8.2, 1.8.1, 1.8.0, 1.7.2, 1.7.1, 1.7.0, 1.6.2, 1.6.1, 1.6.0, 1.5.3, 1.5.2, 1.5.0, 1.4.2, 1.4.1, 1.4.0, 1.3.7, 1.3.6, 1.3.5, 1.3.4, 1.3.3, 1.3.2, 1.3.1, 1.3.0, 1.2.0, 1.1.1, 1.1.0, 1.0.1, 1.0.0, 0.9.5, 0.9.4, 0.9.3, 0.9.2, 0.9.1, 0.9.0, 0.8.11, 0.8.10, 0.8.8, 0.8.6, 0.8.5, 0.8.4, 0.8.3)

Nous voulons donc la 1.6.2:

$ gem update --system 1.6.2
...
$ gem -v
1.6.2

Noter que d’anciennes versions de la commande gem, comme la 1.3.7 recommendée par Redmine, ne supportent pas de spécifier la version dans la commande gem update --system. Dans ce cas, vous devez d’abord obtenir la dernière version et ensuite la downgrader:

$ gem update --system
$ gem update --system 1.6.2

Passons maintenant à l’installation de Redmine.

Installer Redmine

Téléchargez la dernière version stable (1.2.1 du 2011-07-11 au moment d’écrire ces lignes) et décompressez-la.

Nous devons désactiver le Rails 2.3.11 livré et dire à Redmine d’utiliser notre version 2.3.14. Dans config/environment.rb, changer ces lignes:

# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = '2.3.11' unless defined? RAILS_GEM_VERSION

en:

# Specifies gem version of Rails to use when vendor/rails is not present
RAILS_GEM_VERSION = '2.3.14' unless defined? RAILS_GEM_VERSION

Ensuite, déplacez Rails hors du dossier ‘vendor’, sinon Redmine utilisera l’ancienne version, quoique la ligne ci-dessus dise. Je le fais comme ceci:

mv vendor/rails vendor.rails.disabled

Au fait, c’est le passage “read config/environment.rb first” dans la liste des prérequis et le “when vendor/rails is not present” dans le commentaire ci-dessus qui nous indique que nous devons enlever Rails du dossier ‘vendor’. Comme je l’ai dit, une phrase très explicative.

Procédons ensuite à l’installation. Avec SQLite, database.yml a l’allure suivante:

production:
  adapter: sqlite3
  database: db/redmine.db
 
development:
  adapter: sqlite3
  database: db/redmine.db

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  adapter: sqlite3
  database: db/redmine_test.db

Note: Chez moi, les commandes suivantes étaient infestées d’alertes d’obsolescence comme celle-ci:

rake/rdoctask is deprecated.  Use rdoc/task instead (in RDoc 2.4.2+)
Please install RDoc 2.4.2+ to generate documentation.
WARNING: 'task :t, arg, :needs => [deps]' is deprecated.  Please use 'task :t, [args] => [deps]' instead.
    at redmine-1.2.1/lib/tasks/email.rake:170

À ma connaissance elles ne dérangent pas, à part en rendant difficile de savoir si la tâche s’est achevée avec succès ou pas.

Créez un ‘session store secret’ (n’oubliez pas de taper rvm rake au lieu de rake):

rvm rake generate_session_store

Créez la structure de la base de données:

RAILS_ENV=production rvm rake db:migrate

Insérez la configuration par défaut dans la base de données:

RAILS_ENV=production rvm rake redmine:load_default_data

Testez ensuite votre installation. Cela prend un petit moment pour démarrer. Les deux premières lignes apparaissent rapidement et vous permettent de vérifier que Redmine utilise la bonne version de Rails:

=> Booting WEBrick
=> Rails 2.3.14 application starting on http://0.0.0.0:3000

Le serveur est prêt quand vous voyez ceci:

=> Call with -d to detach
=> Ctrl-C to shutdown server
[2011-09-25 14:28:09] INFO  WEBrick 1.3.1
[2011-09-25 14:28:09] INFO  ruby 1.8.7 (2011-06-30) [i686-darwin10.8.0]
[2011-09-25 14:28:09] INFO  WEBrick::HTTPServer#start: pid=39670 port=3000

Faire tourner Redmine sous Unicorn

Avertissement: Je n’ai aucune idée de si utiliser Unicorn pour faire tourner Redmine est une bonne idée. Je sais juste que WEBrick n’est pas destiné à la production et que Passenger est un module Apache, et je préfère l’éviter si possible. Après-tout, nous sommes arrivés jusqu’ici sans nécessiter de droits administrateur.

J’ai trouvé les instructions sur Install Redmine on Ubuntu Server dans la liste des HowTo de Redmine, sauf la partie concernant le wrapper RVM, qui vient de Brandon Tilley.

Installez Unicorn, toujours sous RVM:

$ gem install unicorn

Créez un wrapper pour unicorn_rails. Le wrapper fera tourner unicorn_rails avec la bonne version de Ruby et le bon gemset:

$ rvm wrapper ruby-1.8.7-p352@redmine redmine unicorn_rails

Cela crée une commande redmine_unicorn_rails qui utilise l’environnement ruby-1.8.7-p352@redmine.

Créez le fichier de configuration d’Unicorn, par example unicorn.conf dans le dossier config de Redmine:

# /var/www/redmine/config/unicorn.conf

# Number of CPU Cores
worker_processes 2

# Same Redmine User
user "redmine", "redmine"
working_directory "/var/www/redmine"

# Listen on Both UNIX and TCP Sockets for Testing
listen "/var/www/redmine/tmp/sockets/.sock", :backlog => 64
listen 8080, :tcp_nopush => true

# Default Timeout
timeout 30

# Pid/Logging Config
pid "/var/www/redmine/tmp/pids/unicorn.pid"
stderr_path "/var/www/redmine/log/unicorn.stderr.log"
stdout_path "/var/www/redmine/log/unicorn.stdout.log"

# Preload Rails App for Performance
preload_app true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

Cela suppose que vous avez décompressé Redmine dans /var/www/redmine et que vous avez un utilisateur redmine appartenant au groupe redmine. Si nécessaire, modifiez toutes les occurrences de /var/www/redmine vers le chemin où vous avez installé Redmine et la ligne user "redmine", "redmine" avec l’utilisateur et le groupe sous lesquels vous voulez que Redmine s’exécute. Pour mes tests j’ai utilisé mon compte utilisateur, mais ce n’est certainement pas recommandé:

user "olivier", "staff"

Démarrez ensuite Unicorn en utilisant le wrapper, ce qui signifie qu’il n’est pas nécessaire de changer l’environnement RVM. Cela sera pratique si vous utilisez launchd ou un autre gestionnaire de services pour lancer Redmine:

$ sudo -u redmine redmine_unicorn_rails -c /var/www/redmine/config/unicorn.conf -D -E production

Si comme moi vous avez utilisé votre propre compte utilisateur comme test, alors le sudo n’est pas nécessaire:

$ redmine_unicorn_rails -c /var/www/redmine/config/unicorn.conf -D -E production

D’après le fichier de configuration, Unicorn tourne sur le port 8080. Si vous avez un serveur Apache sur le port 80 et désirez que Redmine apparaisse sous un préfixe donné, alors vous pouvez probablement utiliser une réécriture de type proxy pour atteindre ce but, à condition d’avoir activé mod_proxy.

Pour arrêter Unicorn, tuez le process unicorn_rails master.

Conclusion

C’est tout pour aujourd’hui, j’espère que cela a été utile. Comme je l’ai déjà mentionné, je débute avec les applications Rails, alors j’ai probablement fait des erreurs. N’hésitez pas à les signaler dans les commentaires, j’essaierai de mettre à jour ce post en conséquence. Il se peut aussi que j’ajoute quelque chose concernant l’utilisation de launchd pour exécuter Redmine sous Unicorn et de mod_proxy pour l’intégrer avec un site web existant.

Do not meddle in the affairs of Coding Ninjas, for they are subtle and quick to anger.