Closed tchakravarty closed 6 years ago
I think you will have to configure the base_url
property of JupyterHub to match you subpath:
https://github.com/jupyterhub/jupyterhub/blob/a58bea6d933b7bc0bcfe4b08dfff4f31dd2b5909/jupyterhub/app.py#L347-L352
Closing this issue since it appears to be resolved. Please feel free, if this is still an issue, to leave a comment requesting this issue be reopened. Thanks to all!
I'd like to re-discuss this issue, as I'm having similar troubles.
I want to deploy JupyterHub (in a Docker container) with Dockerspawner behind an SSL handling Apache Reverse Proxy (also in a Docker container) on the subpath /jupyter
. The users shall log in via Keycloak (also containerized), which is running on the same host on the subpath /
. The JupyterHub is spawning the notebook containers as "siblings".
My problem right now is that the notebook container does not bind to the JupyterHub. I can log in successfully at https://localhost/jupyter/hub/login
, but I always run into a redirect loop afterwards.
This is from the JupyterHub container's log:
[I 2018-08-09 14:06:18.111 JupyterHub base:499] User logged in: demo1
[I 2018-08-09 14:06:18.112 JupyterHub log:158] 302 GET /jupyter/hub/oauth_callback?state=[secret]&session_state=[secret]&code=[secret] -> /jupyter/user/demo1/ (@::ffff:192.168.80.3) 65.41ms
14:06:18.119 - debug: [ConfigProxy] PROXY WEB /jupyter//user/demo1/ to http://jupyterhub:8081
[I 2018-08-09 14:06:18.123 JupyterHub log:158] 302 GET /jupyter/user/demo1/ -> /jupyter/hub/user/demo1/ (@::ffff:192.168.80.3) 0.78ms
14:06:18.145 - debug: [ConfigProxy] PROXY WEB /jupyter//hub/user/demo1/ to http://jupyterhub:8081
[I 2018-08-09 14:06:18.204 JupyterHub dockerspawner:452] Container 'jupyter-demo1' is gone
[I 2018-08-09 14:06:18.290 JupyterHub dockerspawner:540] Created container 'jupyter-demo1' (id: ff10fe4) from image jupyter/datascience-notebook:latest
[I 2018-08-09 14:06:18.291 JupyterHub dockerspawner:557] Starting container 'jupyter-demo1' (id: ff10fe4)
[I 2018-08-09 14:06:19.774 JupyterHub log:158] 200 GET /jupyter/hub/api (@192.168.80.6) 0.65ms
[I 2018-08-09 14:06:20.171 JupyterHub base:628] User demo1 took 2.004 seconds to start
[I 2018-08-09 14:06:20.171 JupyterHub proxy:242] Adding user demo1 to proxy /jupyter/user/demo1/ => http://192.168.80.6:8888
14:06:20.177 - info: [ConfigProxy] Adding route /jupyter/user/demo1 -> http://192.168.80.6:8888
14:06:20.179 - info: [ConfigProxy] 201 POST /api/routes/jupyter/user/demo1
[I 2018-08-09 14:06:20.186 JupyterHub log:158] 302 GET /jupyter/hub/user/demo1/ -> /jupyter/user/demo1/?redirects=1 (demo1@::ffff:192.168.80.3) 2037.98ms
14:06:20.211 - debug: [ConfigProxy] PROXY WEB /jupyter//user/demo1/?redirects=1 to http://jupyterhub:8081
[I 2018-08-09 14:06:20.220 JupyterHub log:158] 302 GET /jupyter/user/demo1/?redirects=1 -> /jupyter/hub/user/demo1/?redirects=1 (@::ffff:192.168.80.3) 2.57ms
14:06:20.245 - debug: [ConfigProxy] PROXY WEB /jupyter//hub/user/demo1/?redirects=1 to http://jupyterhub:8081
[W 2018-08-09 14:06:20.282 JupyterHub base:1061] Redirect loop detected on /jupyter/hub/user/demo1/?redirects=1
[...and so on.]
This is my Apache config:
SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect file:/dev/urandom 512
SSLCipherSuite HIGH:MEDIUM:!SSLv3:!kRSA
SSLProxyCipherSuite HIGH:MEDIUM:!SSLv3:!kRSA
SSLHonorCipherOrder on
SSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3
SSLPassPhraseDialog builtin
SSLSessionCache "shmcb:/usr/local/apache2/logs/ssl_scache(512000)"
SSLSessionCacheTimeout 300
SSLUseStapling On
SSLStaplingCache "shmcb:/usr/local/apache2/logs/ssl_stapling(32768)"
SSLStaplingStandardCacheTimeout 3600
SSLStaplingErrorCacheTimeout 600
Listen 443
<VirtualHost _default_:443>
ServerName ${SERVER_NAME}
ServerAdmin ${SERVER_ADMIN}
ErrorLog "/usr/local/apache2/logs/error_log"
TransferLog "/usr/local/apache2/logs/access_log"
CustomLog /proc/self/fd/1 \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
SSLEngine on
SSLCertificateFile "/usr/local/apache2/certs/apache-selfsigned.crt"
SSLCertificateKeyFile "/usr/local/apache2/certs/apache-selfsigned.key"
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/usr/local/apache2/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-5]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
<Location />
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
ProxyPass http://keycloak:8080/
ProxyPassReverse http://keycloak:8080/
</Location>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/api/v1/websocket [NC,OR]
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR]
RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
RewriteRule /(.*) ws://jupyterhub:8000/jupyter/%{REQUEST_URI} [P,L]
<Location /jupyter>
ProxyPreserveHost On
ProxyPass http://jupyterhub:8000/jupyter/
ProxyPassReverse http://jupyterhub:8000/jupyter/
</Location>
</VirtualHost>
... and here is the relevant part of my jupyterhub_config.py
:
import os
from oauthenticator.generic import GenericOAuthenticator
from dockerspawner import DockerSpawner
## DEBUGGING
c.Spawner.debug = True
c.ConfigurableHTTPProxy.debug = True
#
c.JupyterHub.base_url = "/jupyter"
c.JupyterHub.port = 8000
c.JupyterHub.hub_ip = "0.0.0.0"
c.JupyterHub.hub_connect_ip = "jupyterhub"
c.JupyterHub.authenticator_class = GenericOAuthenticator
c.OAuthenticator.client_id = 'jupyterhub'
c.OAuthenticator.client_secret = str(os.environ.get('KEYCLOAK_CLIENT_SECRET'))
c.GenericOAuthenticator.token_url = str(os.environ.get('OAUTH2_TOKEN_URL'))
c.GenericOAuthenticator.userdata_url = str(os.environ.get('BASE_URL')) + '/userinfo'
c.GenericOAuthenticator.userdata_method = 'GET'
c.GenericOAuthenticator.userdata_params = {"state": "state"}
c.GenericOAuthenticator.username_key = "preferred_username"
c.GenericOAuthenticator.scope = ['openid']
c.JupyterHub.spawner_class = DockerSpawner
c.DockerSpawner.image = 'jupyter/datascience-notebook:latest'
c.DockerSpawner.network_name = "jh_keycloak_default"
c.DockerSpawner.remove_containers = True
The rest in there is only for mounting volumes and starting services, which does work. I tried setting c.JupyterHub.ip = '127.0.0.1'
, but then my browser could not find it anymore. I also tried to set it to the Docker container's IP, but then the redirection loop struck again.
I've been trying to solve this for several days and I'm out of ideas by now. Also, like @tchakravarty, I am aware of all the similar questions here and there, but none of the provided solutions worked for me yet.
Maybe someone has got a hint for me where to start?
Hi anyone,
I just want to share my configurations that worked for me, to launch the JupyterHub through this pattern of url: http://your_ip_domainname/jhub/
Note: I am also running a Shiny-Server Open Source on the same CentOS server;
httpd.conf:
<Proxy *>
Allow from localhost
</Proxy>
<VirtualHost *:80>
RewriteEngine on
#JupyterHub
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /jhub/(.*) ws://127.0.0.1:8000/jhub/$1 [P,L]
RewriteRule /jhub/(.*) http://127.0.0.1:8000/jhub/$1 [P,L]
#Preserve Host header to avoid cross-origin problems
ProxyPreserveHost On
#proxy to JupyterHub
ProxyPass /jhub/ http://127.0.0.1:8000/jhub/
ProxyPassReverse /jhub/ http://127.0.0.1:8000/jhub/
#ServerName sappsveeam.com
#DocumentRoot /srv/shiny-server/sample-apps/hello
#ShinyServer
RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule /shiny/(.*) ws://127.0.0.1:3838/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteRule /shiny/(.*) http://127.0.0.1:3838/$1 [P,L]
ProxyPass /shiny/ http://127.0.0.1:3838/
ProxyPassReverse /shiny/ http://127.0.0.1:3838/
TimeOut 600
</VirtualHost>
jupyterhub_config.py
--The public facing URL of the whole JupyterHub application.
--This is the address on which the proxy will bind. Sets protocol, ip, base_url
--c.JupyterHub.bind_url = 'http://:8000'
c.JupyterHub.bind_url = 'http://127.0.0.1:8000/jhub/'
Hope it is helpful.
Thanks @DataVictorEngineer!
Thank you @DataVictorEngineer. As it turns out, I just messed things up with Docker networking. The basic configuration also works for me.
This is very valuable information, @DataVictorEngineer! I believe this should be somewhere in the JupyterHub docs, probably at jupyterhub/jupyterhub/docs/source/reference/config-proxy.md. I'm not affiliated to this project, but maybe @willingc has an opinion?
@andreas-h Pull requests are very much welcome. I think the referenced page would be a good location too 👍
@andreas-h and @willingc the modifications are merged to the documentation: https://github.com/jupyterhub/jupyterhub/blob/master/docs/source/reference/config-proxy.md
Thanks for pointing out @andreas-h !
Anyone have an equivalent nginx
config working? Currently wrestling with this same issue, but in an nginx
-based setup - tried the nginx instructions, and then attempted to:
bind_url = http://localhost:8000/jupyter
;location /
to location /jupyter/
;rewrite /jupyter/(.*) /$1 break;
in the location
block.This results in a bunch of 404s for static resources.
...found that rewrite /jupyter/(.*) /jupyter/$1 break;
works.
@candu would you mind sharing your full nginx config?
@DataVictorEngineer : Thank you very much, you set me on the right path. My task was to proxy JupyterHub and Rstudio from http://my.domain/jhub
and http://my.domain/rstudio
, respectively. It turned out that JupyterHub requires the ProxyPreserveHost On
directive, which, alas, screws up Rstudio. The solution was to enclose the JupyterHub-relevant proxy settings in a <Location ...>
"directory", as shown below:
<Proxy *>
Allow from localhost
</Proxy>
RewriteEngine on
### JupyterHub
# add trailing slash
RedirectMatch permanent ^/jhub$ /jhub/
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /jhub/(.*) ws://127.0.0.1:8000/jhub/$1 [P,L]
RewriteRule /jhub/(.*) http://127.0.0.1:8000/jhub/$1 [P,L]
<Location /jhub/>
# preserve Host header to avoid cross-origin problems
# this setting screws up Rstudio, use for JupyterHub only
ProxyPreserveHost On
# proxy to JupyterHub, omit location parameter from ProxyPass etc
ProxyPass http://127.0.0.1:8000/jhub/
ProxyPassReverse http://127.0.0.1:8000/jhub/
</Location>
### Rstudio Server Proxy
# add trailing slash
RedirectMatch permanent ^/rstudio$ /rstudio/
# if websocket, then ws://localhost...
RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule /rstudio/(.*) ws://127.0.0.1:8787/$1 [P,L]
# if not websocket, then http://localhost...
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteRule /rstudio/(.*) http://127.0.0.1:8787/$1 [P,L]
# proxy to Rstudio
ProxyPass /rstudio/ http://127.0.0.1:8787/
ProxyPassReverse /rstudio/ http://127.0.0.1:8787/
This cost me 2 hours of my life, but it works now.
for @nstickney and anyone else who's curious, here's the full nginx config:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
# ports, server name, SSL certs, etc. go here
location /jupyter/ {
rewrite /jupyter/(.*) /jupyter/$1 break;
proxy_pass http://localhost:8086;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Anyone able to do this with Jupyterhub version 1.3. I have jupyterhub deployed in kubernetes and want to reverse proxy through apache.
Apache config
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /jupyter/(.) ws://
Jupyterhub config.yaml
hub:
cookieSecret: "e83c19ff895bf91adea7bf74b05120e9d18cbcd2e32c733436129e2d8b2b7cf2"
service:
loadBalancerIP: 10.0.1.226
extraConfig:
first-config: |# some code
c.JupyterHub.allow_named_servers = True
c.JupyterHub.bind_url = 'http://
For some reason it always redirects to /hub/jupyterhub/...
Logs from hub pod
[I 2021-01-27 22:08:54.552 JupyterHub log:181] 302 GET /jupyter/user/mnygk3djnnqw4/lab/?token=[secret] -> /hub/jupyter/user/mnygk3djnnqw4/lab/?token=[secret] (@::ffff:100.126.0.0) 0.94ms [I 2021-01-27 22:08:54.606 JupyterHub log:181] 302 GET /jupyter/user/mnygk3djnnqw4/lab/?token=[secret] -> /hub/jupyter/user/mnygk3djnnqw4/lab/?token=[secret] (@::ffff:100.126.0.0) 0.83ms [I 2021-01-27 22:08:54.698 JupyterHub log:181] 302 GET /jupyter/user/mnygk3djnnqw4/lab/?token=[secret] -> /hub/jupyter/user/mnygk3djnnqw4/lab/?token=[secret] (@::ffff:100.126.0.0) 0.89ms [I 2021-01-27 22:08:54.743 JupyterHub log:181] 302 GET /jupyter/user/mnygk3djnnqw4/lab/?token=[secret] -> /hub/jupyter/user/mnygk3djnnqw4/lab/?token=[secret] (@::ffff:100.126.0.0) 0.77ms
The JupyterHub documentation shows how to reverse proxy JH on the root path (
/
). However, I would like to access JH atxxx.yyy.com/jupyter
, that is, on the subpathjupyter
.Here is the relevant block in my
000-default.conf
. Note that there is no JH config file that is being used, i.e., default configuration.Now when I go to
xxx.yyy.com/jupyter
it redirects toxxx.yyy.com/hub
and I get the message:Any help with this configuration would be appreciated. I am aware of similar questions here, here and here, but none of them appear to resolve this issue, specifically for apache & JupyterHub.