Search code examples
nginxflaskreverse-proxygunicornbasic-authentication

Avoid duplication in password protect URL with proxy in nginx


I have a Flask application served using gunicorn, and with NGINX on top of it. I want to use Basic Authentication (user/password) to protect all URL's starting with /admin, which is the back office, but still continue serving all other URLs with gunicorn without password.

Here is my current NGINX config:

server {
    listen 80;
    server_name example.com;
    charset utf-8;

    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /admin {
        auth_basic "Administrator Login";
        auth_basic_user_file /home/app/.htpasswd;
        # the following four directives are duplicated :(
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

If I don't duplicate the proxy_* directives in the second location block, then the URLs starting with /admin doesn't get forwarded to gunicorn and I get a 404.

Is there any way to avoid the configuration duplication? I tried location nesting but apparently in the end NGINX only "executes" a single location block.


Solution

  • The proxy_pass must be within the location block. However, there's no need to duplicate the proxy_set_header directives, they can be moved into the server block. So your mistake was simply the assumption that proxy_pass could live in the server block :-)