Posterous theme by Cory Watilo

Cloud-Deployment von Webanwendungen auf Basis von PHP

Vor einer ganzen Weile berichtete ich über den PaaS-Anbieter Heroku, der sein Portfolio an Programmiersprachen mittlerweile deutlich erweitert hat. Bis vor nicht allzu langer Zeit fehlte aber noch ein vergleichbarer Anbieter für das Deployment von PHP-Anwendungen. Verwunderlich gerade deswegen, weil PHP nach wie vor zu den beliebtesten Programmiersprachen im weltweiten Netz gehört und einige sehr bekannte Systeme in PHP entwickelt wurden.

Diese Lücke füllt nun der Anbieter PHP Fog, welcher, genau wie Heroku auf das Deployment von Anwendungen über das Versionierungstool Git setzt. Das verspricht eine äußerst einfache Handhabung und ist deutlich zeitgemäßer als das sonst übliche Deployment über FTP. Allein schon in Sachen Geschwindigkeit steckt Git die Datenübertragung via FTP locker in die Tasche. Vor einiger Zeit meldete ich mich dann bei PHP Fog an und begann, ein wenig zu experimentieren. Vorbildlich ist, dass man gängige PHP-Anwendungen per One-Click-Installer installieren kann. Dazu gehört unter anderem auch das äußerst beliebte CMS WordPress. In der Anfangsphase aber war eine bei PHP Fog abgelegte WordPress-Installation aber nahezu unbrauchbar, da man keine beschreibbaren Verzeichnisse einrichten konnte und somit viele Funktionen von WordPress nicht nutzbar waren. Updates scheiterten, die Installation von Plugins oder der Upload von Dateien war unmöglich. Der einzige Ausweg war, die WordPress-Installation lokal zu warten und die Änderungen per Git zu deployen. Problematisch war aber natürlich hier, dass Einträge in der lokalen Datenbank nicht auf der Infrastruktur von PHP Fog landeten. Die Anfangsphase war kurzum ziemlich enttäuschend. Ständige Downtimes und ein erfolgreicher, groß angelegter Hackerangriff trübten den Ersteindruck weiter. Mittlerweile ist der Service deutlich gereift und die oben genannten Kritikpunkte sind allesamt eliminiert worden. Dennoch reicht der Bedienungskomfort leider nach wie vor nicht an den von Heroku ran. Lokale Änderungen an Theme-Dateien bspw. kann man leider nicht zurück auf den eigenen Rechner bekommen, da die Versionierung nur in eine Richtung funktioniert. Gleiches gilt für hochgeladene Dateien, beispielsweise Fotos. Diese nachträglich auf den eigenen Rechner zu bekommen, bspw. um einen Anbieterwechsel durchzuführen ist nicht möglich, wenigstens nicht ohne Umwege über WordPress-Plugins, die das erlauben. Dieser Nachteil existiert natürlich auch bei Heroku, nur bringt jede Rails-basierte Anwendung einen integrierten Webserver mit und verfügt im Regelfall über mehrere Datenbanken (Production, Development, Test), sodass man Änderungen an der Anwendungsstruktur ohne Probleme lokal vornehmen und auch gleich testen kann. Die Schuld ist hier also nicht bei PHP Fog zu suchen, sondern vielmehr bei der Struktur von PHP-Anwendungen. Ohne eine lokale Installation eines Webservers und einer MySQL-Datenbank ist eine solche Arbeitsweise nicht möglich. In Sachen Simplizität schlägt Rails hier PHP ganz bequem. Die Idee, das Deployment von PHP-Anwendungen über das effiziente und einfach zu bedienende Git vorzunehmen ist gut, leider scheitert die Benutzbarkeit in der Praxis an dem doch recht angestaubten Konzept von PHP-Anwendungen. Heroku verbietet das Schreiben in das Dateisystem des Anbieters einfach, um genau solchen Problemen vorzubeugen. Rails-Anwendungen spielen da im Regelfall auch problemfrei mit, und man bindet Storage über Services wie Amazons S3 an. Bei PHP Fog ist das Schreiben ins Dateisystem (leider) ohne weiteres möglich. Dortige Änderungen lassen sich aber nicht reflektieren. Meine Idee wäre, dass man im Backend von PHP Fog einen Button finden sollte, der auf der entfernten Maschine eine git add .; git commit -am ‘Kommentar’ ausführt und man dann mittels git pull die Änderungen auf seine eigene Maschine bekommt. Ich werde wohl mal ein Support-Ticket einreichen …

