Continuous Integration for Symfony apps, the modern stack: quality checks, private Composer, headless browser testing…

Jenkins / Symfony

Updated 2014/11/21 : Fixed a bug when deploying (thanks @meyer_baptiste). Added a command to update GitHub commit status (thanks @samuelroze).

At Les-Tilleuls.coop, we built great e-commerce platforms and high-performance web applications with quality and agility in mind.

Most of our applications share the same technical stack:

  • the PHP language with the Symfony framework and Doctrine for back applications
  • front applications developed with CoffeeScript or JavaScript, AngularJS and Twitter Bootstrap (Grunt as build system, Yeoman for scaffolding, Karma and Jasmine for tests)
  • private Git repositories (hosted on GitHub)
  • private libraries and bundles shared between applications and exposed as Composer packages
  • phpspec unit tests
  • Doctrine Data Fixtures (enhanced with Alice and Faker)
  • Behat scenarios
  • exhaustive PHPDoc
  • capifony scripts for deployment

I managed to build a pretty cool CI system allowing us to deliver high quality Symfony applications. In this tutorial, you’ll see how it looks and how to install it step by step. If you aren’t using a CI system, it will increase drastically the quality of your Symfony projects and over the time, it will increase your team your development skills.

Our CI system mostly relies on Jenkins. At every commit (on every branch) it:

  • updates our private Composer package repository index
  • runs all tests and scenarios, including web acceptance test trough headless and real browsers
  • runs a bunch of quality checks on the code: security issues, dead code and code duplication detection, cyclomatic complexity analysis, good structuration and following of Symfony’s best practices
  • checks Coding Standards conformance
  • generates a browsable API documentation
  • instantly deploys the new version of the application on testing and sometimes even production servers (continuous deployment)

Finished feature branches are reviewed and merged in the master branch through GitHub Pull Requests by a lead dev only when all tests and checks are green.

The following tutorial can be followed on Debian (wheezy) and Ubuntu.

Installing Jenkins

The Jenkins team maintains a Debian repository providing up to date binary packages. Add it to your CI box and install the package (as root):

If nothing goes wrong, the Jenkins UI is now available on the port 8080 of your CI box. Open the UI in your favorite web browser. So easy.

Securing the installation

Jenkins Security

Currently, anyone knowing the URL of your Jenkins install can take the control over it. It’s a good idea to set credentials required to access the CI:

  1. go to “Manage Jenkins” then “Setup Security”
  2. check “Enable security”
  3. in the “Security Realm” section, select your user provider (“Jenkins’ own user database” is a good default if you don’t have a LDAP directory or any other centralized user provider for your organization)
  4. don’t forget checking “Allow users to sign up”, it’s mandatory to be able to log in after enabling the security
  5. in the “Authorization” section, choose “Project-based Matrix Authorization Strategy”, leave all checkboxes for “anonymous” empty and create a super admin user having all rights
  6. enable CSRF protection by checking “Prevent Cross Site Request Forgery exploits”
  7. save and go back to the homepage
  8. you’re prompted to authenticate, click “Sign up” and create an account with the same username you given administration rights earlier

Jenkins is now secured! Go back to security settings to disable the signup form.

Connecting Jenkins with GitHub repositories

Jenkins must be able to pull data from your privates GitHub repository. The best way I found is to create a GitHub machine user with a read-only access to private repositories. You can add users with write access to your repositories from GitHub by clicking “Settings” then “Collaborators” (the write permission is necessary to update the build status on GitHub. If you don’t care about this feature, just set a read only access to the repo).

Now, we’ll create private and public SSH keys for the UNIX account running Jenkins (on Debian it is called jenkins):

The last step is adding the public key to the GitHub account of the machine user. From GitHub’s homepage, logged in as your machine user account, go to “Settings” then “SSH Keys”. Add a new key with the content of  /var/lib/jenkins/.ssh/id_rsa.pub.

Jenkins is now able to connect to our GitHub repositories.

