En ce moment je développe la nouvelle version de seedbox-manager (sbm)

J'ai eu des soucis avec la configuration, surtout pour faire fonctionner l'application dans une uri.
Donc à cette occasion je me suis littéralement plongé dans la doc nginx pour comprendre comment fonctionne réellement nginx. Et j'ai appris pas mal de chose notamment sur les bonnes pratiques.

Vous avez surement déjà vu cette erreur php-fpm dans vos logs nginx elle est relativement très répandue
FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream
Pour ma part elle a presque réussi à me rendre fou 😂

Pour faire simple dans la plupart des cas c'est un mauvais chemin attribué à la variable SCRIPT_FILENAME lorsque nginx essaye de résoudre l'uri. Nginx en fonction des location dans le vhost server détermine le chemin physique pour afficher le fichier.

Et là ça devient intéressant puisque les location on peut les configurer de plein de manière différente.

Les location nginx

Donc voici les types

server {

    location = /coucou {
    }

    location /hello-world {
    }

    location ~ /rutorrent/(conf|share)$ {
        alias /var/www/site/web;
    }

    location ~* /rutorrent/(conf|share)$ {
         # config ...
    }

    location ^~ /salut {
    }
}

Donc il y a 5 directives en tout, une vide et le reste = ~ ~* ^~

Nginx commence par les directives = s'il trouve rien il enchaine sur les directives vide ensuite ^~ ensuite ~ et ~*

Pour les directives = match exactement /coucoudans mon exemple. Ensuite il fait la routine que vous décidez dans location

Pour les directives vide comme celle-ci location /hello-world {} nginx match toutes les uri qui commence par /hello-world mais aussi /hello-world/jaime/ma/femme 🙂

Pour les directives ^~ elle empêche que d'autre location match l'uri que vous allez configurer, de plus vous pouvez utiliser les expressions régulières PCRE

Exemple :

location /rutorrent {}
location ^~ ^/rutorrent/conf/(.+)$ {}

Dans cet exemple la location location /rutorrent match aussi l'uri /rutorent/conf/blalbla
Et bien comme la location location ^~ ^/rutorrent/conf/(.+)$ {} match aussi la première location va se faire sortir. Et donc la deuxième location est prioritaire en quelque sorte.

Pour les autres directives ~ ~* ça indique que l'on peut utiliser les expressions régulières PCRE.
A la différence de ^~ les autres location peuvent match l'uri choisie.
~ sensible à la casse
~* insensible à la casse

Pour les expressions régulières vous pouvez tester sur des sites comme celui-ci si votre regex est correct.
exemple : http://www.regexpal.com/97251

Primary script unknown et SCRIPT_FILENAME

Pour parler de cette erreur je suis d'abord obligé de faire une petite explication sur les directives root et alias

Donc root sert à déterminer dans quel dossier nginx va travailler.
Il est d'ailleurs déconseillé de mettre root partout.
L'idéal est de mettre root dans server et d'éviter autant que possible d'en mettre dans les location.
Ex :

server {

    root /var/www;
    index index.html index.php;

    location /coucou {
        # on évite les directives root ici.
    }
    
    location /hello/world {
        alias /var/www/application/public;
    }
}

Ici contenu de cette configuration lorsque la requête /coucou est appelée, nginx va chercher soit :

  • le fichier /var/www/coucou/index.html
  • ou le fichier /var/www/coucou/index.php
  • ou une erreur 404 si les deux fichiers n'existent pas.

Pour la requête /hello/world c'est différent ici il y a une directive alias
C'est comme root à l'exception que nginx ne rajoute pas dans le chemin l'uri comme un dossier

Exemple avec comme root dans le vhost server /var/www

  • Sans rien et la requête /coucou nginx va résoudre comme ceci : /var/www/coucou
  • Avec alias et la requête /hello/world nginx va résoudre comme ceci : /var/www/application/public

Contenu de tout cela on peut maintenant regarder le problème avec php-fpm et SCRIPT_FILENAME

Pour cela j'ai une petite astuce pour debug que j'ai trouvé ici http://serverfault.com/a/754378

Ajouter ceci dans http {} dans normalement dans le fichier nginx.conf

http {
    log_format php '$document_root$fastcgi_script_name > $request';
}

et ajouter ceci dans le server concerné par le souci

server {
    access_log /var/log/nginx/php.log php;
}

on reload nginx

nginx -s reload

Maintenant il y a plus qu'à ajuster la configuration des location de root ou alias en fonction des logs

Voilà avec cela vous avez quelques armes pour vous débrouiller sur votre prochaine config nginx 😃

4 mois plus tard

Un grand merci pour ces explications claires et précises !!!
Ça faisait un moment que j'essayais de comprendre les conf de Nginx et ce petit cours m'éclaire beaucoup !!!
😄

2 ans plus tard

Pareil, ce post est ancien mais il m'a beaucoup aidé à comprendre le fonctionnement de nginx.
Un grand merci à toi 😃

    Répondre…