Varnish-php-fpm-nginx

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
Fiche express
Type Architecture de stack complète (cache + reverse proxy + PHP)
Composants Varnish, Nginx, PHP-FPM, MariaDB
Voir aussi Varnish · Php-fpm · Nginx · Proxy nginx

Exemple historique d'installation d'une stack complète associant Varnish (cache HTTP en frontal), Nginx (serveur web / TLS), PHP-FPM (exécution PHP) et MariaDB (base de données), typique d'un hébergement d'application PHP (ex. MediaWiki) sous forte charge en lecture.

Cette page décrit une installation d'origine CentOS 6 : plusieurs éléments sont datés (dépôt MariaDB 10.0, extension php-mcrypt retirée de PHP depuis la version 7.2, CentOS 6 en fin de vie depuis fin 2020). Elle reste utile pour comprendre l'architecture de la chaîne cache/proxy/PHP, mais toute installation neuve doit se référer à la documentation actuelle de chaque composant plutôt qu'aux commandes ci-dessous telles quelles.

Architecture

Le trafic HTTP en clair (susceptible d'être mis en cache) passe par Varnish, qui transmet à Nginx sur un port interne ; le trafic HTTPS est terminé directement par Nginx sans passer par le cache (voir la mise en garde équivalente sur Proxy nginx) :

Client HTTP  → Varnish (:80)     → Nginx (127.0.0.1:8080) → PHP-FPM (socket) → application
Client HTTPS → Nginx (:443, TLS, bypass du cache) → PHP-FPM (socket) → application

Prérequis PHP

yum -y install git epel-release php-pear php-imap php-cli php-devel php-gd php-pdo php-fpm php-process php-mysql php-intl php-mbstring php-common php php-xml php-xmlrpc ImageMagick

(L'extension php-mcrypt de la liste d'origine a été retirée : mcrypt est abandonné et absent de PHP depuis la 7.2 — utiliser openssl/sodium côté applicatif à la place.)

MariaDB

Dépôt (exemple historique CentOS 6 — sur un système actuel, utiliser le dépôt officiel à jour ou le paquet de la distribution) :

[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.0/centos6-amd64
gpgkey = https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck = 1
yum install mariadb mariadb-server mysql

/etc/my.cnf.d/server.cnf :

[mysqld]
bind-address = 127.0.0.1
systemctl restart mariadb
mysql_secure_installation

Répondre "oui" à toutes les questions de mysql_secure_installation (mot de passe root, retrait des comptes anonymes, interdiction de la connexion root distante, retrait de la base de test).

Nginx

yum install nginx

Adapter le nombre de workers au nombre de CPU disponibles :

grep -c processor /proc/cpuinfo

/etc/nginx/nginx.conf :

worker_processes  2;
include /etc/nginx/sites-enabled/*;
http {
    server_tokens   off;   # ne pas exposer la version de Nginx
}

Réduction du bruit de log et durcissement basique (extrait de configuration à inclure) :

location = /robots.txt  { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
location ~ /\.          { access_log off; log_not_found off; deny all; }
location ~ ~$           { access_log off; log_not_found off; deny all; }

Exemple de vhost PHP

server {
    server_name mondomaine.tld;
    listen 127.0.0.1:8080;
    root /srv/www/mondomaine.tld;
    access_log /var/log/nginx/mondomaine.tld-access.log;
    error_log /var/log/nginx/mondomaine.tld-error.log;
    index index.php;

    location / {
        try_files  $uri $uri/ /index.php?$args;
    }

    location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
        access_log off;
        expires max;
    }
    location ~ /\.ht {
        deny  all;
    }
    location ~ \.php {
        try_files $uri = 404;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

PHP-FPM

yum install php-fpm php-mysql

/etc/php.ini — points clés :

date.timezone = Europe/Paris
memory_limit = 128M
expose_php = Off
session.save_path = "/var/lib/php/session"
chown -R nginx:nginx /var/lib/php/session

/etc/php-fpm.d/www.conf — faire tourner le pool sous l'utilisateur Nginx, et utiliser un socket Unix plutôt que TCP (légèrement plus rapide, pas de port réseau exposé) :

user = nginx
group = nginx
listen = /var/run/php-fpm/php-fpm.sock
chown nginx:root -R /var/log/php-fpm/
systemctl enable --now php-fpm

Voir Php-fpm pour le détail de la configuration du pool.

Varnish

yum install varnish

Point d'attention : Varnish ne gère pas nativement TLS — il faut un frontal TLS devant lui, ou (comme ici) le placer en frontal HTTP pur pendant que Nginx gère HTTPS séparément sur le même serveur (voir l'architecture ci-dessus).

/etc/varnish/default.vcl, avec des adaptations pour un site type MediaWiki :

vcl 4.0;

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

sub vcl_recv {
    set req.http.X-Forwarded-For = client.ip;
    set req.backend_hint = default;

    if (req.method != "GET" && req.method != "HEAD" &&
        req.method != "PUT" && req.method != "POST" &&
        req.method != "TRACE" && req.method != "OPTIONS" &&
        req.method != "DELETE") {
        return (pipe);
    }

    if (req.method != "GET" && req.method != "HEAD") {
        return (pass);
    }

    if (req.http.Authorization || req.http.Cookie) {
        return (pass);
    }

    if (req.http.If-None-Match) {
        return (pass);
    }

    if (req.http.Accept-Encoding) {
        if (req.http.User-Agent ~ "MSIE 6") {
            unset req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        } else {
            unset req.http.Accept-Encoding;
        }
    }

    return (hash);
}

sub vcl_backend_response {
    set beresp.grace = 120s;
    if (beresp.ttl < 48h) {
        set beresp.uncacheable = true;
        return (deliver);
    }
    if (!beresp.ttl > 0s) {
        set beresp.uncacheable = true;
        return (deliver);
    }
    if (beresp.http.Set-Cookie) {
        set beresp.uncacheable = true;
        return (deliver);
    }
}

sub vcl_deliver {
    # Point d'extension : accounting, ajout d'en-têtes de debug (X-Cache…), etc.
}

Ajouter l'utilisateur Nginx au groupe Varnish si nécessaire (accès au socket de contrôle) :

usermod -aG varnish nginx

Paramètres de démarrage

CentOS 6 :

vi /etc/sysconfig/varnish

CentOS 7+ :

vi /etc/varnish/varnish.params
VARNISH_LISTEN_ADDRESS=<IP_d_ecoute>
VARNISH_LISTEN_PORT=80
systemctl enable --now varnish

Vérification

chown -R nginx:nginx /var/www/
curl -I http://203.0.113.10

(La valeur d'origine de cette page — une IP publique réelle — a été génériquée en adresse de documentation RFC 5737.)

Voir aussi

  • Varnish — présentation détaillée du cache et de ses commandes (varnishstat, varnishlog...)
  • Php-fpm — configuration détaillée du pool PHP-FPM
  • Nginx — serveur web / TLS
  • Proxy nginx — reverse proxy Nginx seul, sans Varnish