<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cloud Connected &#187; apache</title>
	<atom:link href="http://www.cloudconnected.fr/tag/apache/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cloudconnected.fr</link>
	<description>Thoughts of a french web developer</description>
	<lastBuildDate>Wed, 01 Feb 2012 08:53:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>One PHP error log per developer</title>
		<link>http://www.cloudconnected.fr/2010/09/16/one-php-error-log-per-developer/</link>
		<comments>http://www.cloudconnected.fr/2010/09/16/one-php-error-log-per-developer/#comments</comments>
		<pubDate>Thu, 16 Sep 2010 15:50:09 +0000</pubDate>
		<dc:creator>Rémi</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.cloudconnected.fr/?p=608</guid>
		<description><![CDATA[At work we&#8217;re using a shared web development server, with a setup that allows every developer to have his own compartmentalized development space. It requires some tricky configurations, but in the end I find it way more efficient than the policy &#8220;every developer installs its own Apache/PHP/MySQL stack&#8221;. I already talked about the general ideas [...]]]></description>
			<content:encoded><![CDATA[<p>At work we&#8217;re using a shared web development server, with a setup that allows every developer to have his own compartmentalized development space. It requires some tricky configurations, but in the end I find it way more efficient than the policy &#8220;every developer installs its own Apache/PHP/MySQL stack&#8221;. I already talked about the general ideas <a href="/2008/07/08/developpement-web-collaboratif/">in a previous article </a> (in french) two years ago, and so far it works like a charm. Our setup it constantly improving, and today&#8217;s big question is: how to make so that every developer has it&#8217;s own PHP error log?</p>
<h3>Apache config</h3>
<p>First, a little insight on the Apache configuration. If we would be using one virtual host directive per developer, this wouldn&#8217;t be an issue at all. Just set up the proper <code>error_log</code> path (using Apache&#8217;s <code>php_value</code> directive like so: <code>php_value error_log /var/log/php/errors_username.log</code>) for every virtual host, reload Apache and you&#8217;re done.</p>
<p>Our Apache, however, is using <code>mod_vhost_alias</code>. Basically we have &#8220;one virtual host to rule them all&#8221;, because I&#8217;m lazy and I don&#8217;t want to write one virtual host for every new dev, or modify a dozens of virtual host directives everytime I change a setting.</p>
<p>So how does it works? The first part of the URL is the developer username, then the second part is the project&#8217;s folder name, then the remaining part is the dev server hostname. With the <code>VirtualDocumentRoot</code> directive, you use parts of the URL has variable for calculating the correct document root path. (Actually, our setup includes a third part which is the subfolder to separate the document root of a project from all the include files, but that&#8217;s not the point of this article). Example:</p>
<pre>
&lt;VirtualHost *:80&gt;
	ServerName dev.domain.com
	ServerAlias *.dev.domain.com

	UseCanonicalName off
	VirtualDocumentRoot /home/%1/web/%2

	&lt;Directory /home/*/web/*/*&gt;
		Allow from all
		AllowOverride all
	&lt;/Directory&gt;
&lt;/VirtualHost&gt;
</pre>
<p>The address <code>http://remi.awesome.dev.domain.com</code> will automagically has a document root located in: <code>/home/remi/web/awesome</code>. The benefit is obvious: simplicity and flexibilty. I love <a href="http://en.wikipedia.org/wiki/Convention_over_configuration">convention over configuration</a> design principle.</p>
<h3>PHP config</h3>
<p>Now the problem is that it&#8217;s impossible to tell PHP to logs the errors on a different file based on the first part of the URL directly into the Apache configuration, because the <code>%1</code>, <code>%2</code>,&#8230; variable are only valid inside the <code>VirtualDocumentRoot</code> directive.</p>
<p>So we need to do it inside PHP or inside an <code>htaccess</code> file on every folder. But doing it for every project is a pain, not to mention the conflicts to come in SVN because every developer will have his own path. That&#8217;s when PHP&#8217;s <code>auto_prepend_file</code> option come into play (and honestly, I would never have thought it&#8217;ll be useful one day).</p>
<p>I just create a file named <code>/etc/php5/prepend.php</code> with that one-liner:</p>
<pre>
&lt;?php ini_set('error_log',sprintf('/var/log/php/errors_%s.log',substr($_SERVER['SERVER_NAME'], 0, strpos($_SERVER['SERVER_NAME'],'.'))));
</pre>
<p>And add this settings to <code>php.ini</code>:</p>
<pre>
auto_prepend_file = /etc/php5/prepend.php
</pre>
<p>Note that the directory <code>/var/log/php</code> will not be created out of the blue, so you have to take care of it, and it must be writeable by <code>www-data</code>. Files will be named <code>errors_(first part of the url).log</code>, so for example <code>errors_remi.log</code> in the previous example. Users belongs to group <code>www-data</code>, so as long as the logs are readable by the group (what they are by default) they&#8217;ll be able to read their logs.</p>
<p>And now the cherry on top of the cake, the logrotate configuration to rotate logs weekly, and keep one month (4 files) of archive:</p>
<pre>
/var/log/php/errors_*.log {
        weekly
        missingok
        rotate 4
        compress
        delaycompress
        notifempty
        create 640 www-data www-data
}
</pre>
<p>Et voilà!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudconnected.fr/2010/09/16/one-php-error-log-per-developer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Développement web collaboratif</title>
		<link>http://www.cloudconnected.fr/2008/07/08/developpement-web-collaboratif/</link>
		<comments>http://www.cloudconnected.fr/2008/07/08/developpement-web-collaboratif/#comments</comments>
		<pubDate>Tue, 08 Jul 2008 13:47:14 +0000</pubDate>
		<dc:creator>Rémi</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[gestion de projet]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[samba]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.the-asw.com/?p=305</guid>
		<description><![CDATA[On me demande souvent comment j&#8217;organise le développement web dans mon entreprise : comment on arrive à coder à plusieurs sur le même fichier sans se marcher sur les pieds, comment on archive les versions, comment on effectue les livraisons en production, etc. Il est vrai que le développement web collaboratif est souvent mal organisé, [...]]]></description>
			<content:encoded><![CDATA[<p>On me demande souvent comment j&#8217;organise le développement web dans mon entreprise : comment on arrive à coder à plusieurs sur le même fichier sans se marcher sur les pieds, comment on archive les versions, comment on effectue les livraisons en production, etc. Il est vrai que le développement web collaboratif est souvent mal organisé, et il est courant d&#8217;avoir comme seul outil un simple dossier partagé&#8230;</p>
<h3>Contraintes liées au développement web collaboratif</h3>
<p>Contrairement à un projet classique qui ne nécessite &#8220;que&#8221; un compilateur et des bibliothèques, une application web est une association complexe de plusieurs composants logiciels dont les versions et les configurations très variables peuvent influer sur le bon fonctionnement de l&#8217;application :</p>
<ul>
<li>un serveur web (vhost, htaccess, mod_rewrite, etc.),</li>
<li>l&#8217;interpréteur php (options de php.ini, modules supplémentaires comme pdo, gettext, etc.),</li>
<li>le sgbd (configuration des users, etc.).</li>
</ul>
<p>Donc la solution &#8220;classique&#8221; d&#8217;avoir un poste de développement par développeur est ici difficile à maintenir : il faudrait installer tous ces logiciels sur chaque poste et surtout veiller à avoir une configuration identique partout. Et ça se complique dès qu&#8217;il faut faire une mise à jour de la config&#8230;</p>
<p>Une autre solution serait d&#8217;avoir un serveur de dev unique (pour éviter les problèmes de maintenance évoqués ci-avant), et de travailler directement dessus via des partages de fichiers (Samba, NFS, etc.). Or cette solution pose plusieurs problèmes :</p>
<ul>
<li>en cas d&#8217;accès concurrents à un fichier : le risque est grand de voir ses modifications écrasées par un autre développeur ;</li>
<li>en cas de modifications lourdes (exemple : un refactoring de la base) : les autres développeurs sont bloqués ;</li>
<li>impossible d&#8217;utiliser correctement le svn : il n&#8217;y a qu&#8217;une seule version des fichiers et on ne sait pas qui l&#8217;a modifiée.</li>
</ul>
<p>Nous avons donc créée une solution intermédiaire : un serveur de dev unique (pour une maintenance facile), qui fournit des serveurs virtuels pour chaque développeur (pour une bonne séparation des données et une utilisation optimale de svn).</p>
<p>Le serveur de dev fonctionne avec Debian GNU/Linux, les postes clients avec Windows XP.</p>
<p><span id="more-305"></span></p>
<h3>Plateforme technique</h3>
<h4>Compte sur le serveur</h4>
<p>Chaque développeur dispose d&#8217;un compte uniquement sur le serveur de dev, qui lui permet de se connecter dessus en SSH (bien utile pour tester des tâches en ligne de commande tel que des scripts de maintenance). De plus, tous les développeurs appartiennent au même groupe (<code>www</code>) et les permissions sont par défaut en <code>rw</code> pour le groupe.</p>
<h4>Partage Windows : Samba</h4>
<p>Grace à Samba, chaque développeur dispose d&#8217;un partage windows identifié par son login. Le partage est également accessible en local sur la machine, dans son <em>home</em>.</p>
<h4>Vhost Apache</h4>
<p>Pour chaque dossier créé dans le partage, il existe un vhost permettant d&#8217;y accéder, sous la forme <code>http://login.dossier.dev.bso</code>.</p>
<p>Exemple, je crée le dossier <code>monboprojet</code> dans mon partage <code>monbologin</code>. L&#8217;URL est : <code>http://monbologin.monboprojet.dev.bso</code></p>
<p>Pour les projets dont le <code>documentRoot</code> n&#8217;est pas à la racine (c&#8217;est à dire à peut près tous les projets sur svn, puisque la racine contient seulement <code>trunk/</code>, <code>branches/</code> et <code>tags/</code>), il vaut mieux les mettre dans un répertoire suffixé par &#8220;-src&#8221; et faire un lien symbolique. Par exemple :</p>
<pre>
$ svn checkout http://mon.beau.svn/monboprojet monboprojet-src
$ ln -s monboprojet-src/trunk/htdocs monboprojet
</pre>
<h4>BDD Mysql</h4>
<p>Il n&#8217;y a qu&#8217;un seul serveur MySQL. Chaque développeur peut disposer de son propre compte et de ses propres bases. Cependant, pour des raisons pratiques, on utilise la plupart du temps les mêmes bases. Un développeur ne va utiliser des bases à part que s&#8217;il a besoin de faire des opérations lourdes (genre modifier la structure d&#8217;un ensemble de tables) qui bloqueraient tout le monde le temps que le code mis à jour soit commit.</p>
<h3>Coordination du développement</h3>
<h4>SVN</h4>
<p>Un serveur Subversion (SVN) est utilisé pour gérer les sources. Le serveur svn est sur une machine différente du serveur de dev ce qui permet de sécuriser les données (en cas de crash de la machine de dev, on peut récupérer les dépots ; en cas de crash de la machine svn, on a toujours les versions locales).</p>
<p>Les dépots sont organisés de la manière classique avec 3 repertoires :</p>
<ul>
<li>branches/</li>
<li>trunk/</li>
<li>tags/</li>
</ul>
<p>Un commit ne doit pas casser le dépôt. C&#8217;est à dire qu&#8217;un développeur qui ferait un update doit pouvoir continuer à utiliser l&#8217;application sans être bloqué par un bug, une fonctionnalité manquante, ou autre. Il est tout à fait possible de faire un commit d&#8217;une feature non terminée, à partir du moment où le reste de l&#8217;application n&#8217;est pas impacté.</p>
<h4>Fichiers de config</h4>
<p>On ne commit jamais un fichier de config. En effet, d&#8217;une part un fichier de configuration est spécifique à un environnement (options de mise en cache, url, etc.) et d&#8217;autre part un fichier de configuration contient des logins et des mots de passes spécifiques.</p>
<p>On commit donc des modèles de fichiers de configuration, dont le nom se termine par .orig. Chaque développeur doit créer ses propres fichiers à partir des modèles. Quand on voit passer un &#8220;.orig&#8221; dans les logs d&#8217;update, on sait qu&#8217;il faut mettre à jour ce fichier. Cela est valable également pour les livraisons.</p>
<h4>SQL</h4>
<p>Pour permettre les livraisons (en préprod et en prod), à chaque modification de la base un fichier sql contenant les requêtes de mise à jour (alter, etc.) doit être écrit par le développeur. Pour éviter d&#8217;en avoir trop à gérer, il est intéressant de créer un fichier de mise à jour sql par version que l&#8217;on a prévu de livrer (<code>upgrade_1.0.sql</code>, <code>upgrade_1.1.sql</code>, etc.)</p>
<h4>Livraison</h4>
<p>Pour livrer, un développeur (en général le responsable du projet) utilise <code>rsync</code> depuis sa copie locale sur la machine de dev pour synchroniser les sources avec la préprod ou la prod. Puis il se connecte en SSH pour executer les scripts d&#8217;upgrade sql (d&#8217;où l&#8217;interet de les avoir écrit au fur et à mesure) et mettre à jour les fichiers de config.</p>
<p>Une option interessante de rsync est <code>--exclude-from=<em>nom_de_fichier</em></code>, qui permet d&#8217;exclure du rsync tous les fichiers ou les répertoires qui matchent les noms présents dans <code>nom_de_fichier</code>. Très pratique pour éviter de livrer les fichiers inutiles (.svn, .mo, &#8230;) et éviter d&#8217;écraser les fichiers de config&#8230; Exemple de fichier d&#8217;exclusion : </p>
<pre>
.svn
rsync*
doc*
config/*
Thumbs.db
*.mo
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.cloudconnected.fr/2008/07/08/developpement-web-collaboratif/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

