Nginx document root based on client ip?

Solution 1:

This should work:

root /$root;

set $root default/path;
if ($remote_addr ~ "^(127\.0\.0\.1|10\.20\.30\.40|111\.222\.33\.44)$") {
    set $root another/path;
}

Do not forget to escape dots in regexp for IPs.

Solution 2:

You can also combine Alexey Ten's answer with the geo module as mentioned in Nginx - How to redirect users with certain IP to special page This makes it easier to match multiple IP addresses due to CIDR notation and ranges support.

E.g.

geo $geo_host {
    default       0;
    127.0.0.1/16  1;
    1.2.3.4       1;
}

server {
    ... # Skipping details unrelated to this example.
    root /$root;

    set $root default/path;
    if ($geo_host = 1) {
        set $root other/path;
    }
}

This can also be combined with proxies, e.g. Varnish. This example has only the server {} contents, see the geo block in the above example.

server {
    ... # Skipping details unrelated to this example.

    set $proxy_host maintenance.example.org;
    location / {
        if ($geo_host = 1) {
            set $proxy_host $host;
        }

        proxy_pass http://varnish;
        proxy_set_header Host $proxy_host;
        ... # Your other proxy config.
    }
}

This example redirects everyone not on the geo whitelist to see a maintenance page (which is served by whatever http server is after the Varnish cache). Varnish gets passed the real host for those on the whitelist and the maintenance host for those not on the whitelist.