Search code examples
nginxconfigurationfastcginginx-location

nginx server using multiple fastcgi backends for different subfolders


there are multiple questions on StackOverflow how to use subfolders with different fastcgi backends or questions similar but nothing is working correct - and after hours of trying and reading the documentation (maybe missing a small detail) i am giving up.

I have the following requirements:

  • on / a php 5.6 application is running (fastcgi backend 127.0.0.1:9000)
  • on /crm a php 7.0 application is running which has to believe it's running on / (fastcgi backend 127.0.0.1:9001)
  • infact there are few more backends, but with these two i can make them by my own

I tried defining separate php contexts for location prefixes first, before trying to remove /crm prefix. But it seems i am doing something wrong because /crm is everytime using the php context of /.

My actual stripped-down configuration, removed everything not relevant and all failed tests:

server {
    listen       80;
    server_name  myapp.localdev;

    location /crm {
        root       /var/www/crm/public;
        index      index.php;
        try_files  $uri /index.php$is_args$args;

        location ~ \.php$ {
            # todo: strip /crm from REQUEST_URI
            fastcgi_pass   127.0.0.1:9001; # 9001 = PHP 7.0
            fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
    }

    location / {
        root       /var/www/intranet;
        index      index.php;
        try_files  $uri /index.php$is_args$args;

        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000; # 9000 = PHP 5.6
            fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
    }
}

Solution

  • There are two minor errors in your config:

    1. The last argument of try_files is an internal redirect when none of the files before could be found. That means that for the CRM location you want to set it to try_files $uri /crm/index.php$is_args$args;

    2. You have to strip /crm from the $fastcgi_script_name. The recommended way of doing it is to use fastcgi_split_path_info ^(?:\/crm\/)(.+\.php)(.*)$;

    A possibly working config would look like this:

    server {
        listen       80;
        server_name  myapp.localdev;
    
        location /crm {
            root       /var/www/crm/public;
            index      index.php;
            try_files  $uri /crm/index.php$is_args$args;
    
            location ~ \.php$ {
                # todo: strip /crm from REQUEST_URI
                fastcgi_pass   127.0.0.1:9001; # 9001 = PHP 7.0
    
                fastcgi_split_path_info ^(?:\/crm\/)(.+\.php)(.*)$;
                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    
                include        fastcgi_params;
            }
        }
    
        location / {
            root       /var/www/intranet;
            index      index.php;
            try_files  $uri /index.php$is_args$args;
    
            location ~ \.php$ {
                fastcgi_pass   127.0.0.1:9000; # 9000 = PHP 5.6
                fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include        fastcgi_params;
            }
        }
    }