JupyterHub
JupyterHub 是一个用于 Jupyter notebook 的多用户 Web 服务器。它由四个子系统组成
请参阅 JupyterHub 文档中的技术概述以了解更多详情。
安装
安装 jupyterhubAUR 软件包。在大多数情况下,您还需要安装 jupyter-notebook 软件包(一些更高级的 spawner 可能不需要它)。也可以安装 jupyterlab 软件包,以使 JupyterLab 界面可用。
运行
启动/启用 jupyterhub.service
。使用默认配置,您可以通过在浏览器中访问 127.0.0.1:8000 来访问 hub。
配置
JupyterHub 配置文件位于 /etc/jupyterhub/jupyterhub_config.py
。这是一个 Python 脚本,用于修改配置对象 c
。软件包提供的配置文件显示了可用的配置选项及其默认值。
配置中的任何相对路径都从 hub 运行的工作目录解析。软件包提供的 systemd 服务使用 /etc/jupyterhub
作为工作目录。这意味着,例如,默认数据库 URL c.JupyterHub.db_url = 'sqlite:///jupyterhub.sqlite'
对应于文件 /etc/jupyterhub/jupyterhub.sqlite
。
所有配置选项都可以在命令行上被覆盖。例如,配置文件设置 c.Application.show_config = True
可以使用命令行标志 --Application.show_config=True
代替设置。请注意,提供的 systemd 服务使用命令行显式设置 c.JupyterHub.pid_file
和 c.ConfigurableHTTPProxy.pid_file
值到一个合适的运行时目录,因此配置文件中它们的任何值都将被忽略。
身份验证器
身份验证器控制对 hub 和单用户服务器的访问。文档的身份验证器部分包含关于身份验证器如何工作以及如何编写自定义身份验证器的详细信息。身份验证器 wiki 页面列出了身份验证器;其中一些已打包并在下面描述。
请注意,用户状态存储在 cookie 中,由 cookie 密钥 加密。如果您切换到不同的身份验证器,或修改您选择的身份验证器的设置,以致允许的用户列表可能会更改,则应更改 cookie 密钥。这将注销所有当前用户,并强制他们使用您的新设置重新进行身份验证。这可以通过删除 cookie 密钥文件并重启 hub 来执行,这将自动生成新的密钥。使用默认配置,cookie 密钥存储在 /etc/jupyterhub/jupyterhub_cookie_secret
。
PAM 身份验证器
PAM 身份验证器使用 PAM 允许本地用户登录 hub。它包含在 JupyterHub 中,并且是默认的身份验证器。使用它需要 hub 具有读取 /etc/shadow
(其中包含用户密码的哈希版本)的权限,以便对用户进行身份验证。默认情况下,/etc/shadow
归 root 用户所有,并且具有 -rw------
的文件权限,因此以 root 用户身份运行 hub 将满足此要求。一些来源提倡删除 /etc/shadow
的所有权限,使其无法被泄露的守护进程读取,并授予需要访问权限的进程 DAC_OVERRIDE
capability。如果您的 /etc/shadow
像这样设置,请为该服务创建一个 drop-in 文件,以将此 capability 授予 JupyterHub
/etc/systemd/system/jupyterhub.service.d/override.conf
[Service] CapabilityBoundingSet=CAP_DAC_OVERRIDE
PAM 身份验证器依赖于 Python 软件包 pamela。对于基本故障排除,可以在命令行上进行测试。要尝试以用户 testuser
身份进行身份验证,请运行以下命令
# python -m pamela -a testuser
(如果您以非 root 用户身份运行 JupyterHub,请以该用户而不是 root 用户身份运行命令)。如果身份验证成功,则不会打印任何输出。如果失败,将打印错误消息。
以非 root 用户身份进行 PAM 身份验证
如果您以非 root 用户身份运行 JupyterHub,您将需要授予该用户读取 shadow 文件的权限。JupyterHub 文档推荐的方法是创建一个 shadow
组,使 shadow 文件可由此组读取,并将 JupyterHub 用户添加到此组。
/etc/shadow
中的哈希密码进行只读访问。请注意,每个单用户服务器都在其自己的帐户下运行,因此在这些服务器中执行的代码将无法访问。另请注意,如果 JupyterHub 以 root 用户身份运行,则 JupyterHub 中的安全漏洞将允许对哈希密码进行相同的访问。创建组,修改 shadow 文件权限并将用户 jupyterhub
添加到组可以通过以下四个命令完成
# groupadd shadow # chgrp shadow /etc/shadow # chmod g+r /etc/shadow # usermod -aG shadow jupyterhub
Spawner
Spawner 负责启动和监控每个用户的 notebook 服务器。文档的 spawner 部分 包含关于它们如何工作以及如何编写自定义 spawner 的更多详细信息。Spawner wiki 页面 列出了 spawner;其中一些已打包并在下面描述。
LocalProcessSpawner
这是 JupyterHub 附带的默认 spawner。它在单独的本地进程中,在其用户帐户下运行每个单用户服务器(这意味着每个 JupyterHub 用户必须对应于一个本地用户帐户)。它还要求 JupyterHub 以 root 用户身份运行,以便它可以以不同的用户帐户启动进程。jupyter-notebook 软件包必须安装才能使此 spawner 工作。
SudoSpawner
SudoSpawner 使用使用 sudo 创建的中间进程来启动单用户服务器。这允许 JupyterHub 进程以非 root 用户身份运行。要使用它,请安装 jupyterhub-sudospawnerAUR 软件包。
要使用它,创建一个系统用户帐户(以下假设该帐户名为 jupyterhub
)和一个组,其成员资格将定义哪些用户可以访问 hub(此处假定称为 jupyterhub-users
)。首先,我们必须配置 sudo 以允许 jupyterhub
用户在没有密码的情况下启动服务器。使用 visudo 创建一个 drop-in sudo 配置文件
# visudo -f /etc/sudoers.d/jupyterhub-sudospawner
# The command the hub is allowed to run. Cmnd_Alias SUDOSPAWNER_CMD = /usr/bin/sudospawner # Allow the jupyterhub user to run this command on behalf of anybody # in the jupyterhub-users group. jupyterhub ALL=(%jupyterhub-users) NOPASSWD:SUDOSPAWNER_CMD
默认服务文件以 root 用户身份运行 hub。它还对服务应用了许多强化选项,以限制其 capability。此强化功能阻止 sudo 工作;为了允许它工作,NoNewPrivileges
服务选项(以及任何其他隐式设置它的选项,请参阅 systemd.exec(5) 以获取服务选项列表)需要关闭。创建一个 drop-in 文件 以使用 jupyterhub
用户身份运行 hub
/etc/systemd/system/jupyterhub.service.d/override.conf
[Service] User=jupyterhub Group=jupyterhub # Required for sudo. NoNewPrivileges=false # Setting the following would implicitly set NoNewPrivileges. PrivateDevices=false ProtectKernelTunables=false ProtectKernelModules=false LockPersonality=false RestrictRealtime=false RestrictSUIDGID=false SystemCallFilter= SystemCallArchitectures=
如果您之前以 root 用户身份运行过 hub,您将需要更改用户数据库和 cookie 密钥文件的所有权
# chown jupyterhub:jupyterhub /etc/jupyterhub/{jupyterhub_cookie_secret,jupyterhub.sqlite}
如果您正在使用 PAMAuthenticator,您将需要配置您的系统以允许它以非 root 用户身份工作。
最后,编辑 JupyterHub 配置并将 spawner 类更改为 SudoSpawner
/etc/jupyterhub/jupyterhub_config.py
c.JupyterHub.spawner_class='sudospawner.SudoSpawner'
要授予用户访问 hub 的权限,请将他们添加到 jupyterhub-users
组
# usermod -aG jupyterhub-users <username>
systemdspawner
systemdspawner 使用 systemd 来管理每个用户的 notebook,这允许配置资源限制、更好的进程隔离和沙箱,以及动态分配的用户。要使用它,请安装 jupyterhub-systemdspawnerAUR 软件包,并在配置文件中设置 spawner 类
/etc/jupyterhub/jupyterhub_config.py
c.JupyterHub.spawner_class = 'systemdspawner.SystemdSpawner'
请注意,根据 systemdspawner 的 readme,当前使用它需要以 root 用户身份运行 JupyterHub。
服务
JupyterHub 服务定义为通过其 API 与 Hub 交互的进程。服务可以由 hub 运行,也可以作为独立进程运行。
空闲剔除器
空闲剔除器服务可用于自动关闭空闲的单用户服务器。要使用它,请安装 jupyterhub-idle-cullerAUR 软件包。要通过 hub 运行服务,请将服务描述添加到 c.JupyterHub.services
配置变量
/etc/jupyterhub/jupyterhub_config.py
import sys c.JupyterHub.services = [ { 'name': 'idle-culler', 'admin': True, 'command': [ sys.executable, '-m', 'jupyterhub_idle_culler', '--timeout=3600' ], } ]
有关命令行选项的描述以及如何作为独立进程运行服务的详细信息,请参阅服务文档或 python -m jupyterhub_idle_culler --help
的输出。
技巧和窍门
以非 root 用户身份运行
默认情况下,主 hub 进程以 root 用户身份运行(各个用户服务器在 spawner 设置的相应本地用户下运行)。要以非 root 用户身份运行,您需要使用 SudoSpawner(上面列出的其他 spawner 需要以 root 用户身份运行)。如果您正在使用 PAM 身份验证器,您还需要为非 root 用户配置它。
使用反向代理
反向代理可用于将外部请求重定向到 JupyterHub 实例。如果您想从一台机器提供多个站点,或者使用现有服务器来处理 SSL,这将非常有用。JupyterHub 文档的 使用反向代理 部分包含关于使用 nginx 或 Apache 作为反向代理的示例配置。
代理其他 Web 服务
Jupyter Server Proxy 扩展允许您在 JupyterHub 旁边运行其他 Web 服务,例如 Code Server 或 RStudio,并为它们提供经过身份验证的 Web 访问。要使用它,请安装 python-jupyter-server-proxyAUR 并使用 /etc/jupyter/jupyter_notebook_config.py
文件进行配置。例如,代理 code-serverAUR
/etc/jupyter/jupyter_notebook_config.py
c.ServerProxy.servers = { 'code-server': { 'command': [ 'code-server', '--auth=none', '--disable-telemetry', '--disable-update-check', '--bind-addr=localhost:{port}', '--user-data-dir=.config/Code - OSS/', '--extensions-dir=.vscode-oss/extensions/' ], 'timeout': 20, 'launcher_entry': { 'title': 'VS Code' } } }
有关配置 Jupyter Server Proxy 的更多详细信息,请参阅文档。
访问 GPU
如果您在访问 GPU 时收到错误(例如,如果 nvidia-smi
报告无法与 NVIDIA 驱动程序通信),您必须考虑 JupyterHub systemd 单元文件附带的强化措施。要广泛允许访问 GPU(和其他硬件),您可以将其添加到 drop-in 文件中
/etc/systemd/system/jupyterhub.service.d/override.conf
[Service] PrivateDevices=false