BACKGROUND:
I am running a LEMP server with Ubuntu Server 20.04 with Nginx v1.25.1 Mainline and php7.4-fpm. In my virtual hosts file I am trying to set the proper and working fastcgi_split_path_info
in the location ~ \.php$ {
directive, but I'm not sure exactly what to put as the value, and I don't think my current fastcgi_split_path_info
is correct.
NOTE: Instead of using "try_files $fastcgi_script_name =404
", I am using the "if
" statement
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
recommended by Nginx.org. I'm not sure if this matters when splitting fastcgi path info, but it should be noted just in case.
NOTE2: I am using cgi.fix_pathinfo = 1
(which is the default for PHP 7.4) in my php.ini
file.
QUESTION:
Could someone please take a look at my Nginx Virtual host and tell me the correct value that I should put for fastcgi_split_path_info
in location ~\.php$
?
Below is my Nginx virtual host example.com.conf
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen *:443 ssl;
http2 on;
server_name example.com www.example.com;
root /var/www/example.com/;
##
# SECURITY HEADERS
##
# Strict Transport Security Response Header
# Use "always" Paramater to help prevent MITM attacks.
# ADMIN Note: Including the Preload Paramerter will cause web browsers to cache this header
# permanently in their browser code for about two months. Use only if you want to permanently
# commit this header to your site. If you change it, it will take a long time for changes to
# be reflected in the web browsers.
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Content Security Policy (CSP)
#add_header Content-Security-Policy "frame-ancestors 'self';";
# https://gabriel.nu/tutorials/Ubuntu-20.04-NGINX-LEMP-secure-web-server-for-WordPress-DIY.html
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
#add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'";
# https://walterebert.com/blog/using-csp-wordpress/
#add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: http: https: *.gravatar.com; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' http: https: fonts.googleapis.com; font-src 'self' data: http: https: fonts.googleapis.com themes.googleusercontent.com;" always;
# https://nowherelan.com/2018/12/27/secure-your-wordpress-site-with-the-content-security-policy-csp-http-header-in-apache/
#add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: http: https: *.gravatar.com *.wp.com *.wordpress.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' http: https: *.wp.com *.wordpress.com; style-src 'self' 'unsafe-inline' http: https: fonts.googleapis.com *.wp.com *.wordpress.com; font-src 'self' data: http: https: fonts.googleapis.com themes.googleusercontent.com *.wp.com *.wordpress.com; frame-src 'self' 'unsafe-inline' 'unsafe-eval' http: https: *.wp.com *.wordpress.com"
# Secure MIME Types with X-Content-Type-Options. Below line adds the X-Frame-Options header in Nginx.
add_header X-Content-Type-Options "nosniff" always;
# Referrer Policy
#add_header Referrer-Policy "strict-origin";
# https://gabriel.nu/tutorials/Ubuntu-20.04-NGINX-LEMP-secure-web-server-for-WordPress-DIY.html
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Permissions Policy
add_header Permissions-Policy "geolocation=(), autoplay=(), encrypted-media=(), midi=(), usb=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(self), payment=(self)";
# X-FastCGI-Cache
# This line adds the X-FastCGI-Cache header in the HTTP response. It can be used to validate whether
# the request has been served from the FastCGI cache or not.
# ADMIN Note: Linuxbabe originally had this directive in "location ~ \.php$ {", however, we don't use it
# there because it invalidates any other currently used headers and only implements itself.
add_header X-FastCGI-Cache $upstream_cache_status always;
# Clear Site Data
# When we use a webpage, we can leave various pieces of data in the browser that we’d like to clear
# out if the user logs out or deletes their account. Clear Site Data gives us a reliable way to do
# that.
# ADMIN Note: We decided to enable it globally on all pages via:
add_header Clear-Site-Data "*";
# X-Frame Options
# Prevent click jacking by adding an X-Frame-Options header
add_header x-frame-options "SAMEORIGIN" always;
# X-SSS Protections
# Enable X-XSS-Protection header in Nginx
add_header X-XSS-Protection "1; mode=block" always;
# LINUXBABE
# If you allow people to upload files, or are concerned about intruders using a different flaw to get
# files onto your server AND the content on your domain should not be accessed via other websites
# possibly trying to impersonate you, then yes X-Permitted-Cross-Domain-Policies "none" will provide a
# security benefit. The attack is less relevant these days, as any user of modern software first
# needs to be tricked into allowing Flash or active PDF content.
# If your website is just a regular website with nothing that requires a login to access, then you don't need it.
# https://www.linuxbabe.com/ubuntu/install-wordpress-ubuntu-20-04-nginx-mariadb-php7-4-lemp
# https://security.stackexchange.com/questions/166024/does-the-x-permitted-cross-domain-policies-header-have-any-benefit-for-my-websit
add_header X-Permitted-Cross-Domain-Policies none;
# LINUXBABE (User recommendation)
# Ignore Cache Control
# Keep fastcgi working if it's not getting hits
# ADMIN Note: Only use this if fastcgi cache status is not getting hits
#fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
##
# SSL
##
# Certificate Path (signed)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # Managed by ADMIN
# Certificate Path (intermediate)
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # Managed by ADMIN
# Certificate Path (Chain of trust of OCSP response using Root CA and intermediate certificates)
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; # Managed by ADMIN
# Perfect Forward Secrecy (Diffie Hellman 4096) Path
ssl_dhparam /etc/ssl/private/dhparams4096.pem; # Managed by ADMIN
# Mozilla Modern Compatibilty
# Strict Settings with OCSP stapling turned on for A+ Rating at ssllabs.com
ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLERequires nginx >= 1.13.0 else use TLSv1.2 # Dropping TLSv1.1 for modern compatability.
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
ssl_prefer_server_ciphers on;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # About 40000 sessions
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1;
##
# LOGS
##
# ADMIN Note: Adding "if=$log_ip" to the end of access log lines will exclude your own ip address from access logs to prevent skewing data
# Access Log (Netdata)
access_log /var/log/nginx/example.com.access.log netdata if=$log_ip;
# Access Log (Amplify)
access_log /var/log/nginx/example.com.access.log apm if=$log_ip;
# Error Log
error_log /var/log/nginx/example.com.error.log warn;
##
# PAGESPEED
##
# ADMIN Note: Pagespeed is broken on Nginx v1.25.1 and up, so we should comment all of it out here and in the "nginx.conf" file
# Settings per this virtual host
# Enable Pagespeed module
#pagespeed on;
#pagespeed Domain http*://*.example.com;
# Settings per all virtual hosts
#include /etc/nginx/pagespeed.conf;
##
# LOCATION DIRECTIVES 1
##
index index.php index.html index.htm index.nginx-debian.html;
# ADMIN
# https://serverfault.com/questions/1137324/difference-between-3-similar-nginx-location-directives-provided-in-three-separat/1137342#1137342
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
### BEGIN: "Converter for Media" Wordpress Plugin
set $ext_avif ".avif";
if ($http_accept !~* "image/avif") {
set $ext_avif "";
}
set $ext_webp ".webp";
if ($http_accept !~* "image/webp") {
set $ext_webp "";
}
location ~ /wp-content/(?<path>.+)\.(?<ext>jpe?g|png|gif|webp)$ {
add_header Vary Accept;
expires 365d;
try_files
/wp-content/uploads-webpc/$path.$ext$ext_avif
/wp-content/uploads-webpc/$path.$ext$ext_webp
$uri =404;
}
### END: "Converter for Media" Wordpress Plugin
# ADMIN
# https://serverfault.com/questions/755662/nginx-disable-htaccess-and-hidden-files-but-allow-well-known-directory
# location ~ /.well-known {
location ~ /\.well-known {
allow all;
}
# ADMIN
location = /favicon.ico {
log_not_found off;
access_log off;
}
# ADMIN
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# LINUXBABE
location ~ ^/wp-json/ {
rewrite ^/wp-json/(.*?)$ /?rest_route=/$1 last;
}
# LINUXBABE
location ~ /wp-sitemap.*\.xml {
try_files $uri $uri/ /index.php$is_args$args;
}
# LINUXBABE
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
# LINUXBABE
location = /50x.html {
root /var/www/html;
}
# ADMIN
# DISALLOW ACCESS of /xmlrpc.php
# EXCEPT FROM internal IP's and Home & Apartment IP's.
#location ^~ /xmlrpc.php$ {
#allow xxx.xxx.xx.x/24; # LAN IP Address
#allow xxx.xxx.xx.x/32; # Home IP address
#allow xxx.xxx.xx.x/32; # Apt. IP Address
#deny all;
#}
# ADMIN
# DISALLOW ACCESS of /admin
# EXCEPT FROM internal IP's and Home & Apartment IP's
location ^~ /admin/ {
#satify all;
allow xxx.xxx.xx.x/24; # LAN IP Address
allow xxx.xxx.xx.x/32; # Home IP address
allow xxx.xxx.xx.x/32; # Apt. IP Address
deny all;
# Require basic auth login for allowed IP's
auth_basic "You Don't belong here. Get out!";
auth_basic_user_file /etc/nginx/basic_auth/auth.admin;
}
# ADMIN
# DISALLOW ACCESS of /wp-login.php
# EXCEPT FROM internal IP's and Home & Apartment IP's.
#location ^~ /wp-login.php {
#allow xxx.xxx.xx.x/24; # LAN IP Address
#allow xxx.xxx.xx.x; # Home IP address
#allow xxx.xxx.xx.x; # Apt. IP Address
#deny all;
# Require basic auth login for allowed IP's
#auth_basic "You Don't belong here. Get out!";
#auth_basic_user_file /etc/nginx/basic_auth/auth.wp-login;
#}
# ADMIN
# DISALLOW ACCESS of PHP In Upload Folder
location /wp-content/uploads/ {
location ~ \.php$ {
deny all;
}
}
# ADMIN
# DISALLOW ACCESS of hidden files
location ~ /\. {
access_log off;
log_not_found off;
deny all;
}
##
# BEGIN: CACHE / SKIP CACHE
##
# LINUXBABE
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
# Don't Skip Cache by Default
set $skip_cache 0;
# LINUXBABE
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
# POST requests should always go to PHP
if ($request_method = POST) {
set $skip_cache 1;
}
# LINUXBABE
# URLs containing query strings should always go to PHP
# ADMIN Note: You might want to be sure to turn off query strings in H-code wordpress theme, and other themes
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
if ($query_string != "") {
set $skip_cache 1;
}
# LINUXBABE
# Don't cache uris containing the following segments
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
# https://easyengine.io/wordpress-nginx/tutorials/plugins/woocommerce/
# https://docs.cleavr.io/guides/woocommerce/
if ($request_uri ~* "/wp-admin/|/wp-json/|/login/|/register/|/shopping-cart.*|.*add-to-cart.*|.*empty-cart.*|/cart.*|/checkout.*|/addons.*|/my-account.*|/wishlist.*|/xmlrpc.php|wp-.*.php|^/feed/*|/tag/.*/feed/*|index.php|/.*sitemap.*\.(xml|xsl)") {
set $skip_cache 1;
}
# LINUXBABE
# Don't use the cache for logged in users or recent commenters
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
# LINUXBABE
# Cache Bypass for specified IP's
# Test the upstream (PHP-FPM and MariaDB) response time. By adding the following
# lines we tell Nginx to bypass the FastCGI cache for our own public and local IP addresses.
# Skip the fastCGI Cache for "Apartment Public IP|Work Public IP|Apartment LAN Subdomain".
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
#if ($remote_addr ~* "xxx.xxx.xx.x|108.231.125.254|xxx.xxx.xx.x|192.168.25..*") {
# set $skip_cache 1;
#}
##
# END: CACHE / SKIP CACHE
##
# LINUXBABE
# Google Sitemaps / Yoast SEO Rules:
# If you use the Yoast SEO or Google XML Sitemap plugins to generate sitemap, then
# you need to move the Yoast/Google XML rewrite rules here, below the skip cache rules (below this line).
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
# Rules:
##
# LOCATION DIRECTIVES 2
##
# LINUXBABE
# Pass Fastcgi to PHP
location ~ \.php$ {
# Pass FastCGI to PHP 7.4
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# Add to SCRIPT_FILENAME to fastcgi params file
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# FastCGI Split Path Info (Possibly Incorrect, need help from serverfault.com)
# There are a couple of options for fastcgi_split_path_info, but we don't know which one, if any, are correct (Question for serverfault.com)
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
#fastcgi_split_path_info ^(.+\.php)(.*)$;
#fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Check that the PHP script exists before passing it by using an "if" statement instead of using "try_files $fastcgi_script_name =404"
# The if lets NGINX check whether the *.php does indeed exist,
# to prevent NGINX from feeding PHP FPM non php script files (like uploaded images).
# see https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
# Mitigate https://httpoxy.org/ vulnerabilities
# Note: see https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
# also see https://www.digitalocean.com/community/tutorials/how-to-protect-your-server-against-the-httpoxy-vulnerability
# if configuring Nginx for conventional HTTP proxying
fastcgi_param HTTP_PROXY "";
# Fastcgi index
fastcgi_index index.php
# Include fastcgi_params file
include fastcgi_params;
fastcgi_buffers 1024 4k;
fastcgi_buffer_size 128k;
# FastCGI Cache
#fastcgi_cache off;
fastcgi_cache example.com;
fastcgi_cache_valid 200 301 302 12h;
fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
fastcgi_cache_min_uses 1;
fastcgi_cache_lock on;
# Tell Nginx to send requests to upstream PHP-FPM server, instead of trying to find files in the
# cache. If the value of $skip_cache is 1, then the first directive tells Nginx to send request
# to upstream PHP-FPM server, instead of trying to find files in the cache.
# ADMIN Note: fastcgi_cache_bypass $skip_cache and fastcgi_no_cache $skip_cache should be
# uncommented if using google XML sitemap plugin, or Yoast SEO Plugin, or if you want to
# enable the skip cache rules above.
fastcgi_cache_bypass $skip_cache;
# This directive tells Nginx not to cache the response.
fastcgi_no_cache $skip_cache;
}
# LINUXBABE (+ ADMIN Extra Extensions)
# Speed up repeat visits to your page with a long browser cache lifetime
location ~ \.(txt|flv|pdf|avi|mov|ppt|wmv|mp3|ogg|webm|aac|jpg|ogg|ogv|svgz|eot|otf|mp4|rss|atom|zip|tgz|gz|rar|bz2|doc|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|jpeg|gif|png|swf|jpeg|webp|svg|woff|woff2|ttf|css|js|ico|xml|otf|woff|woff2)$ {
access_log off;
log_not_found off;
expires 1y;
}
}