To update the GitHub commit status, our machine user will also need an access token to the GitHub API. Go to the settings page of the user, click on “Applications” then click on “Generate new token” and be sure to check the “repo:status” permission. Save the token, we’ll use it our build script.

Installing PHP

The PHP interpreter is needed to run our projects tests and other tools such as Composer and Satis. Install it:

apt-get install php5-cli php5-apc php5-sqlite

You noticed that I also installed APC to speed up script execution. I’ve also installed SQLite. I use it as DBMS for the  test  environment of Symfony applications.

Installing Satis

Satis

Satis is the most popular (and the only open source) private Composer package repository. This tool generates a static Composer index. Later, we will add a task in Jenkins to rebuild the repository at each commits. It will allow us to have an always up to date Composer Package Repository. To do that, we must install Satis and make the  jenkins user must able to run it.

Satis must be installed through Composer. Switch to the jenkins user and start by installing Composer, then Satis:

Then, create a config file for Satis called packages.json:

This config file will enable 2 privates Composer packages ( repo1  and repo2 ). Thanks to the SSH keys we configured later, the jenkins  user is able to connect to our privates GitHub repositories. Of course those repositories must have a composer.json file at their root. Full configuration options of Satis is documented on the Composer website.

Generate the package repository manually for the first time:

satis/bin/satis --no-interaction build /var/www/packages.json packages

The next and step is exposing our packages over HTTP. We will use nginx to do it. Switch back to the root user ( Ctrl + d) and type:

# apt-get install nginx

Then change the content of /etc/nginx/sites-enabled/default by the following:

Don’t forget to replace <my-ip>  by the list of IPs allowed to access the package repository. It will prevent exposing your private repository on the whole internet.

Restart nginx:

We should be able to browse the repository through our favorite web browser.

Enabling Git and GitHub support

GitHub Jenkins Webhook

Git and GitHub support are available through plugins. Go to “Manage Jenkins” then “Manage Plugins” and install plugins called “Git Plugin” and “GitHub Plugin”. Their names should be explicit.

Then, we will setup a GitHub Webhook to trigger a build every time a commit is pushed, in any branch.

Go to your GitHub repository, click on “Settings” then “Webhooks & Services”. Click on the “Add service” select box and choose “Jenkins (GitHub plugin)”. Enter your Jenkins’ webhook endpoint in the box, it should be something like http://ci.les-tilleuls.coop:8080/github-webhook/  (just replace the domain part of the URL) and click “Add service”.

The webook is set! Jenkins will be notified every time we push something our GitHub repo. Repeat this step for every GitHub repository you want to trigger builds.

Installing PHP CS Fixer

PHP CS Fixer is an awesome tool provided by SensioLabs. It’s 1.0 version has just been released. It automatically fixes PSR-0PSR-1PSR-2 and Symfony coding standard violations.

With its --dry-run option, it can be used in our CI to check if the produced code is clean.

PHP CS Fixer is packaged as a PHAR archive. Lets install it:

Installing phpDocumentator

phpDocumentator

phpDocumentator generates a beautiful HTML documentation based on DocBlocks documenting your classes and methods.

As for PHP CS Fixer, we will install its PHAR version, but before downloading it, we need to install some extra Debian packages:

Web Acceptance Testing with Behat and PhantomJS

We love Behat and Mink. We use them to manage our user stories and to run automated web testing scenarios.

Standards Symfony controllers are tested with the Symfony2 extension. But nowadays, we create more and more Single Page Applications usually composed of a Symfony 2 backed JSON / REST API and an AngularJS client.

It sounds like a good idea to also test interactions between AngularJS clients and Symfony REST API in the CI system. Behat and Mink will help.

I usually use Mink Selenium2 to drive PhantomJS, an awesome headless browser based on Webkit. Unlike the Symfony2 extension, the PhantomJS needs to access the application trough a public URL. We need a front controller exposing the test environment. Lets write it. We will also configure the built-in web server provided by Symfony to avoid configuring a heavier solution like nginx + PHP FPM.

