Accélérer son site sur serveur Dédié avec NGINX + Varnish + PHP-FPM + APC + CDN

Ça fait déjà un peu plus de 2 ans que ce site est présent sur un serveur dédié, avec le même CMS (WordPress) et malgré quelques évolutions notamment l’année dernière ou j’ai changé vers un thème plus lourd (animations etc) j’en avais profité pour passer vers un serveur Kimsufi KS2 4Go de RAM et un processeur Atom n2800 d’1,86Ghz, 4Go de RAM), mon site est alors bien propulsé surtout que j’avais bien optimisé Apache et j’utilisais le cache PHP Memcache.

Mais il y a peu, j’ai décidé de migrer vers un nouveau Kimsufi, le KS2-SSD. La seule différence avec mon ancien dédié est que je passais d’un disque dur de 1To vers un SSD de 40Go !


J’ai donc franchi le pas du SSD (d’une offre lowcost à 9€99 HT par mois) fasse à un gros disque qui ne me servait à rien pour l’hébergement d’un unique site web (et quelques applications), passant d’une vitesse de lecture de 170 à 258Mo/s (test à l’appui).

Je ne cherche pas à faire de pub pour les serveurs dédiés kimsufi de la société OVH que je connais très bien par le boulot que ce soit dédié ou mutualisé et ça fait des années que j’utilise des kimsufi pour mes projets persos. Il y a bien sur d’autres hébergeurs reconnus qui disposent d’offres +/- équivalentes comme Online, Digicube ou encore FirstHeberg.

Qui dit migration, dit forcément installation des composants : installer le serveur Web sur le dédié ! J’ai donc pris les devants en faisant table rase de ma configuration stable mais vieillissante (le couple apache/php classique des serveurs linux). Je vais donc expliquer ici les étapes à suivre pour avoir à terme un site rapide (tant qu’il n’est pas lui même trop « lourd ») et exploiter mieux les ressources de votre serveur surtout s’il ne sert qu’à héberger votre ou vos site(s). Je vais vous montrer comment depuis une distribution Ubuntu, passer à NGINX pour le serveur, Varnish pour l’accès rapide à vos fichiers classiques et utiliser une version optimisée de PHP avec un cache amélioré. En dernier lieu je vous présenterai un CDN connu (Cloudflare) gratuit qui à l’avantage de vous permettre de mettre ne cache js/css en minimisée sans action de votre part..

Sommaire

Pré-requis

Afin de commencer sans problème, je partirai du principe que vous disposez d’un serveur déjà installé, avec si possible une distribution Ubuntu récente (14.10 ou 15.04) ou Debian. Il vous faut donc les éléments suivants :

  • Un serveur dédié à jour. Je conseille Ubuntu afin de disposer des versions les plus récentes d’NGINX et de Varnish dans les repositories, afin de vous éviter de compiler manuellement une version plus récente mais non testée sur une autre distribution. Vous pouvez éventuellement utiliser une distribution différente, comme Debian ou Linux Mint, néanmoins pour Debian j’ai constaté qu’NGINX était encore en version 1.2 à ce jour (avril 2015), alors que sous Ubuntu j’ai la version 1.6.X…
  • Votre serveur WEB est déjà fonctionnel pour tout ce qui est serveur ftp, bind, mail, MySQL, phpmyadmin etc car je ne vais pas en parler dans ce tutoriel. Vous pouvez faire l’installation de votre côté au préalable. Je conseil ces tutoriels vidéos très bien faits pour tout ça  mais qui datent malheureusement pour ce qui concerne l’installation de l’OS sur Kimsufi, et ne suivez pas l’installation d’Apache et de PHP puisque c’est ici qu’il faudra le faire ^^.
  • Enfin, votre site doit fonctionner dans une version de PHP récente. Soit la 5.5. Normalement si vous utilisez un CMS (WordPress, Prestashop) ou un framework (Symfony2) ou encore Drupal, ça ne devrait pas poser de problème du fait qu’ils peuvent se mettre à jour facilement.

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. 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.

