Multi-user server for Jupyter notebooks

Overview

Technical Overview | Installation | Configuration | Docker | Contributing | License | Help and Resources


Please note that this repository is participating in a study into the sustainability of open source projects. Data will be gathered about this repository for approximately the next 12 months, starting from 2021-06-11.

Data collected will include the number of contributors, number of PRs, time taken to close/merge these PRs, and issues closed.

For more information, please visit our informational page or download our participant information sheet.


JupyterHub

Latest PyPI version Latest conda-forge version Documentation build status GitHub Workflow Status - Test DockerHub build status Test coverage of code GitHub Discourse Gitter

With JupyterHub you can create a multi-user Hub that spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server.

Project Jupyter created JupyterHub to support many users. The Hub can offer notebook servers to a class of students, a corporate data science workgroup, a scientific research project, or a high-performance computing group.

Technical overview

Three main actors make up JupyterHub:

  • multi-user Hub (tornado process)
  • configurable http proxy (node-http-proxy)
  • multiple single-user Jupyter notebook servers (Python/Jupyter/tornado)

Basic principles for operation are:

  • Hub launches a proxy.
  • The Proxy forwards all requests to Hub by default.
  • Hub handles login and spawns single-user servers on demand.
  • Hub configures proxy to forward URL prefixes to the single-user notebook servers.

JupyterHub also provides a REST API for administration of the Hub and its users.

Installation

Check prerequisites

  • A Linux/Unix based system

  • Python 3.6 or greater

  • nodejs/npm

    • If you are using conda, the nodejs and npm dependencies will be installed for you by conda.

    • If you are using pip, install a recent version (at least 12.0) of nodejs/npm.

  • If using the default PAM Authenticator, a pluggable authentication module (PAM).

  • TLS certificate and key for HTTPS communication

  • Domain name

Install packages

Using conda

To install JupyterHub along with its dependencies including nodejs/npm:

conda install -c conda-forge jupyterhub

If you plan to run notebook servers locally, install JupyterLab or Jupyter notebook:

conda install jupyterlab
conda install notebook

Using pip

JupyterHub can be installed with pip, and the proxy with npm:

npm install -g configurable-http-proxy
python3 -m pip install jupyterhub

If you plan to run notebook servers locally, you will need to install JupyterLab or Jupyter notebook:

python3 -m pip install --upgrade jupyterlab
python3 -m pip install --upgrade notebook

Run the Hub server

To start the Hub server, run the command:

jupyterhub

Visit https://localhost:8000 in your browser, and sign in with your unix PAM credentials.

Note: To allow multiple users to sign in to the server, you will need to run the jupyterhub command as a privileged user, such as root. The wiki describes how to run the server as a less privileged user, which requires more configuration of the system.

Configuration

The Getting Started section of the documentation explains the common steps in setting up JupyterHub.

The JupyterHub tutorial provides an in-depth video and sample configurations of JupyterHub.

Create a configuration file

To generate a default config file with settings and descriptions:

jupyterhub --generate-config

Start the Hub

To start the Hub on a specific url and port 10.0.1.2:443 with https:

jupyterhub --ip 10.0.1.2 --port 443 --ssl-key my_ssl.key --ssl-cert my_ssl.cert

Authenticators

Authenticator Description
PAMAuthenticator Default, built-in authenticator
OAuthenticator OAuth + JupyterHub Authenticator = OAuthenticator
ldapauthenticator Simple LDAP Authenticator Plugin for JupyterHub
kerberosauthenticator Kerberos Authenticator Plugin for JupyterHub

Spawners

Spawner Description
LocalProcessSpawner Default, built-in spawner starts single-user servers as local processes
dockerspawner Spawn single-user servers in Docker containers
kubespawner Kubernetes spawner for JupyterHub
sudospawner Spawn single-user servers without being root
systemdspawner Spawn single-user notebook servers using systemd
batchspawner Designed for clusters using batch scheduling software
yarnspawner Spawn single-user notebook servers distributed on a Hadoop cluster
wrapspawner WrapSpawner and ProfilesSpawner enabling runtime configuration of spawners

Docker

A starter docker image for JupyterHub gives a baseline deployment of JupyterHub using Docker.

Important: This jupyterhub/jupyterhub image contains only the Hub itself, with no configuration. In general, one needs to make a derivative image, with at least a jupyterhub_config.py setting up an Authenticator and/or a Spawner. To run the single-user servers, which may be on the same system as the Hub or not, Jupyter Notebook version 4 or greater must be installed.

The JupyterHub docker image can be started with the following command:

docker run -p 8000:8000 -d --name jupyterhub jupyterhub/jupyterhub jupyterhub

This command will create a container named jupyterhub that you can stop and resume with docker stop/start.

The Hub service will be listening on all interfaces at port 8000, which makes this a good choice for testing JupyterHub on your desktop or laptop.

If you want to run docker on a computer that has a public IP then you should (as in MUST) secure it with ssl by adding ssl options to your docker configuration or by using a ssl enabled proxy.

Mounting volumes will allow you to store data outside the docker image (host system) so it will be persistent, even when you start a new image.

The command docker exec -it jupyterhub bash will spawn a root shell in your docker container. You can use the root shell to create system users in the container. These accounts will be used for authentication in JupyterHub's default configuration.

Contributing

If you would like to contribute to the project, please read our contributor documentation and the CONTRIBUTING.md. The CONTRIBUTING.md file explains how to set up a development installation, how to run the test suite, and how to contribute to documentation.

For a high-level view of the vision and next directions of the project, see the JupyterHub community roadmap.

A note about platform support

JupyterHub is supported on Linux/Unix based systems.

JupyterHub officially does not support Windows. You may be able to use JupyterHub on Windows if you use a Spawner and Authenticator that work on Windows, but the JupyterHub defaults will not. Bugs reported on Windows will not be accepted, and the test suite will not run on Windows. Small patches that fix minor Windows compatibility issues (such as basic installation) may be accepted, however. For Windows-based systems, we would recommend running JupyterHub in a docker container or Linux VM.

Additional Reference: Tornado's documentation on Windows platform support

License

We use a shared copyright model that enables all contributors to maintain the copyright on their contributions.

All code is licensed under the terms of the revised BSD license.

Help and resources

We encourage you to ask questions and share ideas on the Jupyter community forum. You can also talk with us on our JupyterHub Gitter channel.

JupyterHub follows the Jupyter Community Guides.


Technical Overview | Installation | Configuration | Docker | Contributing | License | Help and Resources

