Note to English speaking readers: I've written this tutorial in German because there are a lot of good Rails deployment tutorials out there in English, but not so many in German. If enough people email me or comment and say they want this in English I might translate it ;-).
So, jetzt auf Deutsch: Du willst deine grossartige nagelneu programmierte Ruby On Rails Anwendung fuer die Welt (oder immerhin fuer deinem Kunden) nutzbar machen. Dann will ich dich nicht aufhalten und dir in 27 einfachen Schritten zeigen, wie es geht. Dann wollen wir mal...
- Log dich mit ssh in den Server ein, auf dem die Rails Applikation laufen soll.
- Wenn du dich nicht als root angemeldet hast, werde jetzt root (su -)
- Stell sicher, dass ein Editor wie vi richtig funktioniert. Wenn man von Mac OS X auf einen Linux Rechner geht kann es manchmal Probleme geben. Auf Debian Systemen schafft da oft
apt-get install ncurses-term
Abhilfe. - Aktualisiere die verfuegbaren Pakete:
apt-get update - Installiere folgende Pakete:
apt-get install mysql-server
apt-get install ruby
apt-get install ruby1.8-dev
apt-get install rubygems
apt-get install subversion
apt-get install make
apt-get install build-essential
apt-get install curl
apt-get install apache2 - Installiere folgende Ruby Gems:
gem install --include-dependencies rails
gem install --include-dependencies capistrano
gem install --include-dependencies mongrel (jeweils die neuste ruby version nehmen)
gem install --include-dependencies mongrel_cluster - Gehe nochmal sicher, dass alles aktuell ist:
gem update --system
Wenn du irgendwo den Fehler/usr/bin/gem:23: uninitialized constant Gem::GemRunner (NameError)
bekommst ist das damit zu loesen, folgende Zeile in /usr/bin/gem einzufuegen:require 'rubygems/gem_runner'
Und um den Fehlerundefined method `require_gem' for main:Object
spaeter beim Deployment zu vermeiden solltest du nochmalgem install --remote rake
ausfuehren. Wenn das nicht hilft, in /var/lib/gems/1.8/bin/rakerequire_gem 'rake', version
in
gem 'rake', version
abaendern. - Jetzt musst du die Datenbank einrichten. Wir nehmen hier MySQL und der Einfachheit halber nenne ich in dieser Anleitung die Datenbank, den Datenbank Benutzer und die Rails-Anwendung "springenwerk".
Root Passwort setzen:
mysqladmin -u root password ein_passwort_meiner_wahl
(danach am besten die bash_history loeschen) Dann die Datenbank anlegen und die Berechtigung setzen:
mysql -u root -p
CREATE DATABASE springenwerk;
GRANT ALL PRIVILEGES ON springenwerk.* TO 'springenwerk'@'localhost' IDENTIFIED BY 'ein_password_meiner_wahl' WITH GRANT OPTION;
Die Angaben fuer die Produktions-Datenbank (Name, Username und Passwort) muessen den Angaben in der app/config/database.yml Datei der Rails Anwendung entsprechen.
Jetzt kannst du den Mysql Client mit 'exit' verlassen. - Die ausfuehrbaren Ruby Gems willst du jetzt natuerlich gerne in deinem Pfad haben. Also
in der /etc/profile
/var/lib/gems/1.8/bin
an die PATH Variable haengen. Das kann man so machen:
PATH=$PATH:/var/lib/gems/1.8/bin
Du musst nur aufpassen, dass die das vor die Zeile "export PATH" schreibst. - Dann die Aenderungen in der aktuellen Session nutzbar machen:
source /etc/profile
Wenn du dannrails -v
ausfuehren kannst hat alles geklappt. - Jetzt solltest du einen eigenen User fuer deine Rails Anwendung anlegen:
useradd -m springenwerk
und das Passwort setzten:
passwd springenwerk
Und ihn zu den sudoers packen:
visudo
und dann unten folgende Zeile hinzufuegen (natuerlich "springenwerk" wieder mit deinem Produktions-Usernamen ersetzen):
springenwerk ALL=(ALL) ALL - Da sich Capistrano per SSH einloggt aber auch ein gewisse Benutzerumgebung braucht (z.B. den PATH) musst du in die /etc/ssh/sshd_config folgende Zeilen einfuegen:
# for capistrano
PermitUserEnvironment yes - Dann SSHD neu starten:
/etc/init.d/ssh restart - In /home/springenwerk/.ssh/environment (ggf. ".ssh" Verzeichnis und Datei anlegen) folgende Zeilen einfuegen:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/var/lib/gems/1.8/bin
RUBYOPT=rubygems - Jetzt musst du auf dem CLIENT Capistrano und Mongrel Cluster installieren (ich gehe davon aus, dass Ruby und Rails schon installiert sind)
sudo gem install capistrano
sudo gem install capistrano-ext
sudo gem install mongrel_cluster
Ab Mac OS X Leopard ist capistrano schon dabei, aber stelle mit
sicher, dass du mindestens Version 2.1 hast.
sudo gem update capistrano - Wechsle in dein Rails Projekt Verzeichnis:
cd /Users/johannes/Code/springenwerk/trunk/springenwerk - Jetzt erstellst du eine Konfigurationsdatei fuer den Mongrel Cluster:
mongrel_rails cluster::configure -e production -p 8000 -a 127.0.0.1 -N 2 -c /home/springenwerk/springenwerk/current
-p 8000 sagt, dass die Server ab Port 8000 lauschen, -N 2 sagt, dass es zwei Instanzen geben wird (also eine auf Port 8000, eine auf 8001) und mit -c gibt man das Verzeichnis an, wo auf dem PRODUKTIONSSERVER die Applikation liegen wird (in diesem Fall ein Unterverzeichnis, das so heisst wie die Applikation im Home-Verzeichnis des Users, den wir angelegt haben (welcher auch so heisst wie die Applikation) und mit dem Zusatz "current". Das musst da stehen, denn das
ist ein Symlink, den Capistrano anlegt und der immer auf die aktuelle Version zeigt. - Jetzt musst du dein Rails Projekt capistranofizieren ;-). Wechsle in dein Rails Projekt Verzeichnis:
cd /Users/johannes/Code/springenwerk/trunk/springenwerk
und fuehre capify aus:
capify . - Oeffne jetzt config/deploy.rb in deinem Editor und passe die Datei so an, dass sie so aussieht (mit deinen User- und Projektnamen und Passwoertern natuerlich):
require 'mongrel_cluster/recipes'
default_run_options[:pty] = true # to make sure password prompts are forwarded to you, the user
set :application, "springenwerk"
set :repository_url, "svn://DEIN_SVN_USER@DEIN_SVN_SERVER/springenwerk/trunk/springenwerk"
if ENV['svn_prompt'] and ENV['svn_prompt'] == '1'
set :svn_user, Proc.new { Capistrano::CLI.password_prompt('SVN User: ') }
set :svn_password, Proc.new { Capistrano::CLI.password_prompt('SVN Password: ') }
set :repository, Proc.new { "--username #{svn_user} --password #{svn_password} #{repository_url}" }
else
set :repository, repository_url
end
set :deploy_to, "/home/#{application}/#{application}" # defaults to "/u/apps/#{application}"
set :deploy_via, "export"
set :user, application # in our case, the user and the application have the same name.
set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml"
role :app, "DEIN_PRODUCTION_SERVER"
role :web, "DEIN_PRODUCTION_SERVER"
role :db, "DEIN_PRODUCTION_SERVER", :primary => true
# Task to copy production db config after deployment
task :after_update_code, :roles => :app do
db_config = "#{shared_path}/config/database.yml.production"
run "cp #{db_config} #{release_path}/config/database.yml"
end
Die Datei werde ich hier nicht gross erklaeren, dazu gibt es andere Stellen.
Diese deploy.rb Datei hat aber eine kleine Besonderheit (Danke an Jonathan).
Da Subversion natuerlich einen Benutzernamen und ein Passwort erwartet wird normalerweise empfohlen, einmal irgendwo auf dem Produktionsserver das Rails Projekt auszuchecken, damit die Credentials gecachet werden und Capistrano nicht mehr nach SVN Benutzernamen und Passwort fragt. Das koennen wir uns jetzt sparen.
Wir koennen naemlich jetzt angeben, dass Capistrano uns beim ersten Mal einfach nach den Zugangsdaten fuer SVN fragt. Dazu gleich mehr. - Jetzt kann Capistrano die Verzeichnisse auf dem Produktionsserver anlegen. Auf deinem CLIENT fuehre folgendes aus:
cap deploy:setup - Stelle die neuen Konfigurationsdateien unter Versionskontrolle und checke sie ein:
svn add Capfile config/mongrel_cluster.yml config/deploy.rb
svn ci -m "capistrano config" - Du willst aus Sicherheitsgruenden deine Produktionsdatenbank Passwoerter nicht ins SVN einchecken. Deshalb solltest du eine Datei namens database.yml.production anlegen, die die
Zugangsdaten fuer deine Produktionsdatenbank enthaelt. Unser "after_update_code" Task in deploy.rb erwartet diese Datei und kopiert sie dann ueber die ausgecheckte database.yml. Zum Beispiel koennte sie so aussehen:
development:
adapter: mysql
database: springenwerk_development
username: root
password: root
host: localhost
socket: /Applications/MAMP/tmp/mysql/mysql.sock
# 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: mysql
database: springenwerk_test
username: root
password: root
host: localhost
production:
adapter: mysql
database: springenwerk
username: springenwerk
password: DEIN_PASSWORT
host: localhost
socket: /var/run/mysqld/mysqld.sock
Diese packst du auf dem Produktionsserver in folgendes Verzeichnis:
Das config Verzeichnis musst du vorher anlegen.
/home/springenwerk/springenwerk/shared/config - Jetzt kannst du mit Capistrano von deinem CLIENT ein Erst-Deployment (cold deployment) durchfuehren (in deinem Rails Projektverzeichnis)
"svn_prompt" ist einen Umgebungsvariable, die unserem deploy.rb Skript sagt, dass es nach den SVN Zugangsdaten fragen soll. Denke daran, dass wenn Capistrano dich nach dem Passwort fuer deinen Produktionsserver fragt das Passwort fuer den nicht-root User (in diesem Beispiel "springenwerk") fragt!
svn_prompt=1 cap deploy:cold
Achte darauf, dass es keine Fehler gibt, am Ende sollte
stehen.
command finished - Pruefe auf dem SERVER, ob die Mongrel Dienste laufen:
Wenn Mongrel laeuft, sollte die Ausgabe ungefaehr so aussehen:
curl -I http://127.0.0.1:8000
HTTP/1.1 302 Moved Temporarily
Connection: close
Date: Wed, 06 Feb 2008 11:42:33 GMT
Set-Cookie: _springenwerk_session_id=f4a9b408f36d0df7561fd778e46d2c62; path=/
Status: 302 Found
Location: http://127.0.0.1:8000/session/new
Cache-Control: no-cache
Server: Mongrel 1.1.3
Content-Type: text/html; charset=utf-8
Content-Length: 101
Sehr gut. Jetzt musst du nur noch Apache als Loadbalancer einrichten. Ein Kinderspiel ;-) - Ok, Apache. Bevor du die folgenden Sachen machst, ein kleiner Disclaimer: ich bin kein Apache-Config-Profi. Es kann gut sein, dass es elegantere Wege gibt, das gute Stueck zu konfigurieren. Alle Hinweise die zur Ergreifung des Taeters fuehren werden sehr geschaetzt.
Ans Ende von /etc/apache2/apache2.conf folgendes anfuegen (im vi mit G ans Ende der Datei springen):
Der Inhalt der /etc/apache2/sites-available/000-default Datei muss so aussehen (ich gehe in dem Beispiel davon aus, dass der Apache nur fuer deine Rails Anwendung benutzt wird):
<Proxy balancer://mongrel_cluster>
BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001
</Proxy>
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /home/springenwerk/springenwerk/current/public
<Directory /home/springenwerk/springenwerk/current/public>
Options FollowSymLinks
AllowOverride None
Order allow,deny
allow from all
</Directory>
RewriteEngine On
RewriteLog /var/log/apache2/rewrite.log
RewriteLogLevel 9
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]
RewriteRule ^/$ /index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
ErrorLog /var/log/apache2/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog /var/log/apache2/access.log combined
ServerSignature Off
</VirtualHost> - Dann musst du in /etc/apache2/mods-enabled folgende Symlinks anlegen:
ln -s ../mods-available/proxy_balancer.load
ln -s ../mods-available/proxy.conf
ln -s ../mods-available/proxy_http.load
ln -s ../mods-available/proxy.load
ln -s ../mods-available/rewrite.load
Der Inhalt der proxy.conf muss so aussehen:
<IfModule mod_proxy.c>
#turning ProxyRequests on and allowing proxying from all may allow
#spammers to use your proxy to send email.
ProxyRequests Off
<Proxy *>
AddDefaultCharset off
Order allow,deny
Allow from all
</Proxy>
# Enable/disable the handling of HTTP/1.1 "Via:" headers.
# ("Full" adds the server version; "Block" removes all outgoing Via: headers)
# Set to one of: Off | On | Full | Block
ProxyVia On
</IfModule> - Dann nur noch Apache neu starten:
/etc/init.d/apache2 restart - Feierabend. Das wars.
Wenn du jetzt eine neue Version deiner Anwendung live stellen willst, musst du nur in deinem Rails Projektverzeichnis
cap deploy
bzw
cap deploy:migrations
ausfuehren wenn es neue Datenbankmigrationen gibt. Capistrano macht dann den Rest!
Bitte benutze die Kommentarfunktion wenn du beim Folgen dieser Schritte ein paar Tipps oder Probleme gefunden hast.
Grosser Dank gilt noch dem grossartigen Tutorial von Coda. Da gibt es noch sehr viel Hintergrundinfos. Ich wollte das hier nicht alles wiederholen, sondern es eher kurz und knapp halten. Ich hoffe, dass es ganz hilfreich ist.


0 comments:
Post a Comment