Séparation des applications avec PHP-FPM et Nginx

Voici un petit billet technique sur l’administration de serveur Web, plus précisément sur comment configurer PHP et Nginx en isolant les applications (j’utilise OpenBSD mais ça devrait fonctionner sur GNU/Linux également).

L’idée consiste à créer une configuration PHP-FPM par application PHP.

Cela apporte deux grands intérêts:

  • Avec PHP-FPM il est possible de configurer +/- de ressource par application.
  • Sécurité:
    • Les applications ne partage pas le même espace mémoire, en cas de faille les risques sont réduit.
    • Les applications peuvent être associées à des utilisateurs système différents: séparation des privilèges.

En pratique voilà comment ça se présente, par exemple pour l’application dokuwiki.

  • La configuration de Nginx:
        location ~ ^/wiki/(data|conf|bin|inc)/ {   # secure DokuWiki
            deny all;
        }

        location ~ ^/wiki/(README|VERSION|COPYING)$ {
            deny all;
        }

        location ~ ^/wiki/.+\.php$ {
            root           /var/www/htdocs;
            fastcgi_pass   unix:run/php-wiki.sock;
            fastcgi_index  index.php;
            include        fastcgi_params;
        }

        location ~ ^/wiki/ {
              index doku.php;
              try_files $uri $uri/ @dokuwiki;
        }

        location @dokuwiki {
            rewrite ^/wiki/_media/(.*) /wiki/lib/exe/fetch.php?media=$1 last;
            rewrite ^/wiki/_detail/(.*) /wiki/lib/exe/detail.php?media=$1 last;
            rewrite ^/wiki/_export/([^/]+)/(.*) /wiki/doku.php?do=export_$1&id=$2 last;
            rewrite ^/wiki/(.*) /wiki/doku.php?id=$1 last;
        }

        # Files (statics)
        location ~/files/ {
            autoindex on;
            autoindex_exact_size off;
            expires 1d;
        }

La ligne importante est : fastcgi_pass unix:run/php-wiki.sock , la socket PHP php-wiki.sock est exécuté que pour cette application.

Ensuite, il faut créer la configuration php-fpm associée dans /usr/local/etc/fpm.d/. Le fichier doit se terminer en .conf, par exemple wiki.conf:

[wiki]

user = www-wiki
group = www-wiki

listen = /var/www/run/php-wiki.sock

pm = dynamic
pm.max_children = 128
pm.start_servers = 32
pm.min_spare_servers = 16
pm.max_spare_servers = 64

chroot = /var/www

php_flag[display_errors] = off
php_value[session.cookie_path] = '/wiki/'
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 128M
php_value[session.save_path]= "0;/tmp-wiki"

www-wiki est l’utilisateur système créé spécifiquement pour dokuwiki. Il a les mêmes caractéristiques que www (home dans /var/www, pas de login, etc..).

Pour la configuration des threads se reporter à la doc.

Donner les droits à l’utilisateur www-wiki sur le répertoire de l’installation. Créer un répertoire /var/www/tmp-wiki pour les sessions et donner les droits en écriture à l’utilisateur www-wiki.

Voilà c’est terminé, il suffit de reproduire ça pour chaque application PHP installée sur le serveur.

Cette technique peut également être utilisée pour proposer un hébergement mutualisé, chaque utilisateur aura sa propre instance de PHP-FPM.

Côté performance c’est très intéressant, cela permet de repartir la charge suivant l’utilisation et l’exposition des applications.