How to reverse proxy an Nginx server to different web apps based on username and password

Viewed 365

Context:

I have two identical python web apps running on ports http://localhost:6001/ and http://localhost:6002/respectively. Both of these apps serve the same end points but they process input data (from users) slightly differently. We can consider them as dev instance and staging instance.

Now I want to add Nginx web server as a reverse proxy for both of these websites. There are 2 reasons for this:

  1. I don't want users to access these two ports directly. I want to hide these 2 ports from public and make them accessible via only the port on which Nginx server is listening. Let's say it is listening on port 7000
  2. To add a username password setup to authenticate the users (with the help of auth_basic and proxy_pass provided by Nginx)

Current Setup:

First I tried implementing the basic auth for one app. I have a file named pyapp under /etc/nginx/sites-available. I linked the same file to the location /etc/nginx/sites-enabled/. The configuration file looks like this:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server{
    listen 7000;
    server_name _;
    
    location / {
            auth_basic "baisc auth";
            auth_basic_user_file /etc/nginx/.htpasswd;
            proxy_pass http://127.0.0.1:6001/;
            include /etc/nginx/proxy_params;
    }

    location ^~ /static {
        proxy_pass http://127.0.0.1:6001/static/;
    }

    location ^~ /healthz {
        proxy_pass http://127.0.0.1:6001/healthz/;
    }

    location ^~ /vendor {
        proxy_pass http://127.0.0.1:6001/vendor/;
    }
    
    location /stream { # this is a socket

        proxy_pass http://127.0.0.1:6001/stream/;

        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 86400;
    }
}

With this setup, when I directly enter http://127.0.0.1:7000/ in my browser, I get the prompt to enter username and password. I enter the credentials which are present in .htpasswd file (which I created). Now I get to see the app which is running on port 6001 while the address in browser still shows http://127.0.0.1:7000/. So far so good.

Question:

Is there a way that I can do a conditional proxy_pass based on the username and password entered? basically when user visits http://127.0.0.1:7000/

  • if username1 and password1 are entered, then load the app from port 6001
  • if username2 and password2 are entered, then load the app from port 6002

I'm aware that we can get the details of authenticated user with $REMOTE_USER and also use a variable (something like $app_port) for storing the port of the app (idea is to replace harcoded 6001 with this variable and set it to 6001 or 6002 based on $REMOTE_USER). But I'm new to Nginx and not aware if this is actually possible because I couldn't find much info regarding this

It will be of great help if anyone can point me to the right documentation. Thanks a ton!!

PS: Here is a similar question that is close to what I want to do. Please let me know if I can provide more relevant information which improves clarity.

0 Answers
Related