运行Notebook服务器

这个 Jupyter notebook Web应用程序基于服务器客户端结构。Notebook服务器使用 two-process kernel architecture 基于 ZeroMQ, 以及 Tornado 为HTTP请求提供服务。

注解

默认情况下,Notebook服务器以127.0.0.1:8888本地运行,只能从 localhost . 您可以使用 http://127.0.0.1:8888 .

本文档描述了如何 secure a notebook server 以及如何 run it on a public interface .

重要

This is not the multi-user server you are looking for . 本文档介绍如何使用单个用户运行公共服务器。这只能由希望远程访问其个人计算机的人完成。即便如此,要做到这一点,也需要对设置限制和安全含义有一个透彻的了解。如果您允许多个用户访问本文档中描述的Notebook服务器,则他们的命令可能会相互冲突、冲突和覆盖。

如果您需要多用户服务器,官方解决方案是 JupyterHub. 要使用jupyterhub,需要在网络上用户可以访问的地方运行一个Unix服务器(通常是Linux)。这可能在公共互联网上运行,但这样做会带来额外的 security concerns .

保护Notebook服务器

你可以用一个简单的密码保护你的Notebook服务器。从Notebook5.0开始,这可以自动完成。要手动设置密码,可以配置 NotebookApp.password 设置在 jupyter_notebook_config.py .

先决条件:Notebook配置文件

检查是否有Notebook配置文件, jupyter_notebook_config.py . 此文件的默认位置是位于主目录中的jupyter文件夹:

  • 窗户: C:\Users\USERNAME\.jupyter\jupyter_notebook_config.py

  • 操作系统X: /Users/USERNAME/.jupyter/jupyter_notebook_config.py

  • Linux: /home/USERNAME/.jupyter/jupyter_notebook_config.py

如果您还没有jupyter文件夹,或者jupyter文件夹不包含Notebook配置文件,请运行以下命令:

$ jupyter notebook --generate-config

如果需要,此命令将创建jupyter文件夹,并创建Notebook配置文件, jupyter_notebook_config.py ,在此文件夹中。

自动密码设置

从Notebook5.3开始,当您第一次使用令牌登录时,Notebook服务器应为您提供从用户界面设置密码的机会。

您将收到一份表格,要求提供当前 _token_, 以及你的 _new_ _输入密码并点击 Login and setup new password .

下次需要登录时,您将能够使用新密码而不是登录令牌,否则请按照以下过程从命令行设置密码。

通过设置 --NotebookApp.allow_password_change=False

从Notebook5.0版开始,您可以用一个命令输入和存储Notebook服务器的密码。 jupyter notebook password 将提示您输入密码并在 jupyter_notebook_config.json .

$ jupyter notebook password
Enter password:  ****
Verify password: ****
[NotebookPasswordApp] Wrote hashed password to /Users/you/.jupyter/jupyter_notebook_config.json

这可以用于重置丢失的密码;或者如果您认为您的凭据已被泄露,并希望更改您的密码。更改密码将使服务器重新启动后的所有登录会话失效。

准备哈希密码

您可以使用函数手动准备哈希密码 notebook.auth.security.passwd()

In [1]: from notebook.auth import passwd
In [2]: passwd()
Enter password:
Verify password:
Out[2]: 'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed'

警告

passwd() 如果不带参数调用,将提示您输入和验证密码,如上面的代码段中的密码。尽管函数也可以作为参数传递字符串,例如 passwd('mypassword') 在IPython会话中传递字符串作为参数,因为它将保存在输入历史记录中。

将哈希密码添加到Notebook配置文件中

然后可以将哈希密码添加到 jupyter_notebook_config.py . 此文件的默认位置 jupyter_notebook_config.py 在你的主目录的jupyter文件夹中, ~/.jupyter ,例如:

c.NotebookApp.password = u'sha1:67c9e60bb8b6:9ffede0825894254b2e042ea597d771089e11aed'

自动密码设置将哈希存储在 jupyter_notebook_config.json 当此方法将哈希存储在 jupyter_notebook_config.py . 这个 .json 配置选项优先于 .py 因此,如果JSON文件设置了密码,则手动密码可能不会生效。

使用SSL进行加密通信

当使用密码时,最好将SSL与Web证书一起使用,这样您的哈希密码就不会以未加密的方式发送给浏览器。

重要

网络安全正在迅速变化和发展。我们提供此文档是为了方便用户,并建议用户对可能影响安全性的更改保持最新状态,例如OpenSSL的新版本。开放式Web应用程序安全项目 (OWASP) 网站是一个关于一般安全问题和网络实践的好资源。