Da ist es: Ubuntu 11.04

Ubuntu 11.04, das scheinbar umstrittenste Release seit langem ist nun da. Umstritten, weil nicht mehr Gnome, sondern Unity der neue Desktop-Manager ist. Ich persönlich mag ihn eigentlich. Liegt aber vielleicht daran, dass ich generell Veränderungen gerne mag.

Was sich aber nicht ändert ist die Tatsache, dass ich mal wieder einen Mirror für alle verfügbaren Versionen von Ubuntu anbiete:

ubuntu-11.04-desktop-amd64.iso

ubuntu-11.04-desktop-i386.iso

ubuntu-11.04-server-amd64.iso

ubuntu-11.04-server-i386.iso

ubuntu-11.04-alternate-amd64.iso

ubuntu-11.04-alternate-i386.iso

Die letzte Beta habe ich schon ein wenig angetestet und ich mag Unity. Nur schade, dass es ohne 3D-Hardware nicht läuft. Dafür gibt es aber einen Fork namens Unity2D. Eine kleine Google-Suche dürfte euch bei der Installation behilflich sein. Und nun, frohes Saugen.

Aus und vorbei mit der Ordnerwirtschaft

Die Zeiten der Ordner sind gezählt. Immer mehr verlieren starre Ordnerstrukturen an Relevanz und auch an Sinn.

Google hat das schon vor Jahren erkannt und das klassische Ordnerkonzept bei ihrem E-Mail-Dienst Google Mail über den Haufen geworfen. Dort gibt es keine Ordner mehr. Deren Nachfolger heißen Labels und sind universeller einsetzbar. Musste man im Zeitalter der Ordner eine E-Mail einem einzigen, eindeutigen Ordner zuordnen, kann man dank des Label-Konzepts eine E-Mail (oder einen ganzen Konversationsverlauf) mehreren Themen, Labels, zuordnen. Denn nicht immer kann man den Sachverhalt einer E-Mail oder einer ganzen Konversation einem einzigen Thema zuordnen. Nicht zuletzt dank der integrierten Archiv-Funktion kann man das Inbox-Zero-Konzept verfolgen, ohne jemals wieder eine E-Mail löschen zu müssen. E-Mails lassen sich aber auch ohne die Verwendung von Labels blitzschnell wiederfinden, Google ist nicht umsonst Experte im Finden von Dingen. Eine Suche nach einer bestimmten E-Mail dürfte im Zweifelsfalle also schneller gehen, als in vier Dutzend Ordnern händisch nach einer E-Mail zu suchen.

Aber die fehlende Notwendigkeit, penibel Ordnung halten zu müssen hat sich mittlerweile auch außerhalb des E-Mail-Postfachs manifestiert. Zu verdanken hat der Computerbenutzer das den systemweit funktionierenden Metasuchen, die alle modernen Betriebssysteme mittlerweile implementiert haben. Begonnen hat damit Apple anno 2005, als sie ihrem Betriebssystem Mac OS 10.4 Tiger die systemweite Suche Spotlight spendierten. Spotlight funktioniert wie eine Suchmaschine für den eigenen Computer und weiß immer bescheid, wo welche Dateien mit welchen Inhalten (sofern sie nicht verschlüsselt sind) liegen. Anstatt also aufwändig nach einer Datei unter dutzenden oder gar hunderten zu fahnden, rufe ich einfach Spotlight auf und lasse für mich finden. Windows hat seit Vista eine ähnliche Methodik implementiert, Linux kann das auch schon eine ganze Weile. Diese eingebauten Suchindizes lassen sich aber nicht nur für das Auffinden von Dateien nutzen, Programme lassen sich auf diese Art und Weise auch schneller starten. Anstatt auf meinem iMac ein Programm aufwändig im Programme-Verzeichnis zu suchen oder meinen Schreibtisch bzw. mein Dock mit Verknüpfungen zu verschandeln, drücke ich einfach Alt-Space und gebe die ersten zwei, drei Buchstaben des zu startenden Programms ein. Im Regelfall genügt ein Druck auf die Entertaste, das gewünschte Programm startet. Für Linux gibt es ähnliche Lösungen, unter Windows kann man die eingebaute Suchbox im Startmenü nutzen (Druck auf die Windows-Taste, tippen, Enter drücken).

