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

Francis Daly francis at
Fri Nov 22 02:16:22 UTC 2013

On Thu, Nov 21, 2013 at 08:45:02PM +0000, Francis Daly wrote:
> On Wed, Nov 20, 2013 at 10:31:07PM -0500, Ben Johnson wrote:

...and one more possibility...

If your application directory structure is such that:


contains only static files that should be served as-is if requested,
with appropriate "index" files for some directories if wanted; and


contains "myapp.php", which is the single controlling script that will
always be called if the web request is not for a static file; and

whatever other scripts, templates, and other things that are necessary
for myapp.php to refer to are here, or are anywhere other than in

and the application should be accessible from the web url "/app1/",

then possibly all the locations you need are

    # all requests for this app
    location ^~ /app1/ {
      alias /var/www/myapp/web/;
      error_page 404 403 = @app1;
    # the main controller. Set whatever you want in the include file
    location @app1 {
      fastcgi_pass unix:php.sock;
      fastcgi_param SCRIPT_FILENAME /var/www/myapp/php/myapp.php;
      include fastcgi_params;

> > 	if ($uri ~ '/download/.*/$') {
> > 		rewrite ^/(.*)/$ /$1 permanent;

> > 	if ($uri !~ '(/|\.[a-zA-Z0-9]{1,12}|/download/.*)$') {
> > 		return 301 $uri/$is_args$args;

> > 	if ($uri ~ '(/|/download/.*|/css2/.*|/js2/.*)$') {
> > 		rewrite  ^(.*)$  /index.php?q=$1  last;

If you want to keep those "rewrites" within nginx.conf, just use the
first two directly within @app1, and I think the third will not be needed.

myapp.php should be able to find all it needs in _SERVER["DOCUMENT_URI"],
so it shouldn't need _REQUEST["q"].

And a staging version would merely be another application -- copy the
two locations, change the prefix and name, change the alias, error_page,
and SCRIPT_FILENAME. All done.

An application at / or at /sub/url/ would be no different. You might be
able to use "root" instead of "alias" in some cases, but I don't think
it matters here.

> > If there is a better, more concise, or more secure way to accomplish the
> > above, then I am eager to learn.

The above is more concise -- partly because it tries to do less. The
previous version allowed you to access the urls /app1/one.php
and /app1/two.php in the client, and the separate files would be
processed. This version would return the php files directly from web/,
or would let php/myapp.php decide what to do if the files aren't in web/.

That's the key to the smaller config -- nginx only tells the fastcgi
server to process a single file.

Francis Daly        francis at

More information about the nginx mailing list