通过设置 certfile 选择您的自签名证书,即 mycert.pem ,命令为:

$ jupyter notebook --certfile=mycert.pem --keyfile mykey.key

小技巧

自签名证书可以用 openssl . 例如,以下命令将创建一个有效期为365天的证书,同时将密钥和证书数据写入同一文件:

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mykey.key -out mycert.pem

启动Notebook服务器时,浏览器可能会警告您的自签名证书不安全或无法识别。如果您希望拥有一个完全兼容的自签名证书,而该证书不会引发警告,则可以(但更重要的是)创建一个自签名证书,如本文中详细说明的那样。 tutorial . 或者,您可以使用 Let's Encrypt 要获取免费的SSL证书,请执行中的步骤 使用让我们加密 设置公共服务器。

运行公共Notebook服务器

如果要通过Web浏览器远程访问Notebook服务器,可以通过运行公共Notebook服务器来实现。为了在运行公共Notebook服务器时获得最佳安全性,应首先使用密码和ssl/https保护服务器,如中所述。 保护Notebook服务器 .

首先创建证书文件和哈希密码,如中所述。 保护Notebook服务器 .

如果您还没有配置文件,请使用以下命令行为Notebook创建配置文件:

$ jupyter notebook --generate-config

~/.jupyter 目录,编辑Notebook配置文件, jupyter_notebook_config.py . 默认情况下,Notebook配置文件将所有字段都注释掉。应取消注释并在其中编辑的最小配置选项集 jupyter_notebook_config.py 以下是:

# Set options for certfile, ip, password, and toggle off
# browser auto-opening
c.NotebookApp.certfile = u'/absolute/path/to/your/certificate/mycert.pem'
c.NotebookApp.keyfile = u'/absolute/path/to/your/certificate/mykey.key'
# Set ip to '*' to bind on all interfaces (ips) for the public server
c.NotebookApp.ip = '*'
c.NotebookApp.password = u'sha1:bcd259ccf...<your hashed password here>'
c.NotebookApp.open_browser = False

# It is a good idea to set a known, fixed port for server access
c.NotebookApp.port = 9999

然后您可以使用 jupyter notebook 命令。

使用让我们加密

Let's Encrypt 提供免费的SSL/TLS证书。还可以使用 Let's Encrypt 证书。

运行公共Notebook服务器 当使用带有少量配置更改的let's加密证书时,将类似。步骤如下:

  1. 创建一个 Let's Encrypt certificate .

  2. 使用 准备哈希密码 创建一个。

  3. 如果您还没有Notebook的配置文件,请使用以下命令创建一个:

    $ jupyter notebook --generate-config
    

4。在 ~/.jupyter 目录,编辑Notebook配置文件, jupyter_notebook_config.py . 默认情况下,Notebook配置文件将所有字段都注释掉。应在其中取消注释和编辑的最小配置选项集 jupyter_notebook_config.py 以下是:

# Set options for certfile, ip, password, and toggle off
# browser auto-opening
c.NotebookApp.certfile = u'/absolute/path/to/your/certificate/fullchain.pem'
c.NotebookApp.keyfile = u'/absolute/path/to/your/certificate/privkey.pem'
# Set ip to '*' to bind on all interfaces (ips) for the public server
c.NotebookApp.ip = '*'
c.NotebookApp.password = u'sha1:bcd259ccf...<your hashed password here>'
c.NotebookApp.open_browser = False

# It is a good idea to set a known, fixed port for server access
c.NotebookApp.port = 9999

然后您可以使用 jupyter notebook 命令。

重要

使用“HTTPS”。 请记住,启用SSL支持时,必须通过 https:// ,不在平原上 http:// . 来自服务器的启动消息在控制台中打印提醒,但是 it is easy to overlook this detail and think the server is for some reason non-responsive .

When using SSL, always access the notebook server with 'https://'.

现在可以通过将浏览器指向 https://your.host.com:9999 在哪里? your.host.com 是公共服务器的域。

防火墙设置

要正常工作,运行JupyterNotebook服务器的计算机上的防火墙必须配置为允许从访问端口上的客户端计算机进行连接。 c.NotebookApp.port 设置在 jupyter_notebook_config.py 允许连接到Web界面。防火墙还必须允许从49152到65535端口上的127.0.0.1(本地主机)进行连接。服务器使用这些端口与Notebook内核通信。内核通信端口由zeromq随机选择,每个内核可能需要多个连接,因此必须访问大量端口。

使用自定义的URL前缀运行Notebook

Notebook仪表板是工作目录中Notebook概述的登录页,通常可以在默认URL中找到和访问。 http://localhost:8888/ .

