diff --git a/README.md b/README.md index 2fc37039..9e9c504f 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ 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. +configuration or by using an ssl enabled proxy. [Mounting volumes](https://docs.docker.com/engine/admin/volumes/volumes/) will allow you to **store data outside the docker image (host system) so it will be persistent**, even when you start diff --git a/docs/source/contributing/docs.rst b/docs/source/contributing/docs.rst index 6b6b647f..3e954224 100644 --- a/docs/source/contributing/docs.rst +++ b/docs/source/contributing/docs.rst @@ -27,7 +27,7 @@ change renders correctly, it is good practice to test it locally. python3 -m pip install -r docs/requirements.txt #. Build the html version of the docs. This is the most commonly used - output format, so verifying it renders as you should is usually good + output format, so verifying it renders correctly is usually good enough. .. code-block:: bash @@ -46,6 +46,8 @@ change renders correctly, it is good practice to test it locally. On macOS, you can open a file from the terminal with ``open ``. On Linux, you can do the same with ``xdg-open ``. + After opening index.html in your browser you can just refresh the page whenever + you rebuild the docs via ``make html`` .. _contributing/docs/conventions: diff --git a/docs/source/contributing/setup.rst b/docs/source/contributing/setup.rst index aa0f0595..4ef70b08 100644 --- a/docs/source/contributing/setup.rst +++ b/docs/source/contributing/setup.rst @@ -30,6 +30,9 @@ JupyterHub, is written in Javascript to run on `NodeJS recommend installing it in the ``miniconda`` environment you set up for Python. You can do so with ``conda install nodejs``. +Many in the Jupyter community use [``nvm``](https://github.com/nvm-sh/nvm) to +managing node dependencies. + Install git ----------- @@ -75,9 +78,9 @@ happen. npm install -g configurable-http-proxy - If you get an error that says ``Error: EACCES: permission denied``, - you might need to prefix the command with ``sudo``. If you do not - have access to sudo, you may instead run the following commands: + If you get an error that says ``Error: EACCES: permission denied``, you might need to prefix the command with ``sudo``. + ``sudo`` may be required to perform a system-wide install. + If you do not have access to sudo, you may instead run the following commands: .. code:: bash diff --git a/docs/source/contributing/tests.rst b/docs/source/contributing/tests.rst index a59487c0..27022156 100644 --- a/docs/source/contributing/tests.rst +++ b/docs/source/contributing/tests.rst @@ -4,7 +4,7 @@ Testing JupyterHub ================== -Unit test help validate that JupyterHub works the way we think it does, +Unit testing helps to validate that JupyterHub works the way we think it does, and continues to do so when changes occur. They also help communicate precisely what we expect our code to do. diff --git a/docs/source/getting-started/authenticators-users-basics.md b/docs/source/getting-started/authenticators-users-basics.md index b954f88d..f4b9dff4 100644 --- a/docs/source/getting-started/authenticators-users-basics.md +++ b/docs/source/getting-started/authenticators-users-basics.md @@ -101,6 +101,9 @@ popular services: - Okpy - OpenShift +NOTE: Open issue asking for more details on this generic implementation. +It's not clear if this is a different implementation or if the JupyterHub OAuth +_is_ the generic implementation. A generic implementation, which you can use for OAuth authentication with any provider, is also available. diff --git a/docs/source/getting-started/config-basics.md b/docs/source/getting-started/config-basics.md index 47850ac9..f4ae9e4d 100644 --- a/docs/source/getting-started/config-basics.md +++ b/docs/source/getting-started/config-basics.md @@ -93,7 +93,7 @@ use a custom proxy (e.g. Traefik), this also not needed. Connections to user servers go through the proxy, and *not* the hub itself. If the proxy stays running when the hub restarts (for -maintenance, re-configuration, etc.), then use connections are not +maintenance, re-configuration, etc.), then user connections are not interrupted. For simplicity, by default the hub starts the proxy automatically, so if the hub restarts, the proxy restarts, and user connections are interrupted. It is easy to run the proxy separately, diff --git a/docs/source/getting-started/networking-basics.md b/docs/source/getting-started/networking-basics.md index 86c80dcc..0c86e181 100644 --- a/docs/source/getting-started/networking-basics.md +++ b/docs/source/getting-started/networking-basics.md @@ -12,7 +12,7 @@ This section will help you with basic proxy and network configuration to: The Proxy's main IP address setting determines where JupyterHub is available to users. By default, JupyterHub is configured to be available on all network interfaces (`''`) on port 8000. *Note*: Use of `'*'` is discouraged for IP configuration; -instead, use of `'0.0.0.0'` is preferred. +instead, use of `'0.0.0.0'` is preferred. Changing the Proxy's main IP address and port can be done with the following JupyterHub **command line options**: @@ -41,9 +41,9 @@ port. ## Set the Proxy's REST API communication URL (optional) -By default, this REST API listens on port 8081 of `localhost` only. -The Hub service talks to the proxy via a REST API on a secondary port. The -API URL can be configured separately and override the default settings. +By default, the proxy's REST API listens on port 8081 of `localhost` only. +The Hub service talks to the proxy via a REST API on a secondary port. +The REST API URL (hostname and port) can be configured separately and override the default settings. ### Set api_url diff --git a/docs/source/getting-started/security-basics.rst b/docs/source/getting-started/security-basics.rst index 80996555..9223c362 100644 --- a/docs/source/getting-started/security-basics.rst +++ b/docs/source/getting-started/security-basics.rst @@ -76,9 +76,9 @@ In certain cases, for example if the hub is running behind a reverse proxy, and `SSL termination is being provided by NGINX `_, it is reasonable to run the hub without SSL. -To achieve this, simply omit the configuration settings -``c.JupyterHub.ssl_key`` and ``c.JupyterHub.ssl_cert`` -(setting them to ``None`` does not have the same effect, and is an error). +To achieve this, remove ``c.JupyterHub.ssl_key`` and ``c.JupyterHub.ssl_cert`` +from your configuration (setting them to ``None`` or an empty string does not +have the same effect, and will result in an error). .. _cookie-secret: diff --git a/docs/source/getting-started/services-basics.md b/docs/source/getting-started/services-basics.md index 9014fb9b..e6562520 100644 --- a/docs/source/getting-started/services-basics.md +++ b/docs/source/getting-started/services-basics.md @@ -67,7 +67,7 @@ c.JupyterHub.services = [ Upon restarting JupyterHub, you should see a message like below in the logs: -``` +```none Adding API token for ``` diff --git a/docs/source/quickstart-docker.rst b/docs/source/quickstart-docker.rst index d4153a14..bded4ac7 100644 --- a/docs/source/quickstart-docker.rst +++ b/docs/source/quickstart-docker.rst @@ -35,7 +35,7 @@ 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 using a ssl enabled proxy. +configuration or using an ssl enabled proxy. `Mounting volumes `_ will allow you to store data outside the docker image (host system) so it will diff --git a/docs/source/reference/authenticators.md b/docs/source/reference/authenticators.md index 0775809f..c7016d0d 100644 --- a/docs/source/reference/authenticators.md +++ b/docs/source/reference/authenticators.md @@ -31,8 +31,7 @@ popular services: - Okpy - OpenShift -A generic implementation, which you can use for OAuth authentication -with any provider, is also available. +A [generic implementation](https://github.com/jupyterhub/oauthenticator/blob/master/oauthenticator/generic.py), which you can use for OAuth authentication with any provider, is also available. ## The Dummy Authenticator @@ -113,7 +112,9 @@ to uid to username), which is useful in case you use some external service that allows multiple usernames mapping to the same user (such as ActiveDirectory, yes, this really happens). When `pam_normalize_username` is on, usernames are *not* normalized to -lowercase. +lowercase. +NOTE: Earlier it says that usernames are normalized using PAM. +I guess that doesn't normalize them? #### Validate usernames @@ -169,7 +170,7 @@ setup( ``` If you have added this metadata to your package, -users can select your authenticator with the configuration: +admins can select your authenticator with the configuration: ```python c.JupyterHub.authenticator_class = 'myservice' @@ -259,8 +260,8 @@ class MyAuthenticator(Authenticator): ## pre_spawn_start and post_spawn_stop hooks Authenticators uses two hooks, [pre_spawn_start(user, spawner)][] and -[post_spawn_stop(user, spawner)][] to add pass additional state information -between the authenticator and a spawner. These hooks are typically used auth-related +[post_spawn_stop(user, spawner)][] to pass additional state information +between the authenticator and a spawner. These hooks are typically used for auth-related startup, i.e. opening a PAM session, and auth-related cleanup, i.e. closing a PAM session. diff --git a/docs/source/reference/config-proxy.md b/docs/source/reference/config-proxy.md index 564f2efc..26ec8546 100644 --- a/docs/source/reference/config-proxy.md +++ b/docs/source/reference/config-proxy.md @@ -207,8 +207,8 @@ httpd.conf amendments: ``` jupyterhub_config.py amendments: - ```bash - --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://127.0.0.1:8000/jhub/' - ``` +```python +# 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://127.0.0.1:8000/jhub/' +``` diff --git a/docs/source/reference/config-sudo.md b/docs/source/reference/config-sudo.md index fc0d4865..b2f32e82 100644 --- a/docs/source/reference/config-sudo.md +++ b/docs/source/reference/config-sudo.md @@ -70,7 +70,8 @@ Cmnd_Alias JUPYTER_CMD = /usr/local/bin/sudospawner rhea ALL=(JUPYTER_USERS) NOPASSWD:JUPYTER_CMD ``` -It might be useful to modify `secure_path` to add commands in path. +It might be useful to modify `secure_path` to add commands in path. (Search for +`secure_path` in the [sudo docs](https://www.sudo.ws/man/1.8.14/sudoers.man.html) As an alternative to adding every user to the `/etc/sudoers` file, you can use a group in the last line above, instead of `JUPYTER_USERS`: @@ -152,7 +153,8 @@ then you will need to give `node` permission to do so: ```bash sudo setcap 'cap_net_bind_service=+ep' /usr/bin/node ``` -However, you may want to further understand the consequences of this. +However, you may want to further understand the consequences of this. +([Further reading](http://man7.org/linux/man-pages/man7/capabilities.7.html)) You may also be interested in limiting the amount of CPU any process can use on your server. `cpulimit` is a useful tool that is available for many Linux @@ -163,7 +165,8 @@ instructions](http://ubuntuforums.org/showthread.php?t=992706). ### Shadow group (FreeBSD) -**NOTE:** This has not been tested and may not work as expected. +**NOTE:** This has not been tested on FreeBSD and may not work as expected on +the FreeBSD platform. *Do not use in production without verifying that it works properly!* ```bash $ ls -l /etc/spwd.db /etc/master.passwd @@ -249,6 +252,6 @@ $ semodule -i sudo_exec_selinux.pp ## Troubleshooting: PAM session errors If the PAM authentication doesn't work and you see errors for -`login:session-auth`, or similar, considering updating to a more recent version +`login:session-auth`, or similar, consider updating to a more recent version of jupyterhub and disabling the opening of PAM sessions with `c.PAMAuthenticator.open_sessions=False`. diff --git a/docs/source/reference/config-user-env.md b/docs/source/reference/config-user-env.md index c085b106..27fd9b30 100644 --- a/docs/source/reference/config-user-env.md +++ b/docs/source/reference/config-user-env.md @@ -7,8 +7,8 @@ environment in some way. Since the `jupyterhub-singleuser` server extends the standard Jupyter notebook server, most configuration and documentation that applies to Jupyter Notebook applies to the single-user environments. Configuration of user environments -typically does not occur through JupyterHub itself, but rather through system- -wide configuration of Jupyter, which is inherited by `jupyterhub-singleuser`. +typically does not occur through JupyterHub itself, but rather through system-wide +configuration of Jupyter, which is inherited by `jupyterhub-singleuser`. **Tip:** When searching for configuration tips for JupyterHub user environments, try removing JupyterHub from your search because there are a lot @@ -43,9 +43,13 @@ sudo python3 -m pip install numpy to install the numpy package in the default system Python 3 environment (typically `/usr/local`). +TODO: Get a link from the conda team for a description of what "appropriate permissions for users" is + You may also use conda to install packages. If you do, you should make sure that the conda environment has appropriate permissions for users to be able to -run Python code in the env. +run Python code in the env. The env must be *readable and executable* by all +users. Additionally it must be *writeable* if you want users to install +additional packages. ## Configuring Jupyter and IPython diff --git a/docs/source/reference/proxy.md b/docs/source/reference/proxy.md index fd58816a..620073b6 100644 --- a/docs/source/reference/proxy.md +++ b/docs/source/reference/proxy.md @@ -138,7 +138,7 @@ async def delete_route(self, routespec): For retrieval, you only *need* to implement a single method that retrieves all routes. The return value for this function should be a dictionary, keyed by -`routespect`, of dicts whose keys are the same three arguments passed to +`routespec`, of dicts whose keys are the same three arguments passed to `add_route` (`routespec`, `target`, `data`) ```python @@ -204,7 +204,7 @@ setup( ``` If you have added this metadata to your package, -users can select your proxy with the configuration: +admins can select your authenticator with the configuration: ```python c.JupyterHub.proxy_class = 'mything' @@ -216,7 +216,7 @@ instead of the full c.JupyterHub.proxy_class = 'mypackage:MyProxy' ``` -previously required. +as previously required. Additionally, configurable attributes for your proxy will appear in jupyterhub help output and auto-generated configuration files via `jupyterhub --generate-config`. diff --git a/docs/source/reference/separate-proxy.md b/docs/source/reference/separate-proxy.md index 92c19ef4..56f3dd2b 100644 --- a/docs/source/reference/separate-proxy.md +++ b/docs/source/reference/separate-proxy.md @@ -14,8 +14,8 @@ because the proxy is automatically managed by the hub. This is great for getting started and even most use, but everytime you restart the hub, all user connections also get restarted. But it's also simple to run the proxy as a service separate from the hub, so that you are free -to reconfigure the hub while only interrupting users who are currently -actively starting the hub. +to reconfigure the hub while only interrupting users who are waiting for their notebook server to start. +starting their notebook server. The default JupyterHub proxy is [configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy), diff --git a/docs/source/reference/services.md b/docs/source/reference/services.md index 24de3bdd..3020fa69 100644 --- a/docs/source/reference/services.md +++ b/docs/source/reference/services.md @@ -65,7 +65,7 @@ If a service is also to be managed by the Hub, it has a few extra options: A **Hub-Managed Service** is started by the Hub, and the Hub is responsible for the Service's actions. A Hub-Managed Service can only be a local subprocess of the Hub. The Hub will take care of starting the process and -restarts it if it stops. +restart the service if the service stops. While Hub-Managed Services share some similarities with notebook Spawners, there are no plans for Hub-Managed Services to support the same spawning @@ -201,8 +201,18 @@ below. The reference, or base, implementation is the [`HubAuth`][HubAuth] class, which implements the requests to the Hub. -To use HubAuth, you must set the `.api_token`, either programmatically when constructing the class, -or via the `JUPYTERHUB_API_TOKEN` environment variable. +To use HubAuth, you must set the `.api_token` instance variable. This can be +done either programmatically when constructing the class, or via the +`JUPYTERHUB_API_TOKEN` environment variable. A number of the examples in the +root of the jupyterhub git repository set the `JUPYTERHUB_API_TOKEN` variable +so consider having a look at those for futher reading +([cull-idle](https://github.com/jupyterhub/jupyterhub/tree/master/examples/cull-idle), +[external-oauth](https://github.com/jupyterhub/jupyterhub/tree/master/examples/external-oauth), +[service-notebook](https://github.com/jupyterhub/jupyterhub/tree/master/examples/service-notebook) +and [service-whoiami](https://github.com/jupyterhub/jupyterhub/tree/master/examples/service-whoami)) + + +(TODO: Where is this API TOKen set?) Most of the logic for authentication implementation is found in the [`HubAuth.user_for_cookie`][HubAuth.user_for_cookie] @@ -353,13 +363,13 @@ and taking note of the following process: ```json { "name": "inara", - "groups": ["serenity", "guild"], + "groups": ["serenity", "guild"] } ``` An example of using an Externally-Managed Service and authentication is -in [nbviewer README][nbviewer example] section on securing the notebook viewer, +in the [nbviewer README][nbviewer example] section on securing the notebook viewer, and an example of its configuration is found [here](https://github.com/jupyter/nbviewer/blob/master/nbviewer/providers/base.py#L94). nbviewer can also be run as a Hub-Managed Service as described [nbviewer README][nbviewer example] section on securing the notebook viewer. diff --git a/docs/source/reference/spawners.md b/docs/source/reference/spawners.md index 37937c72..cc3b7a65 100644 --- a/docs/source/reference/spawners.md +++ b/docs/source/reference/spawners.md @@ -16,9 +16,9 @@ Some examples include: - [DockerSpawner](https://github.com/jupyterhub/dockerspawner) for spawning user servers in Docker containers * `dockerspawner.DockerSpawner` for spawning identical Docker containers for - each users + each user * `dockerspawner.SystemUserSpawner` for spawning Docker containers with an - environment and home directory for each users + environment and home directory for each user * both `DockerSpawner` and `SystemUserSpawner` also work with Docker Swarm for launching containers on remote machines - [SudoSpawner](https://github.com/jupyterhub/sudospawner) enables JupyterHub to @@ -222,8 +222,8 @@ discover these resource limits and guarantees, such as for memory and CPU. For the limits and guarantees to be useful, **the spawner must implement support for them**. For example, LocalProcessSpawner, the default spawner, does not support limits and guarantees. One of the spawners -that supports limits and guarantees is the `systemdspawner`. - +that supports limits and guarantees is the +[`systemdspawner`](https://github.com/jupyterhub/systemdspawner). ### Memory Limits & Guarantees @@ -283,9 +283,10 @@ container `ip` prior to starting and pass that to `.create_certs` (TODO: edit). In general though, this method will not need to be changed and the default `ip`/`dns` (localhost) info will suffice. -When `.create_certs` is run, it will `.create_certs` in a default, central -location specified by `c.JupyterHub.internal_certs_location`. For `Spawners` -that need access to these certs elsewhere (i.e. on another host altogether), -the `.move_certs` method can be overridden to move the certs appropriately. -Again, using `DockerSpawner` as an example, this would entail moving certs -to a directory that will get mounted into the container this spawner starts. +When `.create_certs` is run, it will create the certificates in a default, +central location specified by `c.JupyterHub.internal_certs_location`. For +`Spawners` that need access to these certs elsewhere (i.e. on another host +altogether), the `.move_certs` method can be overridden to move the certs +appropriately. Again, using `DockerSpawner` as an example, this would entail +moving certs to a directory that will get mounted into the container this +spawner starts. diff --git a/docs/source/reference/urls.md b/docs/source/reference/urls.md index 6497fcb1..53aefe4b 100644 --- a/docs/source/reference/urls.md +++ b/docs/source/reference/urls.md @@ -119,14 +119,9 @@ This URL indicates a request for a user server that is not running (because `/user/...` would have been handled by the notebook server if the specified server were running). -Handling this URL is the most complicated condition in JupyterHub, -because there can be many states: +Handling this URL depends on two conditions: whether a requested user is found +as a match and the state of the requested user's notebook server. -1. server is not active - a. user matches - b. user doesn't match -2. server is ready -3. server is pending, but not ready If the server is pending spawn, the browser will be redirected to `/hub/spawn-pending/:username/:servername`