Préambule

Bonjour,

j'aurais besoin de conseils avisés à propos de la conception logique d'un serveur web sous Debian8.4 avec Nginx/PHP7/PHP-FPM.
Je suis nouveau dans le monde Linux et c'est la première fois que j'installe un serveur. J'apprends vite et dévore des masses de documentation en ligne (dont les excellents tutoriels vidéo de grafikart qui m'ont donné envie de m'inscrire ici, merci !) Partant de 0 et sans avoir jamais utilisé Linux, j'ai pu tout installer et faire marcher en dix jours. Mais quand j'ai voulu partir trop loin des configurations par défaut en recherchant la performance, je me suis perdu.

Je bloque - et obtient des erreurs 400 et 500 en masse... - parce que je ne maîtrise pas assez bien les concepts nécessaires à la configuration. Je pourrai me débrouiller avec le codage, ce qui me pose problème c'est vraiment la conception d'ensemble, qui suppose que je comble mes lacunes et que je corrige ce que je viens d'apprendre en vrac.

Objectifs poursuivis

D'abord, ce que je cherche c'est la vitesse pure.

Mon serveur servira principalement des pages de sites Wordpress (dont un site simple et un multisite en 5 langues) et autres CMS, pour moi et mes amis. Ces Wordpress, qui tournent actuellement ailleurs, j'ai déjà pu les migrer et y accéder sans souci. Leur BDD passée de MySQL à MariaDB tourne bien. Sur mon serveur Debian, les deux Wordpress sont stockés dans deux dossiers de var/www/ : var/www/domaine1.com et var/www/domaine2.fr

L'objectif est de tout configurer pour obtenir les temps de réponse les plus rapides possibles.

Je ne prévois pas de trafic très fort, donc on pourrait se dire que mes choix sont bêtement trop ambitieux.

Mais l'objectif c'est de servir une page de 500k avec 15-20 requêtes le plus vite possible, sous la seconde, proche de la demi-seconde.
J'ai pu tester à vide sur Pingdom et Pagespeed Insights : mon serveur, une config de base et le thème wordpress par défaut: temps total 0,6 secondes. Je veux tendre vers ça avec de vraies pages.

Donc je souhaite utiliser Nginx comme reverse proxy et comme serveur web - je l'ai installé en version co-construite avec le module pagespeed de Google -, et je veux le faire marcher avec PHP7 (en version pas encore officielle), et PHP-FPM.

J'aurai aussi besoin d'un cache, et idéalement je voudrais même préloader ce cache - j'aurais dans les 600 pages à charger pour l'instant.

Mes questions

Les principales questions que je me pose :
1/ Quel est le meilleur schéma logique de mon installation ?
Si j'avais un bon schéma logique je pourrais le traduire en code.
Je pense que ce que je dois faire c'est :

A. Dans etc/nginx/nginx.conf, définir un proxy avec upstream+ block serveur de ce type :

        upstream backend  {
         server 127.0.0.1:9000;
     }
     server {
          listen       80;
          server_name  localhost;
          location / {
               proxy_pass        http://backend;
               proxy_redirect    off;
               proxy_set_header  X-Forwarded-For $remote_addr;
          }
   }

Mais avec FPM et PHP7, il faudrait que je change la ligne

         server 127.0.0.1:9000;

en

          server unix:/run/php/php7.0-fpm.sock;

est-ce correct, ou je me trompe déjà ? Ou le code devrait-il être

           server /run/php/php7.0-fpm.sock;

?
Je me trompe probablement, ce socket-là ne devrait peut-être pas recevoir tous les contenus mais seulement le PHP ? Mais dans ce cas, quel est le bon protocole pour le proxy, c'est le TCP/IP du code initial ?

B. Toujours dans nginx.conf, dans le block http, inclure mes /sites-available/ avec symlink vers /sites-enabled/