Une petite astuce si vous faites une migration de dédié à dédié (ou VPS) et que vous ne voulez pas y passer des heures via FTP. Si vous avez un accès SSH des 2 côtés et un site remplis de fichiers, utilisez la commande SCP depuis le dédié qui accueillera votre site. SCP permet de récupérer par un tunnel SSH les fichiers et dossiers d’un autre serveur :

scp -r -P 22 user-ancien-dedie@XX.XX.XX.XX:"/chemin/vers/mon/ancien/site/" /chemin/vers/mon/nouveau/site/

La commande vous demandera le mot de passe de session. j’ai volontairement indiqué « -P 22 » optionnelle au cas ou vous utiliseriez un autre port SSH par sécurité (conseillé). Dans ce cas, remplacez 22 par le port que vous avez choisi.

Installation de NGINX

On commence par les simples commandes. Il faut mettre à jour les applications de votre serveur en mettant à jours vos dépots :

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install nginx

Vérifiez si vous avez une version récente d’NGINX sur votre serveur. La dernière version stable se trouve ici

nginx -v
# nginx version: nginx/1.6.2 (Ubuntu)

Ensuite, il va falloir démarrer NGINX et le configurer pour qu’il fonctionne sur un port. Vous pensez au port 80 le port par défaut ? Et bien non déjà parce qu’il y a peut être Apache dessus et que de toute façon ici nous allons utiliser Varnish pour écouter le port 80 😉

nano /etc/nginx/nginx.conf

Vérifiez bien que « user » est www-data, et surtout « server_tokens » à off afin de ne pas divulguer la version de votre serveur nginx dans le DOM de vos pages ou dans les erreurs 404/500… (Rappel pour faire une recherche : Ctrl+W, tapez votre mot puis Entrer ^^). Allez dans l’équivalent du virtualhost d’apache :

nano /etc/nginx/sites-available/default

Ce fichier celui servant à afficher la page d’exemple d’nginx dans /usr/share/nginx/html. Vous allez la modifier pour qu’elle corresponde à la configuration de votre nom de domaine actuel. Dans la partie server, voici ce que vous devez mettre en écoute de port :

listen 8080 default_server;
listen [::]:8080 default_server ipv6only=on;

Puis vous allez renseigner l’endoit ou est stocké votre site, le fichier à lire par defaut (index.htm, index.php…) puis le nom de domaine qui y accédera (ou localhost) :

root /home/bxnxg/www;
index index.php index.html index.htm; #index.php en 1er, index.html sinon etc...
server_name www.bxnxg.com blog.bxnxg.com; #possibilité de rajouter plusieurs ndd

Si vous utilisez la réécriture d’url depuis WordPress voici ce que vous devez mettre à la partie location / :

location / {
try_files $uri $uri/ /index.php?q=$request_uri; #ou encore : try_files $uri $uri/ /index.php?q=$uri&$args;
}

Votre site est en PHP, dans ce cas trouvez « location ~ \.php$ » et éditez-le afin qu’il corresponde au code ci-dessous :

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;
}

Ensuite on va rajouter d’autres éléments comme bloquer la lecture du fichier .htaccess (si éventuellement votre site en a un) :

location ~ /\.ht { #vous pouvez ajouter d'autres fichiers ou des dossiers privés etc...
deny all;
}

Si vous utilisez WordPress, nous allons par la suite créer un fichier « nginx.conf » qui y inclura les paramètres de compression gzip et de cache qui seront ajoutés automatiquement par le plugin W3 Total Cache :

include /dossier-vers-la-racine-du-site/nginx.conf;

Toujours si vous utilisez WordPress, allez dans le dossier de votre site afin de créer votre fichier « nginx.conf » :

cd /dossier-vers-la-racine-du-site/
nano nginx.conf

Copiez/Code suivant. Je force le cache navigateur, active la compression gzip et précise des durées d’expiration de cache des fichiers. J’ai spécialement indiqué 10 sec. pour l’xml afin que votre futur sitemap.xml soit à jour régulièrement.

