Mise à jour 24/01/2016 : Mise à jour vers la version 1.9.9 d’NGINX et merci à hokydok pour les retours d’erreurs et suggestions
Voilà 5 mois que j’étais sur la configuration Varnish+NGINX+PHP-FPM+APC que j’ai expliqué en détails dans un précédent article. Cette configuration ne me convenait plus car j’étais dépendant des mises à jours stables venant d’une distriburion plus trop à jour d’Ubuntu 14.10. Je voulais aller plus loin et utiliser les toutes dernières versions d’NGINX de PHP.
Alors ce n’est pas pour dire que l’ancien tutoriel est mauvais non non, c’est juste qu’il utilise des paquets stables et disponibles dans les repositories d’Ubuntu ou Debian. C’est plutôt conseillé mais si vous voulez aller plus loin dans les perfs, il suffit de récupérer les dernières versions. Je me suis mis donc dans le but de me faire ma configuration ultime, et de vous la faire partager ici tout en confirmant la stabilité et la rapidité de celle ci !
Hormis avoir les dernières versions, il y a plusieurs intérêts à ça. Déjà NGINX dans sa version 1.9.5 sortie en octobre 2016 inclus le module HTTP/2, cette nouvelle version de protocole que j’ai instauré sur le site récemment et qui va révolutionner un peu le Web d’aujourd’hui (pour la faire simple, l’affichage des pages se feront sans vérification des paquets entrants, ce qui aboutira à un chargement bien plus rapide et sans éventuels blocages).
L’autre intérêt, toujours chez NGINX, c’est d’y intégrer le module Google Pagespeed alias PSOL. Ce dernier qui sert à optimiser le rendu des pages de manière automatique (et discrète) ne pourra se faire qu’en compilant la dernière version d’NGINX avec la dernière version de pagespeed.
Vous êtes prêt ?
Sommaire
- Pré-requis
- Conseil
- Installation de NGINX + Pagespeed compilé
- Configuration de NGINX avec http2 et pagespeed sur un nom de domaine
- Installation de PHP-FPM via dotdeb
- Résultats PageSpeed
- Conclusion
Pré-requis
Les quelques pré-requis qui diffèrent un peu de l’ancien tutoriel (et oui on peut changer)
- Distribution Debian 8 Jessie au minimum, pour sa simplicité et sa légèreté. Une distribution Ubuntu Server ou équivalent Debian est toujours possible mais je vous conseille d’avoir une distribution sans fioriture puisqu’on va y rajouter des repositories récents.
- Pas d’autre obligations, on installera le nécessaire (PHP, MySQL) et vous ferez ce que vous voudrez ensuite
- On reste sur la base d’afficher un site compatible PHP 5.6, ça peut être un WordPress par exemple.
- Je vous conseille de sauvegarder vos données, allez voir dans l’ancien tuto pour une petite commande sympa de transfert entre terminaux ssh
Conseil
J’ai fait une copie complète de mon site actuel sur un second serveur dédié, comme ça j’ai pu faire mes propres tests tout en m’assurant que mon site soit toujours accessible. Je vous conseille d’éviter de mettre votre site down si vous faites une migration. Revoir l’ancien article pour sauvegarder votre site sur un autre serveur. Je privilégie une installation fraîche sur un OS tout juste installé, mais c’est tout à fait possible de faire cohabiter NGINX / Varnish avec Apache le temps de faire changer de serveur Web à votre site.
Remarque : je n’utilises plus Varnish et Cloudflare par rapport à l’ancien tutoriel. Pour Varnish, tout simplement parce que le gain de performance est nul, le SSD de mon serveur couplé à Nginx suffit à charger les ressources rapidement. Cloudflare c’est au niveau des redirections en boucles HTTPS > HTTP > HTTPS, je n’ai pas du tout réussi à stopper ce mécanisme, sauf en mettant en pause.
Installation de NGINX + Pagespeed
Nous allons compiler la dernière version d’NGINX (qui est compatible avec HTTP/2 et n’utilise plus SPDY). Pensez à supprimer (apt-get remove nginx) votre ancienne version si installée. On installe tout ce qu’il faut pour compiler :
su # puis votre password root
apt-get -y install build-essential zlib1g-dev libpcre3 libpcre3-dev unzip git libbz2-dev libssl-dev tar libfcgi-dev libfcgi0ldbl libjpeg62-turbo-dbg libmcrypt-dev libssl-dev libc-client2007e libc-client2007e-dev
Ensuite, nous passons au téléchargement d’NGINX et de Pagespeed. Pour ce là, nous allons dans un répertoire non utilisé comme /tmp ou /root afin de faire nos actions. Ce tutoriel a été mis à jour en janvier 2016, la version finale à ce moment est la version 1.9.9, mais vous trouverez la dernière version ici.
cd /root
wget http://nginx.org/download/nginx-1.9.9.tar.gz
tar -xzvf nginx-1.9.9.tar.gz
Téléchargement de Pagespeed, restez toujours dans le répertoire. La version actuelle est là 1.9.32.10, rendez-vous ici pour connaître la dernière version, il suffira de remplacer la version dans la requête wget :
git clone https://github.com/pagespeed/ngx_pagespeed.git
cd /root/ngx_pagespeed/
wget https://dl.google.com/dl/page-speed/psol/1.9.32.10.tar.gz
tar -xzvf 1.9.32.10.tar.gz
La compilation est prête, on configure et on lance l’installation (qui peut prendre quelques minutes) :
cd /root/nginx-1.9.9
./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/access.log --user=www-data --group=www-data --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --add-module=/root/ngx_pagespeed --with-mail_ssl_module --with-mail --with-http_v2_module
make
make install
La compilation peut prendre un moment… Pour terminer la partie NGINX, il va falloir créer un service pour le démarrer à chaque lancement du serveur. Rien de plus simple (lol) sur une distrib debian :
nano /lib/systemd/system/nginx.service
Ce fichier contiendra :
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Ensuite, on démarre le service et on lance le service :
systemctl start nginx
systemctl enable nginx
Vous avez fait le plus dur… Maintenant, allez vous chercher une bière ou faites vous un thé, ça devrait être plus cool 🙂
Promis c’est la seule chose que vous allez compiler.
Configuration de NGINX pour un nom de domaine
Maintenant je vais voir avec vous la configuration la plus simple d’nginx possible. On part du principe que vous avez déjà un certificat SSL pour faire de l’http/2. On va rediriger donc ce qu’il y a dans le port 80 vers le 443 (https) pour un nom de domaine donné, puis nous activerons http2 et pagespeed dessus.
Si vous n’avez pas de certificat SSL, vous aller simplement ignorer la partie redirection et tout faire dans le port 80, enfin tout non vous ne pourrez pas activer http2, simplement pagespeed 🙂
cd /etc/nginx
mkdir sites
nano nginx.conf
Ici on va remplacer par une configuration standard, on mettra nos sites dans ./sites/fichier1 ./sites/fichier2 etc. Je vous conseille par exemple de faire un /var/www/index.php contenant phpinfo() afin de tester après avoir installé php5. Voici le contenu de nginx.conf :
user www-data;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#access_log logs/access.log main;
server_tokens off;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name localhost;
root /var/www;
location / {
index index.php index.html index.htm;
}
location ~ \.php(?:$|/) {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
include /etc/nginx/sites/*;
}
On se dirige ensuite dans le dossier sites/ pour ajouter la configuration pour un nom de domaine précis :
cd /etc/nginx/sites
nano default
Voici le contenu du fichier default. Pour un nom de domaine donné, il redirigera le http port 80 vers le https port 443. Puis dans la partie listen du port 443, nous activerons http2. Nous ajoutons des paramètres ssl pour y insérer les certificats (ssl_certificate) et la clé privée (ssl_certificate_key). Et enfin nous activons pagespeed, avec d’autres paramètres qui créeront des dossiers de cache ou vous n’aurez rien à faire à part profiter de ses performances finales :
Remarque : je suis parti du principe que le site se situe dans /home/monsite, il peut très bien se trouver ailleurs comme /var/www. Si vous avez plusieurs sites, je vous conseille de créer un utilisateur par site, et ainsi avoir tous vos sites dans /home. Pour créer un utilisateur un simple « adduser <nouveau_nom> » suffit.
server {
listen 80;
server_name monsite.com www.monsite.com *.monsite.com;
return 301 https://www.monsite.com$request_uri;
}
server {
listen 443 default_server ssl http2;
server_name monsite.com www.monsite.com *.monsite.com;
ssl_certificate /home/monsite/ssl/monsite.pem;
ssl_certificate_key /home/monsite/ssl/monsite.key;
if ($ssl_protocol = "") {
rewrite ^ https://$server_name$request_uri? permanent;
}
#ssl_session_cache shared:SSL:1m;
#ssl_session_timeout 5m;
#ssl_ciphers HIGH:!aNULL:!MD5;
#ssl_prefer_server_ciphers on;
proxy_set_header X_FORWARDED_PROTO https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Url-Scheme $scheme;
proxy_redirect off;
proxy_max_temp_file_size 0;
root /home/monsite/www;
client_max_body_size 128M;
pagespeed on;
pagespeed FileCachePath /var/cache/nginx-pagespeed;
location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" {
add_header "" "";
}
location ~ "^/ngx_pagespeed_static/" { }
location ~ "^/ngx_pagespeed_beacon$" { }
location / {
index index.php index.html index.htm;
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php(?:$|/) {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
location ~ /nginx.conf {
deny all;
}
include /home/monsite/www/nginx.conf;
}
Vous avez remarqué déjà que j’ai indiqué des paramètres pour PHP, notamment celui d’écouter le port 9000. PHP va donc devenir un service, mais rien ne changera dans ces performances.
Maintenant, comme ce tuto est un peu basé sur ma propre configuration, je vous montre mon fichier nginx.conf que j’inclus à la fin du fichier default et qui a été généré par le module W3 total cache sur mon site wordpress. Vous pouvez très bien les intégrer dans le fichier de conf de votre site, à l’intérieur de « server » :
# BEGIN W3TC Browser Cache
gzip on;
gzip_types text/css text/x-component application/x-javascript application/javascript text/javascript text/x-js text/richtext image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon;
location ~ \.(css|htc|less|js|js2|js3|js4)$ {
expires 31536000s;
add_header Pragma "public";
add_header Cache-Control "max-age=31536000, public";
add_header X-Powered-By "W3 Total Cache/0.9.4.1";
}
location ~ \.(html|htm|rtf|rtx|svg|svgz|txt|xsd|xsl|xml)$ {
expires 86400s;
add_header Pragma "public";
add_header Cache-Control "max-age=86400, public";
add_header X-Powered-By "W3 Total Cache/0.9.4.1";
}
location ~ \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|json|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|otf|odb|odc|odf|odg|odp|ods|odt|ogg|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|tif|tiff|ttf|ttc|wav|wma|wri|woff|xla|xls|xlsx|xlt|xlw|zip)$ {
expires 31536000s;
add_header Pragma "public";
add_header Cache-Control "max-age=31536000, public";
add_header X-Powered-By "W3 Total Cache/0.9.4.1";
}
# END W3TC Browser Cache
# BEGIN W3TC Minify core
rewrite ^/wp-content/cache/minify.*/w3tc_rewrite_test$ /wp-content/plugins/w3-total-cache/pub/minify.php?w3tc_rewrite_test=1 last;
rewrite ^/wp-content/cache/minify/(.+/[X]+\.css)$ /wp-content/plugins/w3-total-cache/pub/minify.php?test_file=$1 last;
rewrite ^/wp-content/cache/minify/(.+\.(css|js))$ /wp-content/plugins/w3-total-cache/pub/minify.php?file=$1 last;
# END W3TC Minify core
N’oubliez pas enfin de mettre les bons droits d’exécution sur votre dossier www, avec du chmod 644 au minimum :
chown www-data:www-data -Rf /var/www #ou votre répertoire de site
chmod 755 -Rf /var/www #ou votre répertoire de site
Installation de PHP-FPM via dotdeb
Un moyen simple d’obtenir la dernière version de PHP sous debian ou ubuntu est d’utiliser les repositories de dotdeb :
nano /etc/apt/sources.list
Ajoutez les repositories suivants (pour Debian 8 jessie) ou Ubuntu 15.X, voir ici pour les autres versions) :
deb http://packages.dotdeb.org jessie all deb-src http://packages.dotdeb.org jessie all
Installez la clé GnuPEG pour activer les paquets dotdeb :
wget https://www.dotdeb.org/dotdeb.gpg sudo apt-key add dotdeb.gpg
On met à jour le serveur et on installe les composants de php5 fpm :
apt-get update
apt-get upgrade
apt-get install libapache2-mod-php5 php5 php5-cgi php5-cli php5-common php5-curl php5-dev php5-gd php5-imagick php5-mcrypt php5-mysql php5-pgsql php5-memcached php5-fpm php5-common php5-xcache php5-curl php5-intl php5-sqlite php5-xmlrpc php5-xsl php5-gd
Normalement tout devrait bien se passer, installez vos modules préférés (php5-pear…). Ensuite il faut configurer php5 pour qu’il soit écouté sur le port 9000 :
nano /etc/php5/fpm/pool.d/www.conf
Voici les paramètres à changer :
[www]
listen = 127.0.0.1:9000
user = www-data
group = www-data
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 0
# à la fin :
php_flag[display_errors] = off
php_admin_value[error_reporting] = 0
php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 256M
php_admin_value[session.save_path] = /tmp/
PHP5-FPM vient avec le module opcache, vous pouvez normalement l’activer dans php.ini :
nano /etc/php5/fpm/php.ini
Trouvez (Ctrl+W) opcache.enable et changez les valeurs suivantes :
short_open_tag = Off
ignore_user_abort = Off
post_max_size = 128M
upload_max_filesize = 128M
default_charset = "UTF-8"
allow_url_fopen = Off
default_socket_timeout = 30
mysql.allow_persistent = Off
date.timezone = Europe/Paris #ou votre propre région
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=5000
opcache.revalidate_freq=60
opcache.fast_shutdown=0
Voilà, redémarrer les services php5-fpm et nginx et ça devrait prendre forme…
service php5-fpm restart
service nginx restart
Rapidement voici comment installer votre serveur mysql :
apt-get install mysql-server
Suivez les étapes notamment la génération du mot de passe root, pensez aussi à sécuriser votre mysql (supprimer les users et tables de tests) avec cette commande :
mysql_secure_installation
Voilà, vous avez une machine fonctionnelle ! Vous pouvez tester votre configuration en tapant votre IP sur votre navigateur. Normalement si vous avez créé une page /var/www/index.php contenant phpinfo(); vous devriez avoir une jolie page d’info PHP avec tous les modules activés…
Résultats PageSpeed
Les résultats devraient être visibles sur de gros CMS comme WordPress souvent lourds avec leurs modules et thèmes plus ou moins gourmands. Après quelques tests, j’obtiens 50% du temps un score au dessus de 90%. Encore une fois c’est bien un résultat irrégulier dues aux caches et aux ressources de votre serveur. Plus votre serveur sera puissant, meilleur en sera votre résultat. Encore une fois c’est le travail des différents caches (nginx, php, pagespeed) qui est responsable. Et même si vous avez un score en dessous de 90, ce qui compte c’est le ressenti final de l’utilisateur.
A noter que l’outil en ligne pagespeed insight de Google n’intégre pas les optimisations d’http2 en comptes.
Conclusion
Il y a bien encore des choses à faire pour optimiser les sites web de son serveurs, comme toute la partie minification des ressources HTML, CSS et JavaScript. Néanmoins vous avez déjà les bases d’un serveur véloce, qui utilises sa RAM et son stockage pour mettre en cache dans les différentes couches logicielles que sont NGINX, PageSpeed et PHP-FPM. Je n’ose même pas imaginer la vitesse d’execution sur un framework optimisé comme Symfony, EzPublish ou même Laravel ! Il arrive toutefois des limitations matérielles, et même si cette configuration ne va pas faire tomber votre serveur, plus votre serveur sera puissant et cher, meilleur seront les résultats.
L’inconvénient de ce tutoriel, concerne la mise à jour d’NGINX. Comme il est compilé par vos soins avec pagespeed, le seul moyen de le mettre à jour consistera à recompiler les dernières versions. A l’heure actuelle, il n’existe aucun repositories qui intègrent un module nginx-pagespeed, et c’est bien dommage…
Il est possible d’utiliser les optimisations du précédent tutoriel, notamment Varnish, le CDN Cloudflare ou encore l’optimisation WordPress en détail.