The first step is to create a new front controller for the test  environment (Symfony comes with front controllers for prod  and dev  environments but not for test ).

Create a new front controller called app_test.php  in the web/  directory your application. It should contain something like the following:

We also need a custom router for the built-in web server. It will allow to use the test env. Create a file in the app/config/  directory of your application called router_test.php . Here is the sample code:

The next step is to install PhantomJS. The PhantomJS package is not available in Debian stable. We will fallback to the binary version provided on the official website:

The behat.yml  file  of your project must be changed to specify the base URL and the Selenium2’s WebDriver host to use. Here is a sample file:

You are ready to write scenarios testing the whole app. They will be executed at each commit! To test consistency across browsers and platforms (mobile devices, exotic systems…), you can take a look to SauceLabs. This SaaS platform is well integrated with Behat and can be a good (but more expensive) replacement to PhantomJS!

Checking code quality with SensioLabs Insight

SensioLabs Insight

SensioLabs published earlier this year a SaaS platform running quality analysis for PHP and especially Symfony projects. That service is called Insight. It’s user friendly, cool to play with (it provides some gamification with a system of “medals”) and finds a lot of bad practices in bundles and Symfony applications.

The first step is to create an account and register your project on the Insight website. Configure your credentials, set the Git repository to analyse and run manually a first analysis. You will probably find some problems in your app that must be fixed!

SensioLabs Insight provides a tool allowing to run new analysis in a CI system. Like other tools we already installed, the insight command is available as a PHAR. Download it as the jenkins user:

Find the uuid of the project you want to analyse with the following command:

The first time you’ll use insight.phar, you’ll be prompted for your user id and API token. You can find them in your SensioLabs Insight account page (“API/SDK” tab). Your credentials will be saved by insight.phar.

We are now able to integrate SensioLabs Insight in the Jenkins script. Write the uuid of your project somewhere, we will need it later.

Insight can output violations in the PMD format. You guessed it, Jenkins has a PMD plugin able to display nicely that sort of output.

Go to “Manage Jenkins”, “Plugin Manager”, click on the “Available” tabs and search for “PMD plugin”. Install it.

SensioLabs Insight is free for public open source projects but a subscription is needed to analyse private projects. I think it’s a good investment but I can’t blame you if you prefer using open source softwares. Sebastian Bergmann (the author of phpunit) maintains a great documentation explaining how to set up open source quality checking tools including PHPMD, phploc, PHP_Depend and phpcpd. Fell free to complete your installation with jenkins-php.org.

Note: at the time I write these lines there is some issues with the PMD output and the fail-condition option of the insight command. I’ve submitted fixes to them and I hope they will be integrated soon in the PHAR file.

Continuous Deployment with Capifony

It’s always good to have a testing server running the last version of the project. Sometimes, we go one step beyond and we let Jenkins pushing stable code in production thanks to Git’s tags (not detailed here).

Anyway, I use a tool you probably already know: capifony. It’s a deployment software specialized for Symfony projects built on top of Capistrano. It’s the easy way to deploy your application. It handle copying the source code to the server using Git, setting correct directory permissions, installing project’s dependencies, running database migration scripts, restarting services such as PHP FPM and many more. If you don’t already use it, give it a try, you will love it.

Like most Ruby applications, capifony is available as a gem. There is nothing easier than installing it on Debian:

Creating the Jenkins project

Jenkins Project

Go back to the Jenkins Dashboard and click on the “create new jobs” button. On the next screen give a name to your project and choose “Freestyle project”.

On the next screen:

  1. fill the “GitHub project” input with the base URL of your GitHub repository

In the “Source Code Management” section:

  1. select “Git” as “Source Code Management”
  2. in “Repository URL”, enter the SSH clone URL of your Git repository (it must be like git@github.com:coopTilleuls/myrepo.git )
  3. click the “Add” button below “Credentials”
  4. choose “SSH Username with private key” as “Kind”
  5. choose “From a file on Jenkins master” for “Private Key” and click “Add” (It allows to use SSH keys we created and added to GitHub in the previous step)
  6. set “Branches to build” to empty (to build all branches of the repository)
  7. select “githubweb” as “Repository browser” and enter the URL of your repo’s homepage again

