Nginx: route to index.php within alias for specific path component

Rotharius asked:

I’m trying to make nginx route to the index.php within an alias for a specific path. It would be easier to just use subdomains (and add serverblocks with different names), but my project requires this structure for several non-topical reasons. Simply put, I would like the following:

1. www.example.com         --> /home/user/www/public/index.php
2. www.example.com/a/b     --> /home/user/www/public/index.php
3. www.example.com/api     --> /home/user/api/public/index.php
4. www.example.com/api/a/b --> /home/user/api/public/index.php

Numbers 1 and 2 are pretty standard: always serve the index.php file (in a certain root) and let php take care of the routing. Number 3 simulates a subdomain construction (and should point to index.php in a different directory).

I’ve managed to get numbers 1-3 to work, but not number 4. Whenever I go to www.example.com/api/a/b it gives a 404. The error logs tell me nginx is trying to serve me /home/user/api/public//a/b/. I feel like I’m pretty close to the solution, but I don’t seem to get it right. I would also be able to serve static files in the same manner.

The following configurations are relevant:

server {
    listen 80;
    server_name example.com www.example.com;
    root /home/user/www/public;

    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php;
    }
    location ~ .php$ {
            try_files $uri /index.php =404;
            fastcgi_split_path_info ^(.+.php)(/.+)$;
            fastcgi_index   index.php;
            fastcgi_pass    unix:/var/run/php5-fpm.sock;
            include         fastcgi_params;
            fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    } 
    location /api {
        alias /home/user/api/public/;

        location ~ .php$ {
           try_files $uri /index.php =404;
           fastcgi_split_path_info ^(.+.php)(/.+)$;
           fastcgi_index   index.php;
           fastcgi_pass    unix:/var/run/php5-fpm.sock;
           include         fastcgi_params;
           fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
         }
    }      
}

Thanks in advance.

Solution

server {
    listen 80;
    server_name example.com www.example.com;
    root /home/user/www/public;

    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php;
    }
    location ~ .php$ {
            try_files $uri /index.php =404;
            fastcgi_split_path_info ^(.+.php)(/.+)$;
            fastcgi_index   index.php;
            fastcgi_pass    unix:/var/run/php5-fpm.sock;
            include         fastcgi_params;
            fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    } 
    location /api/ {
        alias /home/user/api/public/;
        try_files $uri /api/index.php =404;

        location ~ .php$ {
           try_files $uri /index.php =404;
           fastcgi_split_path_info ^(.+.php)(/.+)$;
           fastcgi_index   index.php;
           fastcgi_pass    unix:/var/run/php5-fpm.sock;
           include         fastcgi_params;
           fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
         }
    }      
}

My answer:


You’re pretty close. But you need to match the trailing / characters for location and its corresponding alias.

You also need to add a try_files in that block to refer to the correct index.php, which is probably /api/index.php.

    location /api/ {
        alias /home/user/api/public/;
        try_files $uri /api/index.php;

View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.