Der Bereich der Medienverwaltung verzeichnet ähnliche Tendenzen. Wenn ich Musik auf meinen Rechner kopiere, kümmere ich mich nicht um die Ablage, sondern schiebe das Verzeichnis einfach in iTunes. Möchte ich dann mal Musik eines bestimmten Interpreten hören, gebe ich dessen Namen einfach in die Suchbox ein. Wenn ich von einer Fototour wieder komme, klemme ich meine Kamera nur an und überlasse Aperture die Verwaltung meiner Bilddaten. Bin ich der Meinung, dass einige Fotos mehreren Alben zugeordnet werden sollten, ist das kein Problem, doppelte Datenmengen habe ich dadurch nicht.

Natürlich gibt es nach wie vor weiterhin gute Anwendungsfälle für Ordner, im Bereich der eigenen Datenverwaltung kann ich aber keinen mehr entdecken. Mir ist es herzlich egal, wo meine Daten liegen. Ich brauche meinen Kopf für andere Dinge, mein Computer kann das deutlich besser.

Leider immer noch kein SNI mit Windows XP und dem Internet Explorer

Und wieder mal bremst Microsoft das Web aus. Dank der Marktmacht von Microsoft und der immer noch gigantischen Verbreitung von Windows XP kann ein hochgradig wichtiges Feature moderner Webserver nicht uneingeschränkt verwendet werden: SNI.

SNI steht für Server Name Indication und macht möglich, was vorher nicht möglich war. Nämlich auf einer IP mehrere SSL-Zertifikate zu verwenden. Gerade heutzutage, in denen IP-Adresse ein knappes Gut sind ein nahezu unverzichtbares Feature. Aber dank Microsofts Nachlässigkeit für all diejenigen, die aus welchem Grunde auch immer an einer Windows-XP-Maschine mit einem Internet Explorer, unabhängig von der Version, sitzen unzugänglich. Der Grund hierfür erschliesst sich mir nicht, da alle anderen Browser (getestet mit Firefox 3.6.13, Opera 11.01, Safari 5.0.3, Chrome 9.0.597.98) unter Windows XP einwandfrei mitspielen. Außerdem liegt der entsprechende Entwurf seit 2006, also mittlerweile rund fünf Jahren, vor.

Die weiterhin starke Verbreitung von Windows XP und des Internet Explorers macht es zu einer Gratwanderung, SNI tatsächlich im Produktiveinsatz zu betreiben. Nutzbar ist die Technologie dann, wenn man maßgeblichen Einfluss auf die Arbeitsumgebung derer hat, die die SSL-gesicherte Verbindung tatsächlich nutzen sollen. Möchte man aber einen kleinen Onlineshop betreiben, für den sich SSL nahezu aufdrängt, kann man die IP-Adressen-sparende Variante SNI von vornherein ausschliessen, da man sich durch die Verwendung dieser Technologie gegen alle Internet-Explorer-nutzende Windows-XP-Benutzer ausspricht. Eine entsprechende Abfrage des Clients vor Aufnahme der Verbindung ist zwar möglich, aber was möchte man mit den Internet Explorern machen? Sie auf eine ungesicherte Verbindung weiterleiten? Eine Warnmeldung ausgeben lassen? Beides ist eigentlich nicht erstrebenswert. Es bleibt also wieder nur die alte Methode, ein Zertifikat pro IP-Adresse zu verwenden.