如果希望自定义Notebook仪表板的URL前缀,可以通过修改 jupyter_notebook_config.py . 例如,如果您希望Notebook仪表板具有包含其他IPython文件的子目录,例如 http://localhost:8888/ipython/ ,您可以使用如下配置选项进行此操作(有关修改的说明,请参阅上面的 jupyter_notebook_config.py ):

c.NotebookApp.base_url = '/ipython/'

将Notebook嵌入其他网站

有时,您可能希望将Notebook嵌入网站上的某个位置,例如在iframe中。为此,您可能需要重写内容安全策略以允许嵌入。假设您的网站位于 https://mywebsite.example.com ,您可以在网站上嵌入具有以下配置设置的Notebook jupyter_notebook_config.py

c.NotebookApp.tornado_settings = {
    'headers': {
        'Content-Security-Policy': "frame-ancestors https://mywebsite.example.com 'self' "
    }
}

使用iframe将Notebook嵌入网站时,请考虑将Notebook置于单选项卡模式。由于Notebook在默认情况下会在新选项卡中打开一些链接,因此单选项卡模式会阻止Notebook打开其他选项卡。将以下内容添加到 ~/.jupyter/custom/custom.js 将启用单选项卡模式:

define(['base/js/namespace'], function(Jupyter){
    Jupyter._target = '_self';
});

使用网关服务器进行内核管理

现在,您可以将内核管理重定向到网关服务器(即, Jupyter Kernel GatewayJupyter Enterprise Gateway )只需通过以下命令行选项指定网关URL:

$ jupyter notebook --gateway-url=http://my-gateway-server:8888

环境:

JUPYTER_GATEWAY_URL=http://my-gateway-server:8888

或在 jupyter_notebook_config.py

c.GatewayClient.url = http://my-gateway-server:8888

提供后,将从指定的网关服务器检索所有内核规范,并且所有内核将由该服务器管理。此选项允许针对托管群集以内核进程为目标,同时允许Notebook的管理保留在Notebook服务器的本地。

已知问题

代理人

当位于代理之后时,特别是当系统或浏览器设置为自动检测代理时,NotebookWeb应用程序可能无法连接到服务器的WebSockets,并在启动时向您显示警告。在这种情况下,需要配置系统,使其不使用服务器地址的代理。

例如,在Firefox中,转到“首选项”面板的“高级”部分的“网络”选项卡,单击“设置…”,然后将Notebook服务器的地址添加到“无代理服务器”字段中。

内容安全策略(CSP)

确定的 security guidelines 建议服务器使用内容安全策略(CSP)头来防止跨站点脚本漏洞,特别是限制在 default-src: https: 如果可能的话。这项指令给朱彼特带来了两个问题。首先,它禁用内联javascript代码的执行,这是jupyter广泛使用的代码。第二,它将通信限制到HTTPS方案,并防止WebSocket工作,因为它们通过WSS方案通信(或用于不安全通信的WS)。Jupyter使用WebSockets与内核进行交互,因此当您访问具有这样一个CSP的服务器时,您的浏览器将阻止使用WSS的尝试,这将导致您看到来自JupyterNotebook的“连接失败”消息,或者根本没有来自Jupyter终端的响应。通过查看浏览器的javascript控制台,您可以看到任何错误消息,这些消息将解释失败的原因。

为了避免这些问题,您需要添加 'unsafe-inline'connect-src https: wss: 到你的CSP报头,至少是Jupyter提供的页面。(也就是说,对于网站的其他部分,可以保持CSP不变。)请注意,允许使用多个CSP头,但连续的CSP头只能限制策略;它们不能松开策略。例如,如果服务器同时发送这两个头

内容安全策略“default src https:'unsafe inline'”内容安全策略“connect src https:wss:”

第一个策略已经消除了WSS连接,因此第二个策略没有效果。因此,您不能简单地添加第二个头;您必须实际修改您的CSP头,使其看起来更像这样:

内容安全策略“default src https:'unsafe inline';connect src https:wss:”

码头工人

使用 jupyter notebook 作为一个 Docker CMD 导致谷粒反复破碎,可能是由于缺乏 PID reaping . 要避免这种情况,请使用 tini init 作为你的码头文件 ENTRYPOINT ::

# Add Tini. Tini operates as a process subreaper for jupyter. This prevents
# kernel crashes.
ENV TINI_VERSION v0.6.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /usr/bin/tini
RUN chmod +x /usr/bin/tini
ENTRYPOINT ["/usr/bin/tini", "--"]

EXPOSE 8888
CMD ["jupyter", "notebook", "--port=8888", "--no-browser", "--ip=0.0.0.0"]