Nginx doesn't pick the right php-stack in location

TL;dr

I created a location block (/de/forums/) outside of the nginx root folder but the php gets sent to the php compiler inside root so there is a directory mismatch. It wont take the defined php stack inside the new location block. Help!

The location block /de/forums/ works, but just for files, not for php. With php I get a "File not Found" because it uses the main root folder as base and not the new alias.
And I cant figure out how to force nginx to use the more specific php with the right fastcgi_param SCRIPT_FILENAME $request_filename;.

Following situation:

LEMP Stack with php7.2-fpm

Wordpress Multisite Installation on domain.com - configured to use Subdirectorys. There are two for this domain: domain.com/de/ and domain.com/en/. As you probably guessed for different language versions of a Blog. An example page is domain.com/en/contact-us and a blog post would be domain.com/en/this-is-a-blog-1451

So we have:

domain.com/de/
domain.com/en/
domain.com/en/contact-us
domain.com/en/this-is-a-blog-1451


We want to add:

domain.com/de/forums/
domain.com/en/forums/


And this is how the folder stucture looks:

/var/www/domain.com/
/var/www/domain.com/html/
/var/www/domain.com/html/index.php #(Wordpress)
/var/www/domain.com/forum-de/index.php #(Xenforo)
/var/www/domain.com/forum-en/index.php #(Xenforo)
/var/www/domain.com/logs/
/var/www/domain.com/ssl/
/var/www/domain.com/wp-config.php


So we need to create a location blog for the forum folders. In theory, a more specific location block (/de/forums/) should take precedent over a general / so the block should always point to the forum and not to Wordpress.