In “Build triggers”:

  1. check “Build when a change is pushed to GitHub”

In “Build”:

Add a new “Execute shell” build step and use the following script as a template to fit your own needs:

Basically, the script run the various tools we installed earlier and don’t stop when an error occurs. Instead, it collect the return status of commands, and returns at the end of the script if the build is successful or not. It allows to always run all checks, even if one fail. The deployment (if enabled) only occurs if the build is successful. The built-in web server and PhantomJS run in background to allow them working simultaneously with Behat. They are killed after Behat exited.

Don’t fortget to customize value of variables in the top of the script.

Why not a XML file? Because I sometimes use other build servers such as Travis CI and Bamboo. Using a simple shell script allows to easily replace Jenkins with another server. Shell scripts can also be versioned directly in the Git repository.

In “Post-build Actions”:

  1. Add the “Set build status on GitHub commit” step
  2. Add “Publish JUnit test result report” and specify build/unit.xml for “Test report XMLs”
  3. Add “Publish PMD analysis results” and specify build/pmd.xml for “PMD results”
  4. Add “Publish Javadoc” and set build/doc as “Javadoc directory”
  5. Add other actions you’re interested in (like sending mails)

Troubleshooting GitHub API rate errors

If your start getting errors like “Could not fetch https://api.github.com/[…], enter your GitHub credentials to go over the API rate limit” in the console output, it’s because you exceed GitHub API rates for anonymous users. Just open a shell, switch to the Jenkins user, download something with Composer and enter your machine user credentials when prompted:

Because Composer stocks an OAuth in .composer/auth.json , all next calls to GitHub will succeed, even when launched by Jenkins.

Troubleshooting mails

To make Jenkins able to send mails (when a build fails for instance), you need to configure a SMTP server. The easier way is to install a local server on your CI server:

Default options should be OK.

To customize mail parameters, from the Jenkins homepage go to “Manage Jenkins” then “Configure System”. SMTP settings are under the “E-mail notification” section and the address used by Jenkins to send mails in “Jenkins Location”.

 Updating automatically the localy installed tools

As any software, all tools used by our CI server get updates fixing bugs and adding new features. Debian and Jenkins can be updated using apt. Jenkins plugins updates are managed directly trough the Jenkins user interface. But software we installed locally must be updated “by hand”. We will periodically run a small shell script I’ve written to update those tools.

Create the following update-tools.sh script as the jenkins user in its home directory ( ~jenkins):

Don’t forget to make it executable by executing  chmod +x update-tools.sh. To get the updates every night, run  crontab -e and add the following line:

00 00 * * * ~/update-tools.sh

 

You’re CI system is now ready. Your full test suit and quality analysis are running against new produced code in realtime! We also have quality checking and tests specifics for our frontend apps. Maybe If people are interested about that, maybe I’ll write another post detailing our infrastructure.

I’m sure you have your own preferred quality tools and CI best practices for Symfony projects. Share them with us in the comments 🙂

Installer un stack LAMP sur un dédié OVH avec Ubuntu 12.10

Petit mémo pour configurer un serveur web LAMP sur un dédié OVH fraichement livré. La distro choisie est Ubuntu 12.10.

Apache, PHP, MySQL

Commençons par mettre à jour la liste des paquets :

# apt-get update

Puis la distribution elle même :

# apt-get dist-upgrade

Installons Apache, PHP, MySQL, phpMyAdmin et les extensions qui vont bien pour faire tourner Symfony 2, WordPress, Prestashop

# apt-get install phpmyadmin mysql-server php5-intl php5-mcrypt php5-xsl php5-cli php5-sqlite php5-memcached php5-curl php-apc php-pear

L’installateur nous demande de rentrer un mot de passe root pour le serveur MySQL (tant mieux) et le serveur web à configurer pour phpMyAdmin. Choisir apache2.

