Shiny happy people coding

Codons avec le sourire

Deployer un blog Typo grâce à Capistrano2

| Comments

Voulant utiliser capistrano2 et mettre en place un blog Typo, j'ai décidé de déployer mon blog Typo grâce à Capistrano2. Je vais indiqué ici toutes les étapes que j'ai effectuées. Ce post aura ainsi un double intérêt.

  • Expliquer comment deployer une application Typo avec Capistrano2
  • Expliquer par l'exemple d'une utilisation de Capistrano2

Pour commencer Capistrano2 est vraiment très dépendant d'un système de versionning. Dans mon cas j'ai utilisé le dépôt subversion de Typo et comme je voulais utiliser leur version 4.1, j'ai récupérer l'url suivante qui est le tag de la version 4.1:

http://svn.typosphere.org/typo/tags/release_4_1/

Préparation de l'application à déployer

Préparation en local

Il faut commencer d'abord par faire un checkout complet de la version que l'on désire déployer. Ca permet surtout d'avoir une sorte de miroir de la version qui sera sur le serveur et ainsi faire des modifications sur cette version pour testé et ensuite les déployer sur le serveur.

On va maintenant commencer à créer un projet capistrano2. Pour cela, il suffit d'aller à la racine du répertoire de checkout et de lancer la commande :

capify

Grâce à cette commande le fichier config/deploy.rb est crée. C'est lui qui nous permettra de définir la configuration de notre application sur le serveur distant. Le fichier Capfile est lui aussi crée à la racine et il permet d'ajouter des tâches. Il suffit de le considérer comme une sorte de fichier de RakeFile.

Voici ce que j'ai mis dans mon fichier deploy.rb. Bien sur, il n'y avait pas ces informations à la base

set :application, "typoblog-dev"
set :repository,  "http://svn.typosphere.org/typo/tags/release_4_1/"

# If you aren't deploying to /u/apps/#{application} on the target
# servers (which is the default), you can specify the actual location
# via the :deploy_to variable:
set :deploy_to, "/var/rails/#{application}"

# If you aren't using Subversion to manage your source code, specify
# your SCM below:
#set :scm, :subversion

role :app, "shingara.fr"
role :web, "shingara.fr"
role :db,  "shingara.fr", :primary => true

Voici une explication de chaque champs

  • set :application => Défini le nom de l'application qu'on va être déployé. C'est surtout utilisé pour le nom du répertoire de déploiement.
  • set :repository => le chemin du dépôt Subversion qui sera récupéré lors du déploiement.
  • set :deploy_to => Défini le répertoire sur le serveur distant où seront placés les sources de l'application
  • set :scm => Le type de système de versionning qui permettra de récupérer les sources. Par défaut il s'agit de subversion.
  • role :xxx => permet de définir les serveur où seront chaque rôle. serveur web, mysql et fichier. Dans mon cas il s'agit du même serveur.

Il ne reste plus qu'à voir pour le fichier Capfile, mais je le ferais dans un second temps.

Préparation sur le serveur

Il faut penser à préparer la base de donnée qui recevra les informations de notre blog. Il faut donc que la base et les accès soient prêts. C'est la seule manipulation réelle à effectuer sur le serveur.

Déploiement

On pourrait faire simple pour déployer notre application et faire ainsi :

$cap deploy:setup
$cap deploy:migrations

La première tâche permettant de préparer le terrain en créant les répertoires de base. La deuxième permettant que :

  • les sources soient déposées sur le serveur distant
  • rake db:migrate soit lancé
  • le serveur est lancé en fastcgi

Mais voilà, rien ne fonctionnera, car il n'y a pas de fichier database.yml sur le serveur car il n'existe pas sur le dépôt subversion. Il va donc falloir en ajouter un sur le serveur.

Création de tâches personnalisées

Voici le fichier CapFile que j'ai ainsi créé.

load 'deploy' if respond_to?(:namespace) # cap2 differentiator
load 'config/deploy'


after 'deploy:symlink', 'deploy:upload_database_config'
after 'deploy:symlink', 'deploy:upload_mongrel_cluster'

