Minimal configuration

One could imagine a minimal server configured as such:
in /nginx/nginx.conf:
http {
#All default http stuff, like MIME type inclusion, etc.
include conf.d/
.conf
}

in */nginx/conf.d/default.conf
server {
listen 80;
index index.html index.htm;

try_files $uri $uri/ /;

}

However, unless I made some mistake, it seems that such a configuration
returns a HTTP 500 error (with a ‘too much internal redirection’ error).

​Does nginx require any location block at all?
Or am I mistaken?

B. R.

On Sat, Feb 15, 2014 at 12:29:00PM +0100, B.R. wrote:

One could imagine a minimal server configured as such:

If you want the minimal config, start with an empty file and see what
you need to add to get it to work.

I suspect that

===
events{}
http{ server{} }

will probably work usefully.

server {
listen 80;
index index.html index.htm;

try_files $uri $uri/ /;

}

However, unless I made some mistake, it seems that such a configuration
returns a HTTP 500 error (with a ‘too much internal redirection’ error).

What request did you make? What response did you expect? What did the
error log say? What did the debug log say?

Does nginx require any location block at all?

No.

f

Francis D. [email protected]

Thanks for your input Francis.
What I suspected seemed old but I really don’t understand the problem I
am
facing.

Consider the following server configuration for some phpBB forum:
server {
listen 80;
server_name b.cd;
try_files $uri $uri/;

    root    /var/www/phpBB3;
    index   index.html index.htm index.php;
    include fastcgi.conf;

    location /favicon.ico {
        access_log off;
        log_not_found off;
        expires 7d;
        return 204;
    }

    location ~ \.php$ {
            try_files $uri =404;
            fastcgi_pass    unix:/var/run/php5-fpm.sock;
    }

}

Requesting b.cd in the browser ends up wth a HTTP 500 error:
‘[error] 12345#0: *42 rewrite or internal redirection cycle while
internally redirecting to “/”, client: 12.34.56.78, server: b.cd,
request:
“GET / HTTP/1.1”, host: “b.cd”’

Adding / at the end of try_files so it reads:
try_files $uri $uri/ /;
solves the problem…

Really, I don’t get it.
Any insight on what is going on?

B. R.

On Sun, Feb 16, 2014 at 08:43:45PM +0100, B.R. wrote:

Hi there,

    try_files       $uri $uri/;

The final argument to “try_files” is special.

Requesting b.cd in the browser ends up wth a HTTP 500 error:
‘[error] 12345#0: *42 rewrite or internal redirection cycle while
internally redirecting to “/”, client: 12.34.56.78, server: b.cd, request:
“GET / HTTP/1.1”, host: “b.cd”’

Yes.

The debug log may show you why.

Adding / at the end of try_files so it reads:
try_files $uri $uri/ /;
solves the problem…

Adding pretty much anything else at the end of try_files should also
work,
for this request.

Really, I don’t get it.
Any insight on what is going on?

The final argument to “try_files” is a uri for an internal redirect,
not a file to be served.

http://nginx.org/r/try_files

f

Francis D. [email protected]

On Sun, Feb 16, 2014 at 11:00:07PM +0100, B.R. wrote:

Hi there,

Right, I did not pay attention to that.

I think you’re still not understanding it.

However, when requesting the root (by typing b.cd in the browser), $uri
should be empty, thus why can’t ‘$uri/’ act as ‘/’ and redirect accordingly?

It can. It does.

When it redirects to /, the location match starts again, and try_files
applies again, and you get the “rewrite or internal redirection cycle”
that you saw in the logs.

(Strictly, when you type b.cd in the browser, it requests /, so $uri is
not empty. But that’s not related to what try_files does here.)

f

Francis D. [email protected]

Right, I did not pay attention to that.

However, when requesting the root (by typing b.cd in the browser), $uri
should be empty, thus why can’t ‘$uri/’ act as ‘/’ and redirect
accordingly?

B. R.

Thanks for you time, Francis.

I understand the loop cycles (and thanks for the clarification about
$uri
content).

If I may, there is still a little something bothering me:
The condition required for a loop to be created is that $uri (= /)
doesn’t
match any file, thus redirecting and trying again.
Why on Earth does ‘/’ as error handler matches anything then?

Stated otherwise, why does ‘/’ as error handler uses index files to find
something while ‘/’ contained in $uri doesn’t find anything? Isn’t the
‘index’ directive used there?

B. R.

Sorry for my fluffy terminology.
What I called ‘error handler’ was the final argument of the try_files
directive, the one used if any other one fails to detect a valid
file/directory.

We ended concluding that:
try_files $uri $uri/; was invalid, looping internally for an infinite
amount of time
try_files $uri $uri/ /; was valid

I still don’t get why the first case is invalid, with all the input you
provided me with:
The request URI was ‘/’, so $uri = /, thus the first agument of
try_files
should match the root directory and process it further (finding the
index
file, etc.).
Why hasn’t it been the case?