Wie schon eingangs erwähnt, mal wieder ist Microsoft eine bremsende Kraft beim Fortschritt im Web. Wie sie es schon seit Jahren sind, spätestens nämlich seitdem der Internet Explorer 6 als veraltet gilt, was seit nunmehr bestimmt sieben Jahren der Fall ist…

Fehlende Autovervollständigung in OpenVZ-Containern

Aus einem mir nicht so wirklich ersichtlichen Grunde ist in den OpenVZ-Templates von Debian und Ubuntu (die anderen habe ich noch nicht getestet) die bash-autocompletion deaktiviert. Gerade wer viel mit aptitude oder dessen Bruder apt-get arbeitet, wird diese Autovervollständigung aber schmerzlich vermissen.

Aktiviert wird sie wie folgt:

In der Datei /etc/bash.bashrc müssen die folgenden Zeilen ohne die Kommentarzeichen (ausgenommen von der ersten Zeile, die ist nämlich tatsächlich ein Kommentar) stehen:

# enable bash completion in interactive shells
if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi

Das Paket bash-autocompletion muss installiert sein:

sudo aptitude install bash-autocompletion

Beim nächsten Anmelden sollten die Autovervollständigungen nun funktionieren. In meinen Tests hat das sowohl bei Debian 5.0 als auch Ubuntu 10.04 funktioniert.

Rails 3 liefert 0 Byte große Dateien aus

Rails-3-Anwendungen in Verbindung mit Nginx liefern 0 Byte große Dateien aus. Um das zu verhindern, muss in der config/environments/production.rb die entsprechend gekennzeichnete Zeile aktiviert werden:

# For nginx:
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'

Nach einem Neustart der Anwendung sollten die Dateien korrekt an euren Browser geliefert werden.

Quelle: http://stackoverflow.com/questions/3724853/rails-sends-0-byte-files-using-sen...

Duplikate aus einer PostgreSQL-Datenbank sicher entfernen

Kleine Notiz, auch für mich selbst. Wer aus einer PostgreSQL-Datenbank mal flott alle Duplikate löschen möchte, kann wie folgt vorgehen:

DELETE
FROM    tabellenname
WHERE   feldmituniquekey NOT IN
  (SELECT   MAX(dup.feldmituniquekey)
  FROM      tabellenname As dup
  GROUP BY  dup.doppeltezeile1, dup.doppeltezeile2, dup.doppeltezeile3, dup.doppeltezeile4);

Die Anzahl der GROUP-BY-Felder kann beliebig erweitert werden, um das versehentliche Löschen von teilweise identischen Datensätzen zu verhindern.

Drei PPAs für den modernen Mann

Um die Vorteile eines LTS-Release von Ubuntu (aktuell 10.04.2) weiterhin genießen zu können, ohne auf aktuelle Software verzichten zu müssen, gibt es unter Ubuntu die so genannten PPAs, Personal Package Archives. Das sind separate Repositorys, mit denen man sein Ubuntu füttern kann um Pakete über die Paketverwaltung zu installieren, die aus irgendeinem Grunde noch keinen Weg in die offiziellen Repositorys der Distribution gefunden haben. Canonical verfolgt die Philosophie, innerhalb eines Release keine Versionssprünge der ursprünglich ausgelieferten Software mitzumachen. Was sehr schade ist, hängt man doch so auf PostgreSQL 8.4, Git 1.7 und Nginx 0.7 fest. Dank einiger fleissiger Paketschnürer gibt es aber PPAs, die genau diese Probleme beheben. Da ich alle drei zuvor genannten Anwendungen/Dienste regelmäßig und auf verschiedenen Servern nutze, habe ich mir dafür entsprechende PPAs rausgesucht.

Um PPAs zum System hinzuzufügen, bietet sich das Kommando add-apt-repository an. Sollte das Kommando nicht gefunden werden können, leistet folgender Befehl Abhilfe:

sudo aptitude install python-software-properties

Dieses Kommando fügt das Repository zur Apt-Sources-Liste hinzu und importiert gleich den passenden GPG-Schlüssel.

Fügen wir nun nacheinander die drei zuvor erwähnten PPAs hinzu:

sudo add-apt-repository ppa:nginx/stable
sudo add-apt-repository ppa:git-core/ppa
sudo add-apt-repository ppa:pitti/postgresql

Ein abschließendes sudo aptitude update nicht vergessen und schon sind die aktuellen Versionen von Nginx, Git und PostgreSQL via apt/aptitude verfügbar.

Rails-Anwendung auf https umleiten

Immer wieder stehe ich vor dem gleichen Problem, der Blogbeitrag soll also auch gleichzeitig als Gedächtnisstütze für mich dienen.

Für mein Standardsetup verwende ich als Webserver nginx (Anzahl Worker = Anzahl Cores), als Rails-Applicationserver kommt thin mit zwei Workern zum Einsatz. Eine Standardkonfiguration könnte nun beispielsweise so aussehen:

# /etc/nginx/sites-available/my-site.de

upstream my-site {
  server   unix:/tmp/thin.my-site.0.sock;
  server   unix:/tmp/thin.my-site.1.sock;
}

server {
  listen   80;
  server_name my-site.de www.my-site.de;

  access_log /var/www/my-site.de/www/logs/access.log;
  error_log /var/www/my-site.de/www/logs/error.log;

  root   /var/www/my-site.de/www/htdocs/public/;
  index  index.html;

  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    off;

    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://my-site;
      break;
    }

  }
}

In Verbindung mit dieser /etc/thin/my-site.yml funktioniert eine Rails-Anwendung auch einwandfrei:

---
pid: tmp/pids/thin.pid
wait: 30
timeout: 30
log: log/thin.log
max_conns: 1024
require: []

environment: production
max_persistent_conns: 512
servers: 2
daemonize: true
chdir: /var/www/my-site.de/www/htdocs
socket: /tmp/thin.sock

Sämtlicher Traffic läuft bei diesem Setup unverschlüsselt über Port 80, also Standard-http. Wenn man nun aber ein Login, bspw. für ein CMS wie Radiant, realisieren möchte, wäre es natürlich wünschenswert, den Traffic verschlüsselt über Port 443, also https, laufen zu lassen. Notwendig ist das aber aus meiner Sicht nur bei Zugriffen auf das Admin-Backend. Im nachfolgenden Setup werden sämtliche Anfragen auf http://www.my-site.de/admin/{IRGENDWAS} auf https://www.my-site.de/admin/{IRGENDWAS} umgeleitet. Requests auf die Website selbst bleiben von der Umleitung also unberührt.

# /etc/nginx/sites-available/my-site.de

upstream my-site {
  server   unix:/tmp/thin.my-site.0.sock;
  server   unix:/tmp/thin.my-site.1.sock;
}

server {
  listen   80;
  server_name my-site.de www.my-site.de;

  access_log /var/www/my-site.de/www/logs/access.log;
  error_log /var/www/my-site.de/www/logs/error.log;

  root   /var/www/my-site.de/www/htdocs/public/;
  index  index.html;

  rewrite ^/admin/(.*) https://www.my-site.de/admin/$1 permanent; # Rewrite-Regel für die Umleitung aller Anfragen auf /admin

  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    off;

    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://my-site;
      break;
    }

  }
}

server {
  listen 443;
  server_name my-site.de www.my-site.de;

  ssl                 on;
  ssl_certificate     /etc/ssl/certs/startssl.crt;
  ssl_certificate_key /etc/ssl/private/startssl.key;
  ssl_ciphers         ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM;
  ssl_protocols       SSLv3 TLSv1;

  access_log /var/www/my-site.de/www/logs/access.log;
  error_log /var/www/my-site.de/www/logs/error.log;

  root   /var/www/my-site.de/www/htdocs/public/;
  index  index.html;

  location / {
    proxy_set_header  X-FORWARDED_PROTO https;
    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    off;

    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://my-site;
      break;
    }
  }

}

Meine Zertifikate beziehe ich übrigens zumeist von StartSSL. Die Zertifikate kosten nichts und werden trotzdem von allen aktuellen Browsern akzeptiert. Nur den grünen Hintergrund bekommt man mit diesem Zertifikat nicht, was ich persönlich aber als unkritisch einstufe. Googles Chrome wird derzeit aber leider nicht für die Erstellung der Zertifikate unterstützt, mit der aktuellen Version von Apples Safari geht’s aber einwandfrei.