namespace :deploy do

  desc 'Upload the config database file in release path'
  task :upload_database_config do
    #Define a database file
    database = {'production' => {
            'database' => 'typo',
            'adapter' => 'postgresql',
            'host' => 'localhost',
            'username' => 'xxxx',
            'password' => 'xxxx'
        }
    }
    #upload
    put database.to_yaml, "#{current_path}/config/database.yml", :mode => 0444
  end

end

Dans ce fichier j'ai ainsi créé une nouvelle tâche. Cette tâche me permettra de créer un fichier database.yml sur le serveur et ainsi en avoir un spécifique à mon serveur. J'ai aussi défini que cette tâche sera toujours lancée après la tâche deploy:symlink. Tâche qui est réalisée lors de la tâche deploy.

Pour créer la tâche d'envoi sur le serveur du fichier database.yml, j'ai utilisé la méthode "put" de Capistrano. Elle se base sur le système de connexion au serveur pour envoyer des fichiers dessus. Avec la variable #{current_path}, j'ai pu définir le chemin vers le dossier contenant les sources utilisées pour lancer l'application.

Pour définir que cette tâche se lance après une autre tâche Capistrano, il suffit tout simplement d'appeler la méthode after.

Ca y est maintenant si vous relancez toute la procédure que je vous ai indiquée précédemment avec les tâches Cap vous aurez votre application qui démarrera avec FastCGI.

Et avec Mongrel_Rails et Nginx

Personnellement, je ne passe pas par FastCGHI, j'utilise mongrel_rails et Nginx. Donc voici les modifications que j'ai réalisées pour que tout passe de la même manière.

J'ai tout d'abord ajouté des tâches Cap:


after 'deploy:symlink', 'deploy:upload_mongrel_cluster'
namespace deploy do
  desc 'Upload the mongrel_cluster.yml in release path'
  task :upload_mongrel_cluster do
    mongrel_conf = {'environment' => 'production',
        'port' => 44000,
        'pid_file' => "#{shared_path}/pids/mongrel.pid",
        'servers' => 4,
        'log_file' => "#{shared_path}/log/mongrel.log"}
    put mongrel_conf.to_yaml, "#{current_path}/config/mongrel_cluster.yml"
  end
  
  desc 'Start mongrel_rails'
  task :start do
    run "cd #{current_path} && mongrel_rails cluster::start"
  end
  
  desc 'Stop mongrel_rails'
  task :stop do
    run "cd #{current_path} && mongrel_rails cluster::stop"
  end
  
  desc 'Restart mongrel_rails'
  task :restart do
    run "cd #{current_path} && mongrel_rails cluster::stop && mongrel_rails cluster::start"
  end
end

Une tâche qui permet d'envoyer mon fichier mongrel_cluster.yml sur le serveur. Une tâche qui démarre le serveur avec mongrel_cluster, une tâche qui arrête le serveur et une tâche qui le redémarre. La tâche d'envoi est bien sûr après la tâche de symlink. Par contre, pour les trois autres tâches, elle remplace en fait les originales qui lancaient FastCGI.

Enfin il ne reste plus que la conf de nginx

     upstream mongrel_blog_dev {
        server 127.0.0.1:44000;
        server 127.0.0.1:44001;
        server 127.0.0.1:44002;
        server 127.0.0.1:44003;
    }

    server {
        listen      80; 
        server_name blog.shingara.fr;
            
            
        location /log_typo {  
            alias /var/rails/typoblog-dev/log/;
            autoindex  on; 
        }   
            
        location / { 
            root /var/rails/typoblog-dev/current/public;
            # needed to forward user's IP address to rails
                proxy_set_header  X-Real-IP  $remote_addr;
            
            # needed for HTTPS
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect false;
            proxy_max_temp_file_size 0;

            #redirect blog to Feedburner
            if ($http_user_agent !~ FeedBurner) {
                rewrite  ^/xml/rss20/feed.xml$ http://feeds.feedburner.com/ProgDreamShiny;
                rewrite  ^/xml/rss20/comments/feed.xml$ http://feeds.feedburner.com/ProgDreamShinyComments;
            }
    
            # If the file exists as a static file serve it directly without
            # running all the other rewite tests on it
            if (-f $request_filename) {
                break;
            }
            if (!-f $request_filename){
                proxy_pass  http://mongrel_blog_dev;
            }


        }
    }