J'entends beaucoup parler de lighttpd, sur le fait qu'il soit léger et performant, Jusque maintenant je n'utilise exclusivement Apache pour mes serveurs http. Donc une procédure d'installation et quelques explications pour arriver à un serveur ouèbe avec support PHP fonctionnel.

1/ Installation de lighttpd

On commence comme d'habitude par récupérer les sources, j'ai inclue le support de mysql et OpenSSL, que j'ai déjà construit sur mon système, a vous d'adapter le configure en fonction de votre système. Idem pour les dépendances, c'est à vous de jouer.

# cd ~/work
# wget http://www.lighttpd.net/download/lighttpd-1.4.18.tar.bz2
# tar xvjf ~/lighttpd-1.4.18.tar.bz2
# cd lighttpd-1.4.18/
./configure --prefix=/applis/lighttpd-1.4.18 \
--enable-lfs \
--disable-ipv6 \
--with-mysql=/applis/mysql/bin/mysql_config \
--with-attr \
--with-openssl=/applis/openssl \
--with-openssl-includes=/applis/openssl/include \
--with-pcre \
--with-memcache

On installe :

# make && make install

2/ Configuration de lighttpd :

Par habitude, je place toujours mes fichiers de configurations dans etc du répertoire de l'applicatif et non dans /etc, à vous de voir et d'adapter les fichiers de conf. en fonction.

# vi /applis/lighttpd-1.4.18/etc/lighttpd.conf

Ce qui donne pour un lighttpd relativement minimaliste et limité ne fonctionnalitées

# =====================================
# Main configuration
# =====================================

server.port = 8080
server.bind = "0.0.0.0"
server.pid-file = "/var/run/lighttpd.pid"
server.username = "httpd"
server.groupname = "httpd"
static-file.exclude-extensions = ( ".fcgi", ".rb", "~", ".inc" )
index-file.names = ( "index.html")
server.tag = "httpd"
url.access-deny = ( "~", ".inc", ".bak", ".swap", ".old" )
dir-listing.activate = "disable"
compress.filetype = ( "text/plain", "text/html", "text/css", "text/javascript" )
compress.cache-dir = "/tmp/lighttpd"
server.document-root = "/var/web/park"

# =====================================
# Modules
# =====================================

server.modules = (
        "mod_access",
        "mod_accesslog",
        "mod_compress"
)

# =====================================
# Logs
# =====================================

accesslog.filename = "/var/log/lighttpd/access.log"
server.errorlog = "/var/log/lighttpd/error.log"

# =====================================
# Type mime
# =====================================

mimetype.assign = (
        ".css" =>  "text/css",
        ".gif" =>  "image/gif",
        ".htm" =>  "text/html",
        ".html" =>  "text/html",
        ".jpeg" =>  "image/jpeg",
        ".jpg" =>  "image/jpeg",
        ".js" =>  "text/javascript",
        ".png" =>  "image/png",
        ".swf" =>  "application/x-shockwave-flash",
        ".txt" =>  "text/plain"
)

Comme prévu, la configuration n'est pas très fournie mais suffit déjà à fournir du contenu statique, alors quelques explications sommaires :

  • On bind sur le port 8080
  • On écoute sur toutes les interfaces
  • On fait tourner lighttpd sous le compte httpd:httpd

Pour les créer :

