# Technical Overview

The **Technical Overview** section gives you a high-level view of:

- JupyterHub's major Subsystems: Hub, Proxy, Single-User Notebook Server
- how the subsystems interact
- the process from JupyterHub access to user login
- JupyterHub's default behavior
- customizing JupyterHub

The goal of this section is to share a deeper technical understanding of
JupyterHub and how it works.

## The Major Subsystems: Hub, Proxy, Single-User Notebook Server

JupyterHub is a set of processes that together, provide a single-user Jupyter
Notebook server for each person in a group. Three subsystems are started
by the `jupyterhub` command line program:

- **Hub** (Python/Tornado): manages user accounts, authentication, and
  coordinates Single User Notebook Servers using a [Spawner](spawners-reference).

- **Proxy**: the public-facing part of JupyterHub that uses a dynamic proxy
  to route HTTP requests to the Hub and Single User Notebook Servers.
  [configurable http proxy](https://github.com/jupyterhub/configurable-http-proxy)
  (node-http-proxy) is the default proxy.

- **Single-User Notebook Server** (Python/Tornado): a dedicated,
  single-user, Jupyter Notebook server is started for each user on the system
  when the user logs in. The object that starts the single-user notebook
  servers is called a **[Spawner](spawners-reference)**.

![JupyterHub subsystems](/images/jhub-parts.png)

## How the Subsystems Interact

Users access JupyterHub through a web browser, by going to the IP address or
the domain name of the server.

The basic principles of operation are:

- The Hub spawns the proxy (in the default JupyterHub configuration)
- The proxy forwards all requests to the Hub by default
- The Hub handles login and spawns single-user notebook servers on demand
- The Hub configures the proxy to forward URL prefixes to single-user notebook
  servers

The proxy is the only process that listens on a public interface. The Hub sits
behind the proxy at `/hub`. Single-user servers sit behind the proxy at
`/user/[username]`.

Different **[authenticators](authenticators-reference)** control access
to JupyterHub. The default one [(PAM)](https://en.wikipedia.org/wiki/Pluggable_authentication_module) uses the user accounts on the server where
JupyterHub is running. If you use this, you will need to create a user account
on the system for each user on your team. However, using other authenticators you can
allow users to sign in with e.g. a GitHub account, or with any single-sign-on
system your organization has.

Next, **[spawners](spawners-reference)** control how JupyterHub starts
the individual notebook server for each user. The default spawner will
start a notebook server on the same machine running under their system username.
The other main option is to start each server in a separate container, often using [Docker](https://jupyterhub-dockerspawner.readthedocs.io/en/latest/).

## The Process from JupyterHub Access to User Login

When a user accesses JupyterHub, the following events take place:

- Login data is handed to the [Authenticator](authenticators-reference) instance for
  validation
- The Authenticator returns the username if the login information is valid
- A single-user notebook server instance is [spawned](spawners-reference) for the
  logged-in user
- When the single-user notebook server starts, the proxy is notified to forward
  requests made to `/user/[username]/*`, to the single-user notebook server.
- A [cookie](https://en.wikipedia.org/wiki/HTTP_cookie) is set on `/hub/`, containing an encrypted token. (Prior to version
  0.8, a cookie for `/user/[username]` was used too.)
- The browser is redirected to `/user/[username]`, and the request is handled by
  the single-user notebook server.

How does the single-user server identify the user with the Hub via OAuth?

- On request, the single-user server checks a cookie
- If no cookie is set, the single-user server redirects to the Hub for verification via OAuth
- After verification at the Hub, the browser is redirected back to the
  single-user server
- The token is verified and stored in a cookie
- If no user is identified, the browser is redirected back to `/hub/login`

## Default Behavior

By default, the **Proxy** listens on all public interfaces on port 8000.
Thus you can reach JupyterHub through either:

- `http://localhost:8000`
- or any other public IP or domain pointing to your system.

In their default configuration, the other services, the **Hub** and
**Single-User Notebook Servers**, all communicate with each other on localhost
only.

By default, starting JupyterHub will write two files to disk in the current
working directory:

- `jupyterhub.sqlite` is the SQLite database containing all of the state of the
  **Hub**. This file allows the **Hub** to remember which users are running and
  where, as well as storing other information enabling you to restart parts of
  JupyterHub separately. It is important to note that this database contains
  **no** sensitive information other than **Hub** usernames.
- `jupyterhub_cookie_secret` is the encryption key used for securing cookies.
  This file needs to persist so that a **Hub** server restart will avoid
  invalidating cookies. Conversely, deleting this file and restarting the server
  effectively invalidates all login cookies. The cookie secret file is discussed
  in the [Cookie Secret section of the Security Settings document](security-basics).

The location of these files can be specified via configuration settings. It is
recommended that these files be stored in standard UNIX filesystem locations,
such as `/etc/jupyterhub` for all configuration files and `/srv/jupyterhub` for
all security and runtime files.

## Customizing JupyterHub

There are two basic extension points for JupyterHub:

- How users are authenticated by [Authenticators](authenticators-reference)
- How user's single-user notebook server processes are started by
  [Spawners](spawners-reference)

Each is governed by a customizable class, and JupyterHub ships with basic
defaults for each.

To enable custom authentication and/or spawning, subclass `Authenticator` or
`Spawner`, and override the relevant methods.