Kurz noch zur Erklärung, wieso nginx und thin:

  • nginx ziehe ich Apache vor, weil er deutlich schlanker und performanter ist. Für PHP-Setups verwende ich zumeist weiterhin den Apache, weil dieser sich deutlich einfacher mit PHP aufsetzen lässt, als dies mit nginx der Fall ist.
  • thin ist extrem einfach aufzusetzen, einfacher als Unicorn oder mongrel_cluster, die im Endeffekt genau das Gleiche tun. Und dank der Fähigkeit von thin, auch als UNIX-Socket zu laufen, ist er auch extrem schnell.

Von Fall zu Fall mag die Eignung der Alternativen eher gegeben sein, ich habe aber ziemlich gute Erfahrungen mit diesem Setup gemacht. Es ist einfach zu administrieren und äußerst performant.

Ein kleiner Tipp noch zum Schluss. Um sowohl thin als auch nginx in den aktuellen Versionen zu fahren, benutze ich folgende Wege der Installation:

nginx installiere ich über das eigens dafür bereitgestellte PPA, welches wie folgt in Ubuntu 10.04 LTS oder neuer eingebunden werden kann:

nginx=stable # use nginx=development for latest development version
sudo su -
add-apt-repository ppa:nginx/$nginx
apt-get update 
apt-get install nginx

thin installiere ich aus den Ruby-Gems heraus und nutze dann den komfortablen Installer, den die Jungs mitliefern:

sudo gem install thin
sudo thin install
sudo /usr/sbin/update-rc.d -f thin defaults

Um die Anwendungsumgebungen nicht händisch erstellen zu müssen, kann man das thin-Kommando benutzen:

sudo thin config -C /etc/thin/my-site.yml -c /var/www/my-site.de/www/htdocs --servers 2 -socket /tmp/thin.my-site.sock -e production

Dieser Befehl erstellt eine Konfigurationsdatei für thin, wie sie weiter oben zu sehen ist.

Heroku: Rails-Anwendungen in der Cloud

Die Cloud, das Buzzword des letzten Jahres, ist in aller Munde. Und hat auch schon erste Federn lassen müssen. Was die Cloud eigentlich kennzeichnet, ist nahezu grenzenlose Skalierbarkeit. Wenn es nach den Befürwortern der Cloud geht, bucht niemand mehr physikalische Maschinen, sondern Speicherplatz, RAM, Rechenleistung in dem Umfang, den er benötigt. Wird zwischenzeitlich mal mehr gebraucht, dreht man kurz an der entsprechenden Schraube und zahlt eben für die Zeit ein wenig mehr. Es gibt unheimlich viele Anbieter, gerade Amazon, eigentlich Interneteinzelhändler, hat in diesem Bereich von sich reden gemacht. Amazon bietet alles denkbare an Cloud-Dienstleistungen an, was man sich nur so vorstellen kann. Genau das ist dem Wikileaks-Projekt zum Verhängnis geworden, weil der Anbieter somit auch am einzigen Hebel sitzt. Legt er den um, ist Feierabend. Amazon bietet zwar eine recht große Produktpalette an, alles abdecken tun sie dann aber auch nicht.

Wer beispielsweise Rails-Anwendungen in der Cloud laufen lassen möchte, ist auf andere Dienstleister angewiesen. In den letzten Jahren hat sich ein Anbieter namens Heroku einen Namen in der Community gemacht. Erst kürzlich wurde Heroku von salesforce.com, einem großen Anbieter von Geschäftsanwendungen, für rund 212 Mio. US-$ aufgekauft.

Heroku hat ein für den Entwickler sehr effizient zu nutzendes und einfaches Deployment-Verfahren entwickelt, welches komplett Git- und Rake-gestützt ist. Der Rails-Entwickler muss sich also nicht mit der Administration und Konfiguration von Webservern herumärgern. Ein Vorteil gegenüber den klassischen Rails-Hostern, von denen es ohnehin relativ wenige gibt ist, dass man nicht auf die vom Hoster installierten Ruby-Gem-Versionen angewiesen ist, sondern seine eigenen Versionen spezifizieren kann, wie man es von seiner Entwicklungsmaschine her kennt.

