Serveur dédié : installer APC comme système de cache et configurer Varnish comme reverse-proxy pour Apache pour améliorer les performances

Allez, on continue d’optimiser notre serveur : aujourd’hui, je vous montre comment améliorer nettement les performances du serveur.

Nous allons d’abord installer un système de cache – j’ai choisi APC – qui va soulager un peu le système en mettant en cache les pages du site les plus demandées.

Cela aura un impact sur le temps de traitement des pages (moins de traitement PHP) et sur la base de données (moins de requêtes SQL).

varnish apache

Dans un second temps, nous installons Varnish comme reverse-proxy pour Apache : tous les objets statiques (images, CSS, JS) seront traités par Varnish, le reste (PHP) sera traité par Apache. Cela divise sensiblement la charge serveur.

Installation d’APC

APC est un système de cache que je trouve très performant. On l’installe avec :

pecl install apc

puis on crée le fichier de configuration :

nano /etc/php/7.4/conf.d/apc.ini

et on y ajoute :

extension=apc.so
apc.enabled=1
apc.shm_size=128M
apc.stat=0
apc.ttl=7200
apc.user_ttl=7200
apc.enable_cli=1
apc.max_file_size=10M
apc.rfc1867 = On

Si vous avez une erreur de compilation lors de l’installation d’APC, c’est sûrement que le paquet libpcre3-dev n’est pas installé. Dans ce cas :

apt-get install libpcre3-devCode language: JavaScript (javascript)

Il ne reste plus qu’à relancer Apache : :

/etc/init.d/apache2 restart

A noter qu’APC est livré avec un script PHP (nommé apc.php) qui vous permet de voir quelques statistiques sur la mise en cache de vos fichiers. Petit exemple de ce que cela donne :

apc cache

Pour installer apc.php, il faut le copier le fichier à la racine de notre site :

cp /usr/share/doc/php-apc/apc.php /home/skyminds/public_html/

puis l’éditer :

nano /home/skyminds/public_html/apc.php

pour y modifier le mot de passe :

defaults('ADMIN_USERNAME','apc');              // Admin Username
defaults('ADMIN_PASSWORD','password');     // Admin Password - CHANGE THIS TO ENABLE!!!Code language: JavaScript (javascript)

Voilà, APC est installé et actif.

Installation de Varnish

Passons maintenant à l’installation du serveur Varnish :

wget http://repo.varnish-cache.org/debian/GPG-key.txt
apt-key add GPG-key.txt 
echo "deb http://repo.varnish-cache.org/debian/ lenny varnish-2.1" >> /etc/apt/sources.list
apt-get update
apt-get install varnishCode language: JavaScript (javascript)

Principe de fonctionnement : Varnish va écouter sur le port 80. C’est lui qui va traiter toutes les requêtes : il va transmettre à Apache (sur le port 8080) tout ce qui est dynamique (PHP etc) et s’occupera lui-même des fichiers statiques (images, javascripts etc).

varnish diagram

Cela va donc alléger notre serveur Apache et nous allons pouvoir mettre en cache tous les éléments statiques.

On configure le serveur Varnish en éditant le fichier de configuration :

nano /etc/default/varnishCode language: JavaScript (javascript)

Dans ce fichier, naviguez jusqu’à l’alternative #2 et changez le port 6081 en 80 (première ligne) :

DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G"Code language: JavaScript (javascript)

Le fichier varnish_storage.bin sera limité à 1 Go, sachant que ma Kimsufi possède 2 Go de RAM.

Comme Varnish tourne maintenant sur le port 80, il faut maintenant forcer Apache à écouter sur le port 8080.

On édite donc :

nano /etc/apache2/ports.conf

et on change toutes les références à 80 en 8080 :

NameVirtualHost *:8080
Listen 8080Code language: CSS (css)

Passons maintenant à la configuration de notre site dans Varnish et éditons /etc/varnish/default.vcl :

nano /etc/varnish/default.vclCode language: JavaScript (javascript)

on y met :

/* ------------------------------------------------------------ */
/*        VCL Configuration by Matt - www.skyminds.net          */
/* ------------------------------------------------------------ */

# Redirect requests to Apache
backend www {
   .host = "127.0.0.1";
   .port = "8080";
   .connect_timeout = 600s;
   .first_byte_timeout = 600s;
   .between_bytes_timeout = 600s;
}