Here is my full server block - with comments for you:
(the relevant location block is 4/5 at the bottom)
NGINX:
server {

    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name domain.com;
  
    root /var/www/domain.com/html;
    error_log /var/www/domain.com/logs/error.log warn;
    access_log /var/www/domain.com/logs/access.log;
    index index.php;
  
    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt { log_not_found off; access_log off; allow all; }
    location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
        expires max;
        log_not_found off;
    }
    # denies all hidden files
    location ~ /\. {
        deny all;
    }
    # Deny access to any files with a .php extension in the uploads directory
    # Works in sub-directory installs and also in multisite network
    # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
    location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
    }
  
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
  
  
      
        location / {
                # This is cool because no php is touched for static content.
                # include the "?$args" part so non-default permalinks doesn't break when using query string
                try_files $uri $uri/ /index.php?$args;
        }
      
        if (!-e $request_filename) {
        rewrite /wp-admin$ $scheme://$host$uri/ permanent;
        rewrite ^(/[^/]+)?(/wp-.*) $2 last;                   
        rewrite ^(/[^/]+)?(/.*\.php) $2 last;                 
        }

      


    # indicate locations of SSL key files.
    ssl_certificate /var/www/domain.com/ssl/ssl.crt;
    ssl_certificate_key /var/www/domain.com/ssl/ssl.key;
  
    # Enable HSTS. This forces SSL on clients that respect it, most modern browsers. The includeSubDomains flag is optional.
    # see https://hstspreload.org/
    # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
  
    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
    ssl_ecdh_curve X25519:P-256:P-384:P-224:P-521;
  
    ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
  

    # generate by "openssl dhparam -outform PEM -out dhparam2048.pem 2048"
    ssl_dhparam /etc/nginx/ssl/dhparam2048.pem;
    #ssl_ecdh_curve secp384r1; SEEMS NOT TO WORK WITH CLOUDFLARE
    ssl_prefer_server_ciphers on;
  
    # Enable HSTS. This forces SSL on clients that respect it, most modern browsers. The includeSubDomains flag is optional.
    # see https://hstspreload.org/
    # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
  
    # DO NOT USE!!!!
    # DO NOT USEadd_header Public-Key-Pins 'pin-sha256="AKTUELLER-KEY-HASH"; pin-sha256="BACKUP-KEY-HASH"; max-age=31536000; includeSubDomains';
    # DO NOT USE!!!!

  
    ssl_session_cache shared:SSL:30m;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_session_tickets on;
    # generate with "head -c 48 /dev/urandom > /etc/nginx/ssl/nginx_ticketkey"
    ssl_session_ticket_key /etc/nginx/ssl/nginx_ticketkey;
    ssl_session_timeout 41m;
  
  
    # resolver conf
    resolver 8.8.8.8 8.8.4.4 valid=1200s;
    resolver_timeout 5s;
  
  
  
        location ~* \.(3gp|gif|jpg|jpeg|png|ico|wmv|avi|asf|asx|mpg|mpeg|mp4|pls|mp3|mid|wav|swf|flv|exe|zip|tar|rar|gz|tgz|bz2|uha|7z|doc|docx|xls|xlsx|pdf|iso)$ {
            # gzip_static off;
            add_header Access-Control-Allow-Origin *;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
            access_log off;
            expires 30d;
            break;
        }

        location ~* \.(js)$ {
            add_header Access-Control-Allow-Origin *;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
            access_log off;
            expires 30d;
            break;
        }

        location ~* \.(css)$ {
            add_header Access-Control-Allow-Origin *;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
            access_log off;
            expires 30d;
            break;
        }

        location ~* \.(html|htm|txt)$ {
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
            access_log off;
            expires 1d;
            break;
        }

        location ~* \.(eot|svg|ttf|woff|woff2)$ {
            add_header Access-Control-Allow-Origin *;
            add_header Cache-Control "public, must-revalidate, proxy-revalidate";
            access_log off;
            expires 30d;
            break;
        }  
      



        location ^~ /de/forums/ {
            alias /var/www/domain.com/forum-de/;
            #also tried root
            index index.php index.html index.htm;
            try_files $uri $uri/ /de/forums/index.php?$uri&$args;
              #also tried just /index.php?$uri&$args;
          
          
        }
      
    location ~  ^/de/forums/(.+\.php)$ {
        alias var/www/domain.com/forum-de/;
         #also tried root  
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        include fastcgi.conf;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $request_filename;
        #also tried using the full path here
    }  


    #cloudflare stuff - cut out for shortness sake
    set_real_ip_from 103.21.244.0/22;
    #many more here

    # use any of the following two
    real_ip_header CF-Connecting-IP;
    #real_ip_header X-Forwarded-For;
  
  
  
        location ~ [^/]\.php(/|$)  {
            #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
            include fastcgi.conf;
            fastcgi_split_path_info ^(.+?\.php)(/.*)$;
            fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
            fastcgi_index index.php;

            fastcgi_connect_timeout 60;
            fastcgi_send_timeout 180;
            fastcgi_read_timeout 180;
            fastcgi_buffer_size 512k;
            fastcgi_buffers 512 16k;
            fastcgi_busy_buffers_size 1m;
            fastcgi_temp_file_write_size 4m;
            fastcgi_max_temp_file_size 4m;
            fastcgi_intercept_errors off;
      

    }
  
    }



I tried:
  • - Using location php as a sub location under /de/forums/
  • - Using root instead of alias (what is wrong but I got desperate)
  • - Not using fastcgi.conf link
  • - Using $request_filename or /var/www/domain.com/html/forum-de/$fastcgi_script_name also /var/www/domain.com/html/forum-de$fastcgi_script_name
  • - deleting the / php block, still didn't use the specific to the location /de/forums/

The only thing that was working, was creating an actual folder like /var/www/domain.com/html/de/forums/index.php. But then I get an 404 with wordpress if I want to access /de/ and all the pages there, because of the try_files. I probably could work with if but thats not recommended as far as I read.

Also I can access files with the location blog (jpgs for example) - so the location block works but not the php.

The error message is File not found. So the forum phps getting sent to the php compiler, but there is - I believe - an adress mismatch with the general root and the new location root. I couldn't even access a phpinfo file.

Please help!


EDIT:

Further readings:
(aka I found helpful stuff here, but didn't solve my problem)
As most of them suggested, fastcgi_param SCRIPT_FILENAME $request_filename; should fix my problem. BUT... nginx just don't uses my php location with correctly set SCRIPT_FILENAME - it keeps using the "main" php location /
 
Last edited:
Top