Wer reine Rails-3-Anwendungen deployen möchte, hat seine Anwendung binnen weniger Minuten online:

sudo gem install heroku
git init
heroku create
git add .
git commit -a -m 'first deployment commit to Heroku'
git push heroku master
heroku rake db:migrate
heroku open

Das war es schon. Die Anwendung sollte online sein und sich im Browser geöffnet haben.

Bei Rails-2-Anwendungen gestaltet sich das Deployment etwas schwieriger, aber auch nicht viel. Bevor man die oben erwähnte Befehlskette anschubsen kann, muss erst einmal eine Datei namens .gems erstellt werden. In dieser müssen dann alle erforderlichen Gems, ggf. inklusive Versionsnummer notiert werden. Beispiel:

rails --version 2.3.5
i18n --version 0.4.2
rack --version 1.0.1

Erst dann darf deployed werden. Neben den oben erwähnten Möglichkeiten gibt es aber noch viele weitere, die allesamt auf den wirklich tollen Support- und Dokumentations-Seiten von Heroku dokumentiert sind. So kann man, sofern man bereits lokal PostgreSQL verwendet, seinen kompletten Datenbankinhalt mittels heroku db:push in die Anwendung bei Heroku pushen. PostgreSQL ist übrigens die einzige Datenbank, die von Heroku angeboten wird. Laut Heroku deswegen, weil sie dort die optimale Kombination zwischen Zuverlässigkeit, Datenintegrität und Geschwindigkeit sehen. Ein Statement, das ich durchaus unterschreiben kann. Das heroku-Gem ist äußerst mächtig und bietet einem Zugriff auf sämtliche installierbare Add-Ons (s.u.), auf die Logs und noch vieles mehr. Eine Studie der Dokumentation ist empfehlenswert.

Ab sofort kann dann direkt in den Anwendungscontainer bei Heroku deployed werden, indem man ein ganz reguläres Git-Commit erstellt. Einfacher geht es kaum noch.

Nachdem die erste Version der Anwendung deployed wurde, kann man sie um einige tolle, teilweise auch kostenlos nutzbare Add-Ons erweitern. Dazu gehören nützliche Erweiterungen wie CNAME-Einträge für die Anwendung (damit man sie auch unter einer eigenen (Sub-)Domain betreiben kann), Jasondb, MongoDB und CouchDB für die NoSQL-Anhänger unter uns, Exception-Tracker, Echtzeitsuche, New Relic, SMS-Gateways, automatisierte Datenbankbackups, etc. Manche kosten gar nichts, manche nur wenig Geld, andere wiederum sind recht teuer (wobei teuer mal wieder relativ ist). Dolle ins Geld geht ein SSL-Zertifikat, da solche Zertifikate weiterhin IP-basiert sind, was bei einem Cloud-basierten Dienst natürlich recht finster werden kann.

Apropos Kosten: jeder kann bei Heroku beliebig viele Anwendungen hosten lassen, die auch erst mal nichts kosten, in der Leistungsfähigkeit aber arg eingeschränkt sind. Benötigt man mehr Ressourcen, muss man in die Tasche greifen, ab ca. 36 US-$ (0,05 $-Cent pro Stunde) monatlich geht es los. Dabei unterteilt Heroku in Dynos und Worker. Dynos beschleunigen das Frontend, Worker die Hintergrundprozesse der Rails-Anwendung. Der Maximalausbau liegt bei 24 Dynos und 24 Workern, wofür dann aber auch 2,35 US-$ pro Stunde, oder umgerechnet rund 1.700 US-$ monatlich anfallen. Die Performancestufe dürfte aber auch „gehobenen“ Ansprüchen genügen.