Comments
  • Embedding jupyterhub in iframe

    Embedding jupyterhub in iframe

    I have embedded jupyter notebook inside iframe, It's working fine. Now, I am trying to embed Jupyterhub inside iframe. But, getting error "Blocked by Content Security Policy". Is Any way to do this?

    opened by satendrakumar 54
  • Deploying behind a reverse proxy

    Deploying behind a reverse proxy

    Has anyone worked on deploying jupyterhub behind a Reverse Proxy?

    I am trying to deploy it on a system that communicates with the open network through an Apache reverse proxy. Authentication works fine, and kernels are created when users open notebooks, but the notebooks cannot connect to their kernels. It looks like requests are coming in, but communication out through the Apache server is not working correctly.

    reference 
    opened by danielballan 51
  • Authorization form must be sent from authorization page

    Authorization form must be sent from authorization page

    Hi! after upgrading to master branch (around 40 days of new commits) admins are no longer able to impersonate users, we get this error right after clicking "Authorize" on the new page:

    https://github.com/jupyterhub/jupyterhub/blob/5b4f0d4304b1ea57b4d398609f2777bd93131ef4/jupyterhub/apihandlers/auth.py#L255

    403 : Forbidden
    Authorization form must be sent from authorization page
    

    We are still using GitHubOAuthenticator and Postgres as backend.

    Also other strange thing is happening, the admin page is not properly listing all users, but this is probably related to some of our custom page.html templates:

    image

    opened by elgalu 47
  • Make JupyterHub Admin page into a React app

    Make JupyterHub Admin page into a React app

    closes #3039

    This PR includes a built out stateless React app meant to replace the server-rendered Jinja templates used for the admin console. The app is pulled into the template as a static bundle, and carries out admin requests through the JuptyerHub REST API. This change (and future ones like it) will likely need to be included in the JupyterHub build process. This will mainly just include React code testing, linting, and transpilation.

    This is currently a work in progress, please feel free to reach out with suggestions / edits you'd like to see as well as further steps needed to integrate 👍

    TODO:

    new 
    opened by naatebarber 45
  • jupyterhub redirect issue

    jupyterhub redirect issue

    I am having issues with jupyterhub public port not working and the private port not being able to redirect the page to jupyter-single notebook after login.

    If I define ports as:

    Private port:

    c.JupyterHub.hub_port = 8089

    Public port:

    c.JupyterHub.port = 8090

    and open this url: http://127.0.0.1:8090/ on the node I get white screen "The connection was reset" but if I use the http://127.0.0.1:8089 (which I should not), it lets me log in but then does not redirect.

    I am attaching my jupyterhub config file and the output I get in my terminal. Any help will be greatly appreciated!

    Here is my config file (it's a big one, so my apologies for that): $ more jupyterhub_config.py

    # Configuration file for jupyterhub.
    c = get_config()
    #This is just an experiment
    #import nbextensions
    #End of experiment
    import os
    pjoin = os.path.join
    
    #runtime_dir = os.path.join('~/.conda/envs/jupyterhub2/bin/jupyterhub')
    runtime_dir = os.path.join('/userhome/username1/Work/Jupyterhub')
    ##ssl_dir = pjoin(runtime_dir, 'ssl')
    ssl_dir = runtime_dir
    if not os.path.exists(ssl_dir):
        os.makedirs(ssl_dir)
    
    # https on :443
    ###c.JupyterHub.port = 80880
    c.JupyterHub.ssl_key = pjoin(ssl_dir, 'ca.key')
    c.JupyterHub.ssl_cert = pjoin(ssl_dir, 'ca.crt')
    
    # put the JupyterHub cookie secret and state db
    # in /var/run/jupyterhub
    c.JupyterHub.cookie_secret_file = pjoin(runtime_dir, 'cookie_secret')
    c.JupyterHub.db_url = pjoin(runtime_dir, 'jupyterhub.sqlite')
    # or `--db=/path/to/jupyterhub.sqlite` on the command-line
    
    #########################Original config start from here on:####################
    #c.JupyterHub.ssl_key = '/userhome/username1/Work/Jupyterhub/ca.key'
    #c.JupyterHub.ssl_cert = '/userhome/username1/Work/Jupyterhub/ca.crt'
    
    ###c.JupyterHub.port = 44223
    ######Private port:
    c.JupyterHub.hub_port = 8089
    
    #c.JupyterHub.hup_ip = 127.0.0.1
    ######Public port:
    c.JupyterHub.port = 8090
    # c.JupyterHub.proxy_api_port = 0
    # c.JupyterHub.statsd_port = 8125
    # This should be the full Error! Hyperlink reference not valid.
    
    #------------------------------------------------------------------------------
    # Configurable configuration
    #------------------------------------------------------------------------------
    
    #------------------------------------------------------------------------------
    # LoggingConfigurable configuration
    #------------------------------------------------------------------------------
    
    # A parent class for Configurables that log.
    #
    # Subclasses have a log trait, and the default behavior is to get the logger
    # from the currently running Application.
    
    #------------------------------------------------------------------------------
    # SingletonConfigurable configuration
    #------------------------------------------------------------------------------
    
    # A configurable that only allows one instance.
    #
    # This class is for classes that should only have one instance of itself or
    # *any* subclass. To create and retrieve such a class use the
    # :meth:`SingletonConfigurable.instance` method.
    
    #------------------------------------------------------------------------------
    # Application configuration
    #------------------------------------------------------------------------------
    
    # This is an application.
    
    # The date format used by logging formatters for %(asctime)s
    #c.Application.log_datefmt = '%Y-%m-%d %H:%M:%S'
    
    # The Logging format template
    #c.Application.log_format = '[%(name)s]%(highlevel)s %(message)s'
    
    # Set the log level by value or name.
    #c.Application.log_level = 30
    
    #------------------------------------------------------------------------------
    # JupyterHub configuration
    #------------------------------------------------------------------------------
    
    # An Application for starting a Multi-User Jupyter Notebook server.
    
    # Grant admin users permission to access single-user servers.
    #
    # Users should be properly informed if this is enabled.
    # c.JupyterHub.admin_access = False
    
    # DEPRECATED, use Authenticator.admin_users instead.
    # c.JupyterHub.admin_users = set()
    
    # Answer yes to any questions (e.g. confirm overwrite)
    # c.JupyterHub.answer_yes = False
    
    # Dict of token:username to be loaded into the database.
    #
    # Allows ahead-of-time generation of API tokens for use by services.
    # c.JupyterHub.api_tokens = {}
    
    # Class for authenticating users.
    #
    # This should be a class with the following form:
    #
    # - constructor takes one kwarg: `config`, the IPython config object.
    #
    # - is a tornado.gen.coroutine
    # - returns username on success, None on failure
    # - takes two arguments: (handler, data),
    #   where `handler` is the calling web.RequestHandler,
    #   and `data` is the POST form data from the login page.
    # c.JupyterHub.authenticator_class = 'jupyterhub.auth.PAMAuthenticator'
    c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
    c.LDAPAuthenticator.server_address = 'nihdcadhub.nih.gov'
    c.LDAPAuthenticator.bind_dn_template = 'CN={username},OU=Users,OU=xxxxx,OU=xxx,OU=xx,DC=xxx,DC=xxx'
    #c.LDAPAuthenticator.allowed_groups = ['CN=xxxxx OEB All,OU=Groups,OU=xxxxx,OU=xxx,OU=xx,DC=xxx,DC=xxx']
    ###c.LDAPAuthenticator.use_ssl = False
    ###c.LDAPAuthenticator.lookup_dn = True
    # Active Directory
    ###c.LDAPAuthenticator.user_attribute = 'sAMAccountName'
    # OpenLDAP
    ###c.LDAPAuthenticator.user_attribute = 'uid'
    
    # The base URL of the entire application
    ###c.JupyterHub.base_url = 'http://127.0.0.1:8088/hub'
    
    # Whether to shutdown the proxy when the Hub shuts down.
    #
    # Disable if you want to be able to teardown the Hub while leaving the proxy
    # running.
    #
    # Only valid if the proxy was starting by the Hub process.
    #
    # If both this and cleanup_servers are False, sending SIGINT to the Hub will
    # only shutdown the Hub, leaving everything else running.
    #
    # The Hub should be able to resume from database state.
    c.JupyterHub.cleanup_proxy = True
    
    # Whether to shutdown single-user servers when the Hub shuts down.
    #
    # Disable if you want to be able to teardown the Hub while leaving the single-
    # user servers running.
    #
    # If both this and cleanup_proxy are False, sending SIGINT to the Hub will only
    # shutdown the Hub, leaving everything else running.
    #
    # The Hub should be able to resume from database state.
    c.JupyterHub.cleanup_servers = True
    
    # The config file to load
    c.JupyterHub.config_file = '/userhome/username1/Work/Jupyterhub/jupyterhub_config.py'
    
    # Confirm that JupyterHub should be run without SSL. This is **NOT RECOMMENDED**
    # unless SSL termination is being handled by another layer.
    # c.JupyterHub.confirm_no_ssl = False
    
    # Number of days for a login cookie to be valid. Default is two weeks.
    # c.JupyterHub.cookie_max_age_days = 14
    
    # The cookie secret to use to encrypt cookies.
    #
    # Loaded from the JPY_COOKIE_SECRET env variable by default.
    # c.JupyterHub.cookie_secret = b''
    
    # File in which to store the cookie secret.
    # c.JupyterHub.cookie_secret_file = 'jupyterhub_cookie_secret'
    
    # The location of jupyterhub data files (e.g. /usr/local/share/jupyter/hub)
    ###c.JupyterHub.data_files_path = '/userhome/username1/.conda/envs/jupyterhub2'
    
    # Include any kwargs to pass to the database connection. See
    # sqlalchemy.create_engine for details.
    # c.JupyterHub.db_kwargs = {}
    
    # url for the database. e.g. `sqlite:///jupyterhub.sqlite`
    # c.JupyterHub.db_url = 'sqlite:///jupyterhub.sqlite'
    
    # log all database transactions. This has A LOT of output
    # c.JupyterHub.debug_db = False
    
    # show debug output in configurable-http-proxy
    c.JupyterHub.debug_proxy = True
    
    # Send JupyterHub's logs to this file.
    #
    # This will *only* include the logs of the Hub itself, not the logs of the proxy
    # or any single-user servers.
    # c.JupyterHub.extra_log_file = ''
    # put the log file in /var/log
    ###c.JupyterHub.extra_log_file = '/var/log/jupyterhub.log'
    c.JupyterHub.extra_log_file = '/userhome/username1/Work/Jupyterhub/jupyterhub.log'
    
    # Extra log handlers to set on JupyterHub logger
    # c.JupyterHub.extra_log_handlers = []
    
    # Generate default config file
    # c.JupyterHub.generate_config = False
    
    # The ip for this process
    # c.JupyterHub.hub_ip = '127.0.0.1'
    
    # The port for this process
    # c.JupyterHub.hub_port = 8081
    
    # The prefix for the hub server. Must not be '/'
    ###c.JupyterHub.hub_prefix = '/userhome'
    
    # The public facing ip of the whole application (the proxy)
    # c.JupyterHub.ip = ''
    
    # Supply extra arguments that will be passed to Jinja environment.
    # c.JupyterHub.jinja_environment_options = {}
    
    # Interval (in seconds) at which to update last-activity timestamps.
    # c.JupyterHub.last_activity_interval = 300
    
    # Specify path to a logo image to override the Jupyter logo in the banner.
    # c.JupyterHub.logo_file = ''
    
    # File to write PID Useful for daemonizing jupyterhub.
    # c.JupyterHub.pid_file = ''
    
    # The public facing port of the proxy
    # c.JupyterHub.port = 8000
    
    # The ip for the proxy API handlers
    # c.JupyterHub.proxy_api_ip = '127.0.0.1'
    
    # The port for the proxy API handlers
    # c.JupyterHub.proxy_api_port = 0
    
    # The Proxy Auth token.
    #
    # Loaded from the CONFIGPROXY_AUTH_TOKEN env variable by default.
    # c.JupyterHub.proxy_auth_token = ''
    c.JupyterHub.proxy_auth_token = 'blah-blah-blah'
    
    # Interval (in seconds) at which to check if the proxy is running.
    # c.JupyterHub.proxy_check_interval = 30
    
    # The command to start the http proxy.
    #
    # Only override if configurable-http-proxy is not on your PATH
    ###c.JupyterHub.proxy_cmd = ['configurable-http-proxy']
    
    # Purge and reset the database.
    # c.JupyterHub.reset_db = False
    
    # The class to use for spawning single-user servers.
    #
    # Should be a subclass of Spawner.
    ###c.JupyterHub.spawner_class = 'jupyterhub.spawner.LocalProcessSpawner'
    c.JupyterHub.spawner_class = 'sudospawner.SudoSpawner'
    # Path to SSL certificate file for the public facing interface of the proxy
    #
    # Use with ssl_key
    # c.JupyterHub.ssl_cert = ''
    
    # Path to SSL key file for the public facing interface of the proxy
    #
    # Use with ssl_cert
    # c.JupyterHub.ssl_key = ''
    
    # Host to send statds metrics to
    # c.JupyterHub.statsd_host = ''
    
    # Port on which to send statsd metrics about the hub
    # c.JupyterHub.statsd_port = 8125
    
    # Prefix to use for all metrics sent by jupyterhub to statsd
    # c.JupyterHub.statsd_prefix = 'jupyterhub'
    
    # Run single-user servers on subdomains of this host.
    #
    # This should be the full Error! Hyperlink reference not valid.
    #
    # Provides additional cross-site protections for javascript served by single-
    # user servers.
    #
    # Requires <username>.hub.domain.tld to resolve to the same host as
    # hub.domain.tld.
    #
    # In general, this is most easily achieved with wildcard DNS.
    #
    # When using SSL (i.e. always) this also requires a wildcard SSL certificate.
    # c.JupyterHub.subdomain_host = ''
    
    # Paths to search for jinja templates.
    # c.JupyterHub.template_paths = []
    
    # Extra settings overrides to pass to the tornado application.
    # c.JupyterHub.tornado_settings = {}
    
    #------------------------------------------------------------------------------
    # Spawner configuration
    #------------------------------------------------------------------------------
    
    # Base class for spawning single-user notebook servers.
    #
    # Subclass this, and override the following methods:
    #
    # - load_state - get_state - start - stop - poll
    
    # Extra arguments to be passed to the single-user server
    # c.Spawner.args = []
    ###c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
    # The command used for starting notebooks.
    c.SudoSpawner.sudospawner_path = '/userhome/username1/.conda/envs/jupyterhub2/bin/sudospawner'
    c.Spawner.cmd = ['jupyterhub-singleuser']
    
    # Enable debug-logging of the single-user server
    c.Spawner.debug = True
    
    # The default URL for the single-user server.
    #
    # Can be used in conjunction with --notebook-dir=/ to enable  full filesystem
    # traversal, while preserving user's homedir as landing page for notebook
    #
    # `%U` will be expanded to the user's username
    ###c.Spawner.default_url = '/userhome/`%U`'
    
    # Disable per-user configuration of single-user servers.
    #
    # This prevents any config in users' $HOME directories from having an effect on
    # their server.
    c.Spawner.disable_user_config = False
    
    # Whitelist of environment variables for the subprocess to inherit
    c.Spawner.env_keep = ['PATH', 'PYTHONPATH', 'CONDA_ROOT', 'CONDA_DEFAULT_ENV', 'VIRTUAL_ENV', 'LANG', 'L
    C_ALL']
    
    # Environment variables to load for the Spawner.
    #
    # Value could be a string or a callable. If it is a callable, it will be called
    # with one parameter, which will be the instance of the spawner in use. It
    # should quickly (without doing much blocking operations) return a string that
    # will be used as the value for the environment variable.
    # c.Spawner.environment = {}
    
    # Timeout (in seconds) before giving up on a spawned HTTP server
    #
    # Once a server has successfully been spawned, this is the amount of time we
    # wait before assuming that the server is unable to accept connections.
    # c.Spawner.http_timeout = 30
    
    # The IP address (or hostname) the single-user server should listen on
    ###c.Spawner.ip = '127.0.0.1'
    
    # The notebook directory for the single-user server
    #
    # `~` will be expanded to the user's home directory `%U` will be expanded to the
    # user's username
    c.Spawner.notebook_dir = '~/notebooks'
    ###c.Spawner.args = ['--NotebookApp.default_url=/notebooks/Welcome.ipynb']
    # An HTML form for options a user can specify on launching their server. The
    # surrounding `<form>` element and the submit button are already provided.
    #
    # For example:
    #
    #     Set your key:
    #     <input name="key" val="default_key"></input>
    #     <br>
    #     Choose a letter:
    #     <select name="letter" multiple="true">
    #       <option value="A">The letter A</option>
    #       <option value="B">The letter B</option>
    #     </select>
    # c.Spawner.options_form = ''
    
    # Interval (in seconds) on which to poll the spawner.
    # c.Spawner.poll_interval = 30
    
    # Timeout (in seconds) before giving up on the spawner.
    #
    # This is the timeout for start to return, not the timeout for the server to
    # respond. Callers of spawner.start will assume that startup has failed if it
    # takes longer than this. start should return when the server process is started
    # and its location is known.
    # c.Spawner.start_timeout = 60
    
    #------------------------------------------------------------------------------
    # LocalProcessSpawner configuration
    #------------------------------------------------------------------------------
    
    # A Spawner that just uses Popen to start local processes as users.
    #
    # Requires users to exist on the local system.
    #
    # This is the default spawner for JupyterHub.
    
    # Seconds to wait for process to halt after SIGINT before proceeding to SIGTERM
    #c.LocalProcessSpawner.INTERRUPT_TIMEOUT = 10
    
    # Seconds to wait for process to halt after SIGKILL before giving up
    #c.LocalProcessSpawner.KILL_TIMEOUT = 5
    
    # Seconds to wait for process to halt after SIGTERM before proceeding to SIGKILL
    #c.LocalProcessSpawner.TERM_TIMEOUT = 5
    
    #------------------------------------------------------------------------------
    # Authenticator configuration
    #------------------------------------------------------------------------------
    
    # A class for authentication.
    #
    # The primary API is one method, `authenticate`, a tornado coroutine for
    # authenticating users.
    
    # set of usernames of admin users
    #
    # If unspecified, only the user that launches the server will be admin.
    c.Authenticator.admin_users = set(['username1'])
    
    # Dictionary mapping authenticator usernames to JupyterHub users.
    #
    # Can be used to map OAuth service names to local users, for instance.
    #
    # Used in normalize_username.
    # c.Authenticator.username_map = {}
    
    # Regular expression pattern for validating usernames.
    #
    # If not defined: allow any username.
    # c.Authenticator.username_pattern = ''
    
    # Username whitelist.
    #
    # Use this to restrict which users can login. If empty, allow any user to
    # attempt login.
    # c.Authenticator.whitelist = set()
    
    #------------------------------------------------------------------------------
    # LocalAuthenticator configuration
    #------------------------------------------------------------------------------
    
    # Base class for Authenticators that work with local Linux/UNIX users
    #
    # Checks for local users, and can attempt to create them if they exist.
    
    # The command to use for creating users as a list of strings.
    #
    # For each element in the list, the string USERNAME will be replaced with the
    # user's username. The username will also be appended as the final argument.
    #
    # For Linux, the default value is:
    #
    #     ['adduser', '-q', '--gecos', '""', '--disabled-password']
    #
    # To specify a custom home directory, set this to:
    #
    #     ['adduser', '-q', '--gecos', '""', '--home', '/customhome/USERNAME', '--
    # disabled-password']
    #
    # This will run the command:
    #
    # adduser -q --gecos "" --home /customhome/river --disabled-password river
    #
    # when the user 'river' is created.
    c.LocalAuthenticator.add_user_cmd = ['adduser', '-q', '--gecos', '""', '--home', '/customhome/USERNAME',
     '--disabled-password']
    
    # If a user is added that doesn't exist on the system, should I try to create
    # the system user?
    c.LocalAuthenticator.create_system_users = True
    
    # Automatically whitelist anyone in this group.
    # c.LocalAuthenticator.group_whitelist = set()
    
    #------------------------------------------------------------------------------
    # PAMAuthenticator configuration
    #------------------------------------------------------------------------------
    
    # Authenticate local Linux/UNIX users with PAM
    
    # The encoding to use for PAM
    #c.PAMAuthenticator.encoding = 'utf8'
    
    # Whether to open PAM sessions when spawners are started.
    #
    # This may trigger things like mounting shared filsystems, loading credentials,
    # etc. depending on system configuration, but it does not always work.
    #
    # It can be disabled with::
    #
    #c.PAMAuthenticator.open_sessions = False
    #c.PAMAuthenticator.open_sessions = True
    
    # The PAM service to use for authentication.
    #c.PAMAuthenticator.service = 'login'
    

    Here is the output:

    $ jupyterhub -f /userhome/username1/Work/Jupyterhub/jupyterhub_config.py --debug
    [D 2016-09-12 14:19:16.907 JupyterHub application:529] Looking for /userhome/username1/Work/Jupyterhub/jupyterhub_config in None
    [D 2016-09-12 14:19:16.908 JupyterHub application:549] Loaded config file: /userhome/username1/Work/Jupyterhub/jupyterhub_config.py
    [I 2016-09-12 14:19:16.974 JupyterHub app:622] Loading cookie_secret from /userhome/username1/Work/Jupyterhub/cookie_secret
    [D 2016-09-12 14:19:16.974 JupyterHub app:694] Connecting to db: sqlite:////userhome/username1/Work/Jupyterhub/jupyterhub.sqlite
    [I 2016-09-12 14:19:17.030 JupyterHub app:785] Not using whitelist. Any authenticated user will be allowed.
    [D 2016-09-12 14:19:17.070 JupyterHub app:888] Loaded users:
        username1 admin
         username2
         username3
    [I 2016-09-12 14:19:17.076 JupyterHub app:1231] Hub API listening on http://127.0.0.1:8089/hub/
    [I 2016-09-12 14:19:17.079 JupyterHub app:968] Starting proxy @ http://*:8090/
    [D 2016-09-12 14:19:17.079 JupyterHub app:969] Proxy cmd: ['configurable-http-proxy', '--ip', '', '--port', '8090', '--api-ip', '127.0.0.1', '--api-port', '8091', '--default-target', 'http://127.0.0.1:8089', '--error-target', 'http://127.0.0.1:8089/hub/error', '--log-level', 'debug', '--ssl-key', '/userhome/username1/Work/Jupyterhub/ca.key', '--ssl-cert', '/userhome/username1/Work/Jupyterhub/ca.crt']
    14:19:17.257 - info: [ConfigProxy] Proxying https://*:8090 to http://127.0.0.1:8089
    14:19:17.261 - info: [ConfigProxy] Proxy API at http://127.0.0.1:8091/api/routes
    [D 2016-09-12 14:19:17.285 JupyterHub app:997] Proxy started and appears to be up
    [I 2016-09-12 14:19:17.286 JupyterHub app:1254] JupyterHub is now running at http://127.0.0.1:8090/
    [I 2016-09-12 14:20:34.809 JupyterHub log:100] 302 GET / (@127.0.0.1) 1.93ms
    [I 2016-09-12 14:20:34.819 JupyterHub log:100] 302 GET /hub (@127.0.0.1) 0.55ms
    [D 2016-09-12 14:20:34.830 JupyterHub pages:35] User is not running: /hub/home
    [I 2016-09-12 14:20:34.835 JupyterHub log:100] 302 GET /hub/ ([email protected]) 3.93ms
    [I 2016-09-12 14:20:34.873 JupyterHub log:100] 200 GET /hub/home ([email protected]) 32.74ms
    [D 2016-09-12 14:20:34.896 JupyterHub log:100] 200 GET /hub/static/css/style.min.css?v=91c753d3c28f12b7480e5d0d9e7c55b2 (@127.0.0.1) 7.97ms
    [D 2016-09-12 14:20:34.898 JupyterHub log:100] 200 GET /hub/static/components/requirejs/require.js?v=6da8be361b9ee26c5e721e76c6d4afce (@127.0.0.1) 1.33ms
    [D 2016-09-12 14:20:34.912 JupyterHub log:100] 200 GET /hub/logo (@127.0.0.1) 13.55ms
    [D 2016-09-12 14:20:34.947 JupyterHub log:100] 200 GET /hub/static/components/font-awesome/fonts/fontawesome-webfont.woff?v=4.1.0 (@127.0.0.1) 1.66ms
    [D 2016-09-12 14:20:34.955 JupyterHub log:100] 200 GET /hub/static/js/home.js?v=(& (@127.0.0.1) 1.42ms
    [D 2016-09-12 14:20:34.993 JupyterHub log:100] 200 GET /favicon.ico (@127.0.0.1) 11.15ms
    [D 2016-09-12 14:20:35.000 JupyterHub log:100] 200 GET /hub/static/components/jquery/jquery.min.js?v=(& (@127.0.0.1) 1.50ms
    [D 2016-09-12 14:20:35.001 JupyterHub log:100] 200 GET /hub/static/js/jhapi.js?v=(& (@127.0.0.1) 1.05ms
    [D 2016-09-12 14:20:35.012 JupyterHub log:100] 304 GET /favicon.ico (@127.0.0.1) 1.01ms
    [D 2016-09-12 14:20:35.026 JupyterHub log:100] 200 GET /hub/static/js/utils.js?v=(& (@127.0.0.1) 1.48ms
    [I 2016-09-12 14:20:40.378 JupyterHub log:100] 302 GET /hub/spawn ([email protected]) 4.58ms
    [I 2016-09-12 14:20:40.382 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.99ms
    [I 160912 14:20:40 mediator:68] Spawning /userhome/username1/.conda/envs/jupyterhub2/bin/jupyterhub-singleuser --user=username1 --port=38610 --cookie-name=jupyter-hub-token-username1 --base-url=/user/username1 --hub-host= --hub-prefix=/hub/ --hub-api-url=http://127.0.0.1:8089/hub/api --ip=127.0.0.1 '--notebook-dir=~/notebooks' --debug
    [D 2016-09-12 14:20:41.410 username1 application:178] Searching ['/userhome/username1', '/userhome/username1/.jupyter', '/userhome/username1/.conda/envs/jupyterhub2/etc/jupyter', '/usr/local/etc/jupyter', '/etc/jupyter'] for config files
    [D 2016-09-12 14:20:41.411 username1 application:529] Looking for jupyter_config in /etc/jupyter
    [D 2016-09-12 14:20:41.411 username1 application:529] Looking for jupyter_config in /usr/local/etc/jupyter
    [D 2016-09-12 14:20:41.411 username1 application:529] Looking for jupyter_config in /userhome/username1/.conda/envs/jupyterhub2/etc/jupyter
    [D 2016-09-12 14:20:41.411 username1 application:529] Looking for jupyter_config in /userhome/username1/.jupyter
    [D 2016-09-12 14:20:41.411 username1 application:529] Looking for jupyter_config in /userhome/username1
    [D 2016-09-12 14:20:41.412 username1 application:529] Looking for jupyter_notebook_config in /etc/jupyter
    [D 2016-09-12 14:20:41.412 username1 application:529] Looking for jupyter_notebook_config in /usr/local/etc/jupyter
    [D 2016-09-12 14:20:41.412 username1 application:529] Looking for jupyter_notebook_config in /userhome/username1/.conda/envs/jupyterhub2/etc/jupyter
    [W 2016-09-12 14:20:41.413 username1 loader:419] Unrecognized JSON config file version, assuming version 1
    [D 2016-09-12 14:20:41.413 username1 application:549] Loaded config file: /userhome/username1/.conda/envs/jupyterhub2/etc/jupyter/jupyter_notebook_config.json
    [D 2016-09-12 14:20:41.415 username1 application:529] Looking for jupyter_notebook_config in /userhome/username1/.jupyter
    [D 2016-09-12 14:20:41.415 username1 application:529] Looking for jupyter_notebook_config in /userhome/username1
    [D 2016-09-12 14:20:41.420 username1 manager:45] [nb_conda_kernels] refreshing conda info
    [D 2016-09-12 14:20:41.737 JupyterHub spawner:316] Polling subprocess every 30s
    Using Anaconda Cloud api site https://api.anaconda.org
    [D 2016-09-12 14:20:41.797 username1 manager:145] [nb_conda_kernels] refreshing conda kernelspecs
    [I 2016-09-12 14:20:41.800 username1 manager:32] [nb_conda_kernels] enabled, 7 kernels found
    [I 2016-09-12 14:20:41.844 username1 handlers:290] [nb_conda] enabled
    [I 2016-09-12 14:20:41.883 username1 handlers:73] [nb_anacondacloud] enabled
    [I 2016-09-12 14:20:41.932 username1 __init__:35] ✓ nbpresent HTML export ENABLED
    [I 2016-09-12 14:20:41.932 username1 __init__:46] ✓ nbpresent PDF export ENABLED
    [I 2016-09-12 14:20:41.938 username1 notebookapp:1128] Serving notebooks from local directory: /userhome/username1/notebooks
    [I 2016-09-12 14:20:41.938 username1 notebookapp:1128] 0 active kernels
    [I 2016-09-12 14:20:41.938 username1 notebookapp:1128] The Jupyter Notebook is running at: http://127.0.0.1:38610/user/username1/
    [I 2016-09-12 14:20:41.938 username1 notebookapp:1129] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
    [I 2016-09-12 14:20:41.941 username1 log:47] 302 GET /user/username1 (127.0.0.1) 0.66ms
    [D 2016-09-12 14:20:41.942 JupyterHub utils:84] Server at http://127.0.0.1:38610/user/username1 responded with 302
    [I 2016-09-12 14:20:41.943 JupyterHub base:306] User username1 server took 1.558 seconds to start
    [I 2016-09-12 14:20:41.943 JupyterHub orm:159] Adding user username1 to proxy /user/username1 => http://127.0.0.1:38610
    [D 2016-09-12 14:20:41.945 JupyterHub orm:146] Fetching POST http://127.0.0.1:8091/api/routes/user/username1
    14:20:41.951 - debug: [ConfigProxy] POST /user/username1 user=username1, target=http://127.0.0.1:38610
    [D 2016-09-12 14:20:41.954 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:41.963 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 1576.38ms
    [I 2016-09-12 14:20:41.970 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 1.21ms
    [D 2016-09-12 14:20:42.202 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:42.208 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 233.92ms
    [I 2016-09-12 14:20:42.212 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.75ms
    [D 2016-09-12 14:20:42.431 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:42.437 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 220.85ms
    [I 2016-09-12 14:20:42.443 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.76ms
    [D 2016-09-12 14:20:42.692 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:42.700 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 251.54ms
    [I 2016-09-12 14:20:42.705 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 1.08ms
    [D 2016-09-12 14:20:42.980 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:42.988 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 276.85ms
    [I 2016-09-12 14:20:42.994 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.94ms
    [D 2016-09-12 14:20:43.233 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:43.239 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 240.30ms
    [I 2016-09-12 14:20:43.243 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.82ms
    [D 2016-09-12 14:20:43.488 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:43.497 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 248.48ms
    [I 2016-09-12 14:20:43.503 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 1.16ms
    [D 2016-09-12 14:20:43.728 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:43.735 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 228.23ms
    [I 2016-09-12 14:20:43.738 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.74ms
    [D 2016-09-12 14:20:43.984 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:43.992 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 248.32ms
    [I 2016-09-12 14:20:43.996 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 1.06ms
    [D 2016-09-12 14:20:44.242 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:20:44.250 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 248.99ms
    [I 2016-09-12 14:22:43.050 JupyterHub log:100] 302 GET / (@127.0.0.1) 1.54ms
    [I 2016-09-12 14:22:43.052 JupyterHub log:100] 302 GET /hub (@127.0.0.1) 0.41ms
    [D 2016-09-12 14:22:43.056 JupyterHub pages:31] User is running: /user/username1
    [D 2016-09-12 14:22:43.057 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:43.062 JupyterHub log:100] 302 GET /hub/ ([email protected]) 5.81ms
    [I 2016-09-12 14:22:43.070 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 1.08ms
    [D 2016-09-12 14:22:43.310 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:43.317 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 242.31ms
    [I 2016-09-12 14:22:43.321 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.95ms
    [D 2016-09-12 14:22:43.568 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:43.576 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 250.24ms
    [I 2016-09-12 14:22:43.581 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 1.07ms
    [D 2016-09-12 14:22:43.825 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:43.831 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 246.42ms
    [I 2016-09-12 14:22:43.835 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.84ms
    [D 2016-09-12 14:22:44.054 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:44.060 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 221.38ms
    [I 2016-09-12 14:22:44.063 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.74ms
    [D 2016-09-12 14:22:44.292 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:44.298 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 231.44ms
    [I 2016-09-12 14:22:44.302 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.72ms
    [D 2016-09-12 14:22:44.540 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:44.549 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 241.75ms
    [I 2016-09-12 14:22:44.553 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 1.01ms
    [D 2016-09-12 14:22:44.793 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:44.803 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 243.02ms
    [I 2016-09-12 14:22:44.811 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 1.22ms
    [D 2016-09-12 14:22:45.093 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:45.100 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 284.35ms
    [I 2016-09-12 14:22:45.105 JupyterHub log:100] 302 GET /user/username1 (@127.0.0.1) 0.85ms
    [D 2016-09-12 14:22:45.370 JupyterHub base:231] Setting cookie for username1: jupyter-hub-token-username1, {}
    [I 2016-09-12 14:22:45.376 JupyterHub log:100] 302 GET /hub/user/username1 ([email protected]) 262.32ms
    [D 2016-09-12 14:24:17.296 JupyterHub orm:146] Fetching GET http://127.0.0.1:8091/api/routes
    [D 2016-09-12 14:25:42.037 username1 jupyterhub-singleuser:211] Clearing cookie cache
    [D 2016-09-12 14:29:17.295 JupyterHub orm:146] Fetching GET http://127.0.0.1:8091/api/routes
    [D 2016-09-12 14:30:41.996 username1 jupyterhub-singleuser:211] Clearing cookie cache
    [D 2016-09-12 14:34:17.295 JupyterHub orm:146] Fetching GET http://127.0.0.1:8091/api/routes
    [D 2016-09-12 14:35:42.038 username1 jupyterhub-singleuser:211] Clearing cookie cache
    [D 2016-09-12 14:39:17.296 JupyterHub orm:146] Fetching GET http://127.0.0.1:8091/api/routes
    
    question 
    opened by ponomarevsy 42
  • Errors getting JupyterHub to launch

    Errors getting JupyterHub to launch

    Hi All,

    Hoping you can help me with errors getting JupyterHub to launch. I have compiled and installed a fresh copy of Python3.6 on RHEL 6, then used pip to install jupyterhub (version jupyterhub-0.7.2). When I try to start JupyterHub as root, I get the following error:

    jupyterhub

    [I 2017-02-15 17:57:57.687 JupyterHub app:745] Writing cookie_secret to /usr/local/bin/jupyterhub_cookie_secret [E 2017-02-15 17:57:57.696 JupyterHub app:1527] Traceback (most recent call last): File "/usr/local/lib/python3.6/site-packages/jupyterhub/app.py", line 1524, in launch_instance_async yield self.initialize(argv) File "/usr/local/lib/python3.6/types.py", line 204, in next return next(self.__wrapped) File "/usr/local/lib/python3.6/site-packages/jupyterhub/app.py", line 1307, in initialize self.init_db() File "/usr/local/lib/python3.6/site-packages/jupyterhub/app.py", line 802, in init_db **self.db_kwargs File "/usr/local/lib/python3.6/site-packages/jupyterhub/orm.py", line 572, in new_session_factory engine = create_engine(url, **kwargs) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/init.py", line 387, in create_engine return strategy.create(*args, **kwargs) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/strategies.py", line 80, in create dbapi = dialect_cls.dbapi(**dbapi_args) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/dialects/sqlite/pysqlite.py", line 339, in dbapi raise e File "/usr/local/lib/python3.6/site-packages/sqlalchemy/dialects/sqlite/pysqlite.py", line 334, in dbapi from pysqlite2 import dbapi2 as sqlite ModuleNotFoundError: No module named 'pysqlite2'

    Reviewing other solutions to this issue, I have installed sqlite-devel.x86_64 with no improvement.

    I have also tried replacing from _sqlite3 import * with import sqlite3 in /usr/local/lib/python3.6/sqlite3/dbapi2.py, but that simply moves the error:

    <...> File "/usr/local/lib/python3.6/sqlite3/init.py", line 23, in from sqlite3.dbapi2 import * File "/usr/local/lib/python3.6/sqlite3/dbapi2.py", line 51, in version_info = tuple([int(x) for x in version.split(".")]) NameError: name 'version' is not defined

    Based on another post, I recompiled Python with the configure option --enable-loadable-sqlite-extensions, but again, it didn't help.

    I'm running out of ideas. Any recommendations? Thanks! Steve

    question configuration needs: upstream action 
    opened by SteveFelker 38
  • Question: Multiple singleuser servers

    Question: Multiple singleuser servers

    Is there plans (or interest) to add support for multiple single-user servers per user? I kinda see it in the roadmap project sharing but not sure how is that planned on being implemented, from what I can guess is basically multiple users pushing to the same git repo that is managed by one service in JupyterHub.

    Is there interest on refactoring the code to support this feature? Looking at the models in orm.py right now the one single-user server is a little hardcoded in the User class but I guess that this is something that can change.

    Another solution is probably to have "admin" servers that multiple users can access based on some permissions.

    Basically I am just asking for thoughts on these ideas and if there is interest on those features to be added upstream in case they get implemented.

    enhancement 
    opened by danielfrg 35
  • JupyterHub does not ask for authentication once you have created a notebook server for a user

    JupyterHub does not ask for authentication once you have created a notebook server for a user

    For the purpose of discussion lets say JupyterHub running in this URL:

    http://10.x.y.z:8080

    For first time login, the chrome browser would show the login page and set cookie for the active user once login is completed.

    At jupyterhub end if there is no Notebook server for that user, it would create an entry in the database and call Spawner to create new Notebook server.

    The next time you hit the site it would send 302 redirect to user specific URL, for example: http://10.x.y.z:8080/user/userx/notebooks/Demo-Spark.ipynb

    Now if you delete the cookies associated with jupyterhub, the hub-token and the user token but start use the notebook server url directly no authentication is seeked for. Once the Notebook server is created, hitting directly to that URL (http://10.x.y.z:8080/user/userx/notebooks/Demo-Spark.ipynb) from browser with no cookie does not redirect back to login page. This is insecure and unexpected.

    IMPORTANT : This happens when notebookserver is running remotely, if the notebook server is running locally this is not seen. So you need to use some remote spawners available out there to try this out and not with LocalSpawner.

    opened by pawannrao-ebay 34
  • Problem when runing jupyterhub.

    Problem when runing jupyterhub.

    Hi guys, I've really looked into the forums (usergroup, internet, stackoverflow, etc..), and closed bugs but I'm unable to find info on a similar problem.

    After installing installing all the requirements, whenever I try to run the jupyterhub command I get the following error (and I'm unable to know whats causing it).

    [luix@boxita jupyterhub]$ jupyterhub
    Traceback (most recent call last):
      File "/usr/bin/jupyterhub", line 3, in <module>
        from jupyterhub.app import main
      File "/usr/lib/python3.4/site-packages/jupyterhub/app.py", line 28, in <module>
        import tornado.httpserver
      File "/usr/lib/python3.4/site-packages/tornado-4.2b1-py3.4-linux-x86_64.egg/tornado/httpserver.py", line 34, in <module>
        from tornado.http1connection import HTTP1ServerConnection, HTTP1ConnectionParameters
      File "/usr/lib/python3.4/site-packages/tornado-4.2b1-py3.4-linux-x86_64.egg/tornado/http1connection.py", line 26, in <module>
        from tornado.concurrent import Future
      File "/usr/lib/python3.4/site-packages/tornado-4.2b1-py3.4-linux-x86_64.egg/tornado/concurrent.py", line 37, in <module>
        from concurrent import futures
      File "/usr/lib/python3.4/site-packages/concurrent/futures/__init__.py", line 8, in <module>
        from concurrent.futures._base import (FIRST_COMPLETED,
      File "/usr/lib/python3.4/site-packages/concurrent/futures/_base.py", line 355
        raise type(self._exception), self._exception, self._traceback
                                   ^
    SyntaxError: invalid syntax
    

    my system information is

    [luix@boxita jupyterhub]$ python --version
    Python 3.4.3
    [luix@boxita jupyterhub]$ ipython --version
    3.2.1
    [luix@boxita jupyterhub]$ uname -a
    Linux boxita 4.1.2-2-ARCH #1 SMP PREEMPT Wed Jul 15 08:30:32 UTC 2015 x86_64 GNU/Linux
    

    any ideas what can be??

    question reference 
    opened by beeva-luisgonzalez 34
  • Kubernetes Spawner

    Kubernetes Spawner

    I have been working a little bit in a Jupyter Hub Kubernetes Spawner (here: https://github.com/danielfrg/jupyterhub-kubernetes_spawner) and I was wondering if there is some interest on moving it to the main supported spawners on the Jupyter Hub organisation on GitHub.

    I have been testing it this week and its been working perfectly but of course there is more work to do. I plan to maintain it and add a couple of other features and example deployments.

    enhancement 
    opened by danielfrg 32
  • Login -> Logout -> Login fails

    Login -> Logout -> Login fails

    I can login once but not twice. Jupyterhub 0.5.0 running under a single user with pam authentication

    $ ./jupyterhub --log-level=DEBUG
    [D 2016-03-20 16:45:56.367 JupyterHub application:529] Looking for ./jupyterhub_config in None
    [D 2016-03-20 16:45:56.367 JupyterHub application:549] Loaded config file: /home/vbraun-hub/JupyterHub/jupyterhub_config.py
    [I 2016-03-20 16:45:56.369 JupyterHub app:558] Loading cookie_secret from /home/vbraun-hub/JupyterHub/jupyterhub_cookie_secret
    [D 2016-03-20 16:45:56.369 JupyterHub app:623] Connecting to db: sqlite:///jupyterhub.sqlite
    [W 2016-03-20 16:45:56.390 JupyterHub app:292] 
        Generating CONFIGPROXY_AUTH_TOKEN. Restarting the Hub will require restarting the proxy.
        Set CONFIGPROXY_AUTH_TOKEN env or JupyterHub.proxy_auth_token config to avoid this message.
    
    [W 2016-03-20 16:45:56.393 JupyterHub app:685] No admin users, admin interface will be unavailable.
    [W 2016-03-20 16:45:56.393 JupyterHub app:686] Add any administrative users to `c.Authenticator.admin_users` in config.
    [I 2016-03-20 16:45:56.393 JupyterHub app:712] Not using whitelist. Any authenticated user will be allowed.
    [D 2016-03-20 16:45:56.400 JupyterHub app:787] Loaded users: 
        vbraun-hub
    [I 2016-03-20 16:45:56.405 JupyterHub app:1113] Hub API listening on http://127.0.0.1:8081/hub/
    [I 2016-03-20 16:45:56.408 JupyterHub app:860] Starting proxy @ http://*:443/
    [D 2016-03-20 16:45:56.408 JupyterHub app:861] Proxy cmd: ['configurable-http-proxy', '--ip', '', '--port', '443', '--api-ip', '127.0.0.1', '--api-port', '444', '--default-target', 'http://127.0.0.1:8081', '--ssl-key', 'letsencrypt/etc/live/vbraun.cc/privkey.pem', '--ssl-cert', 'letsencrypt/etc/live/vbraun.cc/cert.pem']
    16:45:56.542 - info: [ConfigProxy] Proxying https://*:443 to http://127.0.0.1:8081
    16:45:56.545 - info: [ConfigProxy] Proxy API at http://127.0.0.1:444/api/routes
    [D 2016-03-20 16:45:56.612 JupyterHub app:889] Proxy started and appears to be up
    [I 2016-03-20 16:45:56.612 JupyterHub app:1136] JupyterHub is now running at http://127.0.0.1:443/
    [W 2016-03-20 16:46:03.348 JupyterHub auth:383] Failed to open PAM session for vbraun-hub: [PAM Error 14] Cannot make/remove an entry for the specified session
    [I 2016-03-20 16:46:03.353 JupyterHub spawner:436] Spawning jupyterhub-singleuser --user=vbraun-hub --port=36298 --cookie-name=jupyter-hub-token-vbraun-hub --base-url=/user/vbraun-hub --hub-host= --hub-prefix=/hub/ --hub-api-url=http://127.0.0.1:8081/hub/api --ip=127.0.0.1
    Failed to set groups [Errno 1] Operation not permitted
    [D 2016-03-20 16:46:03.434 JupyterHub spawner:287] Polling subprocess every 30s
    [W 2016-03-20 16:46:03.808 vbraun-hub notebookapp:253] ipywidgets package not installed.  Widgets are unavailable.
    [I 2016-03-20 16:46:03.819 vbraun-hub notebookapp:1079] Serving notebooks from local directory: /home/vbraun-hub
    [I 2016-03-20 16:46:03.819 vbraun-hub notebookapp:1079] 0 active kernels 
    [I 2016-03-20 16:46:03.819 vbraun-hub notebookapp:1079] The Jupyter Notebook is running at: http://127.0.0.1:36298/user/vbraun-hub/
    [I 2016-03-20 16:46:03.819 vbraun-hub notebookapp:1080] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
    [I 2016-03-20 16:46:03.826 vbraun-hub log:47] 302 GET /user/vbraun-hub (127.0.0.1) 0.58ms
    [D 2016-03-20 16:46:03.827 JupyterHub utils:84] Server at http://127.0.0.1:36298/user/vbraun-hub responded with 302
    [I 2016-03-20 16:46:03.827 JupyterHub base:301] User vbraun-hub server took 0.738 seconds to start
    [I 2016-03-20 16:46:03.827 JupyterHub orm:159] Adding user vbraun-hub to proxy /user/vbraun-hub => http://127.0.0.1:36298
    [D 2016-03-20 16:46:03.829 JupyterHub orm:146] Fetching POST http://127.0.0.1:444/api/routes/user/vbraun-hub
    [D 2016-03-20 16:46:03.833 JupyterHub base:226] Setting cookie for vbraun-hub: jupyter-hub-token-vbraun-hub, {'secure': True}
    [D 2016-03-20 16:46:03.835 JupyterHub base:226] Setting cookie for vbraun-hub: jupyter-hub-token, {'secure': True}
    [I 2016-03-20 16:46:03.839 JupyterHub log:100] 302 POST /hub/login?next= (@::ffff:x.x.x.x) 791.45ms
    [I 2016-03-20 16:46:03.839 JupyterHub login:79] User logged in: vbraun-hub
    [D 2016-03-20 16:46:03.876 JupyterHub pages:29] User is running: /user/vbraun-hub
    [I 2016-03-20 16:46:03.880 JupyterHub log:100] 302 GET /hub/ (vbraun-hub@::ffff:x.x.x.x) 3.17ms
    [I 2016-03-20 16:46:03.914 vbraun-hub log:47] 302 GET /user/vbraun-hub (::ffff:x.x.x.x) 0.38ms
    [I 2016-03-20 16:46:03.963 JupyterHub log:100] 200 GET /hub/api/authorizations/cookie/jupyter-hub-token-vbraun-hub/[secret] ([email protected]) 7.26ms
    [I 2016-03-20 16:46:09.041 vbraun-hub log:47] 302 GET /user/vbraun-hub/logout (::ffff:x.x.x.x) 0.40ms
    [I 2016-03-20 16:46:09.079 JupyterHub login:17] User logged out: vbraun-hub
    [I 2016-03-20 16:46:09.084 JupyterHub log:100] 302 GET /hub/logout (vbraun-hub@::ffff:x.x.x.x) 5.37ms
    [I 2016-03-20 16:46:09.118 JupyterHub log:100] 302 GET /hub/ (@::ffff:x.x.x.x) 0.59ms
    [I 2016-03-20 16:46:09.174 JupyterHub log:100] 200 GET /hub/login (@::ffff:x.x.x.x) 20.75ms
    [W 2016-03-20 16:46:13.159 JupyterHub auth:372] PAM Authentication failed (@::ffff:x.x.x.x): [PAM Error 7] Authentication failure
    [D 2016-03-20 16:46:13.160 JupyterHub login:81] Failed login for None
    [I 2016-03-20 16:46:13.164 JupyterHub log:100] 200 POST /hub/login?next= (@::ffff:x.x.x.x) 1586.23ms
    

    The "Failed login for None" was already suspicious in #485

    question 
    opened by vbraun 32
  • added note on `Spawner.name_template` setting

    added note on `Spawner.name_template` setting

    Addresses issue jupyterhub/dockerspawner#475

    Adds a note to the docs to mention setting the name_template on the spawner to include the server name when named servers are enabled.

    In my TLJH deployment this was necessary to be able to launch more than 1 server. I'm assuming this is a necessary step?

    I arrived at this fix based on this discussion here: https://discourse.jupyter.org/t/multiple-jupyterhub-servers-per-user-named-servers-does-not-work/2357/5

    opened by stevejpurves 2
  • Dot should not be an allowed domain name character

    Dot should not be an allowed domain name character

    Bug description

    If a username contains a period and subdomains are enabled, they will get a sub-subdomain now because this code doesn't mind sub-subdomains:

    https://github.com/jupyterhub/jupyterhub/blob/49c518940bbdedbaf9037d463bcf455c794e5e3f/jupyterhub/user.py#L58-L60

    I believe, however, that this doesn't match a common use case. For example, wildcard certificates don't support multilevel nesting, if I understand correctly.

    Expected behaviour

    Dot isn't considered a _dns_safe character.

    bug 
    opened by akhmerov 0
  • Audit public APIs on classes accessible to extensions

    Audit public APIs on classes accessible to extensions

    This is prompted by autogenerating API docs in #4253.

    Proposed change

    I think we may need an audit on public method names in classes and functions that are accessible to extension points (Spawners, Authenticators, etc.). For the most part, JupyterHub does not have a public Python API - ~everything in JupyterHub's Python code is only for internal use by JupyterHub itself. As such, most things don't use private-method conventions because everything is private, and that would be a bit silly.

    However, there are a few classes that are regularly exposed to code outside JupyterHub. I think there are probably more public methods and attributes on these objects than there should be, and some should really be private.

    The main classes that are exposed to extension code, and need public API considerations:

    • User
    • Server
    • Spawner
    • Authenticator

    One example:

    • Spawner.run_ methods for running hooks should be private. There's no reason for these to be in API docs, nor for subclasses to override them.

    Alternative options

    • Don't do this, leave everything public that's already public. Just try to be more circumspect in the future.
    • be explicit about public APIs in docs, regardless of naming convention (not a good practice, I think, but essentially what we've been doing so far without communicating it)

    Who would use this feature?

    Maintainers of JupyterHub, Spawners, Authenticators, etc.

    (Optional): Suggest a solution

    I don't think we should or need to break anything in doing this. We should look over the methods and attributes on the classes, and for anything public that ought to be private, we should:

    1. rename to _private convention
    2. keep the public name as a passthrough property with deprecation warnings

    I think we should also clearly document what's public, and explicitly state that things not documented are not public (the de facto state right now).

    enhancement 
    opened by minrk 0
  • Accessibility of not_running page

    Accessibility of not_running page

    WAVE accessibility report

    Details from report:

    Based on evaluation using the WAVE accessibility tool, the following are responsible for accessibility issues on the spawn_pending page:

    • Reoccurring accessibility issues: These include issues like a very Low contrast between nav items and their background, Language missing or invalid and Missing first level header which have been fixed in PR #4274

    • Skipped heading level: A modal's title on the page has a h4 element. So the current hierarchy is <h1> ----> <h4>

    Report:

    Screenshot 2022-12-20 at 12 53 04

    @minrk

    opened by bl-aire 2
  • Restructuring JupyterHub documentation: Which path to take?

    Restructuring JupyterHub documentation: Which path to take?

    @sgibson91 and I are at a crossroad regarding how best to restructure the JupyterHub documentation and we would love some input from the community:

    1. We can select to restructure the docs using vanilla Diataxis framework, in which case, we would organize the articles into four main categories: How-To Guides, References, Explanations, and Tutorials. This way, we would end up with something similar to Django's documentation.
    2. Alternatively, restructure the documentation according to the needs of JupyterHub's core users (Developers and Sys Admins). This way, we would end up with something close to 2i2c's docs, but structured according to the Diataxis framework and segmented to meet the needs of the two user groups.

    Please give your thoughts regarding these two approaches.

    enhancement 
    opened by alwasega 9
  • Accessibility of the 404 page

    Accessibility of the 404 page

    WAVE accessibility report

    Details from report:

    Based on evaluation using the WAVE accessibility tool, the following are responsible for accessibility issues on the 404 page:

    The errors on this page are the same with those on the previous pages evaluated(Home, Login and Token) and can be fixed with the same solutions discussed earlier:

    • Language missing or invalid
    • Skipped heading level
    • Possible heading
    • Noscript element

    Report:

    Screenshot 2022-12-14 at 11 59 47

    @minrk

    opened by bl-aire 3
Owner
JupyterHub
Official JupyterHub-related repositories
JupyterHub
Wasm powered Jupyter running in the browser 💡

JupyterLite JupyterLite is a JupyterLab distribution that runs entirely in the browser built from the ground-up using JupyterLab components and extens

JupyterLite 3k Jan 4, 2023
A Sublime Text package that allows a user to view all the available core/plugin commands for Sublime Text and Sublime Merge, along with their documentation/source.

CommandsBrowser A Sublime Text package that allows a user to view all the available core/plugin commands for Sublime Text and Sublime Merge, along wit

Sublime Instincts 26 Nov 15, 2022
Multi-user server for Jupyter notebooks

Technical Overview | Installation | Configuration | Docker | Contributing | License | Help and Resources Please note that this repository is participa

JupyterHub 7k Jan 2, 2023
Euporie is a text-based user interface for running and editing Jupyter notebooks

Euporie is a text-based user interface for running and editing Jupyter notebooks

null 781 Jan 1, 2023
Plotting library for IPython/Jupyter notebooks

bqplot 2-D plotting library for Project Jupyter Introduction bqplot is a 2-D visualization system for Jupyter, based on the constructs of the Grammar

null 3.4k Dec 29, 2022
Plotting library for IPython/Jupyter notebooks

bqplot 2-D plotting library for Project Jupyter Introduction bqplot is a 2-D visualization system for Jupyter, based on the constructs of the Grammar

null 3.4k Dec 30, 2022
Python game programming in Jupyter notebooks.

Jupylet Jupylet is a Python library for programming 2D and 3D games, graphics, music and sound synthesizers, interactively in a Jupyter notebook. It i

Nir Aides 178 Dec 9, 2022
Plotting library for IPython/Jupyter notebooks

bqplot 2-D plotting library for Project Jupyter Introduction bqplot is a 2-D visualization system for Jupyter, based on the constructs of the Grammar

null 3k Feb 18, 2021
Google maps for Jupyter notebooks

gmaps gmaps is a plugin for including interactive Google maps in the IPython Notebook. Let's plot a heatmap of taxi pickups in San Francisco: import g

Pascal Bugnion 747 Dec 19, 2022
Lets you view, edit and execute Jupyter Notebooks in the terminal.

Lets you view, edit and execute Jupyter Notebooks in the terminal.

David Brochart 684 Dec 28, 2022
📚 A collection of Jupyter notebooks for learning and experimenting with OpenVINO 👓

A collection of ready-to-run Python* notebooks for learning and experimenting with OpenVINO developer tools. The notebooks are meant to provide an introduction to OpenVINO basics and teach developers how to leverage our APIs for optimized deep learning inference in their applications.

OpenVINO Toolkit 840 Jan 3, 2023
Jupyter notebooks for the code samples of the book "Deep Learning with Python"

Jupyter notebooks for the code samples of the book "Deep Learning with Python"

François Chollet 16.2k Dec 30, 2022
PyToQlik is a library that allows you to integrate Qlik Desktop with Jupyter notebooks

PyToQlik is a library that allows you to integrate Qlik Desktop with Jupyter notebooks. With it you can: Open and edit a Qlik app inside a Ju

BIX Tecnologia 16 Sep 9, 2022
STAC in Jupyter Notebooks

stac-nb STAC in Jupyter Notebooks Install pip install stac-nb Usage To use stac-nb in a project, start Jupyter Lab (jupyter lab), create a new noteboo

Darren Wiens 32 Oct 4, 2022
🦩 A Python tool to create comment-free Jupyter notebooks.

Pelikan Pelikan lets you convert notebooks to comment-free notebooks. In other words, It removes Python block and inline comments from source cells in

Hakan Özler 7 Nov 20, 2021
Jupyter Notebooks as Markdown Documents, Julia, Python or R scripts

Have you always wished Jupyter notebooks were plain text documents? Wished you could edit them in your favorite IDE? And get clear and meaningful diff

Marc Wouts 5.7k Jan 4, 2023
A lightweight, pure-Python mobile robot simulator designed for experiments in Artificial Intelligence (AI) and Machine Learning, especially for Jupyter Notebooks

aitk.robots A lightweight Python robot simulator for JupyterLab, Notebooks, and other Python environments. Goals A lightweight mobile robotics simulat

null 3 Oct 22, 2021
Infrastructure template and Jupyter notebooks for running RoseTTAFold on AWS Batch.

AWS RoseTTAFold Infrastructure template and Jupyter notebooks for running RoseTTAFold on AWS Batch. Overview Proteins are large biomolecules that play

AWS Samples 20 May 10, 2022
Library extending Jupyter notebooks to integrate with Apache TinkerPop and RDF SPARQL.

Graph Notebook: easily query and visualize graphs The graph notebook provides an easy way to interact with graph databases using Jupyter notebooks. Us

Amazon Web Services 501 Dec 28, 2022