# BEGIN W3TC Browser Cache
gzip on;
gzip_types text/css text/x-component application/x-javascript application/javascript text/javascrip$
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)$ {
expires 3600s;
add_header Pragma "public";
add_header Cache-Control "max-age=3600, public";
add_header X-Powered-By "W3 Total Cache/0.9.4.1";
}
location ~ \.(xml)$ {
expires 10s;
add_header Pragma "public";
add_header Cache-Control "max-age=10, 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|$
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

Ça devrait le faire pour NGINX. Redémarrez le service :

/etc/init.d/nginx restart

Installation de Varnish

Varnish va nous permettre en gros d’écouter les requêtes du port 80 et afficher très rapidement tout ce qui est contenu multimédia (fichiers js/css, images, vidéos…) et renvoyer tout ce qui est requêtes d’action en PHP par exemple vers le serveur web NGINX.

sudo apt-get install varnish
varnishd -V
> varnishd (varnish-4.0.1 revision 4354e5e)
> Copyright (c) 2006 Verdens Gang AS
> Copyright (c) 2006-2011 Varnish Software AS

À partir d’Ubuntu 14.10, c’est la version 4 de varnish qui sera installée. Si vous avez une version antérieur comme la 3 vous pourrez toutefois utiliser ce tuto mais allez voir les changelogs ici car certains noms de paramètres changent.

C’est parti pour la configuration de varnish. Comme je l’ai précisé plus haut c’est varnish qui doit écouter le port 80 (ou 443 si vous utilisez https).

sudo nano /etc/default/varnish

Allez à la section « Alternative 2 », dé-commentez et remplacez par ses paramètres :

## Alternative 2, Configuration with VCL
#
# Listen on port 6081, administration on localhost:6082, and forward to
# one content server selected by the vcl file, based on the request.
#
DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-u www-data -g www-data \
-S /etc/varnish/secret \
-p thread_pools=2 \
-p thread_pool_min=25 \
-p thread_pool_max=250 \
-p thread_pool_add_delay=2 \
-p timeout_linger=0.050 \
-p cli_timeout=40 \
-s malloc,768m"

* j’ai mis 768Mo pour l’allocation mémoire (dernière ligne) étant donné que je dispose de 4Go de RAM. Il est conseillé d’allouer 20% de la mémoire totale mais vous pouvez adapter selon vos besoins sans dépasser les 50%.

Enregistrez et quittez. Maintenant éditez le fichier default.vcl afin de donner des directives spéciales. Ici nous mettrons des directives propres à un site wordpress, comme par exemple pouvoir vider les cookies wordpress et faire afficher sans cache vos articles en mode preview.

sudo nano /etc/varnish/default.vcl

Allez à la section « Alternative 2 », dé-commentez et remplacez par ses paramètres :

vcl 4.0;
#
backend default {
.host = "127.0.0.1";
.port = "8080";
}
#
sub vcl_recv {
if (req.url ~ "preview=true") {
return(pass);
}
if (!(req.url ~ "wp-(login|admin)")) {
unset req.http.cookie;
}
set req.http.X-Forwarded-For = client.ip;
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") {
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;
}
}
}
#
sub vcl_backend_response {}
#
sub vcl_deliver {
unset resp.http.Server;
unset resp.http.X-Powered-By;
unset resp.http.x-backend;
unset resp.http.Via;
unset resp.http.X-Varnish;
}

Si vous utilisiez Apache, c’est le moment de vous en séparer ! Tapez la commande suivante :

apt-get remove apache2

Redémarrez le service Varnish :

/etc/init.d/varnish restart

Installation de PHP-FPM + APC

Maintenant on passe à PHP. Je vous conseille fortement PHP-FPM (FastCGI Process Manager), une extension performante de PHP qui peut allouer à un cache PHP amélioré comme APC ou Memcached rendre votre site plus rapide à la fois au niveau des process en PHP et au niveau des mises en mémoire.

Pour savoir la liste des modules php à installer executer cette commande :

apt-cache search php5

Voici ce que j’ai installé sur mon serveur :

apt-get install php5-fpm php-apc php5-mysql php5-curl php5-gd php5-intl php-pear php5-mcrypt php5-memcache php5-sqlite php5-tidy php5-xmlrpc php5-xsl

Allez dans le fichier php-fpm.conf :

nano /etc/php5/fpm/php-fpm.conf

pid = /var/run/php5-fpm.pid
error_log = /var/log/php5-fpm.log
emergency_restart_threshold = 5
emergency_restart_interval = 2
events.mechanism = epoll