# groupadd httpd
# useradd -c "httpd user" -d /dev/null -s /bin/false -g httpd httpd
  • On interdit le traitement par lighttpd des .fcgi, etc.
  • On interdit le listage des répertoires (si pas de document d'index)
  • l'index sera index.html
  • On interdit aux visiteurs l'accès à certains fichiers qui pourraient trainer sur le server ( .swp, .bak, etc.)
  • On précise quels type de fichiers on souhaite compresser et où les fichiers compressés seront stockés.
  • le server.document-root est le répertoire par défaut pour les fichiers
  • En ce qui concerne les modules, on est au minimum pour supporter ce fichier de conf,
  • On précise où journaliser l'activité des pages servies.
  • On précise le type mime des fichiers que l'on va servir aux navigateurs,

Et c'est tout :) Bien sur on est loin de tout ce que peut faire lighttpd mais cette conf est un bon début simple, compréhensible et légé. on en verra un peu plus après.

3/ Support de PHP

Pour le PHP, on n'est pas comme sous apache avec la possibilité d'ajouter le support sous forme de module, il va falloir passer par les CGI, en l'occurence ici, on sera en FastCGI, une des petites différences entre les deux ( en gros ) est que FastCGI va garder les scripts en mémoire évitant ainsi au serveur de les recharger et recompiler comme peut le faire CGI, on y gagne en performance, donc on se prive pas. Il faut juste savoir que vous avez plusieurs possibilités, le site officiel explique toutes façons de faire.

On va donc construire php avec le support du FastCGI :

# cd ~/work
# wget http://fr2.php.net/get/php-5.2.5.tar.bz2/from/fr.php.net/mirror
# tar xvjf php-5.2.5.tar.bz2
# cd php-5.2.5

En passant on ajoute le support pour MySQL et OpenSSL préalablement installés sur mon système, à adapter donc :

./configure --prefix=/applis/php-5.2.5 \
--enable-fastcgi \
--enable-discard-path \
--enable-force-cgi-redirect \
--with-mysql=/applis/mysql \
--with-mysql-sock=/tmp/mysql.sock \
--with-mysqli=/applis/mysql/bin/mysql_config \
--enable-mbstring \
--enable-bcmath \
--with-gd=/applis/gd \
--with-zlib

4/ Support de PHP dans lighttpd

Maintenant, on va ajouter le support, donc on remet la tête dans la configuration de lighttpd et on y ajoute/modifie :

On commence par ajouter le support du mod_fastcgi :

server.modules = (
        "mod_access",
        "mod_accesslog",
        "mod_compress",
        "mod_fastcgi"
)

On ajoute les directives pour supporter le PHP à proprement parler :

fastcgi.server = ( ".php" =>
        ((
                "bin-path" => "/applis/php-5.2.5-fcgi/bin/php-cgi",
                "socket" => "/var/tmp/php.socket",
                "max-procs" => 2,
                "idle-timeout" => 10,
                "bin-environment" => (
                        "PHP_FCGI_CHILDREN" => "16",
                        "PHP_FCGI_MAX_REQUESTS" => "10000"
                ),
                "bin-copy-environment" => (
                        "PATH", "SHELL", "USER"
                ),
                "broken-scriptfilename" => "enable"
        ))
)
  • max-procs : Nombre maximal de process lancés
  • PHP_FCGI_CHILDREN : Nombre maximal d'enfants par process
  • PHP_FCGI_MAX_REQUESTS : Nombre maximal de requêtes traitées par le serveur CGI

Modifier également la directive index-file.names histoire de pouvoir servir des sites avec index.php comme index, ca peut servir :)

index-file.names = ( "index.html", "index.php")

On se créé une page de test :

# echo "<?php phpinfo() ?>" > /var/web/park/info.php
# pkill -HUP lighttpd

Vous pouvez vérifier avec votre browser si tout va bien.

5/ Script d'init

Bon un petit script d'init écrit maison, vous pouvez l'enrichir de tests parce qu'il reste assez sommaire en l'état actuel :

#!/bin/sh
PATH=/applis/*/bin:/applis/*/sbin:/sbin:/bin:/usr/sbin:/usr/bin

[[ ! -f /applis/lighttpd/etc/lighttpd.conf ]] && echo -e "Pas de fichier de configuration"
[[ ! -x /applis/lighttpd/sbin/lighttpd ]] && echo -e "Lighttpd non executable"

LIGHTTPD_CONF="/applis/lighttpd/etc/lighttpd.conf"
LIGHTTPD="/applis/lighttpd/sbin/lighttpd"
LIGHTTPD_PID="/var/run/lighttpd.pid"

case "$1" in
        start)
                echo -e "Start de lighttpd... "
                start-stop-daemon --start --quiet --exec "${LIGHTTPD}" \
                --pidfile "${LIGHTTPD_PID} " -- -f "${LIGHTTPD_CONF}"
                ;;

        stop)
                echo -e "Arret de lighttpd... "
                start-stop-daemon --stop --quiet --pidfile "${LIGHTTPD_PID}"
                ;;

        reload)
                echo -e "Reload de lighttpd..."
                start-stop-daemon --stop --oknodo --quiet --pidfile "${LIGHTTPD_PID}" \
                --signal HUP
                ;;

        graceful)
                echo -e "Graceful restart de lighttpd..."
                start-stop-daemon --stop --oknodo --quiet --pidfile "${LIGHTTPD_PID}" \
                --signal INT
                ;;

        restart)
                echo -e "Restart de lighttpd..."
                start-stop-daemon --stop --quiet --pidfile "${LIGHTTPD_PID}"
                sleep 1
                start-stop-daemon --start --quiet --exec "${LIGHTTPD}" \
                --pidfile "${LIGHTTPD_PID} " -- -f "${LIGHTTPD_CONF}"
                ;;

        *)
                echo -e " Usage :"
                echo -e " start : start du serveur lighttpd"
                echo -e " stop : arret du serveur lighttpd"
                echo -e " reload : rachargement de lighttpd"
                echo -e " graceful : redemarrage graceful de lighttpd"
                exit 1
                ;;