# Called after a document has been successfully retrieved from the backend.
sub vcl_fetch {
        # set minimum timeouts to auto-discard stored objects
        set beresp.grace = 5m;
        if (beresp.ttl < 8h)
        {
                set beresp.ttl = 8h;
        }
       if (req.url ~ "\.(png|gif|jpg|swf|css|js)$")
        {
                unset beresp.http.set-cookie;
        }
      
       ## Deliver the content
       return(deliver);
}

sub vcl_recv {

        # Serve objects up to 5 minutes past their expiry if the backend is slow to respond.
        set req.grace = 5m;

        # Compatiblity with Apache log
        remove req.http.X-Forwarded-For;
        set req.http.X-Forwarded-For = client.ip;

        if (req.http.host ~ "^(www\.)?skyminds\.net$")
        {
                set req.backend = www;
        }

        ### always cache these images & static assets & Remove cookies and query string for real static files
        if (req.url ~ "^/[^?]+\.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|rar|lzma|bz2|tgz|tbz|html|htm)(\?.*|)$")
        {
                unset req.http.cookie;
                set req.url = regsub(req.url, "\?.*$", "");
        }

        # Normalize Content-Encoding
        if (req.http.Accept-Encoding)
        {
                if (req.url ~ "\.(jpg|png|gif|gz|rar|tgz|bz2|lzma|tbz|mp3|ogg)(\?.*|)$")
                {
                        remove req.http.Accept-Encoding;
                }
                elsif (req.http.Accept-Encoding ~ "gzip")
                {
                        set req.http.Accept-Encoding = "gzip";
                }
                elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE")
                {
                        set req.http.Accept-Encoding = "deflate";
                }
                else
                {
                        remove req.http.Accept-Encoding;
                }
        }

        ### never cache POST requests
        if (req.request == "POST")
        {
          set req.backend = www;
          return(pass);
        }

        return(lookup);
}
Code language: PHP (php)

et on ouvre les ports dans iptables :

iptables -A OUTPUT -p tcp --dport 8080 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 6082 -s 127.0.0.1 -j ACCEPTCode language: CSS (css)

on redémarre pour appliquer les changements :

/etc/init.d/varnish restart
/etc/init.d/apache2 restart

Modification du Virtual Host

Il faut mettre à jour notre virtual host :

nano /etc/apache2/sites-available/www.skyminds.net

On remplace la ligne des logs par:

# ajout des logs
CustomLog /var/log/apache2/www-access.log varnishcombined
ErrorLog /var/log/apache2/www-error.logCode language: PHP (php)

Ensuite, on édite /etc/apache2/apache2.conf :

nano /etc/apache2/apache2.conf

et on y ajoute, en bas du fichier, au niveau des logs :

# VARNISH
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" varnishcombined
# Access log for VirtualHosts that don't define their own logfile
CustomLog /var/log/apache2/other_vhosts_access.log vhost_combinedCode language: PHP (php)

et on recharge Apache pour prendre en compte nos changements:

/etc/init.d/apache2 reload

Voilà, vos fichiers statiques sont mis en cache et servis par Varnish.

Les fichiers dynamiques sont servis par Apache et mis en cache avec APC.

