When working with JupyterHub, a Service is defined as a process that interacts with the Hub’s REST API. A Service may perform a specific or action or task. For example, shutting down individuals’ single user notebook servers that have been idle for some time is a good example of a task that could be automated by a Service. Let’s look at how the cull_idle_servers script can be used as a Service.
JupyterHub has a REST API that can be used by external services. This document will:
explain some basic information about API tokens
clarify that API tokens can be used to authenticate to single-user servers as of version 0.8.0
show how the cull_idle_servers script can be:
used in a Hub-managed service
run as a standalone script
Both examples for cull_idle_servers will communicate tasks to the Hub via the REST API.
cull_idle_servers
To run such an external service, an API token must be created and provided to the service.
As of version 0.6.0, the preferred way of doing this is to first generate an API token:
openssl rand -hex 32
In version 0.8.0, a TOKEN request page for generating an API token is available from the JupyterHub user interface:
In the case of cull_idle_servers, it is passed as the environment variable called JUPYTERHUB_API_TOKEN.
JUPYTERHUB_API_TOKEN
While API tokens are often associated with a specific user, API tokens can be used by services that require external access for activities that may not correspond to a specific human, e.g. adding users during setup for a tutorial or workshop. Add a service and its API token to the JupyterHub configuration file, jupyterhub_config.py:
jupyterhub_config.py
c.JupyterHub.services = [ {'name': 'adding-users', 'api_token': 'super-secret-token'}, ]
Upon restarting JupyterHub, you should see a message like below in the logs:
Adding API token for <username>
In JupyterHub 0.7, there is no mechanism for token authentication to single-user servers, and only cookies can be used for authentication. 0.8 supports using JupyterHub API tokens to authenticate to single-user servers.
cull-idle
In jupyterhub_config.py, add the following dictionary for the cull-idle Service to the c.JupyterHub.services list:
c.JupyterHub.services
c.JupyterHub.services = [ { 'name': 'cull-idle', 'admin': True, 'command': [sys.executable, 'cull_idle_servers.py', '--timeout=3600'], } ]
where:
'admin': True indicates that the Service has ‘admin’ permissions, and
'admin': True
'command' indicates that the Service will be launched as a subprocess, managed by the Hub.
'command'
Now you can run your script, i.e. cull_idle_servers, by providing it the API token and it will authenticate through the REST API to interact with it.
This will run cull-idle manually. cull-idle can be run as a standalone script anywhere with access to the Hub, and will periodically check for idle servers and shut them down via the Hub’s REST API. In order to shutdown the servers, the token given to cull-idle must have admin privileges.
Generate an API token and store it in the JUPYTERHUB_API_TOKEN environment variable. Run cull_idle_servers.py manually.
cull_idle_servers.py
export JUPYTERHUB_API_TOKEN='token' python3 cull_idle_servers.py [--timeout=900] [--url=http://127.0.0.1:8081/hub/api]