远程访问jupyter notebook的核心是三件事必须同时到位:配置文件中设c.notebookapp.ip='0.0.0.0'、设密码并禁用浏览器,本地用ssh -l 8888:localhost:8888建立隧道;漏任一环将导致连接失败或403错误。

直接说结论:远程访问 Jupyter Notebook 的核心不是“开个端口就行”,而是三件事必须同时到位——jupyter_notebook_config.py 里正确配置监听地址和密码、服务启动时禁用浏览器且不绑定 localhost、本地通过 ssh -L 隧道安全转发。漏掉任一环,都会出现“连得上但打不开”“403 Forbidden”“Connection refused”或“No address associated with hostname”。
为什么 c.NotebookApp.ip = '*' 常报错?试试 '0.0.0.0'
很多教程写 c.NotebookApp.ip = '*',但在部分 Linux 发行版(尤其是较新内核或 systemd 管理的环境)下会解析失败,报错 No address associated with hostname。这不是密码或端口问题,是 DNS 解析层面的歧义。
-
'*'是通配符语义,但某些网络栈不支持直接绑定到通配符 IP -
'0.0.0.0'是明确的 IPv4 任意地址绑定,兼容性更好,Jupyter 官方文档也已将其列为推荐值 - 如果用了
'*'启动失败,改回c.NotebookApp.ip = '0.0.0.0'几乎总能解决 - 别写
'localhost'或'127.0.0.1'——那只会锁死本地访问
jupyter notebook password 和手动生成 passwd() 的区别在哪?
两者生成的哈希格式不同,且存储位置、生效方式也不一样,混用会导致密码无效。
-
jupyter notebook password:Jupyter 5.0+ 推荐方式,生成的 hash 存在~/.jupyter/jupyter_server_config.json,只对jupyter server(新版默认命令)生效;老版本jupyter notebook可能读不到 -
from notebook.auth import passwd; passwd():返回sha1:xxx或argon2:xxx字符串,必须手动填进jupyter_notebook_config.py的c.NotebookApp.password字段,且要加u''前缀(Python 2/3 兼容写法) - 如果你用的是
jupyter notebook命令启动(不是jupyter server),就老老实实用passwd()手动填,别信password命令生成的 json 文件
SSH 隧道为什么必须用 ssh -L 8888:localhost:8888,不能写服务器公网 IP?
因为 Jupyter 默认只监听 127.0.0.1:8888(即使你设了 ip='0.0.0.0',它仍要求请求头 Host 字段匹配本地域名),而 SSH 隧道的本质是把远程 localhost 映射到你本地 localhost。写服务器公网 IP 会绕过隧道,触发 Host 头校验失败,返回 403。
- 正确写法:
ssh -N -L 8888:localhost:8888 user@server_ip - 错误写法:
ssh -N -L 8888:192.168.1.100:8888 user@server_ip(假设这是服务器内网 IP)或ssh -N -L 8888:server_public_ip:8888 user@server_ip - 如果服务器防火墙严格,确保
8888端口没被 iptables/nftables 拦截——但 SSH 隧道本身不依赖该端口对外开放 - 本地端口(第一个 8888)可任意换,只要不被占用;远程端口(第二个 8888)必须和
c.NotebookApp.port一致
最常被忽略的点:启动服务时没加 --no-browser,或者配置里 c.NotebookApp.open_browser = True,会导致 Jupyter 尝试在服务器上打开图形浏览器——而服务器通常无 GUI,进程卡住或静默失败。务必确认这一项为 False,且启动命令显式带 --no-browser。