Damit ist aber noch nicht Schluss, denn eine dedizierte Datenbank ist bei dem Preis noch nicht inklusive. Kostenlos gibt es 5 MB Shared Database, für 20 US-$ monatlich 20 GB Shared Database. Wer gern eine dedizierte Datenbank hätte, muss bspw. für den kleinsten Tarif Ronin 200 US-$ monatlich berappen. Dafür erhält er 16 gleichzeitige Verbindungen, 1,7 GB RAM und 1 computing unit. Für 6.400 US-$ gibt es 400 Verbindungen, 68 GB RAM und 26 computing units. Wer’s braucht…

Herokus Dateisystem ist read-only, Dateiuploads lassen sich also nicht realisieren. Hierzu kann/sollte man, auch laut Heroku-Dokumentation, auf Anbieter wie Amazon S3 ausweichen. Für Rails-Anwendungen gibt es diverse Möglichkeiten, Uploads zu Amazons S3 (Simple Storage Service) aus der Anwendung heraus zu realisieren. Namentlich erwähnt werden Attachment-Fu und Paperclip. Eine persönliche Präferenz kann ich hier abgeben, ich hab mit beiden noch nicht gearbeitet. Heroku empfiehlt im Übrigen generell, große Dateien, die die Applikation zum Download bereitstellen soll, aus Performancegründen zu S3 oder ähnlichen Services auszulagern, weil das Dateisystem von Heroku nicht für derartige Anwendungszwecke konzipiert und optimiert wurde.

Um die Performanceunterschiede messen zu können, habe ich eine Installation von Redmine bei Heroku vorgenommen. Das Deployen dieser Anwendung ist leider nicht total trivial, die einzelnen Schritte habe ich deswegen in einem Gist (welcher auch noch mal ganz unten eingebettet ist) niedergeschrieben.

Zum Ergebnis meiner Benchmarks, gemessen auf einer Projektübersichtsseite mit ab -c 50 -n 200:

  1. 1 Dyno (kostenlos): 7,98 Requests pro Sekunde
  2. 2 Dynos: 13,15 Requests pro Sekunde
  3. 3 Dynos: 18,46 Requests pro Sekunde
  4. 10 Dynos: 53,46 Requests pro Sekunde
  5. 24 Dynos: 84,14 Requests pro Sekunde
  6. 1 Worker: 7,64 Requests pro Sekunde
  7. 2 Worker: 7,74 Requests pro Sekunde

Die Anzahl der Worker wirkt sich also in keiner Weise auf die Anwendungsperformance aus, die Anzahl der Dynos hingegen beträchtlich. Den größten Gewinn (prozentual gesehen) bekommt man hier, wenn man von dem einen kostenlosen Dyno auf einen zweiten, kostenpflichtigen aufrüstet. Die monatlichen Kosten liegen mit diesem bei rund 36 US-$, also umgerechnet in etwa 27 €. Eigentlich nicht zu viel verlangt, man darf nur nicht vergessen, dass in diesem Preis noch kein Storage und nur 5 MB an Datenbankplatz inklusive ist.

Zum Vergleich: mein nicht optimierter Root-Server (Athlon64 X2 6.400+, 4 GB RAM, OpenVZ) liefert rund 10,5 Requests pro Sekunde. Den muss ich natürlich selbst administrieren, warten, etc. Und das Deployment ist auch längst nicht so bequem bzw. müsste erst mal von mir auf diesen Bequemlichkeitslevel gebracht werden.

Heroku bietet für einen akzeptablen Preis einen wirklich tollen und performanten sowie äußerst flexiblen Service an. Für den Rails-Entwickler, der keine Lust hat, sich mit der Einrichtung und Administration eines Rails-fähigen Webservers rumzuschlagen und ggf. auftretende Probleme zu beheben ist Heroku aus meiner Sicht optimal. Zumal man hier nicht gleich einen zweiten Server hinzu kaufen muss, nur weil die Anwendung an ein oder zwei Stunden am Tag mal mehr Ressourcen braucht, als es die eigene Hardware zulässt. Die Anmeldung kostet nichts und das Deployen der eigenen (oder fremden) Anwendung genau so wenig. Einem Versuch steht also nichts im Wege. Viel Spaß dabei.