Otherwise stated: defaulting to ‘/’ in the valid syntax means that both
‘$uri’ and ‘$uri/’ values (both equalling ‘/’ after cleanup of redundant
slashes) don’t point towards a valid directory. This is obviously wrong,
since the root directory exists (and is processed when the fallback to
the
‘/’ argument happens).

Considering all that, one could wonder why the 1st syntax is invalid.

I hope I clarified my question… It seems simple from my point of view
:o\

B. R.

On Mon, Feb 17, 2014 at 02:13:14PM +0100, B.R. wrote:

Hi there,

What I called ‘error handler’ was the final argument of the try_files
directive, the one used if any other one fails to detect a valid
file/directory.

So: the “uri” argument.

If try_files gets as far as the uri argument, there is an internal
redirection – no files or directories are consulted at all.

(It can also be the “=code” argument, but that does not apply in this
example.)

We ended concluding that:
try_files $uri $uri/; was invalid, looping internally for an infinite
amount of time
try_files $uri $uri/ /; was valid

I still don’t get why the first case is invalid, with all the input you
provided me with:
The request URI was ‘/’, so $uri = /, thus the first agument of try_files
should match the root directory and process it further (finding the index
file, etc.).

No.

The first argument is a “file” argument, and is the string “$uri”. That
string does not end in “/” (it ends in “i”), and so try_files
will look for a file. Expand variables in the argument, prepend
$document_root, and try_files checks to see is there a file called
/usr/local/nginx/html/. There is not, so it moves to the next argument.

In the first case above, the next argument is the final argument, and so
is the “uri” argument, and so try_files expands the variables in it and
does an internal redirection to this new request and everything starts
again. In this case, that’s a loop.

In the second case above, the next argument is not the final argument,
and so is another “file” argument. It is the string “$uri/”, which ends
in
“/”, so try_files will look for a directory. Expand, prepend, and see is
there a directory called /usr/local/nginx/html/. There is, and so this
request is processed in the current context using that directory. The
rest of the configuration says “serve from the filesystem”, and “serve
index.html in the directory”, so that’s what happens.

Considering all that, one could wonder why the 1st syntax is invalid.

I hope I clarified my question… It seems simple from my point of view :o\

The best I can suggest is that when you read the documentation, only
read the words that are there.

Don’t read the words that you want to be there, don’t read the words
that would be there if they were put in a different order, and don’t
assume that there are typographical errors and that clearly they meant
to write something else.

(There may well be typos there, in which case corrections are presumably
welcome. But on first reading, if there is a way of parsing the words
that
does not require there to be an error, that’s probably the one to
expect.)

f

Francis D. [email protected]

Thanks for your help, Francis!

That’s an amazingly detailed explanation. The differences in behavior
between ‘normal’ arguments and the last one are the key but the doc does
not (cannot?) go into details about them.

B. R.

On Mon, Feb 17, 2014 at 12:42:28AM +0100, B.R. wrote:

Hi there,

If I may, there is still a little something bothering me:
The condition required for a loop to be created is that $uri (= /) doesn’t
match any file, thus redirecting and trying again.
Why on Earth does ‘/’ as error handler matches anything then?

I may be being confused by terminology here. Where does “error handler”
come in to it?

try_files takes multiple arguments – at least one “file”, plus one
“uri”.

If it gets that far, there is an internal redirect to the final
argument.

The other arguments are tried in turn, by prepending $document_root and
seeing if there is a file or directory with that name available. (If
the argument ends in /, it looks for a directory; otherwise it looks
for a file.)

The first matching file-or-directory is processed in the current
context.

If that isn’t clear, all I can suggest is that you read the source
and/or test, and write the documentation that would make it clear to
you,
and submit that to the official docs.

Stated otherwise, why does ‘/’ as error handler uses index files to find
something while ‘/’ contained in $uri doesn’t find anything? Isn’t the
‘index’ directive used there?

try_files doesn’t use “index”.

try_files can see that (if the current “file” argument ends in a /)
the directory exists, and that therefore this request should be served
by this “file” in this context. After that, “index” can apply and you
get
index.html or 403 or whatever else is appropriate.

f

Francis D. [email protected]

On Mon, Feb 17, 2014 at 11:16:23PM +0100, B.R. wrote:

Hi there,

Thanks for your help, Francis!

You’re welcome.

That’s an amazingly detailed explanation.

It is. But be aware: it is not actually correct.

It covers some of the common cases, which may be good enough for you for
now.

The differences in behavior
between ‘normal’ arguments and the last one are the key but the doc does
not (cannot?) go into details about them.

To my mind, the first paragraph of http://nginx.org/r/try_files does
say that – but only if you read it as if it is a technical document,
where every word means something.

Maybe there’s room for alternate documentation, which spells out things
in much more details and gives even more examples of how things could
be set up – but that is likely to be book-length and more quickly
stale. I suspect that if someone wants to write and maintain it, it
would be welcomed.

Anyway – it’s good that you have the answer you were looking for.

Cheers,

f

Francis D. [email protected]