Donnons ensuite à dbconfig-common les mots de passe nécessaire pour qu’il configure les bases de données utiles à phpMyAdmin.

Beaucoup d’applications PHP utilisent le module rewrite de Apache Activons-le :

# a2enmod rewrite

Notre serveur web est prêt à l’emploi !

Un zeste de sécurité

Commençons par éditer /etc/apache2/conf.d/security pour rendre Apache plus discret. Passons ServerTokens à Prod et ServerSignature à Off.

Au tour de PHP. C’est dans /etc/php5/apache2/php.ini que ça se passe, expose_php doit être à Off. Profitons-en pour régler notre fuseau horraire : date.timezone = Europe/Paris.

Ubuntu 12.10 est fournie avec PHP 5.4. Plus besoin de s’occuper de register_globals et des Magic Quotes, ces “fonctionnalités” ont été supprimées upstream. Bon débarras !

Si vous n’utilisez pas d’applications PHP antédiluviennes, passez short_open_tag à Off .

Redémarrons Apache pour que nos réglages soient pris en considération :

# service apache2 restart

Appliquons les bons conseils de Marion et installons un système de sauvegarde automatisée, disons Backup Manager :

# apt-get install backup-manager

Ajoutons /var/lib aux répertoires sauvegardés quand l’installateur nous le propose (ce répertoire contient entre-autre les base de données binaires MySQL).

Si vous avez opté pour un dédié OVH vous disposez peut-être d’un espace de sauvegarde FTP gratuit (ce service ne semble malheureusement plus exister sur certaines offres Kimsufi). Pour l’activer rendez-vous dans le manager : section Services puis Backup Ftp. Une fois le mail avec les identifiants reçu éditons /etc/backup-manager.conf pour les indiquer à l’utilitaire.

Et le courrier ?

Au cas ou nos applications aient besoin d’envoyer des emails :

# apt-get install postfix

Choisissez le type de configuration “Site internet”.

Note : la configuration d’un serveur mail qui envoi des courriers qui ne finissent pas dans “Spam” nécessiterait un article complet.

Retrouvez l’un de mes articles dans Linux Identity n°6

Les anciens utilisateurs de Easy Ubuntu trouveront sûrement un intérêt à l’article intitulé Installation des pilotes et des extensions nécessaires à une utilisation courante publié dans Linux Starter Kit / Linux Identity n°6. Dedans, j’y détail l’installation des composants soumis à des brevets logiciels et / ou non-libres qui ne sont pas distribués avec Ubuntu mais qui se révèlent malheureusement indispensable pour une utilisation multimédia de son ordinateur (lecture de musiques et de vidéos, de DVD, jeux vidéos en 3D, …). L’article revient en partie sur les fonctionnalités du petit utilitaire que j’avais conçu aux débuts d’Ubuntu et indique comment arriver au mêmes résultats en utilisant les mécanismes qui ont étaient intégrés dans la distribution depuis.

Couverture de Linux Identity

Le magazine est fourni avec un CD d’installation francisé d’Ubuntu Intrepid Ibex et contient bon nombre d’autres articles qui compléteront agréablement la documentation francophone pour vous aider à prendre en main la distribution. Il est disponible en kiosques et depuis le site internet d’Oxy Press pour une dizaine d’euros.

Je ne reviendrais pas sur le choix du Tux Napoléon en couverture 😉

Monter une partition Linux sous Mac OS X

Ou plus précisément une partition de type ext2/3, le système de fichier le plus populaire sous GNU/Linux, utilisé par défaut sur Ubuntu.

Mac OS X n’inclut pas de pilote pour monter les partitions ext2, heureusement un projet libre comble ce manque : ext2fsx. Récupérer la version ext2fsx_dev sur le site du projet, la seule supportant l’architecture x86 (tous les Mac depuis le passage aux processeurs Intel). Un simple double clic sur le fichier .dmg et un redémarrage de l’ordinateur suffira à l’activation du pilote.

Gestionnaire ExtFS