esac

exit 0

Le rendre executable :

# chmod +x /etc/init.d/lighttpd

6/ Assurer le démarrage/arrêt avec le système :

# update-rc lighttpd start 70 2 3 4 5 . stop 30 0 6 .

7/ VirtualHost Le support des VirtualHost dans lighttpd est vraiment bien foutu, j'aime beaucoup le principe. En fait il y a deux modules qui permettent la gestion des VirtualHost.

  • mod_simple_vhost

Directives simples pour créer un vhost.

simple-vhost.server-root = "/var/web/"
simple-vhost.default-host = "www.toto.org"
simple-vhost.document-root = "/"

$HTTP["host"] == "www\.toto\.org" {
        server.document-root = "/var/web/www.toto.org/"
  • mod_evhost

Avec le module de vhosts "enhenced", on peut utiliser des patterns pour faire pointer les requêtes vers des vhosts en fonction du HOST de la requête, c'est une manière très souple de composer les vhosts.... enfin je trouve.

%% => % sign
%0 => domain name + tld
%1 => tld
%2 => domain name without tld
%3 => subdomain 1 name
%4 => subdomain 2 name

Par exemple :

$HTTP["host"] =~ "users\.example\.org" {
    evhost.path-pattern = "/home/%4/public_html/"
}

Donne :

http://johndoe.users.example.org/ => /home/johndoe/public_html/

Ou encore :

var.basedir = "/var/web"
evhost.path-pattern = var.basedir + "/%2/"

Donne :

http://www.toto.org/ => /var/web/toto

Enfin voilà, le principe quoi :) Une chose importante que je n'ai pas abordé mais qui se voit est surtout le fait de pouvoir utiliser des expressions régulières dans la configuration, chose intéressante qui accroit la souplesse/puissance de la configuration. Je vous laisse découvrir tout ca.

8/ Configuration globale :

# =====================================
# Main configuration
# =====================================

server.port = 8080
server.bind = "0.0.0.0"
server.pid-file = "/var/run/lighttpd.pid"
server.username = "apache"
server.groupname = "apache"
static-file.exclude-extensions = ( ".fcgi", ".rb", "~", ".inc" )
index-file.names = ( "index.html", "index.php")
server.tag = "Apache 1.3.39"
url.access-deny = ( "~", ".inc", ".bak", ".swap", ".old" )
dir-listing.activate = "disable"
compress.filetype        = ( "text/plain", "text/html", "text/css", "text/javascript" )
compress.cache-dir = "/tmp/lighttpd"
server.document-root = "/var/web/park"

# =====================================
# Modules
# =====================================

server.modules = (
        "mod_access",
        "mod_accesslog",
        "mod_simple_vhost",
        "mod_compress",
        "mod_fastcgi"
)

# =====================================
# Logs
# =====================================

accesslog.filename = "/var/log/lighttpd/access.log"
server.errorlog = "/var/log/lighttpd/error.log"

# =====================================
# Type mime
# =====================================

mimetype.assign = (
        ".css"        =>  "text/css",
        ".gif"        =>  "image/gif",
        ".htm"        =>  "text/html",
        ".html"       =>  "text/html",
        ".jpeg"       =>  "image/jpeg",
        ".jpg"        =>  "image/jpeg",
        ".js"         =>  "text/javascript",
        ".png"        =>  "image/png",
        ".swf"        =>  "application/x-shockwave-flash",
        ".txt"        =>  "text/plain"
)

# =====================================
# FastCGI / PHP
# =====================================

fastcgi.server = ( ".php" =>
        ((
                "bin-path" => "/applis/php-5.2.5/bin/php-cgi",
                "socket" => "/var/tmp/php.socket",
                "max-procs" => 2,
                "idle-timeout" => 10,
                "bin-environment" => (
                        "PHP_FCGI_CHILDREN" => "16",
                        "PHP_FCGI_MAX_REQUESTS" => "10000"
                ),
                "bin-copy-environment" => (
                        "PATH", "SHELL", "USER"
                ),
                "broken-scriptfilename" => "enable"
        ))
)

# =====================================
# Vhosts
# =====================================

simple-vhost.server-root = "/var/web/"
simple-vhost.default-host = "www.toto.org"
simple-vhost.document-root = "/"

$HTTP["host"] == "www\.toto\.org" {
        server.document-root = "/var/web/www.toto.org/"

}

Pour finir, voilà pour la petite intro sur lighttpd qui mérite vraiment le détour, consultez la doc officielle pour l'exploiter correctement, car je n'ai fait qu'aborder le minimal de ce que peut faire lighttpd.