« Nginx » : différence entre les versions
(8 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
[[Category:Web]] | |||
= Configuration = | = Configuration = | ||
* [http://wiki.nginx.org/CoreModule Core Module] | * [http://wiki.nginx.org/CoreModule Core Module] | ||
Ligne 892 : | Ligne 893 : | ||
= [https://doc.owncloud.org/server/latest/admin_manual/installation/nginx_examples.html ownCloud] = | = [https://doc.owncloud.org/server/latest/admin_manual/installation/nginx_examples.html ownCloud] = | ||
= [ | = Mediawiki = | ||
== [https://www.mediawiki.org/wiki/Manual:Short_URL/Nginx Pretty URL avec php-fpm] == | |||
<filebox fn=/etc/nginx/nginx.conf lang=bash collapsed> | |||
# Explicit access to the root website, redirect to main page | |||
location = / { | |||
return 301 /wiki/Accueil; | |||
} | |||
location ^~ /cache/ { | |||
deny all; | |||
} | |||
# Allow access to those folders | |||
location ^~ /images/ { } | |||
location ^~ /sitemap/ { } | |||
location = /sitemap.xml { } | |||
# Handling for the article path (pretty URLs) | |||
location ^~ /wiki/ { | |||
rewrite ^/wiki/(?<pagename>.*)$ /index.php; | |||
} | |||
# Every other entry point will be disallowed | |||
location / { | |||
return 404; | |||
} | |||
# allow /api.php /load.php /rest.php/v1/search/title | |||
location ~ /\w+\.php { | |||
include snippets/fastcgi-php.conf; | |||
fastcgi_pass unix:/run/php/php-fpm.sock; | |||
} | |||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { | |||
try_files $uri =404; | |||
expires max; | |||
log_not_found off; | |||
} | |||
</filebox> | |||
<filebox fn=LocalSettings.php lang=php collapsed> | |||
$wgArticlePath = "/wiki/$1"; | |||
</filebox> | |||
== Pretty URL avec uwsgi == | == Pretty URL avec uwsgi == | ||
<filebox fn=/etc/nginx/nginx.conf lang=bash> | <filebox fn=/etc/nginx/nginx.conf lang=bash collapsed> | ||
# only in production | # only in production | ||
error_page 403 404 = /index.php; | error_page 403 404 = /index.php; | ||
Ligne 937 : | Ligne 981 : | ||
expires max; | expires max; | ||
} | } | ||
</filebox> | </filebox> | ||
<filebox fn=LocalSettings.php lang=php collapsed> | |||
<filebox fn=LocalSettings.php lang=php> | |||
$wgArticlePath = "/wiki/$1"; | $wgArticlePath = "/wiki/$1"; | ||
</filebox> | </filebox> | ||
== URL classique == | == [https://www.nginx.com/resources/wiki/start/topics/recipes/mediawiki/ URL classique] == | ||
<filebox fn=/etc/nginx/nginx.conf lang=bash> | <filebox fn=/etc/nginx/nginx.conf lang=bash collapsed> | ||
server { | server { | ||
listen 80; | listen 80; | ||
Ligne 1 046 : | Ligne 1 067 : | ||
sudo systemctl start nginx | sudo systemctl start nginx | ||
</kode> | </kode> | ||
{{info | The default served page at http://127.0.0.1 is /usr/share/nginx/html/index.html}} | {{info | The default served page at {{boxx|<nowiki>http://127.0.0.1</nowiki>}} is /usr/share/nginx/html/index.html}} | ||
Dernière version du 25 janvier 2025 à 20:57
Configuration
user
![]() |
Le user et le group par défaut est http. |
worker_processes
Idéalement égal au nombre de processeurs.
nproc
grep -c ^processor /proc/cpuinfo
|
pid
Définit dans quel fichier le Process Id du serveur Nginx est stocké.
Par défaut /run/nginx.pid
worker_connections
Définit le nombre maximum de connexions simultanées qu'un worker process peut ouvrir.
sendfile, tcp_nopush et tcp_nodelay
- tcp_nodelay force l’envoi immédiat des données contenues dans la socket, quelle que soit la taille du paquet.
- tcp_nopush fait exactement le contraire de tcp_nodelay, il force à n’envoyer que des paquets ayant atteint la MSS, qui est égale au MTU moins les 40 octets d’en-tête.
- sendfile force l’utilisation de l’appel système sendfile(2) pour tout ce qui concerne l’envoi de fichiers. Très performant pour les fichiers statiques stockés localement.
keepalive_timeout
Temps en secondes pendant lequel la connexion restera ouverte.
gzip
Zipper les réponses.
/etc/nginx/nginx.conf |
gzip on;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types application/javascript image/svg+xml text/css;
|
Configuration du bloc server
listen
Définit l'adresse et le port qui seront écoutés.
/etc/nginx/nginx.conf |
# default_server définit le serveur par défaut si aucune correspondance n'est trouvée
listen 80 default_server;
|
server_name
Détermine quel bloc server sera utilisé en fonction de la requête.
Ordre de priorité:
- exact name
- longest wildcard name starting with an asterisk, e.g. “*.example.org”
- longest wildcard name ending with an asterisk, e.g. “mail.*”
- first matching regular expression (in order of appearance in a configuration file)
![]() |
Si aucun server_name ne correspond c'est le serveur possédant l'instruction listen 80 default_server qui sera utilisé, sinon le premier serveur. |
root
Définit le chemin le dossier racine pour les requêtes.
Un root différent peut être définit pour chaque location.
![]() |
Si le chemin contient des espaces l'encadrer avec des guillemets simple. |
index
Définit les fichiers à utiliser lorsque la requête se termine par /.
Encodage de caractères
Définit l'encodage de caractères par défaut pour les types text/plain or text/html.
Cette définition écrase celle spécifiée dans la balise meta.
/etc/nginx/nginx.conf |
charset utf-8; |
error_log
/etc/nginx/nginx.conf |
# par défaut
error_log stderr error; # écrit dans le journal à partir du niveau error
server {
# définir un fichier particulier pour le log
error_log /var/log/nginx/mon_site_error.log;
|
![]() |
Il n'est pas possible de modifier le format du log d'erreurs: YYYY/MM/DD HH:MM:SS [LEVEL] PID#TID: *CID MESSAGE |
access_log
/etc/nginx/nginx.conf |
# par défaut
access_log /var/log/nginx/access.log combined; # écrit dans le fichier access.log au format combined
# format combined
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
server {
# définir un fichier particulier pour le log
access_log /var/log/nginx/mon_site_access.log;
# désactiver le log access
access_log off;
# ne pas logguer les erreurs de fichiers non trouvés
log_not_found off;
# compresser le log
access_log /path/to/log.gz combined gzip=9 flush=5m;
# By default, the buffer size is equal to 64K bytes, and the compression level is set to 1.
# The compression level can be set between 1 (fastest, less compression) and 9 (slowest, best compression).
|
![]() |
« nginx -V » pour obtenir les valeurs par défaut des variables définies lors de la compilation.
|
![]() |
Les conditions ne fonctionnent qu'à partir de la version 1.7: invalid parameter "if=loggable" |
log_format
/etc/nginx/nginx.conf |
# formats prédéfinits
http {
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
# combined + $http_x_forwarded_for
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# pour un log multi serveur car il contient $server_name
log_format global '[$time_local] $status $server_name '
'$remote_addr "$request" - '
'"$http_referer" - "$http_user_agent"';
|
$time_local | heure à laquelle la requête a été trairée |
$status | code de retour: 200 Ok, 403 Forbidden, 404 Not Found |
$remote_addr | adresse ip du client |
$http_referer | url de la page précédente |
$request | la requête |
$http_user_agent | information sur le client: logiciel, OS |
$request_time | temps de traitement de la requête |
$server_name | le nom du serveur correspondant à la requête |
$http_x_forwarded_for | vraie adresse ip du client provenant d'un proxy HTTP ou d'un répartiteur de charge |
$cookie_COOKIE | contenu du cookie COOKIE |
$http_HEADER | contenu du header HEADER (ex: http_user_agent) |
map
/etc/nginx/nginx.conf |
# les ip locales 192.168.0.x ne seront pas loguées
# map doit être définit dans http
map $remote_addr $loggable {
~^192\.168\.0\. 0; 0; # 0 → ne pas logguer
default 1;
}
access_log /path/to/access.log combined if=$loggable;
# utiliser plusieurs paramètres en les concaténant en un seul string
# les tests de correspondance se font donc sur ce string concaténé
map $remote_addr$request $loggable {
~^192\.168\.0\. 0; # ne pas logguer les ip 192.168.0.x
"~*GET /wiki/" 1; # logguer les requêtes qui contiennent GET /wiki/
default 0; # ne pas logguer le reste
}
|
Buffer limitations
/etc/nginx/nginx.conf |
# default is 8k or 16k
client_body_buffer_size 1K;
client_header_buffer_size 1k;
# If size is greater the given one, then the client gets the error "Request Entity Too Large" (413).
# Increase this when you are getting file uploads via the POST method.
client_max_body_size 1k;
# Default: large_client_header_buffers 4 8k;
# Context: http, server
large_client_header_buffers 8 32k;
# Default: proxy_buffers 8 4k|8k;
# Context: http, server, location
proxy_buffers 8 32k;
# Default: proxy_buffer_size 4k|8k;
# Context: http, server, location
proxy_buffer_size 64k;
|
Timeout
/etc/nginx/nginx.conf |
# The default is 60
client_body_timeout 10;
client_header_timeout 10;
keepalive_timeout 5 5;
send_timeout 10;
|
location
Permet de modifier la configuration en fonction de la requête.
/etc/nginx/nginx.conf |
server {
# correspond seulement à la requête /
location = / { }
# emplacement par défaut
# si aucun autre emplacement ne correspond, c'est celui-ci qui sera utilisé
location / { }
# correspond aux requêtes commençant par /mon_dossier/
# mais la recherche de correspondances continue
location /mon_dossier/ { }
# correspond aux requêtes commençant par /mon_dossier2/
# la recherche de correspondances s'arrête ici: ^~
location ^~ /mon_dossier2/ { }
# expressions rationnelles: ~ sensible à la casse ~* insensible à la casse
location ~* \.(gif|jpg|jpeg)$ { }
location ~ /(dossier1|dossier2)/ { }
# les locations peuvent s'imbriquer
location /dossier/ {
location ~* \.png$ { }
}
|
Ordre de vérification des correspondances:
- Directives avec le préfixe « = ». S'il y a correspondance la recherche s'arrête là.
- Directives avec une chaîne de caractères. La recherche continue sauf si le prefix « ^~ » a été utilisé.
En cas de correspondances multiples c'est la directive la plus longue qui l'emporte. - Directives avec une expression rationnelle dans l'ordre dans lesquelles elles ont été définies.
S'il n'y a pas de correspondance, c'est la correspondance avec la directive n°2 la plus longue qui est utilisée.
![]() |
^~ ne fonctionne pas avec les regex. |
![]() |
Les arguments (arg=value) ne sont pas pris en compte pour la correspondance. |
Configuration du bloc location
allow / deny
/etc/nginx/nginx.conf |
# interdit l'accès au site à tous sauf à 192.168.0.0/24
allow 192.168.0.0/24;
deny all;
# interdit l'accès aux pages dont l'url contient Spécial à tous sauf à 192.168.0.1
location ~ Spécial {
allow 192.168.0.1;
deny all;
}
# utilisation d'un fichier de configuration contenant toutes les ip à exclure
include /etc/nginx/blacklist;
|
/etc/nginx/blacklist |
deny x.x.x.x; deny y.y.y.y; |
![]() |
Les autorisations sont analysées dans l'ordre, la première correspondance est appliquée. Il faut donc les écrire des plus spécifiques aux plus globales. |
![]() |
En cas d'interdiction le serveur envoie le signal d'erreur 403 Forbidden |
internal
Restreint l'accès aux requêtes internes.
![]() |
Dans le cas d'une requête externe, l'erreur 404 est renvoyée. |
try_files
Test si $uri existe, si ce n'est pas le cas, test si uri/fichier1.html existe puis $uri/fichier2.html
Si un des fichiers existe, il est utilisé. Si aucun fichier de la liste n'existe, une redirection interne est faite vers le dernier.
/etc/nginx/nginx.conf |
try_files $uri $uri/fichier1.html $uri/fichier2.html;
# Si aucun fichier de la liste n'existe, redirection vers la location @other
try_files $uri $uri/fichier1.html $uri/fichier2.html @other;
location @other { }
# génère l'erreur 404 si aucun fichier de la liste n'existe
try_files $uri $uri/fichier1.html $uri/fichier2.html =404;
|
rewrite
/etc/nginx/nginx.conf |
# réécrit les urls: /index.php?title=Sujet → /index.php/Sujet
location = /index.php {
rewrite .* /index.php/$arg_title? permanent;
}
# réécrit les urls: /index.php/Sujet → /index.php?title=Sujet
location / {
try_files $uri $uri/ @rewrite;
}
location @rewrite {
rewrite ^/(.*)$ /index.php?title=$1&$args;
}
|
![]() |
Les arguments sont ajoutés à la fin de la nouvelle. Pour éviter cela, ajouter un '?' à la fin de la nouvelle url. |
alias
/etc/nginx/nginx.conf |
root /srv/http/mon_site;
location ^~ /autre_dossier {
alias /un/autre/dossier;
# la requête /autre_dossier/fichier.html reverra le fichier /un/autre/dossier/fichier.html
# alors que la requête /dossier/fichier.html reverra le fichier /srv/http/mon_site/fichier.html
}
# Si la location correspond à la fin de l'alias, il est préférable d'utiliser la directive root
location ^~ /dossier {
alias /data/dossier;
}
location ^~ /dossier {
root /data;
}
|
error_page
Permet de définir les pages à afficher en cas d'erreurs.
/etc/nginx/nginx.conf |
# redirige vers la page 404.html en cas d'erreur 404
error_page 404 /404.html;
# redirige vers la page 404.html en cas d'erreur 404 et retourne le code 200 au lieu du code 404
error_page 404 =200 /404.html;
# pourl'erreur 403 (forbidden), il faut en plus authoriser l'accès à la page d'erreur
error_page 403 /error403.html;
location = /error403.html {
# internal: page error403.html accessible seulement via ce mécanisme et pas directement
internal;
allow all;
}
|
Index Of
/etc/nginx/nginx.conf |
autoindex on;
# par défaut à off
|
expires
/etc/nginx/nginx.conf |
# forcer les scripts, css et images à rester en cache
location ~* \.(js|css|swf|png|jpg|jpeg|gif|ico|bmp|svg)$ {
expires max;
access_log off;
}
|
- max → sets the Expires header to 31 December 2037 23:59:59 GMT
- 10d → en cache pendant 10 jours (m: minutes, h: hours, d: days, w: weeks, M: months, y: years)
Virtual Hosts
Les hôtes virtuels de NGINX sont appelés blocs serveur.
/etc/nginx/nginx.conf |
http {
# hôte virtuel site1
server {
server_name site1;
}
# hôte virtuel site2 ou alias2 ou *.domain.com ou une expression rationnelle
server {
server_name site2 alias2 *.domain.com ~^www\d+\.example\.com$;
}
# hôte virtuel par défaut
# si aucune autre correspondance n'a été faite, c'est cet hôte qui est utilisé
server {
listen 80 default_server;
index index.html;
root /usr/share/nginx/html;
}
|
Rewrite rules
/etc/nginx/nginx.conf |
# redirection d'un ancien domaine vers un nouveau
server {
server_name www.old-name.com old-name.com;
return 301 $scheme://www.new-name.com$request_uri;
}
# Enabling pretty permalinks
location / {
try_files $uri $uri/ /index.php?$args;
}
# Dropping requests for unsupported file extensions
location ~ .(aspx|php|jsp|cgi)$ {
deny all;
}
# Custom rerouting
rewrite ^/listings/(.*)$ /listing.html?listing=$1 last;
|
if
/etc/nginx/nginx.conf |
location / {
if ($my_var) { # vrai si $my_var non-vide et différente de '0'
return 200;
}
if (!-e $my_var) { # not
return 200;
}
|
Variables
variable | valeur | commentaire |
---|---|---|
$1 .. $9 | correspond aux groupes 1 à 9 dans le cadre d'une expression rationnelle | |
$document_root | /srv/http/monsite | définit par la directive root /usr/share/webapps/mysite; |
$fastcgi_script_name | /page.php | nom du fichier de script |
$fastcgi_path_info | /article/123 | pour la requête /page.php/article/123 |
$uri | /page.php/article/123 | pour la requête /page.php/article/123 |
$arg_name | text | pour la requête /page.php?name=text |
Limitation d'accès
Authentification simple
/etc/nginx/nginx.conf |
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
|
/etc/nginx/.htpasswd |
user_name:mot_de_passe_hashé |
# génération de la ligne a ajouter au fichier de mots de passe (/etc/nginx/.htpasswd)
printf "USER:$(openssl passwd -apr1)\n" >> /etc/nginx/.htpasswd
# -apr1 → MD5-based password algorithm, Apache variant
|
htpasswd
![]() |
htpasswd fait partie du paquet apache |
# création du fichier .htpasswd et ajout de l'utilisateur user_name
htpasswd -c /etc/nginx/.htpasswd user_name
# ajout d'autres utilisateur une fois le fichier créé
htpasswd /etc/nginx/.htpasswd user_name
# afficher l'utilisateur et le mot de passe haché dans la console
htpasswd -n user_name
|
![]() |
Sécurité
Par défaut, c'est l’algorithme MD5 qui est utilisé pour encrypter les mots de passe. Il utilise un grain de sel (salt). |
Connexions simultanées
/etc/nginx/nginx.conf |
# définition de la zone mémoire partagée, utilisée pour partager le compteur associé à la clé de la zone mémoire
# limit_conn_zone CLÉ zone=NOM:TAILLE;
limit_conn_zone $binary_remote_addr zone=addr:10m;
# définit la limitation du nombre de connexions simultanées
limit_conn addr 1;
|
![]() |
$binary_remote_addr → adresse IP du client. Permet de définir une limitation du nombres de connexions simultanées par client (adresse IP). $server_name → nom du serveur. Permet de définir une limitation du nombres de connexions simultanées par serveur. |
Nombre de requêtes par seconde
Permet de limiter le nombre de requêtes par seconde provenant d'une même ip, et ainsi de se protéger contre le flood / DoS.
/etc/nginx/nginx.conf |
# créé une zone de 10 megabyte appelée « flood »
# elle enregistrera le nombre de requêtes par clé,
# ici $binary_remote_addr (adresse ip du client au format binaire pour économiser de l'espace mémoire)
# 1r/s → 1 requête par secondes ; 30r/m → 30 requêtes par minutes
limit_req_zone $binary_remote_addr zone=flood:10m rate=1r/s;
# applique la limitation de requête
# si le nombre de requêtes dépasse le ratio
# les requêtes suivantes sont mise en attente dans la limite de burst (par défaut à 0)
# au delà de burst les requêtes sont terminées avec le code d'erreur 503 (Service Temporarily Unavailable)
limit_req zone=flood burst=5;
# l'option nodelay permet de traiter les requêtes burst sans délai (plus de respect du ratio)
# rate=5r/s équivalent à rate=1r/s burst=4 nodelay
# définit le status à envoyer au client lorsqu'on termine la requête (503 par défaut)
limit_req_status 444;
# 444 code spécifique à nginx fermant la connexion et n'envoyant pas de réponse au client
|
Exemple: limit_req_zone $binary_remote_addr zone=flood:10m rate=1r/s; limit_req zone=flood burst=2 nodelay; Envoie de 3 requêtes par secondes pendant 3 secondes Req.# | Time (sec) | Response 1 0 200 OK rate=1r/s 2 0 200 OK burst +1=1 3 0 200 OK burst +1=2 1 burst -1=1 4 1 200 OK rate=1r/s 5 1 200 OK burst +1=2 6 1 503 burst=2 requête rejetée 2 burst -1=1 7 2 200 OK rate=1r/s 8 2 200 OK burst +1=2 9 2 503 burst=2 requête rejetée
Sécurité
- Qualys SSL test
- Test des headers
- Hardening your HTTP response headers
- Guide to Deploying Diffie-Hellman for TLS
/etc/nginx/nginx.conf |
# hsts, 31536000 s = 1 an
add_header Strict-Transport-Security "max-age=31536000";
# upgrade-insecure-requests → ensures that any HTTP assets are loaded using HTTPS
add_header Content-Security-Policy "upgrade-insecure-requests";
# hide the server version
server_tokens off;
# By preventing a browser from framing your site you can defend against attacks like clickjacking
add_header X-Frame-Options "SAMEORIGIN" always;
# blocks the response if it detects a cross-site script.
add_header X-Xss-Protection "1; mode=block" always;
# support de Forward Secrecy (défaut: HIGH:!aNULL:!MD5)
ssl_ciphers "HIGH:!aNULL:!MD5:!3DES";
ssl_prefer_server_ciphers On;
# Diffie-Hellman pour TLS
ssl_dhparam /path/dhparams.pem;
# fichier à générer avec: openssl dhparam -out dhparams.pem 2048
# performances
ssl_stapling on;
ssl_session_cache shared:SSL:10m;
|
/etc/uwsgi/mysite.ini |
; masquer le header X-Powered-By PHP/x.x.x
php-set = expose_php=Off
|
SSL
Création d'un certificat
# choisir le dossier qui contiendra le certificat
cd /etc/ssl/private
# créer la clé privée
# nombre de bits : 2048 ou 4096
openssl genrsa -out server.key 4096
chmod 400 server.key
# créer le Certificate Signing Request (CSR)
openssl req -new -sha512 -key server.key -out server.csr
# Common Name doit correspondre au nom d'hôte (serveur.domaine.fr ou *.domaine.fr)
# The "challenge password" is basically a shared-secret nonce between you and the SSL issuer, embedded in the CSR,
# which the issuer may use to authenticate you should that ever be needed.
# par défaut sha1 est utilisé
# signer le certificat
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
|
Configuration
/etc/nginx/nginx.conf |
# redirection vers https
server {
server_name site.domaine.fr;
listen 80;
return 301 https://$server_name$request_uri;
}
server {
server_name site.domaine.fr;
listen 443 ssl;
ssl_certificate /etc/ssl/private/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
}
|
Découper le fichier de configuration
/etc/nginx/nginx.conf |
include /etc/nginx/servers/*.conf; |
/etc/nginx/servers/serveur1.conf |
server { listen 80; server_name serveur1.mon-domaine.fr; root /srv/http/serveur1; index index.php; include /etc/nginx/php_files.conf; } |
/etc/nginx/php_files.conf |
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
include /etc/nginx/fastcgi.conf;
}
|
status
Permet de connaître
- le nombre de connexions actuellement ouvertes
- le nombre de connexions acceptés
- le nombre de requêtes gérées
- le nombre de requêtes par seconde = handles requests / handled connections
/etc/nginx/nginx.conf |
location /status { stub_status on; access_log off; allow x.x.x.x; deny all; } |
Bloquer certains user-agents
/etc/nginx/nginx.conf |
# bloque les user-agents wget et curl
if ($http_user_agent ~ (Wget|curl) ) {
return 403;
}
|
![]() |
|
if / else
/etc/nginx/nginx.conf |
if ($request_method = POST ) {
return 405;
}
# astuce pour les conditions multiples
set $test "";
if ($request_method = POST) {
set $test P;
}
if ($http_cookie_cccc) {
set $test "${test}C";
}
if ($test = PC) {
# rewrite rule goes here.
}
# redirection vers une autre location
location / {
error_page 418 = @other;
recursive_error_pages on;
if ($something) {
return 418;
}
}
location @other { }
|
uwsgi
uwsgi_modifier1
modifier1 | packet type |
---|---|
9 | Standard Running CGI scripts on uWSGI request followed by the HTTP request body |
14 | Standard Running PHP scripts in uWSGI request followed by the HTTP request body |
30 | Standard WSGI request followed by the HTTP request body. The PATH_INFO is automatically modified, removing the SCRIPT_NAME from it |
uwsgi_read_timeout
location ~ \.php5?$ {
# par défaut à 60s
uwsgi_read_timeout 90;
|
PHP
php-fpm
# installation
sudo pacman -S php-fpm
# démarrage du service
sudo systemctl start php-fpm
# démarrer php-fpm au démarrage du système
sudo systemctl enable php-fpm
|
/etc/nginx/nginx.conf |
server {
listen 80;
server_name myserver;
root /srv/http/myserverfolder;
index index.html index.htm index.php;
location ~ \.php$ {
# test si le fichier php existe, sinon affiche l'erreur 404 au lieu du message "File not found."
try_files $uri =404;
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
include /etc/nginx/fastcgi.conf;
# augmente le temps d'attente d'une réponse, par défaut à 60s
fastcgi_read_timeout 300;
}
}
|
502 Bad Gateway | php-fpm n'est pas démarré |
504 Gateway Time-out |
|
log
![]() |
Ne semble pas marcher. |
/etc/php/php-fpm.d/www.conf |
php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_flag[log_errors] = on
|
# créer le fichier de log avec les bons droits
touch /var/log/fpm-php.www.log
chmod 777 /var/log/fpm-php.www.log
|
Empêcher les fichiers non-PHP d'être traiter par PHP
nginx gère l'url http://mon.site/image.gif/somefilename.php de cette façon:
- comme l'url se termine par php, elle est transmise au gestionnaire de FastCGI PHP
- PHP examine le path, trouve le fichier image.gif, et stocke /somefilename.php dans $_SERVER['PATH_INFO'], puis execute le contenu du fichier GIF comme du PHP.
Comme les formats d'images peuvent contenir un contenu arbitraire. Il est possible qu'une image contiennent du code PHP malveillant.
Solutions:
- cgi.fix_pathinfo=1 dans le fichier /etc/php/php.ini. Pose problème avec Wordpress.
- try_files $uri =404; dans le bloc location du fichier /etc/nginx/nginx.conf. Fonctionne si nginx et le gestionnaire de script FastCGI PHP sont sur le même serveur.
- Ajoutez un bloc location qui détecte les mauvaises URL.
- Exclure explicitement les urls d'upload du block location.
- Ne pas stocker sur le même serveur les fichiers uploadés et le gestionnaire de script FastCGI PHP.
Cache PHP
Modifiez la configuration PHP
/etc/nginx/nginx.conf |
set $session_root /var/www/dev/$1/sessions;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/other/folder\nsession.save_path=$session_root";
|
![]() |
L'utilisation de PHP_ADMIN_VALUE pose problème: une fois que le serveur contenant la directive est atteint la modification de la configuration PHP se propage à tous les serveur. |
ASP.NET
.Net Core
/etc/nginx/sites-available/webapp.conf |
server {
listen 80;
server_name webapp.local;
location ^~ /api/ {
rewrite ^/api(/.*)$ $1 break;
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://localhost:5001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
|
HTTP Status Codes spécifiques à Nginx
Comparaison des modules Nginx / Apache / Lighttp
Modules
echo
/etc/nginx/nginx.conf |
load_module /usr/lib/nginx/modules/ngx_http_echo_module.so;
http {
server {
location / {
default_type text/plain;
echo "hello, world!";
echo_sleep 1; # wait 1 second
|
njs
/etc/nginx/nginx.conf |
load_module /usr/lib/nginx/modules/ngx_http_js_module.so;
http {
js_include /etc/nginx/scripts/my_script.js;
server {
location / {
default_type text/plain;
js_content my_function;
|
/etc/nginx/scripts/my_script.js |
function my_function(r) {
r.return(200, "Hello world!");
// redirection
r.return(302, 'http://domain.net');
}
function read_file() {
var fs = require('fs');
try {
// throw an exception if the file doesn't exist
var file_content = fs.readFileSync('/tmp/my_file.txt', 'utf8');
if (file_content === '0\n') {
// ...
}
} catch (e) {
}
}
|
Erreurs
could not build optimal types_hash, you should increase either types_hash_max_size: 1024 or types_hash_bucket_size: 6
/etc/nginx/nginx.conf |
# just below keepalive_timeout
# increase from default 1024 to 4096
types_hash_max_size 4096;
|
could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32
Nom de serveur trop long par rapport aux règlages → augmenter la taille autorisée des noms de serveur.
/etc/nginx/nginx.conf |
http { server_names_hash_bucket_size 64; |
client intended to send too large body
Augmenter la valeur de client_max_body_size
/etc/nginx/nginx.conf |
http, server, location {
client_max_body_size 20m; # default 1m
|
ownCloud
Mediawiki
Pretty URL avec php-fpm
/etc/nginx/nginx.conf |
LocalSettings.php |
Pretty URL avec uwsgi
/etc/nginx/nginx.conf |
LocalSettings.php |
URL classique
/etc/nginx/nginx.conf |
![]() |
Le fichier robots.txt devra correspondre aux urls de type /index.php?title=MonTitre |
Wordpress
/etc/nginx/nginx.conf |
server {
location / {
try_files $uri $uri/ /index.php?$args;
}
# Add trailing slash to */wp-admin requests.
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
# Directives to send expires headers and turn off 404 error logging.
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|
jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
# Uncomment one of the lines below for the appropriate caching plugin (if used).
#include global/wordpress-wp-super-cache.conf;
#include global/wordpress-w3-total-cache.conf;
# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ [^/]\.php(/|$) {
include uwsgi_params;
uwsgi_modifier1 14;
uwsgi_pass unix:/run/uwsgi/wordpress.sock;
}
}
|
![]() |
Wordpress a besoin d'autoriser l'ip du serveur pour ses taches cron. |
Installation
sudo pacman -S nginx
# démarrer le serveur
sudo systemctl start nginx
|
![]() |
The default served page at http://127.0.0.1 is /usr/share/nginx/html/index.html |