C. Dans etc/nginx/sites-available/default.conf je ne sais pas trop quoi mettre. En ai-je vraiment besoin ? C'est censé servir à quoi, à traiter toute url qui ne correspondrait pas à mes vhosts déclarés ? Ou c'est juste un fichier d'exemple qui n'est pas vraiment pris en compte et dont on peut se passer si on a géré les uri "inconnus" par ailleurs, genre dès le server web (on fait try-files de l'uri et si c'est inconnu, renvoi vers erreur 404 ?)

D. Dans etc/nginx/sites-available/wordpress-simple.conf, je devrais définir un serveur web qui teste les urls demandées avec try-files. C'est peut-être à ce moment-là que je devrais utiliser la passerelle php7.0-fpm.sock ? Je me demande comment je dois définir le server name de ce premier site, car j'ai un problème temporaire : pour l'instant j'expérimente et mon serveur n'a qu'un domaine, or j'ai deux "vHosts" à déclarer, qui correspondront plus tard à deux domaines bien différents. J'obtiens sans cesse des erreurs de "duplicate server name". Comment contourner le problème, avant que je sois en capacité de faire les bonnes redirections DNS?

E. Dans etc/nginx/sites-available/wordpress-multiste.conf je devrais avoir une config similaire à celle du premier wordpress, sauf que le côté multisite me pose un problème de configuration supplémentaire : le multisite que je migre d'un serveur mutualisé sous Apache vers un dédié sous Nginx est configuré en sous-domaines linguistiques (www.site.com, fr.site.com, de.site.com etc). Je crois que je devrais "mapper" mes sous-domaines mais je ne sais pas comment m'y prendre. Comment faire afficher à Nginx une page dont l'url était http://fr.site.com alors que l'url de mon serveur est maintenant du type http://nom-du-serveur-dédié.eu/wordpress-multisite.com/ ?

F. Avec tout ça, je ne sais pas comment je dois faire communiquer le proxy et le cache, ni qui va gérer le cache. Nginx ? memcache ? autre chose ? Et Pagespeed s'accomodera-t-il de ce cache, faut-il le lui signaler ?

G. Sur tout ça on rajoute Pagespeed. Pagespeed a besoin qu'on insère ce code :

      location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" {
       add_header "" ""; }
      location ~ "^/pagespeed_static/" { }
      location ~ "^/ngx_pagespeed_beacon$" { }

Comme je ne comprends pas bien à quoi sert ce code, je ne sais pas trop dans quel "contexte" (reverse proxy ? serveur web ? vhosts, via un include par exemple ?) le mettre : dans la définition du proxy de nginx.conf ? Dans default.conf, et ce serait donc pris en compte par défaut pour tout site donc pour mes 2 Wordpress, sachant que ce default.conf est appelé par nginx.conf ? Ou encore, dans la définition de mes wordpress dans /sites-available/ ?

De fait, il faudrait peut-être éviter que tout passe par Pagespeed, qui bloquait phpMyAdmin - mais comme j'ai installé PHP7 de toute façon phpMyAdmin ne peut plus marcher et ce n'est pas grave, d'autres solutions plus légères feraient l'affaire. Apparemment l'admin de Wordpress marche toujours bien même avec Pagespeed, j'ai pu voir ça brièvement avant de perdre le contrôle.

