Jupyterhub 4.0.2 and nginx

Does anyone have a working configuration with Jupyterhub 4.x.x,nginx, and jhub_remote_user_authenticator?

My nginx is able to determine the REMOTE_USER. Just for whatever reason keep geting a 401 error.

Could you share your nginx configuration and logs of nginx and JupyterHub? If you are using default header name REMOTE_USER, you will need to set underscores_in_headers to on in nginx. Else it will drop those headers.

1 Like

Understood. Do you have a working configuration with this sort of setup? Also, Jupyterhub what other configuration parameters do you have?

server{
listen 443 ssl;
server_name foo;
location /hub/api {
 proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # websocket headers
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header X-Scheme $scheme;

        proxy_buffering off;
}

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

        # websocket headers
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header X-Scheme $scheme;

        proxy_buffering off;
}

}

You dont need a separate location block for /hub/api, the location block / is enough. How are you setting the REMOTE_USER header? For instance, you can add underscores_in_headers on; before location block. Something like

server{
listen 443 ssl;
server_name foo;
underscores_in_headers on;
location / {
 proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # websocket headers
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header X-Scheme $scheme;

        proxy_buffering off;
}
1 Like

Thankyou for your response. I am setting my remote_user header from nginx auth_gss. I know its working because in my access.log I can see my username.

I took out /hub/api. I still get the login prompt. :frowning:

My jupyterhub config file looks like this:

c.Authenticator.header_name = 'X-Remote-User'
c.JupyterHub.bind_url='http://127.0.0.1:8000'
c.JupyterHub.authenticator_class = 'jhub_remote_user_authenticator.remote_user_auth.RemoteUserLocalAuthenticator'

When I goto my server (via nginx) I get this in my jupyterhub log.

302 GET /401.html -> /hub/401.html
No template for 401
401 GET /hub/login?next=%2Fhub%2F
302 GET /401.html -> /hub/401.html

Anything else I can do?

I think this is your issue. header_name config traitlet does not exist on base Authenticator class. It exists on RemoteUserAuthenticator or RemoteUserLocalAuthenticator class. I am assuming that your nginx is setting usernmae in X-Remote-User header, then hub config should be as follows:

c.JupyterHub.bind_url='http://127.0.0.1:8000'
c.JupyterHub.authenticator_class = 'jhub_remote_user_authenticator.remote_user_auth.RemoteUserLocalAuthenticator'
c.RemoteUserLocalAuthenticator.header_name = 'X-Remote-User'

Could you try with this config?

Nope. I made the change and still same error. I even cleared browser(chrome/edge) cache.

Do I need to change any other settings like base_url, I think this has been deprecated. Just getting desperate. lol

I added
in my nginx location '/;

location /
{
proxy_set_header REMOTE_USER $remote_user;
proxy_pass http://127.0.0.1:8000
}

This gets a bit “further”.
Now I see this in my jupyterhub logs

Saving bearer token..
Deleting oauth code Cjj for jupyter-hub-user-myuser
200 POST /hub/api/user (myuser@127.0.0.1) 
Recording first activity for <APIToken>...
200 GET /hub/api/user (myuser@127.0.0.1)...
Logged-in usr {'admin':False,'kind':'user'...
302 GET /401.html -> /hub/401.html...
200 GET /user/MYUSER/lab?redirect=2
302 GET /401.html
....

Do I need to do anything with scopes?

Could you try with following nginx location config

location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Remote-User $remote_user;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # websocket headers
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header X-Scheme $scheme;

        proxy_buffering off;
}

and following JupyterHub config

c.JupyterHub.bind_url='http://127.0.0.1:8000'
c.JupyterHub.authenticator_class = 'jhub_remote_user_authenticator.remote_user_auth.RemoteUserLocalAuthenticator'
c.RemoteUserLocalAuthenticator.header_name = 'X-Remote-User'

Should I also have

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

in my nginx.conf?

Yes, for websockets. Here is a reference config

ok. Did what you said, still same issue.

In logs I see

200 GET /user/myuser/lab? (myuser@ipaddress)
302 GET /401.html -> /hub/401.html

myuser matches with X-Remote-User

I needed to add /user stanza in nginx.conf. Now it works. Much appreciate your help!