Synopsis » Monter un serveur dédié de A à Z

  1. Serveur dédié : installation d’Apache, PHP, MySQL et Webmin
  2. Serveur dédié : créer la base de données MySQL et importer WordPress
  3. Serveur dédié : créer et activer un Virtual Host sous Apache
  4. Serveur dédié : changer les DNS du nom de domaine et le faire pointer vers le serveur
  5. Serveur dédié : sécurisation des services avec iptables et fail2ban
  6. Serveur dédié : sécurisation de la couche TCP/IP
  7. Serveur dédié : création d’un serveur mail Postfix (sécurisé avec Saslauthd et certificat SSL) et Courier (accès POP et IMAP) utilisant une base MySQL d’utilisateurs/domaines virtuels
  8. Serveur dédié : sécuriser Apache 2 avec ModSecurity
  9. Serveur dédié : CHMOD récursif sur des fichiers ou répertoires en ligne de commande
  10. Serveur dédié : installer APC comme système de cache et configurer Varnish comme reverse-proxy pour Apache pour améliorer les performances
  11. Serveur dédié : afficher la véritable IP derrière un reverse-proxy comme Varnish
  12. Serveur dédié : intégrer SSH à WordPress pour mettre à jour le core, les plugins et les thèmes
  13. Serveur dédié : installer la dernière version d’APC par SVN
  14. Serveur dédié : analyse des performances du serveur
  15. Serveur dédié : mettre à jour le noyau Debian de la Kimsufi
  16. Serveur dédié : sauvegarde automatique des fichiers avec Backup Manager sur le serveur de sauvegarde OVH
  17. Serveur dédié : configurer la limite mémoire pour PHP et Suhosin
  18. Bash : supprimer tous les fichiers et sous-répertoires d’un répertoire
  19. Serveur dédié : impossible de se connecter à un port distant
  20. Rsync: rapatrier les fichiers du serveur à la maison
  21. Bash : réparer les tables MySQL en cas de crash
  22. Serveur dédié : création d’une seedbox avec Transmission
  23. Serveur dédié : des paquets LAMP à jour sous Debian
  24. Serveur dédié : mise à jour vers Debian 7 Wheezy
  25. Serveur dédié : activer X11 forwarding pour SSH
  26. Serveur dédié : optimiser toutes les images JPG et PNG avec OptiPNG et JpegOptim
  27. Postfix : résoudre l’erreur “fatal: www-data(33): message file too big”
  28. Serveur dédié : mise en place de l’IPv6
  29. WordPress : accorder les bonnes permissions aux fichiers et dossiers avec chown et chmod
  30. WordPress : héberger les images sur un sous-domaine
  31. Serveur dédié : ajouter l’authentification SPF, Sender-ID et DKIM à Postfix et Bind9 avec opendkim
  32. Apache : lorsque le domaine seul (sans WWW) renvoie une erreur 403
  33. Serveur dédié : sécuriser Apache avec HTTPS (HTTP avec la couche TLS/SSL) en Perfect Forward Secrecy
  34. Serveur dédié : passer WordPress en HTTPS (TLS/SSL)
  35. Serveur dédié : configurer Webmin en TLS avec un certificat SSL
  36. Serveur dédié : configurer Transmission pour accéder au WebUI via TLS-SSL
  37. Serveur dédié : installer et configurer Varnish 4
  38. Serveur dédié : passage au mod FastCGI et PHP-FPM avec Apache MPM Worker
  39. Récupérer un serveur Kimsufi après un plantage de kernel avec le mode rescue OVH
  40. Serveur dédié : configurer Postfix et Courier pour utiliser TLS-SSL en Perfect Forward Secrecy
  41. Serveur dédié : retirer Varnish, devenu inutile avec HTTPS
  42. Serveur dédié : installer la dernière version d’OpenSSL sous Debian
  43. Serveur dédié : activer l’IP canonique du serveur sous Apache
  44. Serveur dédié : mise à jour vers PHP 5.6
  45. MySQL : convertir les tables MyISAM au format InnoDB
  46. Serveur dédié : optimiser toutes les images GIF avec GIFsicle
  47. Serveur dédié : migration de MySQL vers MariaDB
  48. BASH : lister, bloquer et débloquer des adresses IP avec iptables
  49. Serveur dédié : produire une meilleure réserve d’entropie avec haveged
  50. Serveur dédié : mettre en place DNSSEC pour sécuriser les DNS du domaine
  51. Serveur dédié : mise en place du protocole DANE
  52. 8 règles d’or pour bien déployer DNSSEC et DANE
  53. Serveur dédié : installer PHP7 FPM avec FastCGI sous Debian
  54. Serveur dédié : optimiser la couche TCP
  55. Fail2Ban: protéger Postfix contre les attaques DoS de types AUTH, UNKNOWN et EHLO
  56. Serveur dédié : mettre à jour Apache pour HTTP/2
  57. Serveur dédié : ajouter le domaine à la liste HSTS preload
  58. Serveur dédié : ajouter l’authentification DMARC à Postfix et BIND
  59. Serveur dédié : à la recherche de l’inode perdue ou comment résoudre le problème “no space left on device”
  60. Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian

Rencontrez-vous des défis avec votre site WordPress ou WooCommerce? Laissez-moi les résoudre pour vous.

Discutons des solutions possibles »

Articles conseillés :

Matt

Matt Biscay est développeur WordPress et WooCommerce certifié chez Codeable, ainsi que sysadmin qualifié et enseignant-chercheur. Passionné par le code performant et les solutions sécurisées, je m'efforce d'offrir une expérience utilisateur exceptionnelle sur chaque projet.

