Nginx – Apply basic auth only if an htaccess file exists

conditionalhttp-basic-authenticationnginx

How can I apply basic auth only if an htaccess file exists?

If first tried to put the auth_basic directives in an if block, but
that is not allowed.

Then, I tried redirecting to a named location, but while the location with
basic auth works fine, the redirection (which happens when there is no
htaccess file) is erroring out.

Here's what that config looks like:

server {
    listen 80;
    server_name ~^(?<instance>.+?)\.foo.example.com$;

    set $htaccess_user_file /var/htaccess/$instance.foo.example.com.htaccess;

    if (!-f $htaccess_user_file) {
        rewrite ^ @foo;
    }

    location / {
        auth_basic "Restricted";
        auth_basic_user_file $htaccess_user_file;

        root /var/www/$instance.foo.example.com;
        try_files $uri /index.html =404;
    }

    location @foo {
        root /var/www/$instance.foo.example.com;
        try_files $uri /index.html =404;
    }
}

And here's the error message I'm getting when there's no htaccess file:

2013/07/12 08:37:08 [error] 32082#0:
*192 open() "/usr/html@foo" failed (2: No such file or directory),
client: 1.2.3.4, server: ~^(?<instance>.+?)\.foo.example.com$,
request: "GET / HTTP/1.1", host: "bar.foo.example.com"

I have a feeling it has to do with some variables getting overwritten by the named
location, but I'm not sure.

Finally, I tried using alias in the named location, that way the @foo wouldn't be part
of the search dir, but alias are not allowed in named locations…. fuuuu

Best Answer

This is what MTecknology and kolbyjack advised me to do on #nginx.

server {
    listen 80;
    server_name ~^(?<instance>.+?)\.foo.example.com$;
    root /var/www/$instance.foo.example.com;

    set $htaccess_user_file /var/htaccess/$instance.foo.example.com/.htaccess;

    if (!-f $htaccess_user_file) {
        return 599;
    }

    location / {
        auth_basic "Restricted";
        auth_basic_user_file $htaccess_user_file;

        try_files $uri /index.html =404;
    }

    error_page 599 = @foo;

    location @foo {
        root /var/www/$instance.foo.example.com;
        try_files $uri /index.html =404;
    }
}

Worked flawlessly!

Related Topic