service static files under nginx & HTTP-Authentication
I'm not sure you need
auth_basic off
in the areas that you don't want to do authentication on. The docs say that this serves to "override the action for the inheritable from a lower-level directive", but your parent directive in this case (the server block) doesn't contain any auth directives.
It may be a bug that when you attempt to disable inherited authentication without it already being enabled you turn it on (perhaps it's literally just flipping a bit?), but what I'd suggest is removing that statement from your static locations.
Your use of ^~ on the locations isn't really doing anything as far as I can tell, because you don't have any regular expression matching in the server block. If you look at the resolution order description here:
http://wiki.nginx.org/NginxHttpCoreModule#location
You'll see that using ^~ prevents checking for locations specified by regex. Further down on that doc page, you'll see that for literal matches, nginx chooses the "best" match, where "best" is generally the literal match with the longest substring match. What I'm not sure about is whether internally
location /foo
is "better" than
location ^~ /foo
even though both are literal matches, the latter just having a hint attached. But since you don't need the ^~ bit in your current setup, try dropping those and see if it clears things up. Of course, if you've given us a redacted config for clarify and you do have ~ or ~* matches in your block, this won't help you.
If none of that works, then you could try moving the
auth_basic
and
auth_basic_user_file
statements up into the server block. Then put your
auth_basic off
statements into the static locations, where they will be disabling something you've turned on.
== UPDATE ==
This simple example works for me under 0.7.61:
server { listen 80; server_name test.domain.com; access_log /var/log/nginx/sites/test.domain.com/access.log; error_log /var/log/nginx/sites/test.domain.com/error.log; location /images { root /srv/www/sites/test.domain.com; } location / { root /srv/www/sites/test.domain.com; index index.html; auth_basic test; auth_basic_user_file /etc/nginx/auth/test.htpasswd; if ( -f $request_filename ) { expires 30d; break; } } }
In the site directory, all I have is index.html and a graphic file in /images. If I go to /images/filename.jpg in a fresh browser session, it comes up without error. If then go to the root of the site, I get an auth prompt. If I then return to the image, my log shows the authenticated username (where the first request just showed "-")
A packet trace shows that the auth info was offered by the browser with the GET of /images/filename.jpg (there was no 401 challenge). I assume nginx logs an offered username whether it was specifically required to get the file or not (and of course since the challenge was against /, the browser must supply user-entered credentials for /images/filename.jpg).
Obviously my example doesn't include proxying, but the basic functionality is there.
One mistake I made initially testing this out (which you did as well) is to include the subdirectory of the location block in the root directive. Note how the root for both /images and / are the same - nginx will add on the subdirectory when attempting to retrieve the file.
If I make the root parameter for the /images block include /images, I get a 404 trying to get to the jpg from a fresh browser session (without being prompted for auth). I wonder if your proxy setup is causing the request to be caught by the / block rather than (as in my example) falling through the bottom of the config?