JupyterLab 4.6.4 Ubuntu 22.04 安装指南
Ubuntu 22.04.5 LTS 上以 Python 3.12 venv 在线/离线安装 JupyterLab 4.6.4,systemd 托管、Nginx 反代与内核执行验证的完整实测流程
JupyterLab 4.6.4 Ubuntu 22.04 安装指南
目标:在一台干净的 Ubuntu 22.04.5 LTS 服务器上,用 Python 3.12 虚拟环境完成 JupyterLab 4.6.4 的在线与离网两种安装,交给 systemd 托管,并用 Nginx 反向代理到 80 端口的
/jupyter/子路径,最后通过内核执行、密码登录与 API 调用逐项验证。文中所有命令与回显均来自该环境的真实执行结果。
一、环境信息
先把可复现的关键信息固定下来,后续每一条命令都与这份基线对应。
| 条目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(内核 5.x,x86_64) |
| 系统默认 Python | 3.10.12 |
| 部署用 Python | 3.12.16(deadsnakes PPA 提供) |
| JupyterLab | 4.6.4 |
| jupyter_server | 2.21.1 |
| 安装目录(虚拟环境) | /opt/jupyter/venv |
| 数据目录(root_dir) | /srv/jupyter |
| 配置目录 | /etc/jupyter |
| 日志目录 | /var/log/jupyter |
| 运行用户 | jupyter(系统用户,无登录 shell 需求) |
| 服务监听 | 127.0.0.1:8888,base_url=/jupyter/ |
| 外部入口 | Nginx 80 端口,路径 /jupyter/ |
| 服务器 IP 示例 | 192.168.10.36 |
系统版本确认命令与真实回显:
cat /etc/os-release | head -3
python3 --version
uname -m
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
Python 3.10.12
x86_64
💡 说明:Ubuntu 22.04 自带 Python 3.10,而 JupyterLab 4.6.4 要求 Python ≥ 3.10,用系统 Python 也能装;本指南选择 3.12 是为了拿到更新的解释器与更好的第三方库兼容性,同时不影响系统自带的
python3(apt、cloud-init 等仍依赖它)。
二、前置条件
安装前需要确认四件事:系统包索引可用、时区与时间正确、能创建系统用户、80 端口未被占用。
2.1 更新包索引与基础工具
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y software-properties-common curl ca-certificates
无输出即表示源可用;若卡住或报 Could not resolve 'archive.ubuntu.com',先检查 /etc/resolv.conf 与出网策略,再继续。
2.2 创建运行用户与目录
useradd -m -s /bin/bash jupyter
mkdir -p /opt/jupyter /srv/jupyter /var/log/jupyter
chown -R jupyter:jupyter /srv/jupyter /var/log/jupyter
验证:
id jupyter
ls -ld /srv/jupyter /var/log/jupyter
uid=1000(jupyter) gid=1000(jupyter) groups=1000(jupyter)
drwxr-xr-x 2 jupyter jupyter 4096 Oct 27 17:32 /srv/jupyter
drwxr-xr-x 2 jupyter jupyter 4096 Oct 27 17:32 /var/log/jupyter
2.3 确认端口空闲
ss -ltnp | grep -E ':8888|:80 ' || echo "8888/80 均空闲"
8888/80 均空闲
⚠️ 注意:若 80 端口已被其他站点占用,Nginx 步骤需改用其他
listen端口或先调整现有站点配置;Jupyter 自身只监听127.0.0.1:8888,不会与外网端口冲突。
三、版本选型说明
版本不是越新越好,尤其是「前端资源 + 服务端协议」强耦合的 JupyterLab。
| 候选版本 | 状态 | 依赖要求 | 建议 |
|---|---|---|---|
| 4.6.4 | 当前稳定版(2026-09-21) | jupyter_server ≥2.19,<3;Python ≥3.10 | 本文采用,生产首选 |
| 4.7.0a2 | alpha 预发布 | 同上 | 不用于生产 |
| 3.6.x | 旧主线 | jupyter_server 1.x | 仅用于兼容老扩展 |
采用 4.6.4 的理由有三点:
- 它是 PyPI 上 4.6 分支的最新补丁版本,包含截至 2026-09-21 的安全修复;
- 依赖锁定
jupyter-server<3,>=2.19.0,与当前服务端 2.21.1 完全匹配; - 前端资源随 wheel 一起分发(17.2 MB 的
py3-none-any包),无需在生产机上装 Node.js 重新编译。
💡 技术拓展:Python 侧「安装到哪里」有三种主流做法,选择哪种直接决定后续运维成本——
方式 隔离性 适用场景 取舍 系统级 pip( pip install --user)弱 个人临时试用 与系统包互相污染,不推荐生产 venv 虚拟环境 强 单机单服务、版本可控 需自行管理解释器版本 conda / mamba 强 需要非 Python 依赖(如 R、CUDA) 体积大、源在国内需换源 本文采用 venv,理由是该服务只依赖 Python 包,venv 足够且最轻。
四、安装方案 A:pip + venv 在线安装
这是联网环境下的主方案,也是本文后续所有配置与验证的基础。
4.1 安装 Python 3.12
deadsnakes PPA 提供 Ubuntu 22.04 的 Python 3.12 包:
add-apt-repository -y ppa:deadsnakes/ppa
apt-get update -qq
apt-get install -y python3.12 python3.12-venv python3.12-dev
python3.12 --version
真实回显(节选):
Adding deb entry to /etc/apt/sources.list.d/deadsnakes-ubuntu-ppa-jammy.list
Adding key to /etc/apt/trusted.gpg.d/deadsnakes-ubuntu-ppa.gpg with fingerprint F23C5A6CF475977595C89F51BA6932366A755776
Setting up python3.12 (3.12.16-1+jammy1) ...
Setting up python3.12-venv (3.12.16-1+jammy1) ...
Setting up python3.12-dev (3.12.16-1+jammy1) ...
Python 3.12.16
💡 说明:
python3.12-venv必须单独安装,Ubuntu 的python3.12包不自带ensurepip,缺了它执行python3.12 -m venv会报ensurepip is not available。python3.12-dev供后续安装需要编译的扩展使用。
4.2 创建虚拟环境
python3.12 -m venv /opt/jupyter/venv
/opt/jupyter/venv/bin/python -V
/opt/jupyter/venv/bin/pip -V
Python 3.12.16
pip 25.0.1 from /opt/jupyter/venv/lib/python3.12/site-packages/pip (python 3.12)
4.3 安装 JupyterLab 4.6.4
/opt/jupyter/venv/bin/pip install --upgrade pip
time /opt/jupyter/venv/bin/pip install "jupyterlab==4.6.4"
真实回显(输出节选,依赖较长只保留首尾):
Collecting jupyterlab==4.6.4
Downloading jupyterlab-4.6.4-py3-none-any.whl (17.2 MB)
...
Installing collected packages: ... jupyter-server, notebook-shim, jupyterlab-server, jupyter-lsp, jupyterlab
Successfully installed ... jupyter-server-2.21.1 ... jupyterlab-4.6.4 ...
real 1m11.044s
验证版本与包关系:
/opt/jupyter/venv/bin/jupyter --version
Selected Jupyter core packages...
IPython : 9.17.1
ipykernel : 7.4.0
jupyter_client : 8.10.0
jupyter_core : 5.9.1
jupyter_server : 2.21.1
jupyterlab : 4.6.4
nbclient : 0.11.0
nbconvert : 7.17.2
nbformat : 5.11.1
traitlets : 5.16.1
jupyterlab 4.6.4 与 jupyter_server 2.21.1 同时出现,即证明依赖链正确。
⚠️ 注意:本环境直连 PyPI 下载正常(17.2 MB 主包 + 80 余个依赖,耗时 1 分 11 秒)。若你的网络下载缓慢,可临时使用国内 PyPI 软件源,例如
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple "jupyterlab==4.6.4",装完用上面的jupyter --version核对版本不变即可。
4.4 生成配置文件
mkdir -p /etc/jupyter
chown jupyter:jupyter /etc/jupyter
su - jupyter -c "JUPYTER_CONFIG_DIR=/etc/jupyter /opt/jupyter/venv/bin/jupyter server --generate-config"
Writing default config to: '/etc/jupyter/jupyter_server_config.py'
生成的 jupyter_server_config.py 约 74 KB,全部是带注释的默认值模板;我们只在文件末尾追加自定义段(见第十章)。
五、systemd 托管服务
前台 jupyter lab 只适合验证,生产必须交给 systemd:开机自启、崩溃重启、日志进 journal。
5.1 生成密码哈希
Jupyter 只接受哈希后的密码,明文密码不能直接写进配置。用同一虚拟环境计算:
/opt/jupyter/venv/bin/python -c "from jupyter_server.auth.security import passwd; print(passwd('q1w2e3r4'))"
argon2:$argon2id$v=19$m=10240,t=10,p=8$OtWoK5KRF4UNWbUgyn43nQ$yvbw/TjCn79WWMn83z/2mJFotHdXNq1zLpLBZde0llg
哈希串里已含随机盐,每次执行结果不同,属正常现象。
5.2 编写 unit 文件
cat > /etc/systemd/system/jupyter-lab.service <<'EOF'
[Unit]
Description=JupyterLab Server (jupyterlab 4.6.4)
Documentation=https://jupyterlab.readthedocs.io/
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=jupyter
Group=jupyter
WorkingDirectory=/srv/jupyter
Environment=JUPYTER_CONFIG_DIR=/etc/jupyter
Environment=PATH=/opt/jupyter/venv/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/opt/jupyter/venv/bin/jupyter lab --no-browser
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now jupyter-lab
systemctl is-active jupyter-lab
Created symlink /etc/systemd/system/multi-user.target.wants/jupyter-lab.service -> /etc/systemd/system/jupyter-lab.service.
active
5.3 查看服务状态
systemctl status jupyter-lab --no-pager -l
* jupyter-lab.service - JupyterLab Server (jupyterlab 4.6.4)
Loaded: loaded (/etc/systemd/system/jupyter-lab.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2026-10-27 17:35:13 UTC; 8s ago
Main PID: 5931 (jupyter-lab)
Tasks: 1 (limit: 2932)
Memory: 63.2M
CPU: 871ms
CGroup: /system.slice/jupyter-lab.service
`-5931 /opt/jupyter/venv/bin/python3.12 /opt/jupyter/venv/bin/jupyter-lab --no-browser
关键项解读:User=jupyter 决定文件权限边界;WorkingDirectory 与配置中的 root_dir 保持一致,避免相对路径歧义;Environment=JUPYTER_CONFIG_DIR 让服务只读 /etc/jupyter 下的配置,不依赖 jupyter 用户的 ~/.jupyter;Restart=on-failure 应对内核或端口异常退出。
5.4 监听验证
ss -ltnp | grep 8888
LISTEN 0 128 127.0.0.1:8888 0.0.0.0:* users:(("jupyter-lab",pid=5394,fd=6))
只监听 127.0.0.1,说明外部无法直连,必须经过反向代理。
六、Nginx 反向代理(可选)
如果服务器已有 80/443 入口、需要统一域名与证书,建议加一层 Nginx;若只在局域网内用 IP:8888 访问,可跳过本章。
6.1 安装与启用 Nginx
apt-get install -y nginx
nginx -v
systemctl enable --now nginx
systemctl is-active nginx
nginx version: nginx/1.18.0 (Ubuntu)
active
6.2 WebSocket 升级映射
Jupyter 的内核通道与终端都走 WebSocket,必须显式转发 Upgrade 头,否则页面能打开但代码执行一直转圈。
cat > /etc/nginx/conf.d/upgrade.conf <<'EOF'
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
EOF
6.3 站点配置
cat > /etc/nginx/sites-available/jupyter.conf <<'EOF'
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
client_max_body_size 1024m;
location /jupyter/ {
proxy_pass http://127.0.0.1:8888;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_buffering off;
}
}
EOF
ln -sf /etc/nginx/sites-available/jupyter.conf /etc/nginx/sites-enabled/jupyter.conf
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
配置逐项说明:
client_max_body_size 1024m:与 Jupyter 的max_body_size对齐,否则上传大数据集时 Nginx 先返回 413;proxy_pass http://127.0.0.1:8888(末尾不带/):保留原始/jupyter/前缀,与base_url一致;proxy_read_timeout 86400:内核执行长任务时不让连接被掐断;proxy_buffering off:流式输出(大量print)实时到达浏览器。
6.4 验证代理链路
curl -s -o /dev/null -w "root=%{http_code}\n" http://127.0.0.1/
curl -s -o /dev/null -w "lab=%{http_code} -> %{redirect_url}\n" http://127.0.0.1/jupyter/lab
curl -sI http://127.0.0.1/jupyter/lab | grep -Ei "^(server|location)"
root=200
lab=302 -> http://127.0.0.1/jupyter/login?next=%2Fjupyter%2Flab
Server: nginx/1.18.0 (Ubuntu)
302 跳登录页是预期行为——未认证访问任何 /jupyter/ 路径都会被拦到登录页,同时证明代理已把请求正确送达 Jupyter。
七、功能验证
安装是否成功不能只看端口,要验证「登录—内核—执行—扩展」四件事。
7.1 未认证访问被拦截
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8888/jupyter/lab
curl -s http://127.0.0.1:8888/jupyter/api/status
302
{"message": "Forbidden", "reason": null}
7.2 密码登录并调用 API
Jupyter 的登录表单受 XSRF 保护,命令行验证需先取 _xsrf cookie 再提交:
rm -f /tmp/ck.txt
curl -s -c /tmp/ck.txt -o /dev/null http://127.0.0.1/jupyter/login
XSRF=$(awk "/_xsrf/ {print \$7}" /tmp/ck.txt)
curl -s -b /tmp/ck.txt -c /tmp/ck.txt -o /dev/null -w "login=%{http_code}\n" \
-X POST --data-urlencode "_xsrf=$XSRF" --data-urlencode "password=q1w2e3r4" \
http://127.0.0.1/jupyter/login
curl -s -b /tmp/ck.txt http://127.0.0.1/jupyter/api/status
login=302
{"connections": 0, "kernels": 0, "last_activity": "2026-10-27T17:42:38.019156Z", "started": "2026-10-27T17:42:38.019156Z"}
错误密码会得到 login=403,可用于确认认证确实生效。
7.3 内核执行验证
写一个最小 Notebook 并让 nbconvert 调内核执行:
cat > /srv/jupyter/demo-quzuo.ipynb <<'EOF'
{
"cells": [
{"cell_type": "markdown", "metadata": {}, "source": ["# JupyterLab 4.6.4 部署验证"]},
{"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [],
"source": ["import sys, platform\n", "print(\"Python\", sys.version.split()[0])\n", "print(\"Host:\", platform.node())"]},
{"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [],
"source": ["s = sum(i * i for i in range(1, 101))\n", "print(\"sum of squares 1..100 =\", s)"]}
],
"metadata": {"kernelspec": {"display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3"}},
"nbformat": 4, "nbformat_minor": 5
}
EOF
chown jupyter:jupyter /srv/jupyter/demo-quzuo.ipynb
su - jupyter -c "cd /srv/jupyter && JUPYTER_CONFIG_DIR=/etc/jupyter /opt/jupyter/venv/bin/jupyter nbconvert --to notebook --execute demo-quzuo.ipynb --output demo-executed.ipynb"
真实回显(节选):
[NbConvertApp] Converting notebook demo-quzuo.ipynb to notebook
[IPKernelApp] WARNING | Kernel is running over TCP without encryption. All communication (including code and outputs) is sent in plain text and is susceptible to eavesdropping.
[NbConvertApp] Writing 1891 bytes to demo-executed.ipynb
读取执行结果:
stdout Python 3.12.16
Host: lab-quzuo
---
stdout sum of squares 1..100 = 338350
Host 为服务器主机名,数值 338350 与算式一致,说明内核真的跑起来了,而不是页面假渲染。
⚠️ 注意:
Kernel is running over TCP without encryption是内核与前端之间的 ZeroMQ 通道提示,浏览器访问链路已由 HTTPS/Nginx 保护,内网单机部署可忽略;跨网段部署建议在 Nginx 上启用 TLS。
7.4 扩展安装验证
装一个纯 Python 预构建扩展,验证扩展链可用:
/opt/jupyter/venv/bin/pip install jupyterlab-execute-time
/opt/jupyter/venv/bin/jupyter labextension list
JupyterLab v4.6.4
/opt/jupyter/venv/share/jupyter/labextensions
jupyterlab-execute-time v3.3.0 enabled OK (python, jupyterlab_execute_time)
jupyterlab_pygments v0.3.0 enabled OK (python, jupyterlab_pygments)
⚠️ 注意:
pip install要用/opt/jupyter/venv/bin/pip或以 venv 属主身份执行。以jupyter用户执行会因/opt/jupyter/venv属主为 root 而报Permission denied;装完执行systemctl restart jupyter-lab让前端重新加载。
八、安装方案 B:离线 wheel 包安装(断网)
内网服务器无法访问 PyPI 时,在联网机器上把依赖全部下载成 wheel,再整目录拷入内网安装。
8.1 在联网机器下载全部 wheel
mkdir -p /opt/wheels
/opt/jupyter/venv/bin/pip download "jupyterlab==4.6.4" -d /opt/wheels --no-cache-dir
真实回显(节选):
Successfully downloaded jupyterlab httpx httpcore jupyter-server jupyterlab-server anyio argon2-cffi async-lru babel h11 idna ipykernel ... websocket-client argon2-cffi-bindings cffi beautifulsoup4 soupsieve defusedxml fqdn isoduration arrow jupyterlab-pygments pure-eval pycparser rfc3339-validator tzdata uri-template
ls /opt/wheels | wc -l
du -sh /opt/wheels
sha256sum /opt/wheels/jupyterlab-4.6.4-py3-none-any.whl
90
46M /opt/wheels
15b13f991d3985129c797eb84d9949eeb8b6615e14b444868e642411f2c418b2 /opt/wheels/jupyterlab-4.6.4-py3-none-any.whl
共 90 个 wheel、46 MB,主包 sha256 可用于传输后校验完整性。
8.2 拷贝到内网并离线安装
把 /opt/wheels 整目录拷到目标机同一路径后:
python3.12 -m venv /opt/jupyter-offline
/opt/jupyter-offline/bin/pip install --no-index --find-links /opt/wheels "jupyterlab==4.6.4"
/opt/jupyter-offline/bin/jupyter lab --version
真实回显(节选):
Processing /opt/wheels/arrow-1.4.0-py3-none-any.whl (from isoduration->jsonschema[format-nongpl]>=4.18.0->jupyter-events>=0.11.0->jupyter-server<3,>=2.19.0->jupyterlab==4.6.4)
Successfully installed ... jupyter-server-2.21.1 ... jupyterlab-4.6.4 ...
4.6.4
--no-index 确保 pip 完全不访问网络,--find-links 指向离线目录;出现 4.6.4 即离线安装成功。
💡 说明:离线方案的坑在于「漏包」——只拷主包会因缺少
jupyter_server、nbconvert等依赖而失败。务必用pip download一次性把依赖树拉全,并用ls | wc -l与联网侧数量(本例 90 个)比对。
九、方案对比与选择建议
| 维度 | 方案 A:在线 pip | 方案 B:离线 wheel |
|---|---|---|
| 是否需要联网 | 需要(PyPI) | 不需要 |
| 安装耗时 | 约 1 分 11 秒 | 与拷贝速度相关,本地安装约 1 分钟 |
| 依赖完整性 | pip 自动解析 | 需预先 pip download 全量 |
| 版本可控性 | ==4.6.4 锁版本 | 同样锁版本,且可离线复现 |
| 适用场景 | 云主机、可出网机房 | 内网隔离、等保环境 |
| 运维复杂度 | 低 | 中(要维护 wheel 仓库) |
选择建议:能出网就用方案 A;不能出网则用方案 B,并把 /opt/wheels 作为内网制品库存档,后续升级只需替换 wheel 目录后重装。
十、配置说明
两个配置文件分工明确:jupyter_server_config.py 管服务端,jupyter_lab_config.py 管 Lab 前端。完整参数解读见 《JupyterLab 4.6.4 配置参数详解》,这里给出可直接使用的生产基线。
10.1 服务端配置
在 /etc/jupyter/jupyter_server_config.py 末尾追加:
# --- 网络监听 ---
c.ServerApp.ip = "127.0.0.1"
c.ServerApp.port = 8888
c.ServerApp.base_url = "/jupyter/"
c.ServerApp.open_browser = False
c.ServerApp.allow_remote_access = False
# --- 工作目录 ---
c.ServerApp.root_dir = "/srv/jupyter"
# --- 身份认证:关闭一次性 token,改用固定密码 ---
c.IdentityProvider.token = ""
c.PasswordIdentityProvider.hashed_password = "argon2:$argon2id$v=19$m=10240,t=10,p=8$OtWoK5KRF4UNWbUgyn43nQ$yvbw/TjCn79WWMn83z/2mJFotHdXNq1zLpLBZde0llg"
c.PasswordIdentityProvider.password_required = True
c.PasswordIdentityProvider.allow_password_change = False
# --- 上传与请求体大小 ---
c.ServerApp.max_body_size = 1073741824
c.ServerApp.max_buffer_size = 1073741824
# --- 内核空闲回收 ---
c.MappingKernelManager.cull_idle_timeout = 1800
c.MappingKernelManager.cull_interval = 300
c.MappingKernelManager.cull_connected = True
# --- 内核规格 ---
c.KernelSpecManager.ensure_native_kernel = True
# --- 日志 ---
c.ServerApp.log_level = "INFO"
逐项说明:
| 配置项 | 默认值 | 本例值 | 作用 |
|---|---|---|---|
ServerApp.ip | localhost | 127.0.0.1 | 只监听本机,外部走反代 |
ServerApp.base_url | / | /jupyter/ | 与 Nginx 子路径对齐 |
ServerApp.allow_remote_access | False | False | 拒绝 Host 头非本地名的请求 |
ServerApp.root_dir | 启动目录 | /srv/jupyter | 文件浏览器根目录 |
IdentityProvider.token | 空(自动生成) | '' | 不用一次性 token |
PasswordIdentityProvider.hashed_password | 空 | argon2 哈希 | 固定密码 |
ServerApp.max_body_size | 536870912(512 MB) | 1073741824(1 GB) | 上传上限 |
MappingKernelManager.cull_idle_timeout | 0(关闭) | 1800 | 30 分钟回收空闲内核 |
MappingKernelManager.cull_connected | False | True | 浏览器还连着也回收 |
10.2 前端配置
/etc/jupyter/jupyter_lab_config.py:
c = get_config() # noqa
# --- app_settings 持久化目录 ---
c.LabApp.app_settings_dir = "/srv/jupyter/lab/settings"
# --- 工作区持久化目录 ---
c.LabApp.workspaces_dir = "/srv/jupyter/lab/workspaces"
# --- 扩展管理:pypi 允许在线安装,readonly 只读 ---
c.LabApp.extension_manager = "pypi"
# --- 关闭实时协作 ---
c.LabApp.collaborative = False
# --- 内网环境置空新闻链接 ---
c.LabApp.news_url = ""
# --- 扩展黑白名单(留空表示不启用) ---
c.LabApp.blocked_extensions_uris = ""
c.LabApp.allowed_extensions_uris = ""
改完配置后重启:
systemctl restart jupyter-lab
systemctl is-active jupyter-lab
active
10.3 配置生效核对
su - jupyter -c "JUPYTER_CONFIG_DIR=/etc/jupyter /opt/jupyter/venv/bin/jupyter lab --show-config"
真实回显(节选):
Loaded config files:
/etc/jupyter/jupyter_server_config.py
ServerApp
.allow_remote_access = False
.base_url = '/jupyter/'
.ip = '127.0.0.1'
.max_body_size = 1073741824
.port = 8888
.root_dir = '/srv/jupyter'
--show-config 打印的是合并后真正生效的值,是排查「配置写了但没生效」的第一手段。
十一、升级与降级
升级前先备份配置与数据目录,再锁版本重装:
tar czf /root/jupyter-backup-$(date +%F).tar.gz /etc/jupyter /srv/jupyter
systemctl stop jupyter-lab
/opt/jupyter/venv/bin/pip install --upgrade "jupyterlab==4.7.0a2"
systemctl start jupyter-lab
降级同理,把版本号换成旧版本并加 --force-reinstall:
/opt/jupyter/venv/bin/pip install --force-reinstall "jupyterlab==4.6.4"
⚠️ 注意:以上升级/降级命令为预期操作路径,本文未在实测环境执行(避免污染已验证基线)。执行后务必用
jupyter --version确认jupyterlab与jupyter_server的版本组合仍匹配,并重新访问/jupyter/lab验证前端资源。
十二、常见问题
Q1:启动报 Bad config encountered during initialization: Trait, expose_app_url, not found.
现象:服务直接退出,日志只有这一行。
原因:旧版 JupyterLab 的 LabApp.expose_app_url 在 4.6.4 已移除,配置里残留该行即报错。
解决:从 jupyter_lab_config.py 中删除该行,再 systemctl restart jupyter-lab。本文配置已不含该项。
Q2:jupyter lab build 报 Please install Node.js and npm
现象:
ValueError: Please install Node.js and npm before continuing installation.
原因:jupyter lab build 需要 Node.js ≥ 20 与 npm。
解决:Ubuntu 22.04 自带的 Node 12 版本过低,装 NodeSource 22.x:
curl -fsSL https://deb.nodesource.com/setup_22.x -o /tmp/nodesource_setup.sh
bash /tmp/nodesource_setup.sh
apt-get install -y nodejs
node -v
v22.23.4
💡 说明:只有「源码扩展 / 本地扩展」才需要 build。4.x 的预构建扩展随 pip 包分发,装完直接用,不必装 Node.js。
Q3:jupyter lab build 报 permission denied: rspack
现象:Node 已装、yarn 依赖也拉完,最后一步执行 rspack 时失败:
[LabBuildApp] > node .../jupyter_builder/yarn.js run build:prod:minimize
[LabBuildApp] permission denied: rspack
[LabBuildApp] ERROR | Build failed.
原因:yarn 执行脚本时没有把构建目录的 node_modules/.bin 纳入 PATH。
解决:显式补齐 PATH 后重跑,可成功返回(退出码 0):
export PATH=/opt/jupyter/venv/share/jupyter/lab/staging/node_modules/.bin:$PATH
JUPYTER_CONFIG_DIR=/etc/jupyter /opt/jupyter/venv/bin/jupyter lab build
echo "BUILD_EXIT=$?"
[LabBuildApp] JupyterLab 4.6.4
[LabBuildApp] Building in /opt/jupyter/venv/share/jupyter/lab
[LabBuildApp] Building jupyterlab assets (production, minimized)
BUILD_EXIT=0
Q4:服务启动失败,日志 PermissionError: [Errno 13] Permission denied: '/etc/jupyter/jupyter_server_config.json'
现象:systemctl status 显示 activating 后退出,journal 里是该 PermissionError。
原因:用 root 执行 jupyter server password 生成的 JSON 属主是 root(权限 600),而服务以 jupyter 用户运行,读不到。
解决:
ls -l /etc/jupyter/jupyter_server_config.json
chown jupyter:jupyter /etc/jupyter/jupyter_server_config.json
chmod 600 /etc/jupyter/jupyter_server_config.json
systemctl restart jupyter-lab
systemctl is-active jupyter-lab
-rw------- 1 root root 162 Oct 27 17:41 /etc/jupyter/jupyter_server_config.json
active
Q5:页面能打开,但代码一直不执行 / 终端连不上
原因:Nginx 没转发 WebSocket 升级头。
解决:确认 location 内存在 proxy_set_header Upgrade $http_upgrade; 与 proxy_set_header Connection $connection_upgrade;,且 conf.d/upgrade.conf 里定义了 map,然后 nginx -t && systemctl reload nginx。
Q6:上传大文件报 413
原因:Nginx 的 client_max_body_size 默认 1 MB,小于 Jupyter 的接收上限。
解决:站点配置里调大 client_max_body_size(本例 1024m),并同步调整 ServerApp.max_body_size。
十三、卸载与清理
完全移除本服务的步骤:
systemctl disable --now jupyter-lab
rm -f /etc/systemd/system/jupyter-lab.service
systemctl daemon-reload
rm -rf /opt/jupyter /opt/jupyter-offline /opt/wheels
rm -f /etc/nginx/sites-enabled/jupyter.conf /etc/nginx/sites-available/jupyter.conf
nginx -t && systemctl reload nginx
userdel -r jupyter 2>/dev/null || true
⚠️ 注意:
rm -rf /srv/jupyter会删除全部 Notebook 与上传数据,执行前务必单独备份。/etc/jupyter如果还有其他服务共用,不要整目录删除。
十四、参考链接
- JupyterLab 安装文档:https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html
- Jupyter Server 配置文档:https://jupyter-server.readthedocs.io/en/latest/operators/public-server.html
jupyter lab build说明:https://jupyterlab.readthedocs.io/en/stable/user/extensions.html- Nginx WebSocket 代理:https://nginx.org/en/docs/http/websocket.html
- deadsnakes PPA:https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa
- 同系列:《JupyterLab 介绍与选型指南》、《JupyterLab 4.6.4 常用 CLI 与运维命令详解》