mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-13 21:13:01 +00:00
Some suggestions from reading through the docs
Thanks to @willingc, @minrk and @manics for the review so far. This commit is the PR so far rebased onto master and squashed.
This commit is contained in:
@@ -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
|
||||
|
@@ -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 <path-to-file>``.
|
||||
On Linux, you can do the same with ``xdg-open <path-to-file>``.
|
||||
After opening index.html in your browser you can just refresh the page whenever
|
||||
you rebuild the docs via ``make html``
|
||||
|
||||
|
||||
.. _contributing/docs/conventions:
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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 <https://www.nginx.com/resources/admin-guide/nginx-ssl-termination/>`_,
|
||||
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:
|
||||
|
||||
|
@@ -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 <username>
|
||||
```
|
||||
|
||||
|
@@ -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 <https://docs.docker.com/engine/admin/volumes/volumes/>`_
|
||||
will allow you to store data outside the docker image (host system) so it will
|
||||
|
@@ -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
|
||||
|
||||
@@ -114,6 +113,8 @@ 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.
|
||||
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.
|
||||
|
||||
|
@@ -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/'
|
||||
```
|
||||
|
@@ -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`:
|
||||
@@ -153,6 +154,7 @@ then you will need to give `node` permission to do so:
|
||||
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/node
|
||||
```
|
||||
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`.
|
||||
|
@@ -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
|
||||
|
@@ -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`.
|
||||
|
@@ -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),
|
||||
|
@@ -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.
|
||||
|
@@ -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.
|
||||
|
@@ -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`
|
||||
|
Reference in New Issue
Block a user