H. Maintenant que vous avez une idée plus précise de ce que je veux faire, avez-vous une idée du schéma logique de tout le système ? Moi, je m'y perds. Je voudrais savoir 3 choses fondamentales : 1/ Quelles sont les instances que je dois définir ? 2/ Quels canaux de communication (optimaux) je dois leur attribuer ? 3/ Quelles root et location je dois définir à chaque niveau ? Si j'étais sûr de moi là-dessus, tout deviendrait plus facile. A mon avis dans le piteux état actuel de mes connaissances, je me trompe : pour moi, c'est censé se passer comme ça :

  • Le client envoie une requête
  • Le proxy la reçoit et cherche si on peut la servir depuis le cache. Si oui, la requête est servie et le processus est fini, c'est optimal, sinon étape suivante. Question : je ne sais pas quel canal utiliser, ni qui gère ou peut gérer mon cache. Root: var/www/ et location / ?
  • Le proxy l'envoie au serveur web. Sur quel canal ??? socket ? Comment définir la root et la location ?
  • Le serveur web la reçoit et fait le tri, disons en trois : mon simple wordpress, mon multisite, et l'inconnu. Mettons que la requête concerne mon multisite, donc renvoi vers sa définition dans /sites-available/ Paramètres Root: var/www/ et location / ?
  • Le serveur "vHost" de mon multisite traite la requête et fait le tri (try-files) : si c'est statique... que doit-il faire ? Si c'est du PHP... dois-je à ce moment-là renvoyer vers la socket php7 ? Si oui, à quel endroit ça reviendra, par quel port, quel canal ? Le même ? Je suis pas sûr de comprendre ce que la machine fait quand on lui définit un socket : elle l'utilise POUR ENVOYER son info, et c'est l'instance qui reçoit qui définit le canal de retour, ou bien une fois un canal défini il est utilisé à la fois pour envoyer et recevoir ?? Et, peut-on faire utiliser le même socket par plusieurs instances - ce serait comme une route ouverte à plusieurs véhicules - ou bien est-ce que chaque canal doit avoir un et un seul programme branché dessus en "listen:port" et en "fastcgi-pass ->socket" ou "proxy-pass->socket" ?
  • Pour chaque "vHost" (je sais que le terme vient d'Apache et n'est qu'une métaphore sous Nginx) Root: var/www/ et location /dossier-du-wordpress-concerné et location / ?

Je pense avoir trouvé de bons éléments de réponse sur cette page : https://tweaked.io/guide/nginx-proxying/

  • Il définit le chemin du cache du proxy dans le block http de nginx.conf, et (dans le code du bas de la page, que j'ai du mal à comprendre parce qu'il referme la balise http et n'ouvre pas de baliser server, donc je vois pas bien où doit se trouver sa location...? c'est pas clair) il indique que les ressources statiques doivent rester en cache sans passer par le serveur web.
  • Il définit le proxy au même endroit grâce à server 127.0.0.1:4433 - si j'utilisais ce code je devrais le remplacer par mon socket PHP7, oui ?
  • Il définit un server web qui écoute sur le port 80 et qui porte le nom du domaine du serveur (enfin dans mon cas ça pourrait marcher si j'y mettais le domaine de mon serveur ?) et il le fait passer par le proxy.
    C'est bien ça ?? Pensez-vous que cette configuration puisse marcher dans mon cas ? Ou comment l'adapter à mes besoins ?
IP serveur, domaine serveur et localhost

Un autre point que j'aimerais clarifier : je ne comprends pas bien la différence entre l'IP de mon serveur, le localhost, et son domaine.

Je trouve bizarre l'instruction "server name" (j'enlève l'underscore...) de Nginx qui semble accepter les trois, comme si elles étaient remplaçables. En fait, elles ne le sont pas, est-ce correct ? Puisqu'Nginx signale (warning, ignored) des "duplicate server name".
Je ne sais pas si ce sont trois expressions EXACTEMENT SYNONYMES du point de vue de la machine, ou si on peut utiliser ces trois noms pour différencier des instances logiques, comme si on connectait la même machine physique à elle-même en la câblant à divers endroits logico-physiques :

  • par exemple le server name du proxy serait l'IP du serveur,
  • le server name du serveur web serait l'url du domaine du serveur,
  • et le server name d'autre chose pourrait être localhost ?
    Je suis sur la bonne voie ou c'est encore complètement raté ?
Merci d'avance

Voilà merci d'avance si vous avez une suggestion à me faire pour corriger mes erreurs ou me faire comprendre les choses importantes. Je pense qu'un expert mettrait 5 minutes à conceptualiser ce que je vais mettre 3 semaines à comprendre.

Si jamais vous voulez m'aider je peux rendre service en retour, j'ai surtout des compétences littéraires, j'enseigne l'écriture (mais pas le code ! :) )

Aucune réponse