Jupyter Server Proxy for Panel

October 10, 2025 ยท View on GitHub

Downloads PyPi Downloads
Build Status Linux/MacOS Build Status
Latest dev release Github tag
Latest release Github release PyPI version panel version conda-forge version
Support Discourse Discord

jupyter-panel-proxy integrates HoloViz Panel seamlessly with Jupyter environments (Notebook, JupyterLab, and JupyterHub). When installed, it launches a Panel server automatically at the /panel endpoint of your running Jupyter server.

Visiting /panel will display an index of all available applications, and each application can be accessed at /panel/<name_of_file>.

When to use this project

Use jupyter-panel-proxy when you want to:

  • Serve Panel apps alongside Jupyter notebooks or JupyterHub โ€” without managing a separate web server.
  • Reuse existing authentication from JupyterHub and optionally integrate OAuth2 for finer-grained control.
  • Automatically discover and serve multiple Panel apps in a directory structure (no manual panel serve required).
  • Deploy lightweight dashboards and interactive apps close to your notebooks or lab environment.
  • Run Panel behind a reverse proxy with clean URL prefixing (/panel), and modern server features.

Installation

You can install jupyter-panel-proxy from PyPI:

pip install jupyter-panel-proxy

or from conda:

conda install conda-forge::jupyter-panel-proxy

Once installed, a Panel server will be available at:

https://<your-jupyter-server>/panel

Configuration

You can configure the behavior of the proxy server by creating a jupyter-panel-proxy.yml file in the directory from which your Jupyter server is launched.

Available configuration keys

KeyTypeDescription
appslistList of apps or glob patterns to serve. If not set, apps are discovered automatically by file type.
file_typeslist(str)File extensions to auto-discover apps (default: ipynb, py).
exclude_patternslist(str)Glob/fnmatch patterns to exclude apps.
launcher_entrydictA jupyter-server-proxy launcher entry.
indexstrPath to a custom Bokeh index template.
autoreloadboolAutomatically reload sessions when code changes. It is recommended to use dev instead.
dev boolAutomatically reload sessions when code changes.
adminboolEnable Panel's admin module.
warmboolExecute apps on startup to warm up the server.
num_procsintNumber of worker processes (0 = auto).
num_threadsintNumber of threads in the thread pool.
static_dirslistKey=value routes for serving static files.
reuse_sessionsboolReuse existing sessions (recommended for JupyterHub).
keep_aliveint (ms)Interval for keep-alive pings to clients.
check_unused_sessionsint (ms)How often to check for unused sessions.
unused_session_lifetimeint (ms)How long unused sessions last.
websocket_max_message_sizeintMax message size for WebSocket in bytes.
root_pathstrRoot path can be used to handle cases where Panel is served behind a proxy.
cookie_pathstrPath to apply cookies to.
log_levelstrLog level (info, debug, etc.).
livenessboolEnable a liveness endpoint.
liveness_endpointstrPath of the liveness endpoint (default: /liveness).
profilerstrProfiler to use (e.g. pyinstrument).
global_loading_spinnerboolAdd a global loading spinner to the UI.
oauth_providerstrOAuth2 provider name.
oauth_keystrOAuth2 key.
oauth_secretstrOAuth2 secret.
oauth_redirect_uristrOAuth2 redirect URI.
oauth_extra_paramsdictAdditional parameters for the OAuth provider.
oauth_jwt_userstrJWT key to identify the user.
oauth_optionalboolAllow guest access to all endpoints.
oauth_guest_endpointslist(str)List of endpoints accessible without authentication.
cookie_secretstrSecret key for secure cookies (can also be set via PANEL_COOKIE_SECRET).
oauth_encryption_keystrEncryption key for OAuth user info (can also be set via OAUTH_ENCRYPTION_KEY).

Launcher

When you install jupyter-panel-proxy, it automatically adds a Panel Launcher card to the JupyterLab and Notebook launcher interface:

Panel launcher tile

Clicking this Panel tile opens a new browser tab at /panel where your Panel apps are served. This behavior is controlled by the launcher_entry field in the configuration.

Application discovery

By default, jupyter-panel-proxy automatically discovers Panel applications in the current working directory (or in an examples/ subdirectory if present).

The discovery logic works like this:

  1. If apps is defined in jupyter-panel-proxy.yml:

    • Each entry is interpreted as a file path or glob pattern.
    • All matching files are included.
  2. If apps is not defined:

    • The proxy scans the base directory (or ./examples if it exists) recursively.
    • It includes files that match any extension listed in file_types (default: ipynb, py).
    • It excludes any paths that match exclude_patterns (by default, this includes common patterns like *setup.py or *.ipynb_checkpoints*).
  3. The discovered list of applications is then passed to panel serve.

Example YAML configuration

# jupyter-panel-proxy.yml

log_level: info
liveness: true
liveness_endpoint: /health
global_loading_spinner: true

How it works

  • When the Jupyter server starts, this proxy registers /panel as a route.
  • When a user navigates to /panel, the proxy launches panel serve internally with the configured options.
  • Apps are discovered automatically or defined explicitly.
  • The Panel server runs under the same authentication/session as Jupyter, and can optionally integrate OAuth for additional controls.

Further reading

License

BSD-3-Clause