On vérifie que l’utilisateur pour PHP est bien « www-data » et on va changer le port d’écoute à 9000 car on redirige toutes les requêtes PHP vers ce port depuis Varnish :

nano /etc/php5/fpm/pool.d/www.conf

user = www-data
group = www-data
#
listen = 127.0.0.1:9000
#
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
listen.allowed_clients = 127.0.0.1
#
pm = dynamic
pm.max_children = 50
pm.start_servers = 15
pm.min_spare_servers = 5
pm.max_spare_servers = 25
pm.process_idle_timeout = 60s
#
request_terminate_timeout = 30
security.limit_extensions = .php

À la fin du fichier ajouter ces paramètres :

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/

Maintenant on passe à php.ini :

nano /etc/php5/fpm/php.ini

Changez les valeurs des éléments suivants : (rappel pour faire une recherche Ctrl+W)

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

Et à la fin de ce fichier, ajouter les réglages d’APC suivants :

[apc]
apc.stat = "0"
apc.max_file_size = "1M"
apc.localcache = "1"
apc.localcache.size = "256"
apc.shm_segments = "1"
apc.ttl = "3600"
apc.user_ttl = "7200"
apc.gc_ttl = "3600"
apc.cache_by_default = "1"
apc.filters = ""
apc.write_lock = "1"
apc.num_files_hint= "512"
apc.user_entries_hint="4096"
apc.shm_size = "256M"
apc.mmap_file_mask=/tmp/apc.XXXXXX
apc.include_once_override = "0"
apc.file_update_protection="2"
apc.canonicalize = "1"
apc.report_autofilter="0"
apc.stat_ctime="0"
;This should be used when you are finished with PHP file changes.
;As you must clear the APC cache to recompile already cached files.
;If you are still developing, set this to 1.
apc.stat="0"

On commence à voir la lumière, c’est terminé pour la configuration de PHP-FPM, on redémarre le service :

/etc/init.d/php5-fpm restart

Retour sur son Site / WordPress

Normalement vous devriez avoir accès à votre site 🙂 Vous pourrez constater via une console navigateur l’entête de votre site qui indiquera surement le serveur Nginx « via » varnish.

Si vous utilisez WordPress

Il existe des extensions comme W3 Total cache ou WP Super Cache. J’ai choisi la première afin d’utiliser APC, forcer le cache navigateur, la minification des fichiers et encore pleins d’autre chose. Vous pourrez tester votre site avec PageSpeed et voir comment évolue les performance de votre site en fonction de vos configurations. Petite précision, le plugin est très simple d’utilisation et vous indique souvent les droits d’écriture à mettre dans les fichiers wordpress.

Allez sur le dashboard et cliquez sur le bouton « compatibility check » pour connaitre la configuration de votre serveur.

Installez l’extension et dirigez vous vers la page General Settings.

Éléments de la page General Settings à activer :

  • Activez « Page Cache » avec la méthode « Opcode APC ».
  • Si vous avez un thème par défaut, Activez « Minify » avec les valeurs par défauts avec la méthode « Opcode APC ».
  • Activez « Database Cache » avec la méthode « Opcode APC ».
  • Activez « Object Cache » avec la méthode « Opcode APC ».
  • Activez « Browser Cache » avec la méthode « Opcode APC ».
  • Activez « Reverse Proxy » en activant le varnish cache purging.

Dans la page Browser Cache, partie General, cochez les éléments suivants :

  • Set expires header
  • Set cache control header
  • Set entity tag (eTag)
  • Set W3 Total Cache header
  • Enable HTTP (gzip) compression

Enregistrez, normalement si tout est OK, le plugin va chercher à écrire le fichier nginx.conf, celui que je vous avez fait faire pendant la configuration d’NGINX. Normalement ce devrait être les mêmes paramètres…

Éditer le fichier wp-config.php et ajoutez les paramètres suivants :

define('WP_DEBUG', false);
define('WP_CACHE', true);
define('W3TC_EDGE_MODE', true);

CDN CloudFlare

