Nginx: Matching server host name in location directive

I have nginx running multiple domains under a single server directive as

server {
        listen       80;
        server_name  www.domain.com;
        server_name  x.domain.com;
        server_name  y.domain.com;

----
----
----
}

Now, I need to use location directive to match a subdomain and apply basic auth to it. The equivalent of

location x.domain.com {
        auth_basic "Admin Login";
        auth_basic_user_file /etc/nginx/.htpasswd;
}

How do I do this?


You can use a regular expression to capture the subdomain and then use it later in your location.

server {
    server_name   ~^(?<sub>\.)?(?<domain>.+)$;

    location / {
        root   /sites/$sub;
    }
}

Alternatively, it might be preferable to move all common configurations to an other file, and then create server blocks per-subdomain and include the external file.

server {
        server_name  www.domain.com;
        include /etc/nginx/sites-enabled/default.inc;

    location / {
        ... 
    } 
}

(repeat for other servers)


You don't need to use the location directive if you use map. This is the most simple solution and equivalent i can think of. You can name the htpasswd files according to your $http_host e.g. x.domain.com.htpasswd.

map $http_host $auth_type {
    default "off";               #This will turn off auth-basic
    x.domain.com "Restricted";   #This or any other string will turn it back on
}

server {
    auth_basic $auth_type;
    auth_basic_user_file /etc/nginx/conf.d/$http_host.htpasswd;
}

One option is to return an error and send that error to a location that handles the HTTP authentication:

if ($host = x.domain.com) {
    return 550;
}

error_page 550 = @xauth;

location @xauth {
    auth_basic "Admin Login";
    auth_basic_user_file /etc/nginx/.htpasswd;
}