Mise en place d’une plateforme LAMP – Partie 1

By | 15 mars 2012

Venant de faire l’acquisition d’un serveur dédié destiné à héberger des sites internet, je vais en profiter pour rédiger un article sur la mise en place des différents soft qui vont composer ma plateforme LAMP.

Configuration serveur

La configuration matériel du serveur:

  • Proc: Intel(R) Core(TM) i5-2300 CPU @ 2.80GHz
  • Ram: 4 x 4GiB DIMM Synchronous 1333 MHz (0.8 ns)
  • DD: 2TB Hitachi HUA72202

En terme de distribution, j’ai fait le choix d’une ubuntu, par habitude. J’ai donc choisi la version en LTS (Long Term Support) qui est à l’heure actuelle ubuntu 10.04, qui utilise le noyau dans sa version 2.6.38.

Objectif

Avant de commencer, je vais présenter rapidement les différents logiciels que je vais utiliser.

Friand de nouvelles technologie je vais commencer par l’installation de Nginx, qui est un serveur HTTP qui est réputé pour ses performances (traitement des requêtes HTTP en asynchrone). Ce qui va me permettre de dompter sa configuration.

Couplé avec Nginx je vais installer php 5.4 disponible depuis 15 jours. Concernant le sapi, j’ai fait le choix d’utiliser php-fpm, qui offre une meilleure gestion des processus que fastCGI.

En terme de base de données, je vais partir sur un MySQL 5.5 pour ma base principale.

Redis pour mon système de cache. Pourquoi Redis plutôt que MemCache, tout simplement car ça me permettra tout comme Nginx de faire mes premiers pas sur sa configuration et son utilisation.

Pour le monitoring, je vais mettre en place Munin.

Installation de PHP

Je vais donc commencer par l’installation de PHP.

Récupération des sources et compilation:

$> wget http://www.php.net/get/php-5.4.0.tar.gz/from/fr.php.net/mirror -O php-5.4.0.tar.gz
$> tar -xzvf php-5.4.0.tar.gz
$> cd php-5.4.0
$> ./configure --enable-fpm --enable-mysqlnd --with-pdo-mysql
$> make && make install
$> cp php.ini-development /usr/local/lib/php.ini

Vérification que PHP soit bien installé:

$> php-fpm -v
PHP 5.4.0 (fpm-fcgi) (built: Mar 15 2012 00:09:39)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies

Le fichier de configuration de php-fpm doit se trouver par défaut dans le dossier /usr/local/etc, pour ma part je préfère l’avoir dans mon dossier php, se trouvant dans /usr/local/php/fpm/conf.
Je vais donc copier le fichier de configuration dans le dossier de destination, et modifier le chemin d’accès dans le script de démarrage de service:

$> mkdir -p /usr/local/php/fpm/conf/
$> cp /src/php-5.4.0/sapi/fpm/php-fpm.conf /usr/local/php/fpm/conf/
$> vim /src/php-5.4.0/sapi/fpm/init.d.php-fpm
# Modifier la ligne ci-dessous par la ligne suivante.
# php_fpm_CONF=${prefix}/etc/php-fpm.conf
# php_fpm_CONF=${prefix}/php/fpm/conf/php-fpm.conf

Ajout du script de démarrage du service php-fpm dans init.d:

$> cp /src/php-5.4.0/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
$> chmod 755 /etc/init.d/php-fpm
$> update-rc.d -f php-fpm defaults

On devrait maintenant pouvoir démarrer notre serveur php-fpm:

$> /etc/init.d/php-fpm start
startStarting php-fpm [15-Mar-2012 20:18:49] ERROR: [pool www] cannot get gid for group 'nobody'
[15-Mar-2012 20:18:49] ERROR: FPM initialization failed

Le démon de php-fpm doit donc être associé à un utilisateur, par défault il s’agit de nobody.
Pour ma part je vais crée l’utilisateur php-fpm:

$> useradd php-fpm --no-create-home --system

