Clean-URL rewrite rule with nested "location" and alias directive

Ben Johnson ben at
Tue Nov 19 22:48:59 UTC 2013

On 11/19/2013 3:39 PM, Francis Daly wrote:
> On Tue, Nov 19, 2013 at 01:45:15PM -0500, Ben Johnson wrote:
>> On 11/19/2013 12:38 PM, Francis Daly wrote:
>>> On Tue, Nov 19, 2013 at 10:36:53AM -0500, Ben Johnson wrote:
> Hi there,
>>>> This works as expected, with one major exception: "clean-URL" rewriting
>>>> does not work. In other words, the homepage (/stage/) loads correctly,
>>>> but all sub-pages return a 404.
> Which nginx version do you use, where you get that output with the config
> snippet that you provided?
> I've tried 1.4.3 and 1.5.7, and I don't get /stage/ to load correctly.
> I suspect I'm just doing something silly.

Given your level of expertise, I doubt that you're doing anything wrong.
:) I'm using nginx-1.1.19, because that's what's bundled with Ubuntu
12.04 LTS. It makes sense that without the rewrite rules in-place, only
"index.php" (via /stage/) returns a 200 response and not a 404.

>> Certainly: an example URL is /stage/my-account/ . Ultimately, I would
>> like for this URL to be rewritten to
>> /stage/index.php?q=/stage/my-account/ (the file "index.php" exists on
>> the filesystem at /var/www/
> I think that the problem may be due to the interaction between "alias"
> and "$document_root" being not-always-obvious.
> And $document_root is used in try_files, which is probably what you
> want for "clean URLs" -- serve the file if present, else hand it to
> a controller.

I think that you're exactly right. I had tried try_files first, but was
unable to get it to work given that this site a) must be accessed via a
"subdirectory" relative to the domain-root URL, and b) is comprised of
files that live in a "private" directory that is outside of the
server-root on the filesystem.

> Does the following do what you want for all cases you care about?
> ===
>       location ^~ /stage/ {
>         alias /var/www/;
>         index index.php index.html index.htm;
>         try_files $uri $uri/ /stage//stage/index.php?q=$uri;
>         location ~ ^/stage/(.+\.php)$ {
>                 alias /var/www/$1;
>                 try_files "" / /stage/index.php?q=$uri;
>                 fastcgi_pass unix:/var/run/php5-fpm.sock;
>                 fastcgi_param HTTPS on;
>                 fastcgi_param SCRIPT_FILENAME $request_filename;
>                 include /etc/nginx/fastcgi_params;
>         }
>       }
> ===

Wow, that actually works! While I don't fully understand the try_files
magic, I didn't think try_files would ever serve the purpose because I
had read at : "Note that
there is a longstanding bug that alias and try_files don't work
together" (with link to ).

While I do realize that the above-cited Wiki is obsolete and the current
reference is at , the
referenced bug does not appear to have been closed.

Is the implication here that "alias" does indeed work with "try_files"
(even in my stale nginx-1.1.19 version)? At least in this particular

There is one last trick to pull-off, which is to add very similar
clean-URL functionality for two other files (in addition to index.php),
but I am hoping that I will be able to adapt your working sample myself.

> You may want to use something other than $uri in the last argument to
> try_files, depending on how you want /stage/my-account/?key=value to
> be processed.

Understood; that makes sense.

> And the curious-looking try_files lines are deliberate.
> 	f

You are a true guru, Francis. I can't thank you enough; I've been
struggling with this for days. This is the second time that you've
come-up huge for me.



More information about the nginx mailing list