Vous avez aimé cet article ? Vous avez un projet en tête et vous pensez que je pourrais vous aider à le concrétiser ? N'hésitez pas à me contacter, je serais ravi de discuter avec vous de votre projet !

20 pensées sur “Serveur dédié : installer APC comme système de cache et configurer Varnish comme reverse-proxy pour Apache pour améliorer les performances”

  1. Bonjour,

    Merci pour tes tutos ils me sont très utiles pour la mise en place d’un serveur dédie

    J’ai mis en place mod-security pour sécuriser plusieurs sites en drupal, mais du aux nombres de requêtes a analysées, je l’ai supprime, je perdais trop de performances.

    A propos de varnish, j’ai deux petites questions

    1/ Lorsque varnish fonctionne, les logs d’apache ont comme adresse ip 127.0.0.1, y a t-il moyen de retrouver l’adresse réel du client ?

    2/ Seconde question, comment peut on voir ce que varnish a en cache ? pour apc il existe une page apc.php qui se trouve dans /usr/share/doc/php-apc/ mais pour varnish ?

    Il y a bien varnishtop mais c’est pas super compréhensible

    Merci

    Reply
    • Bonjour salcin,

      J’ai aussi désactivé pas mal de modules pour mod-security qui ralentissait le site. Je referai une liste plus propre.

      Pour l’IP en 127.0.0.1 dans les logs, il faut installer le mod_rpaf pour Apache. J’ai gardé ça pour le prochain tuto qui sera mis en ligne dans quelques jours :

      aptitude install libapache2-mod-rpaf

      En ce qui concerne le cache de Varnish, on ne peut pas voir vraiment les pages en cache mais si tu tapes :

      varnishstat

      tu peux avoir pas mal d’informations en temps réel : request rate, mémoire utilisée, thread usage, uptime…

      Reply
  2. Bonjour,

    Merci pour ces super tuto.

    Je rencontre un soucis pour mettre en place varnish avec la boutique prestashop.

    Le cache est affiché constament sur la boutique du coup on ne voit pas les modification faite.

    le problème est présent dans le back office /front

    J’ai cherché un peu comment faire tout ca mais ne maitrisant pas du tout le language vcl, ca vas être dur. Apparament il y a un histoire de purge a faire mais je ne trouve pas.

    cheers

    Reply
    • Bonjour Majeri,

      Si tu veux ajouter la fonction PURGE, ajoute ceci dans ton fichier .vcl :

      # Purge ACL
      acl purge {
      # Only localhost can purge my cache
      "127.0.0.1";
      "localhost";
      }

      et dans vcl_recv, ajoute :

      # Allow purging from ACL
      if (req.request == "PURGE") {
      # If not allowed then a error 405 is returned
      if (!client.ip ~ purge) {
      error 405 "This IP is not allowed to send PURGE requests.";
      }
      # If allowed, do a cache_lookup -> vlc_hit() or vlc_miss()
      return (lookup);
      }

      Si tu veux exclure une zone de ton site du cache (backoffice ou flux RSS par exemple), tu peux utiliser ce type de code dans vcl_recv :

          # Example : do not cache the RSS feed
          if (req.url ~ "/feed") {
              return (pass);
          }
      Reply
      • Merci Matt.

        Entre temps je me suis renseigné et j’ai trouvé les même commande que ce que tu m’as donnée.

        Par contre apres faut que je trouve une solution simple pour mettre a jour mes page web en faisant un purge.

        Comment tu fais toi pour par exemple mettre a jour le cache des page qui ont un subie une modification de ta part ou tout simplement des pages ou de nouveau commentaire on été posté.

        Tu utilise le plugin wordpress pour varnish je suppose ?

        cheers

  3. Merci,

    Apres quelques tatonement, beacoup de lecture et une nuit blanche, j’ai reussi a faire tourner comme je le souhaite varsnih avec mon prestashop.

    Aussi j’ai rajouter qq ligne pour la sécurité du serveur:

    Au choix: Cela trompera l’attaquant en lui indiquant un mauvais serveur web a rajouter dans le vcl_fetch:

    unset beresp.http.Server;
    set beresp.http.Server = “Lighthttpd Server”;

    Ou encore plus radical: (même si apache sera la cible de choix)

    sub vcl_deliver {
    # Secure the header
    remove resp.http.Via;
    remove resp.http.X-Varnish;
    remove resp.http.Server;
    remove resp.http.X-Powered-By;
    }

    ++

    Reply
  4. Finalement comment as tu réussi a configurer varnish avec Prestashop?

    Pour moi ca me parait impossible car même en “bypassant” varnish via un return(pass); juste pour les sites prestashop j’ai toujours une erreur 503 Guru Meditation lorsque je filtre mes resultat dans la partie administration.

    Reply
    • Finalement j’ai le même problème que toi rc183, quand je filtre une page d’administration dans le catalogue, j’ai la meme erreur :une erreur 503

      POur le moment j’ai toujours pas trouvé une solution.

      De plus j’ai toujours un problème pour que mes pages se purge quand il y a une mise a jour de prix par exemple.

      Certaine page sont mise a jour, d’autre pas.

      Reply
  5. Salut Matt
    j’ai suivi le tuto (sans tout comprendre je reconnais :( )
    aucun soucis à l’install apc. Par contre à la derniere étape de restart varnish j’ai une erreur

    
    Stopping HTTP accelerator: varnishd failed!
    Starting HTTP accelerator: varnishd failed!
    storage_file: filename: /var/lib/varnish/ksxxxxx.kimsufi.com/varnish_storage.bin size 1024 MB.
    Message from VCC-compiler:
    Unused backend default, defined:
    (input Line 89 Pos 9)
    backend default {
    --------#######--
    Running VCC-compiler failed, exit 1
    VCL compilation failed
    

    et mon serveur est complètement down …
    Une idée de solution ? je ne comprends pas du tout le message d’erreur.

    Reply
    • Bonjour Lisa,

      Apparemment, tu n’utilises pas le bon backend (ou tu en a plusieurs définis ?). Quel est le contenu de ton fichier VCL ?

      Reply
  6. Bonjour,

    j’ai suivi votre excellent tutoriel pour l’installation de Varnish. Mais je rencontre une erreur 503 sur toutes les pages, qu’elles soient en html ou en php. Je n’ai pourtant rien de spécial dans mes codes de page. Celles-ci sont très longues à charger et au bout d’un certain temps, apparait une erreur 503.

    Savez-vous comment il est possible de diagnostiquer le problème ?

    Merci,

    Reply
  7. Je m’auto réponds. En fait, pour chaque domaine, dans la config de Varnish, il faut utiliser un backend différent ? Car j’ai configuré un backend “nomdusite” en modifiant la requête http.host et les pages fonctionnent comme il faut maintenant.

    Reply
  8. Bonjour,
    “PHP Warning: Module ‘apc’ already loaded in Unknown on line 0
    PHP Warning: PHP Startup: apc.shm_size now uses M/G suffixes, please update your ini files in Unknown on line 0”

    Pouvez-vous mettre à jour votre tuto – excellent au passage – pour les prochains visiteurs ?

    Infos : Debian 6, dédié, apache2, mysql, php5.

    Reply
      • Right, j’avais même pas fait attention au second article.

        Merci de votre réactivité ( et du tuto :) ), PunKeel.

        PS: je n’ai pas “vu” de config pour fonctionner avec CloudFlare (ouaip, une idée de mise à jour du tuto :D)

        Comme ils le signalent sur leur site : sub vcl_recv {
        # Remove has_js and CloudFlare/Google Analytics __* cookies.
        set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");
        # Remove a ";" prefix, if present.
        set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");

        et
        remove req.http.X-Forwarded-For;
        if (req.http.cf-connecting-ip) {
        set req.http.X-Forwarded-For = req.http.cf-connecting-ip;
        } else {
        set req.http.X-Forwarded-For = client.ip;
        }

        Cordialement, bis.

  9. Bonjour,

    merci pour ce tuto.

    une petite question me tarrode concernant la configuration d’APC.

    Pourquoi mettre apc.ttl=7200 au lieu de apc.ttl=0 qui ne va définir de temps.

    Reply
    • Bonjour Djib’s,

      apc.ttl et apc.user_ttl définissent le temps (en secondes) pendant lequel un fichier reste dans le cache.

      Avec 7200 secondes, les fichiers sont mis en cache pendant 2 heures, ce qui est adapté à ma configuration. On pourrait mettre une expiration beaucoup plus longue si la taille du segment (apc.shm_size) était plus importante.

      Reply

Opinions