Il faut ensuite préciser l’utilisateur et le groupe dans le fichier de configuration de php-fpm. Recherchez la section www, et éditer les directives user et group avec le nom d’utilisateur que vous avez crée pour php-fpm.

$> vim /usr/local/php/fpm/conf/php-fpm.conf

Une fois l’utilisateur crée, on peut démarrer le serveur php-fpm:

$> /etc/init.d/php-fpm start
Starting php-fpm ................................... failed

failed … Donc pour le coup j’ai aucune idée d’où provient le problème, ce qui est encore plus suprenant c’est qu’en regardant les processus actifs je vois bien php-fpm.

Après quelques recherches, apparemment php-fpm n’arrive pas à créer son fichier pid (créé lors du démarrage du service, ce fichier contient l’id du processus afin de pouvoir stopper le service).

$> touch /usr/local/var/run/php-fpm.pid
$> /etc/init.d/php-fpm start
Starting php-fpm  done

Voilà première étape fini, l’installation de php-fpm, je vais maintenant passer à la configuration de php-fpm.

Configuration de Php-fpm

Nous allons maintenant configurer Php-fpm. Comme je l’ai dit plus haut, php-fpm offre une meilleure gestion des processus. Il s’agit en fait de la gestion des processus par pool. Plusieurs paramètres peuvent être configurés par pool, l’utilisateur, le groupe, le nombre de processus fils …

Avant de commencer directement avec la configuration des pools, je vais activer la directive include. Cette directive permet d’ajouter facilement des configurations de pool. Il suffit d’ouvrir le fichier de configuration php-fpm.conf, et de décommenter la ligne include, et mettre en valeur le dossier dans lequel vous souhaitez créer les configurations de vos pools.

Je vais donc mettre en place un pool par site.

Voici le gabarit de configuration par défaut que je vais utiliser:

[default]
user = php-fpm-$pool
group = php-fpm-$pool

listen = /tmp/php-$pool.socket
listen.owner = httpd
listen.group = httpd
listen.mode = 0666

pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 5

La section (default) correspond au nom du pool. Dans les directives qui suivent, j’ai utilisé la variable $pool, qui est le nom défini pour le pool.
Explication de la configuration:

  • user/group correspond à l’utilisateur qui sera utilisé pour exécuter les processus php.
  • listen indique à php-fpm où écouter les requêtes. Deux possibilités s’offrent à nous, soit par socket ou par ip. Si le serveur http que vous utilisez se trouvent sur la même machine que votre serveur php-fpm je vous conseille de passer par des sockets pour éviter l’utilisation de la couche tcp-ip.
  • listen.{owner,group,mode} fixe les permissions du fichier pour une utilisation par socket, dans notre cas l’utilisateur qui écrira dans ce fichier est httpd.
  • pm cette directive qui signifie process manager, indique à php-fpm quel comportant devra suivre php-fpm pour ce pool. Php-fpm gére ses processus de 3 façons différentes:
    • static, qui signifie que le manager devra créer un nombre de processus fils défini, quelques soit la charge.
    • dynamic, comme son nom l’indique le nombre de processus fils pourra varier suivant la charge. Nous avons néanmois un contrôle sur le nombre de processus fils à créer au démarrage du serveur, le nombre de processus maximum …
    • ondemand, php-fpm ne crée pas de processus au démarrage du serveur, il n’en crée que si c’est nécessaire. Les processus créaient dans ce type de gestion auront une durée de vie défini par la directive pm.process_idle_timeout.

Il existe bien-sûr, beaucoup plus de directive que j’en ai présenté ici, la configuration de php-fpm pourrait faire l’objet d’un unique article.

Installation de Nginx

Comme toutes les installations, on commence par télécharger les sources, décompresser et compiler.

$> wget http://nginx.org/download/nginx-1.0.14.tar.gz
$> tar -xzvf nginx-1.0.14.tar.gz
$> cd nginx-1.0.14
$> ./configure
$> make && make install

