skip to Main Content

I have server configured this way:

server {
  listen 80 default_server;
  listen [::]:80 default_server;

  location /health {
    auth_basic "Restricted";
    auth_basic_user_file "/etc/nginx/.htpasswd";

    default_type application/json;
    return 200 '{"status":"Ok"}';
  }
}

/etc/nginx/.htpasswd exists and contains desired credentials.
Now when I try to access this location it just passes all requests without auth check. E.g.:

➜  ~ curl http://localhost:23456/health
{"status":"Ok"}%

Did I miss something?

2

Answers


  1. No you are not "missing" something in general but there is a but 🙂

    NGINX works with something called "access-phases". return kicks in VERY VERY VERY early in the request processing. Having a return statement in a location block tells NGINX to immediately return with this. No matter whats in other phases after it.

    Further reading: http://nginx.org/en/docs/dev/development_guide.html#http_phases

    NGX_HTTP_SERVER_REWRITE_PHASE — Phase where rewrite directives defined in a server block (but outside a location block) are processed. The ngx_http_rewrite_module installs its handler at this phase.
    

    As the return statement is part of the ngx_http_rewrite_module this is the phase where the return statement kicks in. According to the documentation the NGX_HTTP_ACCESS_PHASE in which your auth_basic will be checked comes a lot later.

    So to make this work you have to use a little trick.

    server {
      listen 80 default_server;
      listen [::]:80 default_server;
    
      location /health {
        auth_basic "Restricted";
        auth_basic_user_file "/etc/nginx/.htpasswd";
        proxy_pass http://127.0.0.1:8080;
      }
    }
    
    server {
      listen 8080;
    
      location /{
        default_type application/json;
        return 200 '{"status":"Ok"}';
      }
    }
    
    
    

    Or you can use njs with a js_content as well if you do not want to use a proxy.

    Login or Signup to reply.
  2. As the accepted answer already states, there is no clean solution to this. However, there’s an alternative workaround that doesn’t require an additional server block:

    server {
      listen 80 default_server;
      listen [::]:80 default_server;
    
      location /health {
        auth_basic "Restricted";
        auth_basic_user_file "/etc/nginx/.htpasswd";
        try_files /dev/null @real_health;
      }
    
      location @real_health {
        default_type application/json;
        return 200 '{"status":"Ok"}';
      }
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search