CloudFlare est un CDN qui propose une offre gratuite assez complète. Un CDN c’est quoi, ça remplace votre gestionnaire de DNS de votre nom de domaine pour que votre url passe par le CDN puis vers votre serveur. Comme ça, il peut mettre en cache des éléments de votre site vers des serveurs privés plus proche des utilisateurs dans le monde entier. Exemple court : votre site est hébergé en France, vous qui vivez en France ne constat aucune lenteur mais un visiteur qui vit à l’autre bout du monde va constater un temps de ping plus long. Avec un CDN, votre site (du moins les contenus en cache) peut être répliqué un peu partout dans le monde ce qui permettra à votre visiteur étranger (tout comme vous) de voir votre site plus rapidement.

Les bénéfices d’un CDN :

  • Les contenus de votre site est mis en cache dans des serveurs du monde entier
  • Votre serveur est moins surchargé surtout lors de forts traffics
  • Optimisation de votre site sans demander des compétences confirmées
  • Protections d’ip malveillantes détectées et des attaques Ddos

Les inconvénients :

  • Un service supplémentaire qui passe entre l’utilisateur et votre serveur
  • Peut ralentir légèrement un serveur qui répond très rapidement (dans de rare cas lorsque l’utilisateur est déjà très proche du serveur)
  • Ne pas utiliser ce genre de service pour des sites ou transite des informations privées (e-commerce, partage de fichiers) puisque si un service est gratuit, c’est que vous êtes le produit ^^ !

Ajouter son nom de domaine sur Cloudflare

Pour commencer, il faut ajouter son nom de domaine sur le site. Il vous génèrera 2 DNS primaire et secondaire que vous irez remplacer chez ceux de votre Registrar. Vous serez ensuite rediriger vers les paramétrages des DNS, essayez de mettre ceux que vous avez chez votre registrar.

Il vous reste à patienter que les DNS se propagent, sa peut varier entre 3 minutes et 48h :D.

Configurer Cloudflare

Dans la partie Websites, sélectionner le bouton paramètre à droite de votre site et choisissez « CloudFlare Settings »

Mettez la sécurité à Low ou Medium, pas besoin de ralentir votre serveur mettez le minimum pour bénéficier de la protection anti Ddos. La partie la plus intéressante est l’onglet « Performance settings ». Je conseille de tester une fois que le site est en mode production et que vous êtes sur qu’il n’y aura plus de grosses modification dans le css et le javascript, de choisir « CDN + Full Optimizations ». Il tentera de prendre en cache la majorité des fichiers, d’afficher vos pages en cache si elles ne répondent plus pendant 5 jours et surtout de minifier automatiquement les fichiers html, javascript et css (enfin peut être). Ça peut prendre du temps d’une part pour mettre en cache la totalité du site (48h) mais il peut y avoir des résultats dès les premières minutes…

Le plus : Il existe une extension CloudFlare dans W3 Total Cache que vous pourrez activer dans la rubrique « Extensions » du plugin. Je vous le recommande de l’activer ainsi que le plugin WordPress SEO by Yoast.

Bonus : Tester les performances avec PageSpeed

PageSpeed Insights est produit Google qui permet de mesurer les performances de votre site en analysant votre page web renseignée. En quelque seconde il vous présente un rapport et une note sur 100 pour mobile et desktop.

Il vous indique surtout si votre site est assez rapide à charger, ou si rien ne bloque le chargement de la partie visible de votre page, comme de gros fichiers javascripts ou des images trops volumineuses. Il vous présente aussi des conseils comme le chargement des fichiers fonts ou javascripts non contraignants après la balise </html> ou encore en asynchrone, et vous conseille aussi sur la mise en cache.

Conclusion

Voilà, vous avez une configuration au top pour exploiter les ressource de votre serveur et de bons outils à disposition pour rendre votre site web plus rapide je l’espère ! Surtout ne négligez pas la rapidité d’un site, car un site rapide sera moins contraignant pour la majorité des internautes qui arriveront depuis les moteurs de recherche. Ne négligez pas non plus la sécurité (règles firewall, fail2ban, CDN…) ! N’hésitez pas à partager vos connaissances en commentaire et me prévenir pour d’éventuels rajouts ou modifications !

Article relatifs