Comme pour php-fpm nous allons affecter un utilisateur à Nginx.

$> useradd httpd
$> vim /usr/local/nginx/conf/nginx.conf

Dans le fichier de configuration de nginx il suffit de décommenter la ligne user et de lui affecter en valeur le nom de l’utilisateur que vous avez crée précédemment.

Contrairement à php-fpm, Nginx ne fournit pas de fichier init dans ses sources.
Il nous faudra donc le télécharger:

$> http://nginx-init-ubuntu.googlecode.com/files/nginx-init-ubuntu_v2.0.0-RC2.tar.bz2
$> tar xfv nginx-init-ubuntu_v2.0.0-RC2.tar.bz2
$> mv nginx /etc/init.d/nginx
$> update-rc.d -f nginx defaults

Attention, il vous faut modifier la variable DAEMON (ligne 70) dans le fichier /etc/init.d/nginx. Remplacer /usr/local/sbin/nginx donc par /usr/local/nginx/sbin/nginx.

Plus qu’a démarrer votre serveur et vérifier son bon fonctionnement:

$> /etc/init.d/nginx start
 * Starting NginxServer...    [ OK ]
$> wget localhost
--2012-03-15 21:34:38--  http://localhost/
Résolution de localhost... 127.0.0.1
Connexion vers localhost|127.0.0.1|:80... connecté.
requête HTTP transmise, en attente de la réponse... 200 OK
Longueur: 151 [text/html]
Sauvegarde en : «index.html»

100%[=======================>] 151         --.-K/s   ds 0s      

2012-03-15 21:34:38 (24,1 MB/s) - «index.html» sauvegardé [151/151]

Voilà, installation de Nginx terminée ! Nous allons maintenant attaquer les choses sérieuses, en branchant php-fpm à Nginx.

Configuration de Nginx

Mise en place des hôtes virtuels. Je vais reprendre le même principe qu’avec Apache. Nginx.conf sera mon fichier de configuration principal, et c’est à partir de ce fichier que je vais charger les configurations de mes sites.
Fichier de configuration Nginx (/usr/local/nginx/conf/nginx.conf):

user  httpd httpd; # User / Group

worker_processes  5; # nombre de worker a lancer par défaut

pid        /usr/local/var/run/nginx.pid; # Fichier pid

events {
    worker_connections  1024;
}

