I have an app deployed in testing mode on a server. Access to it has been restricted to a select group of users via HTTP-Authentication. That works fine. The problem is that if I serve static files via different 'location' directive, nginx gives me a "Not Authorized" for those files. I tried auth_basic off, but no dice.
Here's the vhost conf:
# Virtual Host
upstream appname {
server 127.0.0.1:4000;
server 127.0.0.1:4001;
server 127.0.0.1:4002;
}
server {
listen 80;
server_name appname.domain.com;
# write app specific log
# make sure you create this file in your log directory before running behind nginx
access_log /home/apps/appname/shared/log/nginx.log main;
# let nginx serve static files directly
# images
location ^~/images {
auth_basic off;
root /home/apps/appname/current/public/images;
}
location ^~/covers {
auth_basic off;
root /home/apps/covers;
}
# # javascript
location ^~/javascripts {
auth_basic off;
root /home/apps/appname/current/public/javascripts;
}
# # css
location ^~/stylesheets {
auth_basic off;
root /home/apps/appname/current/public/style;
}
# Push all other requests to Merb
location / {
# needed to forward user's IP address to merb
proxy_set_header X-Real-IP $remote_addr;
auth_basic "domains";
auth_basic_user_file htpasswd;
if (!-f $request_filename) {
proxy_pass http://appname;
break;
}
}
}
Any suggestions ?
EDIT:
I tried putting images under another subdomain and configuring a separate 'server' block for it - without any http_auth. But it still gives me a 403 forbidden on the image! Here's what I added:
server {
listen 80;
server_name images.domain.com;
access_log /home/apps/appname/shared/log/nginx_images.log main;
error_log /home/apps/appname/shared/log/nginx_images_error.log;
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/apps/www/http_error_codes;
}
location /images {
root /home/apps/appname/current/public/images;
}
location /covers {
root /home/apps/covers;
}
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}
I also tried to open a new browser and access an image file directly from images.domain.com, but it still says 403 forbidden!
I'm not sure you need
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
is "better" than
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
and
statements up into the server block. Then put your
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:
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?
Try to chown your files to the user running nginx (www-data I suppose)