Vous pouvez désormais monter vos partitions formatés en ext2, 3 ou 4 via la commande mount ou depuis un sympathique petit utilitaire nommé Gestionnaire ExtFS que l’on trouve dans le menu Autre des Préférences Système.

Quel développeur suis-je ?

  • Os : Ubuntu et Mac OS X
  • Éditeurs : Eclipse et vim
  • Langages favoris : Python, C
  • VCS : Subversion
  • Navigateur : Firefox

Alors, quel développeur je suis ?

Programmer hierarchy

Programmer hierarchy

Découvrez Appnr, une interface web d’ajout de programmes pour Ubuntu

Appnr est un portage web du système d’installation de paquets simplifié d’Ubuntu (GNOME Application Installer). Il permet de parcourir les différents logiciels disponibles dans les dépôt de notre distribution favorite depuis un simple navigateur et via une jolie interface AJAX. Appnr reprend les grandes lignes de son grand frère desktop : classement par catégorie, alphabétique et par popularité.

Appnr

L’application utilise le pseudo-protocole apturl afin de permettre l’installation des paquets directement d’un simple click depuis Firefox. Appnr est très pratique pour suggérer l’installation d’un logiciel à un utilisateur d’Ubuntu via le réseau de manière intuitive et user-friendly. Elle pourra également agréablement remplacer le très austère packages.ubuntu.com pour fouiller dans les dépôts depuis un autre système.

Se connecter au chat Facebook via Pidgin sous Ubuntu

Tout comme dans la dernière version de Adium, l’excellent client libre de messagerie instantanée pour Mac, il est possible de se connecter au chat Facebook via Pidgin (anciennement GAIM). Pour ce faire, nous devrons lui greffer un plugin disponible sur Google Code. Voici la marche à suivre pour l’installer sous Ubuntu.

Le chat Facebook pour Pidgin

  1. Récupérez les archives facebook_icons.zip et pidgin-facebookchat-*.deb (à l’heure ou j’écris ces lignes pidgin-facebookchat-1.37.deb) sur la page du projet dans le bloc Featured Downloads.
  2. Installez maintenant le plugin par un simple double-click sur le fichier .deb puis un click sur le bouton Installer le paquet qui se trouve en haut à droite de l’installateur de paquets Gdebi.
  3. Relancez Pidgin si il est déjà en cours d’exécution puis ajouter votre compte Facebook depuis le menu Comptes puis Gérer.

Ça marche !

Il existe également un thème d’émoticones pour Pidgin nommé Original Smileys qui contient tous les smileys officiels de nombreux services dont le Facebook chat. Son installation est simplissime, téléchargez l’archive, déroulez le menu Outils puis sélectionnez Préférences. Rendez-vous dans l’onglet Thèmes des frimousses, cliquez sur Ajouter et sélectionez l’archive téléchargée.

Gandi lance son offre d’hébergement !

Après 9 mois de beta test, Gandi, le célèbre registar qui a démocratisé l’achat de noms de domaines sur Internet, lance son offre d’hébergement extensible et à bas prix.

Pour 10€ HT par mois vous obtenez une “part” sur un serveur virtualisé (la techonologie sous jacente est Xen) ce qui équivaut à un serveur avec processeur Intel Celeron, 256Mo de mémoire vive (et 512Mo de SWAP) et 5 Go de disque dur. Si le besoin sans fait sentir, vous pouvez très simplement ajouter d’autre “parts” à votre serveur via une interface web et augmenter ainsi ses capacités sans avoir besoin de modifier la configuration de votre serveur.

Le traffic est illimité et l’offre inclus un système d’installation de services simplifiés (web, mail, …). Vous avez totalement la main sur votre serveur (shell root) et vous pouvez le configurer comme bon vous semble, comme si vous étiez sur un véritable serveur dédié.

Ce blog est hébergé sur des serveurs Gandi depuis quelques temps et je peux dire que j’en suis très conten, un nouveau concurrent de taille pour les Dedibox d’Illiad et l’offre Kimsufi d’OVH est né.