http {
    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  5;

    server_name_in_redirect off;

    gzip  on;

    index index.html index.htm index.php;

    error_page 400 /error/400.html;
    error_page 401 /error/401.html;
    error_page 403 /error/403.html;
    error_page 404 /error/404.html;
    error_page 405 /error/405.html;
    error_page 500 /error/500.html;
    error_page 502 /error/502.html;
    error_page 503 /error/503.html;

    client_max_body_size 28M;
    client_body_buffer_size 128k;

    # Chargement des configurations des sites actifs
    include /usr/local/nginx/sites-enabled/*;
}

La configuration de Nginx fera l’objet d’un article complet.

Création du dossier sites-enabled et sites-available:

$> mkdir /usr/local/nginx/sites-available/ # Contient les sites disponibles
$> mkdir /usr/local/nginx/sites-enabled/  # Contient les sites activés

Le dossier racine (www) par défaut de Nginx se trouve dans /path/to/nginx/html. Pour ma part je vais placer mes sites dans le dossier /opt/hosting/site_1 /opt/hosting/site_2.
Je commence donc par crée les dossiers:

$> mkdir /opt/hosting/site_1

Je vais ensuite crée un fichier de configuration default, qui sera le fichier de configuration par défaut de mes sites.
Voici la configuration par défaut que j’ai choisi pour le moment (/usr/local/nginx/sites-available/default):

server {
    listen 80; # Ecoute sur le port 80

    server_name default; # Nom du serveur

    root   /opt/hosting/default; # Dossier root du site

    error_log  /usr/local/var/log/nginx/default.error.log; # Log d'erreur
    access_log /usr/local/var/log/nginx/default.access.log; # Log d'accès

    # Location est l'équivalent du directory sur Apache

    # Interdit l'accès aux fichiers .* et désactivation des logs
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Désactivation des logs pour le favicon
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    # Désactivation des logs pour le robots.txt
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # Chargement du module fastcgi pour les fichiers php
    location ~ \.php$ {
        try_files $uri =404; # Si le fichier n'existe pas => 404
        include /usr/local/nginx/conf/fastcgi_params;
        fastcgi_pass unix:/tmp/php.socket;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_intercept_errors on;
    }
}

Voilà, pour mettre en place un nouveau site, il me suffit de copier le fichier de configuration par défaut de Nginx, et de remplacer les occurances default par le nom de mon site:

# Copie du fichier par défaut
$> cp /usr/local/nginx/sites-available/default /usr/local/nginx/sites-available/site_1
# Remplacement des occurances default par site_1
$> sed -i s/default/site_1/g /usr/local/nginx/sites-available/site_1
$> cd /usr/local/nginx/sites-enabled/
# Activation du site
$> ln -s ../sites-available/site_1
# Rechargement de la configuration Nginx
$> /etc/init.d/nginx reload

Bon maintenant pour tester le bon fonctionnement de mon site, je vais faire pointer le domaine site_1 en local et crée un fichier index.php dans le document_root de site_1:

$> echo "127.0.0.1       site_1" >> /etc/hosts
$> echo

site_1

 $> /opt/hosting/site_1/index.php $> 
wget site_1 
--2012-03-17 13:49:42-- http://site_1/ Résolution de site_1... 127.0.0.1 
Connexion vers site_1|127.0.0.1|:80... connecté. 
requête HTTP transmise, en attente de la réponse... 200 OK 
Longueur: non spécifié [text/html] 
Sauvegarde en : «index.html» [] 16 --.-K/s ds 0s 2012-03-17 13:49:42 (768 KB/s) - «index.html» sauvegardé [16]

Voilà tout est OK !

Bon on peut maintenant facilement automatiser l’ajout d’un nouveau site via quelques lignes de shell:

$> vim /usr/local/sbin/create_site.sh
if [ "$1" == "" ] ; then
    echo "server_name required";
    exit 1;
fi

DEFAULT_DOCUMENT_ROOT="/opt/hosting/";
DIR_NGINX="/usr/local/nginx/";
DIR_SITES_AVAILABLE=${DIR_NGINX}"sites-available/";
DIR_SITES_ENABLED=${DIR_NGINX}"sites-enabled/";
SITE_DEFAULT_CONF_NGINX="default";
SITE_NAME=${1};

$> echo "Create site "${SITE_TO_CREATE};
mkdir ${DEFAULT_DOCUMENT_ROOT}${SITE_NAME};
echo "

Welcome to ${SITE_NAME}

;" > ${DEFAULT_DOCUMENT_ROOT}{$SITE_NAME}"/index.html"; 
cp ${DIR_SITES_AVAILABLE}${DEFAULT_CONF_NGINX} ${DIR_SITES_AVAILABLE}${SITE_NAME}; 
sed -i s/${DEFAULT_CONF_NGINX}/${SITE_NAME}/g ${DIR_SITES_AVAILABLE}${SITE_NAME}; 
cd ${SITES_ENABLED}; 
ln -s ../${SITES_AVAILABLE}${SITE_NAME}; 
cd -; 
/etc/init.d/nginx reload;

Le script ci-dessus a été fait rapidement, vous poussez un peu les choses. Déjà en vérifiant que le site n’existe pas déjà, ensuite mettre des options comme l’activation de fastcgi ou non, activation du site ou non, on peut imaginer pas mal de choses.

Installation de Php et Nginx fait, je vais maintenant m’attaquer à l’installation de la base de données et du système de cache dans la seconde partie de cette article.

Category: Php