server { listen 80; server_name _; root /var/www/html; index index.php; charset utf-8; client_max_body_size 64M; # Ne pas annoncer la version du serveur. server_tokens off; # ------------------------------------------------------------------------ # ORDRE IMPORTANT # nginx évalue les expressions régulières dans l'ordre du fichier et retient # la PREMIÈRE qui correspond. Tous les blocs de refus doivent donc précéder # le bloc générique « location ~ \.php$ », sinon ils ne s'appliquent jamais # et les fichiers d'amorçage deviennent exécutables depuis le navigateur. # ------------------------------------------------------------------------ # Fichiers inclus par l'application, jamais des points d'entrée. location ~* ^/(config|db|page_bootstrap)\.php$ { deny all; return 404; } # Classes, modèles, schémas SQL et documentation de version. location ^~ /app/ { deny all; return 404; } location ^~ /database/ { deny all; return 404; } location ^~ /docker/ { deny all; return 404; } location ~* ^/README[^/]*$ { deny all; return 404; } # Configuration, dumps et journaux ne doivent jamais être téléchargeables. location ~* \.(?:env|sql|sql\.gz|ini|log|bak|dump|yml|yaml|md)$ { deny all; return 404; } # Fichiers et dossiers cachés (.env, .git, .htaccess…). location ~ /\. { deny all; return 404; } # ------------------------------------------------------------------------ # Contenus servis # ------------------------------------------------------------------------ location ~* \.(?:css|js|png|jpg|jpeg|gif|svg|ico|webp)$ { expires 7d; add_header Cache-Control "public, max-age=604800"; # Les réponses PHP portent leurs propres en-têtes de sécurité, CSP à # nonce comprise (App\Core\Security) ; ici on couvre le statique. add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer" always; try_files $uri =404; } location ~ \.php$ { try_files $uri =404; include fastcgi_params; fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param HTTP_PROXY ""; # Les erreurs PHP restent gérées par l'application (JSON ou page HTML) : # nginx ne les remplace pas par ses propres pages. fastcgi_intercept_errors off; fastcgi_read_timeout 120s; } location / { try_files $uri $uri/ /index.php?$query_string; } }