Configurare Ruby On Rails un su server web di produzione
La soluzione più diffusa e stabile, per la messa on-line di un applicativo scritto in ruby on rails, è data dall'accoppiata Mongrel e Apache2!
Introduzione
La struttura del nostro ambiente di produzione è descritta nella seguente figura:
Tutte le richieste arriveranno al server web apache, che si occuperà di dirottare le richieste dinamiche a uno dei server mongrel, mentre servirà i contenuti di tipo statico direttamente, senza così appesantire le istanze di mongrel con richieste che possono essere processate direttamente da apache.
Questa struttura, inoltre, permette espansioni future per garantire una buona scalabilità in caso di un forte aumento delle richieste: potremo, in futuro, spostare le verie istanze di mongrel su server differenti, distribuire il filesystem in modo da avere "più apache" pronti ad accettare le richieste, ...
Installazione
Apache2
Per installare Apache è sufficiente un
# apt-get install apache2-mpm-prefork libapache2-mod-proxy-html
Consiglio la versione "prefork" in quanto è supportata pienamente anche da php5, e di conseguenza non ci saranno problemi ad installare anche applicazioni come phpmyadmin, molto comoda per la gestione di database mysql. L'installazione base di apache, però, non è sufficiente per i nostri fini, infatti dobbiamo abilitare alcuni moduli:
- deflate
- proxy_balancer
- proxy_connect
- proxy_html
- proxy_http
- proxy
- rewrite
per abilitarli:
# a2enmod deflate # a2enmod proxy_balancer # a2enmod proxy_connect # a2enmod proxy_html # a2enmod proxy_http # a2enmod proxy # a2enmod rewrite
La configurazione di default del modulo proxy permette connessioni solo dall'indirizzo ip 127.0.0.1. Questa situazione rende impossibile, però, l'accesso al VirtualHost che andremo a configurare dall'esterno. A tal proposito dobbiamo modificare il file di configurazione del modulo (nome del file di configurazione) modificando la seguente riga:
<Proxy *> AddDefaultCharset off Order allow,deny Allow from .example.com Deny from all </Proxy>
in
<Proxy *> AddDefaultCharset off Order allow,deny Allow from all #Allow from .example.com </Proxy>
Una volta abilitati i moduli e fatte le modifiche necessarie, riavviamo apache:
# /etc/init.d/apache2 restart
L'installazione e la configurazione base di apache sono terminate.
Ruby
Se non è già presente sulla macchina, provvediamo ad installare ruby ed i componenti più importanti, necessari alla compilazione di mongrel:
# apt-get install ruby irb ri rdoc ruby1.8-dev build-essential
Rails
Prima di tutto scarichiamo rubygems dal sito ufficiale: http://www.rubygems.org/
In questo momento l'ultima versione è la 0.9.5:
# wget http://rubyforge.org/frs/download.php/28174/rubygems-0.9.5.tgz # tar xzvf rubygems-0.9.5.tgz # cd rubygems-0.9.5 # ruby setup.rb
Ora possiamo installare rails, facendo attenzione alla versione richiesta dal nostro applicativo:
- Ultima versione
# gem install rails
- Una versione specifica
# gem install rails -v 1.2.5
Mongrel
Mongrel si installa allo stesso modo di rails, inoltre installeremo anche mongrel-cluster, che ci semplificherà moltissimo la vita:
# gem install mongrel # gem install mongrel_cluster
Configurazione
Mongrel
La configurazione del cluster di server mongrel è semplice, e si riduce a creare un semplice file di configurazione. Questo è quello base, da cui partire:
--- cwd: /opt/ror/ log_file: log/mongrel.log port: "3000" environment: production address: 127.0.0.1 pid_file: tmp/pids/mongrel.pid servers: 3 user: mongrel group: mongrel
Nei dettagli tutte le voci:
- cwd
- current work directory, cioè la directory in cui è presente l'applicativo. È consigliato usare SEMPRE un percorso assoluto.
- log_file
- dove conservare i log di mongrel. Il valore di default va più che bene
- port
- la porta iniziale per l'array di server mongrel
- environment
- l'envirorment di rails da utilizzare... normalmente si usa production (essendo un server di produzione), ma in casi particolari si può inserire un nuovo ambiente.
- address
- l'indirizzo IP su cui mettersi in ascolto. Le scelte più comuni sono:
- 127.0.0.1
- il cluster sarà raggiungibile solo da applicazioni residenti sul server su cui è in esecuzione mongrel, impostazione consigliata a meno di configurazioni più complesse
- 0.0.0.0
- il cluster sarà raggiungibile da qualsiasi indirizzo esterno, scelta sconsigliata a meno che non ci si trovi in un ambiente protetto
- pid_file
- dove inserire i pid dei vari processi mongrel
- servers
- il numero di server mongrel da lanciare.
- user
- l'utente che sarà usato per lanciare i server mogrel
- group
- come sopra, ma relativo al gruppo
Apache
Questo è un classico file di configurazione di apache per un VirtualHost, che sfrutta 3 server mongrel.
<Proxy balancer://www_test_it_mongrel_cluster> BalancerMember http://127.0.0.1:8000 BalancerMember http://127.0.0.1:8001 BalancerMember http://127.0.0.1:8002 </Proxy> <VirtualHost *> ServerAdmin info@debianizzati.org ServerName www.test.it DocumentRoot /opt/ror/public/ ErrorLog /var/log/apache2/www.test.it-error.log # Superflue, dato che ogni richiesta "non statica" viene gestita da # Mongrel, che usa RubyGems ed ha una configurazione indipendente. # SetEnv RUBYOPT rubygems # SetEnv RAILS_ENV production <Directory /opt/ror/public/> Options -ExecCGI FollowSymLinks -Indexes AllowOverride None Order allow,deny allow from any </Directory> # Inutile cercare di gestire la possibile mancanza di alcuni moduli: ci # servono e quindi assumiamo che siano disponibili. RewriteEngine on # Pagina di "manutenzione" per disabilitare l'accesso all'applicazione. RewriteCond %{DOCUMENT_ROOT}/maintenance.html -f RewriteCond %{SCRIPT_FILENAME} !maintenance.html RewriteRule ^.*$ /maintenance.html [L] # Lasciamo le richieste "statiche" ad Apache. RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f RewriteRule (.*) $1 [L] # Le richieste "non statiche" vengono redirette ai membri del cluster. RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f RewriteRule ^/(.*)$ balancer://www_test_it_mongrel_cluster%{REQUEST_URI} [P,QSA,L] # Comprimiamo un po' di cose. AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE application/xml BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html </VirtualHost>
le spiegazioni sono nei commenti del file di configuarzione. Consiglio di non cancellarli quando si utilizza questo template, in quanto possono sempre tornare utili nel futuro ;)
Avvio, Arresto e Riavvio di un cluster Mongrel
In questa parte del tutorial vedremo come lanciare, fermare e riavviare una batteria di server mongrel:
Avvio
mongrel_rails cluster::start -C /opt/ror/config/mongrel.yml
Arresto
mongrel_rails cluster::stop -C /opt/ror/config/mongrel.yml
Riavvio
mongrel_rails cluster::restart -C /opt/ror/config/mongrel.yml
Inserimento nel processo di Boot
Giunti a questo punto siamo in grado di gestire manualmente l'avvio, l'arresto e il riavvio di un cluster mongrel, però siamo di fronte ad un problema: in caso di riavvio (accidentale o no) della macchina dovremo avviare manualmente tutti i vari cluster... questo problema non è assolutamente accettabile in un ambiente di produzione!!!
Per ovviare a tutti ciò, inseriremo negli script di boot (e di shutdown) uno script che si prenderà il carico di avviare tutti i cluster mongrel da noi specificati.
File di Configurazione
I file di configurazione che verranno letti dallo script andranno inseriti nella directory /etc/mongrel_cluster/. Normalmente non è una buona idea, nelle applicazioni in ruby on rails, inserire file di un progetto all'esterno della directory del progetto stesso, in quanto richiederebbe sempre un accesso alla macchina per l'aggiornamento del file di configurazione del cluster, soprattutto se si utilizza il comodo sistema di deploy capistrano.
Per semplificarci la vita useremo un link simbolico. Supponiamo che la nostra applicazione sia in /opt/ror/, e che il file di configurazione sia nella directory di configurazione dell'applicativo: /opt/ror/config/
# ln -s /opt/ror/config/mongrel.yml /etc/mongrel_cluster/www.test.it.yml
Inserimento dello script
Lo script si trova in /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/mongrel_cluster (supponendo di avere installata la versione 1.0.5 di mongrel_cluster. Per inserirlo nel processo di avvio è sufficiente eseguire i seguenti comandi:
# cp /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/mongrel_cluster /etc/init.d/ # ln -s /etc/init.d/mongrel_cluster /etc/rc2.d/S90mongrel_cluster
Conclusione
Giunti a questo punto abbiamo configurato alla perfezione sia apache che mongrel... se tutto funziona a dovere il nostro applicativo dovrebbe essere visibile dall'esterno ;)