Catégories
Derniers articles
- Augmenter la taille de l'upload possible avec nginx
- Gérer vos bases de données MySQL sur MacOS X
- Migration du site sur le serveur dédié
- Configurer un serveur FreeBSD de A à Z pour Ruby On Rails avec Nginx, Thin, MySQL, Svn, Capistrano, PHP, Lighttpd et phpMyAdmin
- Déménagement sur un serveur dédié OVH
- Pourquoi Rails est-il vraiment sympathique à utiliser ?
- Travailler dans l'ombre
- Projets en cours
- Pluie de CheatSheets
- Migration du site en Rails 2.0.2
Tags
basecamp cap deploy capistrano cheatsheet client_max_body_size cocoa collaboration configuration consommateur freelance hébergement installation lancement léopard less is more lighttpd logiciel meetwines migration mysql named_scope nginx nouveau blog nouveau physalis nouveau projet nouvelle année ombre organisation ovh php phpMyAdmin portail producteur projet projets rails screencast serveur dédié simple et intuitif solisoft sondage svn terre thin Une terre. Des vins upload version vin
Liens RoR et Web2
Syndication
Configurer un serveur FreeBSD de A à Z pour Ruby On Rails avec Nginx, Thin, MySQL, Svn, Capistrano, PHP, Lighttpd et phpMyAdmin
Ruby On Rails | Le 11 Juin, 2008 12:20
Comme signalé dans un précédent billet, je dispose actuellement d’un serveur dédié loué chez l’hébergeur français OVH. Il s’agit d’une machine dotée de 4Go de Ram fonctionnant avec des Core 2 Duo. Nous allons configurer la bête sous FreeBSD pour héberger des sites réalisés avec Ruby On Rails.
Côté serveur et cluster, nous allons installer Nginx et Thin, un duo qui a la côté en ce moment du côté des développeurs RoR !
Pour les mises à jour du site et le déploiement, nous utiliserons SVN et Capistrano. Pour être entièrement dans le mouv des gourous Rails, il aurait été préférable d’utiliser Git, mais chaque chose en son temps…
Enfin pour être complet et surtout pouvoir utiliser phpMyAdmin en exécutant des scripts .php avec fastCGI, nous installerons PHP et le serveur Lighttpd.
Avant de vous lancer dans cette folle aventure, sachez qu’il faut en connaître un minimum en admin système. J’ai perdu énorménent de temps malgré la pléiade de tutorials, articles, documents disponibles sur la toile. Les choix ne sont pas évidents et les UNIX bien trop nombreux… avec leurs différences.
Je tiens à remercier Olivier Dirrenberger et Olivier Bonnaure qui m’ont aiguillé sur les meilleures solutions côté serveur, soutenu pendant cette initiative et apporté de l’aide, ainsi que la terrible efficacité de Google (ne riez pas, je pense avoir googlé plus de 100 fois…).
A savoir : dans cet article, X.X.X.X est en fait l’adresse IP de votre (mon) serveur dédié, et mon-domaine représente le domaine à héberger (sans l’extension).
1-Partitionnement du disque dur
Dans cette première étape, nous allons prendre le serveur en main. J’ai choisi la distribution FreeBSD 6.2 (la 7.0 étant encore en beta). OVH dispose d’une interface d’administration très simple d’utilisation qui permet la réinstallation et le partitionnement de sa machine. Voici les choix effectués, et les tailles correspondantes :
ufs / 10000 Mo
swap none 4000 Mo
ufs /usr 10000 Mo
ufs /home 726000 Mo
Vous l’aurez deviné (ou plutôt calculé), la taille du disque dur est bien de 750 Go, de quoi voir venir… Le tout fonctionne en RAID 1 pour plus de sécurité. Les données sont donc dupliquées d’un disque à l’autre en permanence (ce qui fait perdre un peu de capacité de calcul, mais c’est pour la bonne cause… et surtout pour être plus serein en cas de pépin hardware).
2-Passer le shell en bash
Après quelques dizaines de minutes, nous pouvons enfin nous connecter en root par ssh (là, je vous laisse faire avec les données envoyées par votre hébergeur par email). Pour des questions de préférences personnelles, mais aussi et surtout pour être en adéquation avec mon système local (MacOS X qui est aussi un BSD au passage…), nous passons du C Shell au bash :
# cd /usr/ports/shells/bash
# make install clean
# chsh -s /usr/local/bin/bash root
# exit
Il vous suffit ensuite de vous reloguer par ssh pour voir votre nouveau prompt tout beau tout neuf.
3-Mettre à jour les ports de FreeBSD
C’est très simple, deux commandes suffisent :
# portsnap -s portsnap3.freebsd.org fetch
# portsnap -s portsnap3.freebsd.org extract
Le téléchargement prend un peu de temps (en fait beaucoup…). Vous avez le droit d’aller vour servir un café ou prendre une bière (cela dépend de l’heure), mais pas d’aller faire la sieste car vous avez un site à terminer pour un client. ;-)
4-Changer d’éditeur de texte
Malheureusement, je ne connais ni vi, ni emacs, nous allons donc installer pico (dont je me sers encore une fois déjà sur MacOS X) car je n’ai pas le temps (ni l’envie) d’apprendre les deux autres. Cela amusera sans doute les unixiens les plus chevronnés, mais je n’en aurai besoin que pour configurer 2 ou 3 fichiers après tout. Bien sûr si vous comptez utiliser vi, cette étape n’est pas utile.
Il faut d’abord installer une librairie /usr/share/dict/words supplémentaire. C’est parti :
# sysinstall
Dans les menus :
- Allez à Configure
- Allez à Distributions
- Sélectionnez dict puis validez
- Choisissez un serveur FTP puis validez
- Sortez de sysinstall quand c’est fini
# cd /usr/ports/editors/pico
# make install clean
Puis laissez les options choisies par défaut.
5-Créer un utilisateur
Pour accueillir nos sites, nous allons créer un utilisateur qui lui même contiendra un répertoire /webapps. Auparavant, nous créons un groupe devs à qui appartiendra l’utilisateur (et qui nous servira plus tard pour svn).
# sysinstall
Dans les menus :
- Allez à Configure
- Allez à User Management
- Allez à Add a new user group to the system
- Saisissez un nom de groupe (devs dans mon cas)
- Sortez de sysinstall
Céation de l’utilisateur :
# adduser
puis saisissez les informations requises, sans omettre devs pour le groupe de l’utilisateur, ni de choisir le bash comme shell. Cela donne au final :
Username : hoksitan
Password : *****
Full Name : hoksitan
Uid : 1001
Class :
Groups : devs
Home : /home/hoksitan
Shell : /usr/local/bin/bash
Locked : no
Maintenant déconnectez-vous de root sur le SSH puis connectez vous avec votre nouveau nom d’utilisateur (hoksitan pour moi) en entrant votre mot de passe utilisateur bien sûr :
# exit
# ssh hoksitan@X.X.X.X
Créez un répertoire webapps ainsi qu’un autre répertoire dans celui-ci qui accueillera le premier de nos sites :
# mkdir webapps
# cd webapps
# mkdir mon-domaine
Il est important de créer ces dossiers avec les droits utilisateur et non root, pour SVN et Capistrano.
6-SSH Public/Private key authentification
Pour ne pas avoir à retaper notre mot de passe à chaque connexion ssh avec notre compte utilisateur, ou pour ne pas avoir à le taper à chaque déploiement avec Capistrano, nous allons renseigner une clé publique SSH pour l’utilisateur hoksitan.
Toujours logué avec votre nom d’utilisateur, créez un dossier .ssh dans celui-ci :
# mkdir .ssh
Sur le serveur de développement (en local donc), et seulement si vous n’avez pas encore de clé publique créée (ls -al ~/.ssh/ pour vérifier), saisissez :
# ssh-keygen -t dsa
Connecté en root, entrez ensuite les lignes suivantes pour copier votre clé locale sur le serveur de production :
# scp ~/.ssh/id_dsa.pub hoksitan@X.X.X.X:.ssh/authorized_keys
# exit
puis testez en vous reconnectant avec le login utilisateur par la suite. Maintenant, vous ne devriez plus avoir à taper votre mot de passe, ni par ssh, ni pour SVN, ni pour Capistrano (qui utilisera ssh et svn).
A cette étape, la configuration de FreeBSD en elle-même est terminée. Félicitations !
7-Installer MySQL, Ruby, Rails et Gem
Connectez-vous en root pour installer la suite des outils nécessaires pour notre serveur Ruby On Rails à commencer par le serveur de bases de données MySQL 5 :
# cd /usr/ports
# portinstall databases/mysql50-server
Pour démarrer et arrêter MySQL :
# /usr/local/etc/rc.d/mysql-server start
# /usr/local/etc/rc.d/mysql-server stop
Empressons nous de donner un mot de passe root à MySQL (en remplaçant MYPASSWORD par le mot de passe désiré) :
# mysqladmin -u root password MYPASSWORD
Puis installez Ruby, Rails et Gem :
# portinstall www/rubygem-rails
Vous pouvez confirmer l’options MemCached dans la boîte de dialogue qui s’ouvre.
Maintenant, vérifiez les versions installées par les ports :
# ruby -v
=> ruby 1.8.5 (2006-08-25) [i386-freebsd6]
# rails -v
=> Rails 1.2.6
# gem -v
=> 1.0.1
Empressons-nous de mettre à jour Rails par les gem :
# gem install rails --include-dependencies
et testons à nouveau la version :
# rails -v
=> Rails 2.1.0
Oh ! Rails 2.1 est sorti ! Magnifique.
8-Installer ImageMagick, Rmagick et RedCloth
Vous allez maintenant installer et compiler ImageMagick (autre pause café ?) :
# cd /usr/ports/graphics/ImageMagick
# make install clean
Confirmez la boîte de dialogue. Puis installons son compère indispensable, le bien nommé Rmagick :
# gem install rmagick
ainsi que mon deuxième gem favori RedCloth pour pouvoir écrire en mode Textile :
# gem install RedCloth
9-Installer Nginx et Thin
C’est au tour de Nginx (qui remplacera dans notre cas Apache). Il faut dire que Nginx a le vent en poupe dernièrement (plus facile à configurer, plus réactif) :
# portinstall www/nginx
Confirmons la boîte de dialogue avec les options par défaut.
Ensuite, nous allons installer le fameux Thin qui est un server web léger, performant et stable, et qui remplacera Mongrel et son mongrel-cluster (autre solution possible).
# gem install thin
Profitez-en pour l’installer sur votre machine locale également, nous en aurons besoin. Nous configurerons Nginx et Thin un peu plus tard.
10-Svn et Capistrano
Pour expédier les fichiers de nos sites sur le serveur et déployer les versions désirées, nous allons utiliser le duo SVN + Capistrano :
Installez d’abord Svn :
# cd /usr/ports/devel/subversion
# make install clean
puis Capistrano qui est un gem :
# gem install -y capistrano
Installez-le aussi en local, nous en aurons besoin.
11-Configuration des répertoires source et destination, qui fait quoi, et dans quel ordre ?
Maintenant que tout est installé, nous allons créer un dossier svn de dépôt qui recevra les sites avant le déploiement par Capistrano.
Logué en root, créez un répertoire général pour svn :
# mkdir /var/svn
# chmod -R 775 /var/svn/
# cd /var/svn
Puis nous créons un dossier pour recevoir notre site, donnons les droits au groupe devs (donc à hoksitan également) et vérifions que tout est bien en place :
# svnadmin create mon-domaine
# chmod -R 775 /var/svn/mon-domaine
# chown -R root:devs /var/svn/mon-domaine
# ls -al mon-domaine
Avec la dernière commande, nous devrions voir les fichiers installés par SVN dans le répertoire de notre site.
En local, nous nous plaçons dans le répertoire qui accueillera le site, puis faisons un CheckOut pour le rapatrier :
# cd ~/Sites/webapps
# svn co svn+ssh://hoksitan@X.X.X.X/var/svn/mon-domaine
# cd mon-domaine
Vous pouvez faire un svn info en local pour voir le repository, le path et le numéro de version. Tout semble s’être bien passé. :-)
Ajoutez 3 répertoires “classiques” pour SVN :
# mkdir trunk
# mkdir branches
# mkdir tags
Maintenant, nous pouvons, soit créer une nouvelle application avec la commande rails app, soit déposer les fichiers et dossiers de l’application que nous voulons “déverser” sur le serveur (ce qui est mon cas). Dans tous les cas, il faut se placer dans le dossier trunk.
Je ne vais pas faire un cours sur les bases de SVN, mais vous pouvez ajouter vos fichiers au contrôle de versions avec la commande svn add. Ensuite, vous pouvez faire votre premier commit, c’est-à-dire envoyer les fichiers sur le serveur de production ! Cela tombe bien, c’est exactement ce que l’on veut faire ! ;-)
# cd ~/Sites/webapps/mon-domaine
# svn status
# svn add trunk
# svn commit -m "Import initial"
# svn update
Nous allons maintenant signaler à SVN d’ignorer certains fichiers et dossiers à mettre à jour :
# cd trunk
# svn propset svn:ignore "*.log" log/
# svn propset svn:ignore "*" tmp/
12-L’heure de la capification a sonné !
Il est maintenant temps de passer notre projet sous Capistrano. Une seule commande suffit (en local) :
# cd trunk
# capify .
Cela va générer 2 fichiers. Le plus important est deploy.rb que l’on va remplir un peu plus tard.
13-Configurer Nginx pour Thin
La partie délicate commence. Nous allons éditer le fichier /usr/local/etc/nginx.conf qui contiendra les différents sites que notre serveur gérera.
Sur le serveur de production (et en mode root) :
# pico /usr/local/etc/nginx/nginx.conf
En haut du fichier, passez le nombre de workers nginx à 6 :
# number of nginx workers
worker_processes 6;
Et ajoutez un site de cette façon (mettez le à jour avec vos sites ET vos bons répertoires…) :
# mon-domaine
upstream mon-domaine {
server 127.0.0.1:4000;
server 127.0.0.1:4001;
server 127.0.0.1:4002;
}
server {
listen 80;
server_name mon-domaine.com www.mon-domaine.com;
root /home/hoksitan/webapps/mon-domaine/current/public/;
index index.html;
access_log /home/hoksitan/webapps/mon-domaine/current/log/nginx_access.log;
error_log /home/hoksitan/webapps/mon-domaine/current/log/nginx_error.log;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect false;
if (-f $request_filename/index.html) {
rewrite (.*) $1/index.html break;
}
if (-f $request_filename.html) {
rewrite (.*) $1.html break;
}
if (!-f $request_filename) {
proxy_pass http://mon-domaine;
break;
}
}
}
Pour rendre le démarrage automatique de Nginx et Mysql lorsque le serveur est rebooté, ajouter ces lignes dans /etc/rc.conf :
# pico /etc/rc.conf
mysql_enable="YES"
memcached_enable="YES"
nginx_enable="YES"
Et pour démarrer ou arrêter nginx :
# /usr/local/etc/rc.d/nginx stop
# /usr/local/etc/rc.d/nginx start
Dans cet exemple, nous indiquons à Nginx d’utiliser 3 ports (4000, 4001, 4002) pour le site mon-domaine.com. Ces 3 ports sont en fait les 3 instances de Thin. Voyons pourquoi dans l’étape suivante.
14-Configurer Thin
Maintenant, on crée le fichier de configuration de Thin. Attention, je le crée en local, mais le chemin indiqué est bien celui du site sur le serveur FreeBSD !
# thin config -C config/thin.yml -c /home/hoksitan/webapps/mon-domaine/current --servers 3 -e production -p 4000
Voici son contenu :
---
pid: tmp/pids/thin.pid
log: log/thin.log
timeout: 30
max_conns: 1024
port: 4000
chdir: /home/hoksitan/webapps/mon-domaine/current
environment: production
max_persistent_conns: 512
servers: 3
daemonize: true
address: 0.0.0.0
Il y a plusieurs choses à remarquer. Premièrement, nous avons bien 3 instances (3 servers) qui commenceront au port 4000. Ensuite, le répertoire défini est celui du site déployé (/current) car c’est le répertoire utilisé par Capistrano pour la version courante (en ligne) du site. Et l’environnement rails précisé est bien production.
15-Configurer Capistrano et son deploy.rb… et déployer !
Je crois que j’ai passé un temps fou à trouver comment il fallait configurer ce fichier pour Thin. Voilà au final, la tête de mon fichier deploy.rb :
default_run_options[:pty] = true
set :application, "mon-domaine"
set :domain, "X.X.X.X"
set :user, "hoksitan"
set :scm_username, "hoksitan"
set :scm_password, "PASSWORD"
set :repository, "svn+ssh://hoksitan@X.X.X.X/var/svn/#{application}/trunk"
set :deploy_to, "/home/hoksitan/webapps/#{application}"
role :web, domain
role :app, domain
role :db, domain, :primary => true
# =============================================================
# Application Server Settings (Thin or Mongrel)
# =============================================================
set :app_server, :thin
set :thin_conf, "#{shared_path}/config/thin.yml"
namespace :deploy do
%w(start stop restart).each do |action|
desc "#{action} the Thin processes"
task action.to_sym do
find_and_execute_task("thin:#{action}")
end
end
end
namespace :thin do
%w(start stop restart).each do |action|
desc "#{action} the app's Thin Cluster"
task action.to_sym, :roles => :app do
run "thin #{action} -c #{deploy_to}/current -C #{deploy_to}/current/config/thin.yml"
end
end
end
# =============================================================
# SHARED DOCS
# =============================================================
set :chmod755, %w(app config db lib public vendor script tmp public/dispatch.cgi public/dispatch.fcgi public/dispatch.rb)
task :after_setup, :roles => [:web, :app] do
run "mkdir -m 775 #{shared_path}/config"
run "mkdir -m 775 #{shared_path}/upload"
end
task :after_deploy do
chmod755.each do |item|
run "chmod 755 #{current_path}/#{item}"
end
# upload
run "rm -rf #{release_path}/public/upload"
run "ln -nfs #{shared_path}/upload #{release_path}/public/upload"
end
Quelques remarques :
- Le déploiement ne marchait pas sans la première ligne : default_run_options[:pty] = true or j’avais lu que cette ligne n’était plus nécessaire après Capistrano 2.1, ce qui est mon cas…
- J’ai choisi d’intégrer le login/password SVN, (pas forcément le même que celui demandé par SSH). Au final, et grâce à la clé publique SSH, je ne rentre plus aucun login ni mot de passe pour déployer.
- Le serveur choisi est bien Thin, et l’on indique où est le fichier de configuration thin.yml créé précédemment.
- Enfin les 2 namespaces lancent le Thin Cluster après le déploiement.
Nous sommes (en théorie) en mesure de déployer notre site maintenant. N’oubliez pas de faire un commit pour les nouveaux fichiers ajoutés (après un svn add bien sûr) :
# svn commit -m "thin.yml deploy.rb et autres..."
# cap deploy:setup
# cap deploy
Note : le cap deploy:setup crée les répertoires de base pour Capistrano (shared, releases…) dans le répertoire de votre site.
Mettre à jour votre site est maintenant un jeu d’enfants ! Un svn commit puis un cap deploy est le tour est joué! C’est certes un peu long à mettre en oeuvre mais tellement maniable par la suite !
Pour exécuter une migration, placer vous dans le dossier /current de votre site puis :
# RAILS_ENV="production" rake db:migrate
16-Envoyer un pigeon voyageur à notre nom de domaine
C’est bien joli tout ça, mais comment notre nom de domaine va-t-il savoir où se trouve notre site (et surtout notre serveur)? Il va falloir lui dire. Pour ma part, j’achète mes noms de domaine chez gandi et ensuite je dispatche entre serveurs dédiés ou hébergements mutualisés.
Pour faire pointer le domaine sur un serveur dédié, il faut modifier les zones chez votre registrar, ce qui donne dans mon cas :
@ A X.X.X.X
www A X.X.X.X
Après quelques heures (dû au temps de propaganation des DNS), l’adresse pointera bien sur l’ip de notre serveur. Or, à l’arrivée, nous avons demandé à Nginx d’écouter le port 80 (http). Nginx regarde donc dans son fichier de configuration quels noms de domaines sont associés à quels répertoires. Ce n’est pas plus compliqué !
17-PHP, Lighttpd et PhpMyAdmin sont dans un bateau
J’ai du mal à me passer de PhpMyAdmin pour gérer mes tables et mes bases (même si je me sers des migrations). Je vais donc installer PHP, PhpMyAdmin et le serveur Lighttpd qui lancera les scripts PHP via fastCGI.
En mode root, sur le serveur de production, on installe ces 3 “paquets” :
# portinstall lang/php5
# portinstall databases/phpmyadmin
# cd /usr/ports/www/lighttpd
# make install clean
Le répertoire PhpMyAdmin s’installe ici : /usr/local/www/phpMyAdmin
Pour rendre le démarrage du serveur lighttpd automatique, il faut ajouter cette ligne dans /etc/rc.conf :
lighttpd_enable="YES"
Il est maintenant nécessaire de créer un répertoire pour les logs de lighty et de configurer le fichier lighttpd.conf :
# mkdir /var/log/lighttpd
# chmod 777 /var/log/lighttpd
puis :
# pico /usr/local/etc/lighttpd.conf
Je ne mets pas tout le fichier de conf dans cet article, mais voilà ce qu’il faut changer :
Décommentez les modules requis :
server.modules = (
"mod_rewrite",
"mod_access",
"mod_fastcgi",
"mod_proxy",
"mod_accesslog" )
Changez le répertoire root (celui où se trouve PMA) :
server.document-root = "/usr/local/www/"
Passez le serveur sur le port 81 :
## bind to port (default: 80)
server.port = 81
Décommentez le module fast-cgi, pour l’utiliser :
fastcgi.server = ( ".php" =>
( "localhost" =>
(
"socket" => "/tmp/php-fastcgi.socket",
"bin-path" => "/usr/local/bin/php-cgi"
)
)
)
Enfin, changer la dernière ligne pour le port 81 :
$SERVER["socket"] == "0.0.0.0:81" { }
Enregistrez le nouveau fichier de conf de Lighttpd. Maintenant nous allons indiquer à Nginx que nous voulons transférer les requêtes du répertoire /phpMyAdmin au port 81 géré par Lighttpd, qui lui, lancera PHP via fast-cgi (je sais, ça paraît compliqué !). Pour cela, il faut créer un nouvel item server {} :
# fait tourner phpMyAdmin avec Lighttpd lancé sur le port 81 par une passerelle proxy
server {
listen 80;
server_name X.X.X.X;
location /phpMyAdmin {
proxy_pass http://127.0.0.1:81;
}
}
Ainsi, chaque requête vers http://X.X.X.X/phpMyadmin sera interprétée par Lighttpd. Noter que rien n’empêche de créer un proxy_pass pour phpMyAdmin sur chaque site, mais c’est moins propre à mes yeux. ;-)
Maintenant, il ne vous reste qu’à lancer Lighttpd (notez la commande pour l’arrêter également) :
# /usr/local/etc/rc.d/lighttpd start
# /usr/local/etc/rc.d/lighttpd stop
Evidemment, il faut aussi configurer le fichier config.inc.php dans le répertoire de phpMyAdmin. Mais ça, c’est un classique du genre, je vous laisse faire tout seul.
Et voilà, vous devez normalement pouvoir éxécuter du PHP également sur votre nouveau serveur !
Voilà, c’est terminé, si vous en êtes là, c’est que vous avez bien bossé ! Vous avez donc droit à une belle photo. ;-)
N’hésitez pas à me signaler des erreurs ou approximations. J’ai appris beaucoup de choses en configurant ce serveur, il peut donc y avoir quelques inexactitudes.

Commentaires sur ce billet
Juste une question, pourquoi choisir d’installer MYSQL comme SGBDR, plutot que l’excellentissime (ok j’exagère) postgreSQL ?
Bonne question… J’ai toujours utilisé MySQL… (avec PHP à l’époque) et je ne suis jamais vraiment allé voir ailleurs.
interessant et complet. venant de faire la meme demarche je suis passé à postgres et je ne le regrette pas non plus, ce n’est pas forcement plus compliqué et beaucoup plus rassurant sur les projets clients. Sinon j’avais vu qu’il est possible de brancher directement nginx pour le php. Bon courage et bonne continuation
Quelque chose à dire sur le sujet ?
Tous les champs sont obligatoires. Tous les messages écrits en langage sms seront effacés.