Les pages de ce site sont désormais servies par Nginx depuis quelques semaines, et j’en suis totalement ravi. Au début il y a eu une période d’incertitude et de petite frayeur du au fait de basculer d’Apache que je maitrise relativement bien, vers une plateforme toute nouvelle avec d’autres habitudes à prendre, d’autres conventions, un style différent (mais pas tant que ça). D’ailleurs en parlant de petite frayeur, avant-hier les sites hébergés sur le Kimsufi ont été indisponibles durant environ 4 heures, j’ai bataillé et sué fort pour trouver mon erreur, ma foi comme souvent, un peu bête (*).
Ce billet fait un peu le point sur ma configuration actuelle de Nginx. J’ai essayé de la faire le plus modulaire possible en créant des blocs relatifs à certains environnements qui sont ou non inclus dans les server blocks (le nom des virtual hosts chez Nginx). Par exemple, j’ai un morceau de code pour les spécificités de WordPress, de Koken ou pour ajouter la gestion HTTPS (SSL).
Configuration
Avec Fedora, la configuration de Nginx se situe sous /etc/nginx
, j’y ai créé 2 autres répertoires /etc/nginx/global
et /etc/nginx/vhosts
. Dans le premier je place tous les blocs de code possiblement redondants – ceux cités plus haut – et dans le second sont placés tous les server blocks, personnellement je crée un fichier par domaine, par exemple j’ai /etc/nginx/vhosts/feub.net.conf
pour feub.net.
Le fichier lu par Nginx est /etc/nginx/nginx.conf
, je ne l’ai pour ainsi dire pas touché, j’ai juste ajouté un include
vers mon répertoire de vhosts
, prenant en compte les fichiers se terminant par .conf
uniquement :
include /etc/nginx/vhosts/*.conf;
Et voici un exemple de fichier de configuration pour le domaine feub.net :
server { listen 80; server_name www.feub.net; rewrite ^(.*) http://feub.net$1 permanent; } server { listen 80; server_name feub.net; root /var/www/websites_root/feub.net/www/html; index index.php index.html index.htm; access_log /var/log/nginx/feub.net.access.log; error_log /var/log/nginx/feub.net.error.log; location / { try_files $uri $uri/ /index.php?$args; } include global/php.conf; include global/wordpress.conf; include global/things_not_logged.conf; }
J’aime bien forcer l’accès au site sans le www
(c’est très 2000s les sites en 3W ;P), donc le premier bloc écoute ce qui arrive sur www.feub.net et redirige (redirection permanete 301) vers la version sans www
.
On voit qu’en fin de fichier j’inclus des morceaux spécifiques, dans l’ordre : prise en charge des fichiers PHP, configuration de base relative à WordPress et mon fichier things_not_logged.conf
regroupant des choses comme ne pas logger robots.txt
, ignorer les .htaccess
, etc. Ci-dessous le détail de ces fichiers.
location ~ \.php$ { include fastcgi_params; fastcgi_intercept_errors on; fastcgi_read_timeout 240s; fastcgi_pass unix:/var/run/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }
# Interdit l'accès aux zones non publiques # ou limitation de l'accès en interne seulement location ~* wp-admin/includes { deny all; } location ~* wp-includes/theme-compat/ { deny all; } location ~* wp-includes/js/tinymce/langs/.*\.php { deny all; } location /wp-content/ { internal; } location /wp-includes/ { internal; } location ~* wp-config.php { deny all; } location /medias/ { internal; } # Empêche l'exécution de certains fichiers dans le répertoire d'upload # en forçant leur type MIME à text/plain location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php|js|swf)$ { types { } default_type text/plain; } # Ajoute un slash final aux requêtes vers */wp-admin rewrite /wp-admin$ $scheme://$host$uri/ permanent;
# Ne pas logger les requêtes vers favicon.ico location = /favicon.ico { log_not_found off; access_log off; } # Ne pas logger les requêtes vers robots.txt location = /robots.txt { allow all; log_not_found off; access_log off; } # Maximise la durée de vie des fichiers statiques location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; }
# Active la compression gzip pour de meilleures peformances gzip on; gzip_comp_level 6; gzip_types text/css text/javascript application/json application/javascript application/x-javascript; # Augmentation de la taille des fichiers envoyer client_max_body_size 20M; # Par défaut, les headers n'expirent pas expires 0; # On configure l'expiration des headers pour CSS et JS de la console. Ces fichiers # ont un nouveau timestamp à chaque version, il est donc raisonnable de les mettre en cache. location ~ "console_.*\.(js|css)$" { expires max; } # Si une version en cache n'existe pas, on passe les requêtes vers des images à PHP location ~ "^/storage/cache/images(/(([0-9]{3}/[0-9]{3})|custom)/.*)$" { # Les images en cache ont un timestamp dans l'URL, il est donc raisonnable # de les mettre en cache ici. expires max; try_files $uri /i.php?path=$1; } # On fait de même pour les fichiers de template .lens, Ceux-ci sont mis # en cache lorsque c'est possible. location ~ settings.css.lens$ { default_type text/css; try_files /storage/cache/site/${uri} /app/site/site.php?url=/settings.css.lens; } # Même chose pour le fichier koken.js location ~ koken.js$ { default_type text/javascript; try_files /storage/cache/site/${uri} /app/site/site.php?url=/koken.js; } # Les requêtes standards sont mises en cache avec l'extension .html set $cache_ext 'html'; # Les requêtes PJAX contiennent le paramètre GET _pjax et sont mises en cache # avec l'extension .phtml if ($arg__pjax) { set $cache_ext 'phtml'; } # On intercepte les requêtes à la racine location ~ ^/?$ { try_files /storage/cache/site/index/cache.$cache_ext /app/site/site.php?url=/; } # Toutes les autres requêtes sont passées à Koken sauf si le fichier existe location / { try_files $uri $uri/ /storage/cache/site/${uri} /storage/cache/site/${uri}cache.$cache_ext /app/site/site.php?url=$uri; }
listen 443 ssl; # Certificat et clé ssl_certificate /chemin/vers/mon/certificat.crt; ssl_certificate_key /chemin/vers/ma/cle.key; ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; # Si quelqu'un arrive sur la page en HTTP, pour ne pas avoir # la page d'erreur indiquant que l'on essaie d'accèder à un site # HTTPS en HTTP, on redirige directement vers la version HTTPS error_page 497 = https://$host:443$request_uri;
Voilà ma configuration de base, encore une fois je débute avec Nginx et toute amélioration est la bienvenue, allez-y dans les commentaires ;]
(*) Le problème était le suivant : après un redémarrage du service PHP-FPM, tous les accès vers une page PHP renvoyaient une erreur 403, le reste du contenu statique était normalement accessible. J’ai retourné à peu près tout, entre autres la bonne configuration du paramètre security.limit_extensions = .php
du pool (sous Fedora /etc/php-fpm.d/www.conf
) et ce qui était fautif : le paramètre cgi.fix_pathinfo
qui doit être à 1 dans le php.ini
.
Salut,
Bien détaillé comme article, bravo!
Je suis dans la même position que toi et cherche à basculer d’apache vers nginx. Pour l’heure j’essaye juste de faire cohabiter koken et owncloud, je migrerais wordpress plus tard. Le hic, c’est que j’y arrive pas malgré des heures de recherche et de lecture. Ta config me paraissant assez proche de la mienne, je me permet de te demander conseil : je ne vois pas d’include du koken.conf, j’en déduis qu’il est dans un ‘server block’ avec un server name dédié?
Merci pour ton attention.
Pour Owncloud, je ne m’y suis pas penché. Pour le reste, quel problème rencontres-tu?
Pour le
koken.conf
ethttps.conf
, j’ai juste ajouté ces morceaux de configuration pour info, ils sont inclus dans d’autres server blocks, pas dans celui de ce site.Ok Merci! Je pense que j’ai la réponse à mon problème c’est-à-dire pas de solution! owncloud ou pas, j’essaye de faire cohabiter koken en http avec un website en https sur un seul serveur (1 seul IP – celle de ma box) sans DNS associé pour l’heure.
Ok tu n’as qu’une IP, donc tu ne peux pas avoir de virtual hosts. Il va falloir mettre tes applis web dans des sous-répertoires de ta racine web alors.
Pour Koken pas de soucis, mais pour Owncloud, la dernière version que j’avais utilisé était la 4, donc ça date un peu. Mais c’est tout à fait possible j’imagine en définissant les bons
location
dans ton block server.Bonjour,
Ton article date un peu mais j’ai vu que tu es sous Nginx. Avais-tu fait des Benchmark quand tu as franchi le pas d’Apache vers nginx? Pour quelle partie du site est-ce beaucoup plus rapide?
Nginx a la réputation d’être plus rapide mais j’hésite vraiment car la config de mon site photo basé sur koken: http://www.jr-photo.be est pas mal optimisée.
Je me demandais en fait si ça n’aurait pas du sens d’utiliser memcached+apache pour le contenu dynamique php et NGinx pour le contenu static comme une sorte de cdn local.
Qu’en penses-tu?
Hello Jonathan,
Merci pour ton message. Non je n’ai pas fait de benchmark digne de ce nom, mais passer d’Apache à Nginx en général se voit directement. En plus, tu as un site photo, sous Koken, donc au final tu sers du contenu statique « lourd » (des photos), donc tu vas pleinement bénéficier de Nginx qui est spécialiste du contenu statique.
Mon site photo (anciennement fabienamann.photography) est sous Koken aussi : https://photo.feub.net/ et même s’il pourrait être plus optimisé, il y a déjà de la différence avec Apache. Dans l’article tu as du voir les spécificités pour Koken, comme tu l’as dit qui datent un peu, mais comme j’ai quasiment arrêté la photo, je ne m’en suis plus trop soucié ;]
J’utilise aussi Memcached.
J’ai choisi de n’utiliser que Nginx en front, mais rien ne t’empêche comme d’autres le font de garder ton stack Apache et de mettre Nginx en front d’Apache.