Changer le message d’accueil de votre terminal

Lorsque vous lancez un shell sous votre Unix préféré (que ce soit GNU/Linux ou un BSD ou OS X), un petit texte est affiché avant le prompt, c’est le MOTD (Message Of The Day). Ils sont souvent austère, comme c’est le cas sur les serveurs d’hébergement Gandi :

Pour le changer pour quelque chose de plus joyeux il suffit de modifier le fichier /etc/motd en tant que root !

Petite astuce, vous pouvez utiliser un FIGlet-like pour créer un logo en art ASCII !

Nouvelle offre d’hébergement à bas prix chez Gandi : installez votre serveur web

Gandi m’a gentiment fourni une invitation à la bêta de leur service d’hébergement. Je compte y passer ce blog et voir comment se comportent les frameworks Symfony et Django sur ces serveurs virtualisés et scalable.

J’ai donc pris une part (6€ HT/mois) afin d’y installer un serveur web composé d’Apache, de PHP, de MySQL et géré par hosting.py.

Première opération, créer le serveur. J’ai choisi le mode expert et Ubuntu comme distribution (c’est le choix par défaut). Tout ce fait très simplement via le site internet de Gandi. Quelques minutes après la création du serveur via l’interface un mail arrive vous indiquant l’adresse IP de votre serveur tout neuf.

C’est une version personnalisée par Gandi de Gutsy qui est installée, un peu vieille mais très stable, cela me convient parfaitement.

Première opération : mettre à jour la distribution.

Connectez vous via SSH puis passez en root en tapant su (un peu perturbant pour une Ubuntu n’est-ce pas :P) puis tapez la classique commande apt-get update && apt-get dist-upgrade. Cette mise à jour est importante car elle corrige certaines failles de sécurité critiques dont celle désormais célèbre touchant le protocole DNS.

Installer Apache, PHP et MySQL

La commande magique pour installer le tout : apt-get install apache2 mysql-server php5 libapache2-mod-php5 php5-mysql phpmyadmin.

L’utilitaire d’installation vous demandera d’abord de choisir un mot de passe pour le compte root du serveur MySQL puis de sélectionner quel version d’Apache doit être configurée pour être utiliser avec phpMyAdmin : choisissez apache2.

Vous pouvez taper l’adresse IP de votre serveur dans votre navigateur préféré afin de vérifier que tout fonctionne bien. phpMyAdmin est accessible depuis http://<votre_ip>/phpmyadmin/.

Une petite amélioration afin d’augmenter les performances : installons xcache. Comme son nom l’indique, xcache permet de mettre en cache les versions “compilées” des scripts PHP (opcode) et ainsi d’améliorer grandement les performances du langage le plus populaire du web.

Rien de plus facile : apt-get install php5-xcache. La commande /etc/init.d/apache2 restart vous permettra de rendre effective la mise en cache.

Sécurisons tout ça

Très bien, notre serveur fonctionne. Mais ce n’est pas encore la panacée. Une simple requête HTTP GET nous renvoi comme en-têtes :

Les en-têtes HTTP sont riches, trop riches : on y apprend que le serveur fonctionne sous la distribution Ubuntu Linux, que le serveur web est Apache en version 2.2.4, que le langage de script PHP en version 5.2.3 est disponible et que les versions installées sont celles pacagées par la distribution (ce qui donne des indices supplémentaires sur la configuration utilisée). Ces informations sont en partie reprises dans les pages d’erreurs et les index générés automatiquement du serveur web.

Même si cacher les noms et numéros de versions des logiciels installés n’améliore pas la sécurité réelle de votre serveur elle le rend moins visible des pirates en herbe et autres robots des amateurs de warez.

Pour masquer les informations distillées par Apache éditons le fichier /etc/apache2/apache2.conf, remplaçons la ligne ServerTokens Full par ServerTokens Prod puis ServerSignature On par ServerSignature Off.

