5

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!

Ahsan
  • 103
  • 1
  • 1
  • 7

2 Answers2

1

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?

James F
  • 6,549
  • 1
  • 25
  • 23
  • James, I've tried variations of that. My first attempt was without auth_basic off. I have also tried to change the order of the location blocks without success. – Ahsan Jul 27 '09 at 10:17
  • I can get the basic functionality to work (look at the section under "== UPDATE ==" in the answer) – James F Jul 27 '09 at 15:09
  • I tried this (removing ^~, and removing 'auth_basic off'), but I still get a 403 forbidden... I wonder if it's the proxy setup causing problems ... – Ahsan Jul 28 '09 at 08:04
  • James, I edited my question ... tried putting images in a separate server block - no dice :( – Ahsan Sep 02 '09 at 04:33
0

Try to chown your files to the user running nginx (www-data I suppose)

Thomas Decaux
  • 1,239
  • 11
  • 13