Pour celles que fourni PHP c’est dans /etc/php5/apache2/php.ini que ça se passe. Remplacez expose_php = On par expose_php = Off. Même si cela n’a rien à voir avec les numéros de versions, ça peut être une bonne idée de désactiver églament les magic quotes en remplaçant magic_quotes_gpc = On par magic_quotes_gpc = Off.

Relançons encore une fois Apache /etc/init.d/apache2 restart afin de faire prendre en compte nos modifications, c’est mieux.

Reste MySQL. Nous avons défini un mot de passe pour le compte root lors de l’installation mais il reste quelques brèches importantes comme la possibilité de se connecter sans compte ou celle d’utiliser le compte root depuis l’extérieur (sans passer par une console SSH ou phpMyAdmin – ce qui facilite les attaques par force brute).
Un script fourni nommé mysql_secure_installation permet de remédier à tous ces problèmes. Lancez-le. Excepté pour le changement de mot de passe root que nous venons de définir lors de l’installation je vous conseil de répondre par le choix proposé par défaut à toutes les questions.

Notre serveur est un peu mieux préparé à survivre dans la jungle qu’est le web.

Note : nous n’abordons ici que la sécurisation des composants LAMP de notre serveur. C’est un bon début mais c’est loin d’être une protection absolue ou suffisante.

Installer hosting.py

hosting.py est un petit logiciel que j’ai développé qui permet de gérer de manière très simple des comptes web. Il se base sur le système de gestion des utilisateurs UNIX et automatise les tâches les plus courantes lors de l’administration d’un petit serveur web mutualisé à savoir la mise en place et la modification de compte comprenant un utilisateur UNIX (accès SSH, FTP, …), un hôte virtuel apache, un compte et une base de données MySQL.

Il est conçu pour fonctionner avec les distributions basées sur Debian, Ubuntu en particulier. Il permet de simplement séparer les comptes des différents sites qu’hébergera votre serveur, ce qui n’est pas un mal question sécurité.

Commençons par installer les dépendances nécessaires à la récupération et à l’utilisation de mon script : apt-get install subversion python-mysqldb

Créons maintenant le squelette du répertoire de base des comptes web :

  • mkdir /etc/skel-www
  • mkdir /etc/skel-www/logs
  • mkdir /etc/skel-www/public_html

Comme son nom l’indique, logs accueillera les logs de connexion d’Apache (on pourra plus tard configurer AWstats pour générer des statistiques) et public_html sera le répertoire web de nos utilisateurs.

Récupérons la dernière version de hosting.py via Subversion : svn checkout http://debian-hosting.googlecode.com/svn/trunk/ debian-hosting-read-only

Éditez la variable MYSQL_PASSWD du fichier debian-hosting/hosting.py pour qu’elle contienne le mot de passe MySQL de l’utilisateur root puis donnez les droits en exécution sur ce même fichier en tapant chmod a+x debian-hosting/hosting.py.

Pour créer un compte utilisateur, passez en root avec la commande su puis tapez debian-hosting/hosting.py add monsite.com. Vous pouvez voir les informations de connexion s’afficher, notez les 🙂

Un sous domaine du type monsite.com.dunglas.fr est automatiquement créé (pour être effectif, il nécessite que dunglas.fr, notre domaine de test, dispose d’un wildcard dans ses entrées DNS).

Je vous conseil de le laisser à des fins de test et de debug, néanmoins un vrai nom de domaine c’est mieux. Toujours en tant que root éditez le fichier généré automatiquement nommé /etc/apache2/sites-available/monsite.com et transformez la ligne ServerName monsite.com.dunglas.fr en ServerAlias monsite.com.dunglas.fr. Ajoutez au dessus de celle-ci ServerName monsite.com.

Rechargez Apache (toujours en root) : /etc/init.d/apache2 reload

Votre serveur web est le site que vous avez créé sont fonctionnels si vos entrées DNS sont bien configurées. Placez vos fichiers web dans /home/monsite.com/public_html/ pour qu’ils soient visibles sur http://monsite.com 🙂