---
title: "JupyterHubとは？JupyterLabとの違い・構築手順と6.0の変更点"
url: "https://www.issoh.co.jp/tech/details/3517/"
published: 2024-09-06
updated: 2026-10-15
categories: ["Python"]
publisher: "株式会社一創"
---

# JupyterHubとは？JupyterLabとの違い・構築手順と6.0の変更点

JupyterHub（ジュピターハブ）は、JupyterLabやJupyter Notebookの実行環境を利用者ごとに起動・管理するマルチユーザーサーバーです。利用者はブラウザでログインするだけで自分専用のノートブック環境が起動し、管理者は認証・利用者の追加・計算資源をまとめて管理できます。2026年10月時点の最新版は6.0.1（2026年9月14日公開）で、Python 3.10以上が必要です。本記事では公式Dockerイメージの6.0.1とnginx 1.30を組み合わせた検証と公式仕様をもとに、仕組み、JupyterLabとの違い、構築方法の選び方、本番化で詰まる設定を解説します。

## まとめ：JupyterHubの役割と構築の要点

- **JupyterHubとは**：ノートブック環境そのものではなく、利用者ごとにJupyterLabを起動して振り分ける「配る側」のサーバー。ライセンスはBSD-3-Clauseで無料。
- **JupyterLabとの違い**：JupyterLabは1人が使う作業画面、JupyterHubはそれを多人数へ配る土台。利用者環境にJupyterLabを入れておけば、JupyterHub経由でもその画面で作業できます。
- **構築方法**：1台で100人程度までならThe Littlest JupyterHub（TLJH）、複数台に広げるならKubernetes向けのZero to JupyterHub（Z2JH）。どちらも2026年10月時点では5系のJupyterHubが入ります。
- **ログイン許可の注意**：既定のPAMAuthenticatorでは、5.0以降、許可条件を設定しないと誰もログインできません。画面には「Invalid username or password」としか出ないため、パスワードの誤りと取り違えやすい点に注意が必要です。
- **本番化の注意**：nginxを前に置くときはWebSocketのヘッダを転送しないと、画面は開くのにカーネルにつながりません。常駐はsystemdのユニットで行います。
- **6.0の注意**：5系のデータベースのまま起動すると終了します。バックアップのうえ `jupyterhub upgrade-db` が必須です。

## JupyterHubの仕組み：Hub・Proxy・Spawner・Authenticator

JupyterHubは4つの部品が役割を分けて動きます。ログインを受け付けるのがAuthenticator、利用者ごとのJupyterサーバーを起動するのがSpawner、ブラウザからの通信を各利用者のサーバーへ振り分けるのがProxyで、これらを束ねるのがHub本体です。6.0.1で `jupyterhub --generate-config` を実行して生成される設定ファイルから既定値を拾うと次のとおりです。

| 部品            | 役割            | 既定の実装                     | 主な差し替え先                          |
| ------------- | ------------- | ------------------------- | -------------------------------- |
| Hubのデータベース    | 利用者・サーバー状態の保存 | SQLite（jupyterhub.sqlite） | PostgreSQL・MySQL                 |
| Proxy         | URLごとの振り分け    | ConfigurableHTTPProxy     | Traefik                          |
| Spawner       | 利用者のサーバー起動    | LocalProcessSpawner       | DockerSpawner・KubeSpawner        |
| Authenticator | ログインの判定       | PAMAuthenticator          | OAuthenticator・LDAPAuthenticator |

利用者から見た流れはこうです。ブラウザで `http://サーバー:8000` を開いてログインし、自分のサーバーを起動すると、Proxyに `/user/ユーザー名/` の経路が登録され、以後はその経路で自分のJupyterLabに入ります。利用者aliceとして試した際も、ログイン後に `/hub/spawn` を経て `/user/alice/lab` に着地しました。サーバーの停止や再起動は、JupyterLabのメニュー［File］→［Hub Control Panel］から行います。

既定のLocalProcessSpawnerは、OS上のユーザーアカウントごとにプロセスを立ち上げるだけで、利用者どうしの分離はOSのファイル権限に頼ります。メモリやCPUの上限もこのSpawnerでは効かないため、利用者ごとの資源上限が必要なら、人数にかかわらずDockerSpawner・KubeSpawner・systemdspawnerなど、制限を実装したSpawnerを選ぶべきです。

## JupyterLab・Jupyter Notebookとの違い：作業画面と配布基盤の関係

3つは競合する製品ではなく、層が違います。Jupyter NotebookとJupyterLabは利用者が操作する画面で、JupyterHubはその画面を多人数へ届ける仕組みです。

| 項目            | Jupyter Notebook | JupyterLab  | JupyterHub      |
| ------------- | ---------------- | ----------- | --------------- |
| 最新版（2026年10月） | 7.6.3            | 4.6.4       | 6.0.1           |
| 位置づけ          | 1文書ずつ開く画面        | 複数タブの統合画面   | 多人数への配布基盤       |
| 開くURL         | /tree            | /lab        | /hub/login      |
| 利用者数          | 1人               | 1人          | 複数人             |
| ログイン機能        | トークン・パスワード等      | トークン・パスワード等 | PAM・OAuth・LDAP等 |
| 起動方法          | jupyter notebook | jupyter lab | jupyterhub      |

NotebookとJupyterLabの差は、7系で大きく縮まりました。[Notebook 7の配布ページ](https://pypi.org/project/notebook/)は、画面をJupyterLabの部品、Pythonのサーバー部分をJupyter Serverで作ったと説明しています。違いは「1つの文書に集中する画面か、ファイルブラウザ・ターミナル・複数ノートブックを並べる画面か」という操作感で、同じJupyter Server上に両方を入れれば `/tree` と `/lab` を行き来できます。注意すべきは拡張機能で、Notebook 6以前向けの拡張はNotebook 7では動きません。旧Notebookの拡張に頼っていた授業資料は、JupyterLab向けの拡張へ置き換える必要があります。Notebook単体の入れ方は[Jupyter Notebookのインストール手順｜7.6系をpip・uv・condaで入れる方法](/tech/details/17961/)で扱っています。

個人の分析ならJupyterLab単体で足ります。JupyterHubが必要になるのは、授業や研究室、分析チームのように「同じ環境を複数人に、個別のアカウントで使わせたい」ときです。`c.Spawner.default_url` の既定値は空文字で、この場合は利用者側のJupyter Serverの既定に従います。6.0.1とJupyterLab 4.6.4の組み合わせでは、設定なしでJupyterLab（`/lab`）が開きました。Notebook画面で始めたい場合は `c.Spawner.default_url = '/tree'` を指定します。

## 構築方法の選び方：TLJH・Zero to JupyterHub・pip手動構築

選ぶ基準は「サーバーが1台か複数台か」「コンテナで利用者を分けたいか」「最新版が必要か」の3点です。公式が案内する3方式に、クラウドのマネージド環境を加えて比べます。

| 方式                | 想定規模         | 入るJupyterHub | 主な要件                       |
| ----------------- | ------------ | ------------ | -------------------------- |
| TLJH              | 1台・0〜100人    | 5系（6未満）      | Debian/Ubuntu LTS          |
| Z2JH 4.4.2        | 複数台・数千人規模    | 5.5.2        | Kubernetes 1.28以上・Helm     |
| pip手動構築           | 検証・小規模       | 6.0.1        | Python 3.10以上・Node.js 20以上 |
| Amazon EMR 7.14.0 | Sparkクラスター併用 | 1.5.0        | EMRクラスター                   |

### The Littlest JupyterHub（TLJH）：単一サーバーへの導入

TLJHは公式の配布パッケージで、公式ドキュメントは対象を「単一サーバー上の少人数（0〜100人）」と定めています。対応OSは現行LTSのDebianとUbuntu（amd64・arm64）です。sudo権限のあるサーバーで、最初の管理者名を指定して次を実行します。

```
sudo apt install python3 python3-dev git curl
curl -L https://tljh.jupyter.org/bootstrap.py | sudo -E python3 - --admin 管理者名
```

TLJHはSpawnerにsystemdspawner、ProxyにTraefikを使い、HTTPS化や利用者追加を `tljh-config` コマンドで済ませられる点が利点です。ただし2026年10月時点のTLJHは、ハブ環境の要件を `jupyterhub>=5.2.0,<6` と定めているため、6.0の新機能は使えません。

### Zero to JupyterHub（Z2JH）：Kubernetesによる大規模構築

Z2JHはKubernetes向けのHelmチャートで、利用者ごとにPodを起動します。2026年9月1日公開の4.4.2は、同梱のJupyterHubが5.5.2、KubeSpawnerが7.1.0、要求するKubernetesが1.28以上です。ノードの自動増減や利用者ごとの永続ボリュームをKubernetesに任せられるため、授業のように利用者数が時間帯で大きく変わる用途に向きます。Kubernetesを初めて触るなら、先に[k8sをローカルで動かす手順｜kindでクラスタ構築からDeployment公開・撤収まで](/tech/details/17438/)でクラスタの基本操作を確かめておくと、Helmの値ファイルを読むときに迷いません。

### pipとDockerSpawnerによる手動構築

最新の6.0系を使いたい、または既存サーバーに組み込みたい場合は手動構築になります。1台のサーバーで利用者をコンテナに分けたいときはDockerSpawner（最新版14.0.0）を組み合わせるのが定番で、`c.JupyterHub.spawner_class = 'docker'` と指定して切り替えます。利用者用のDockerイメージにも `jupyterhub` パッケージが必要な点を忘れがちです。Docker自体の導入は[Docker Desktopの導入手順とライセンス境界｜4.89系の要件と無料代替への移行](/tech/details/17442/)を参照してください。

### Amazon EMRのJupyterHub：同梱は1.5.0

AWSでSparkと一緒に使う選択肢として、Amazon EMRはクラスターのプライマリノードにJupyterHubをDockerコンテナで同梱します。ただし[EMR 7.14.0（2026年9月8日公開）のリリースノート](https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-7140-release.html)でも同梱版は1.5.0で、EMR 6.15.0と同じ版のままです。認証はPAMかLDAPです。本記事で扱う5.0以降の許可設定や6.0の機能は無いため、EMRのJupyterHubはSparkと連携する用途の候補になります。EMRでも利用者管理はできますが、JupyterHub 5以降の認可設定や6の機能が要件なら、別途構築する構成を選びます。ノートブック環境ごとマネージドに任せたいなら、[SageMakerとは？SageMaker AIへの改称とPython SDK v3移行を実装手順で解説](/tech/details/17509/)のような専用サービスが候補です。

## 最小構成でJupyterHub 6.0を起動する手順

ここではLinuxサーバーにpipで入れ、OSのユーザーアカウントでログインさせる最小構成を示します。設定例のalice・bob・adminは、ホームディレクトリとログイン可能なパスワードを持つ既存のOSユーザー名に置き換えてください。設定ファイルへの名前の追加だけではOSユーザーは作成されません。JupyterHubは公式にWindowsをサポートしていないため、Windowsで試す場合はWSL2かLinuxの仮想マシンを使います。

### JupyterHubのpipインストールと設定ファイル生成

事前にPython 3.10以上とvenv、Node.js 20以上とnpmを用意します。以下の操作は `sudo -i` で開いたrootシェルで実行し、先に `mkdir -p /etc/jupyterhub` で設定先ディレクトリを作っておきます。既定のProxyであるconfigurable-http-proxy（最新版5.3.0）はNode.js製のため、npmで別に入れます。Pythonの仮想環境の作り方で迷う場合は[pipとcondaの違いと使い分け｜Anaconda・Miniconda・商用ライセンスまで解説](/tech/details/7775/)が参考になります。

```
python3 -m venv /opt/jupyterhub
/opt/jupyterhub/bin/pip install jupyterhub==6.0.1 jupyterlab==4.6.4
npm install -g configurable-http-proxy
/opt/jupyterhub/bin/jupyterhub --generate-config -f /etc/jupyterhub/jupyterhub_config.py
```

生成される設定ファイルは全項目がコメントアウトされた状態で、必要な行だけを有効にして使います。既定の待ち受けは `http://:8000` です。手動起動の前に、後述の許可ユーザー設定を保存します。その後、同じrootシェルで `cd /etc/jupyterhub` を実行してから `/opt/jupyterhub/bin/jupyterhub -f /etc/jupyterhub/jupyterhub_config.py` を実行します。PAMで認証し、各利用者のOSアカウントとしてプロセスを起動するためroot権限が要ります。

### 許可ユーザーの設定：5.0以降の既定のログイン拒否

JupyterHub 5.0で認可の既定が変わりました。4系までは許可設定が空なら「ログインできた人は全員許可」でしたが、5.0以降は既定のPAMAuthenticatorを含む多くのAuthenticatorで `c.Authenticator.allow_all` の既定が `False` になり、許可設定が1つも無いと誰も入れません（DummyAuthenticatorのように既定で全員を許可するものもあります）。

6.0.1で許可設定を書かずに起動すると、ハブのログには「No allow config found, it's possible that nobody can login to your Hub!」という警告が出ます。この状態で正しいパスワードを入れても、ブラウザにはHTTP 403と「Invalid username or password」が返り、ログ側にだけ「User 'alice' not allowed.」と記録されました。画面の文言だけを見るとパスワードの誤りに見えるため、ログインできないときは先にハブのログを確認してください。

```
c = get_config()  # noqa

# 特定の利用者だけ許可する（推奨）
c.Authenticator.allowed_users = {'alice', 'bob'}

# 仮想環境内の利用者サーバーを絶対パスで指定する
c.Spawner.cmd = ['/opt/jupyterhub/bin/jupyterhub-singleuser']
# 管理者（root相当の権限を持つので最小限に）
c.Authenticator.admin_users = {'admin'}

# OSやOAuth側で認証できた人を全員許可する場合
# c.Authenticator.allow_all = True
```

`admin_users` に入れた利用者は、管理画面から他の利用者のサーバーに入ることもできます。公式の設定説明も「管理者権限はrootと同じ扱いにすべき」と明記しているため、講師やチームリーダーを安易に管理者にしない運用が安全です。

### JupyterHubのデータベース・cookie secretの保存先

利用者やサーバーの状態は既定で起動ディレクトリの `jupyterhub.sqlite` に保存され、同じ場所にログイン用の `jupyterhub_cookie_secret` も作られます。起動するディレクトリが変わると別のデータベースを新規に作ってしまうため、次章のsystemdでは作業ディレクトリを `/etc/jupyterhub` に固定します。どちらのファイルもバックアップ対象です。

## 本番化：nginxでのHTTPS化とsystemdでの常駐

設定なしで起動すると「Running JupyterHub without SSL.」という警告が出ます。パスワードが平文で流れるため、インターネットに公開するならTLSが必須です。証明書を `c.JupyterHub.ssl_cert` と `c.JupyterHub.ssl_key` に直接指定する方法もありますが、Let's Encryptの更新や他サービスとの同居を考えるとnginxで終端する構成が一般的です。

### nginxのWebSocket設定：必須ヘッダと接続失敗の症状

JupyterLabはノートブックとカーネルの間をWebSocketでつなぐため、nginxが `Upgrade` と `Connection` のヘッダを転送しないと、ページは開くのにセルを実行できない状態になります。公式6.0.1のDockerイメージとnginx 1.30.5を使い、SharedPasswordAuthenticatorと検証専用のSimpleLocalProcessSpawnerを組み合わせて、ヘッダの有無だけを変えた2つの構成を比較しました。結果は次のとおりです。

| 経路                  | カーネル作成（REST） | カーネルへのWebSocket |
| ------------------- | ------------ | --------------- |
| nginx（Upgradeヘッダなし） | 201          | 400 Bad Request |
| nginx（公式例の設定）       | 201          | 接続・応答あり         |
| ハブへ直接（8000番）        | 201          | 接続・応答あり         |

RESTの呼び出しは成功するため、ログインやファイル一覧は正常に見えます。利用者からは「カーネルが接続中のまま」という症状だけが届くので、nginxを挟んだ直後にこの報告が来たら、まず次の設定を確かめてください。下の例は[JupyterHub公式のnginx設定例](https://jupyterhub.readthedocs.io/en/stable/howto/configuration/config-proxy.html)から、TLS以外の転送部分を抜き出したものです。あわせて、同一ホストのnginxから転送するこの構成では、jupyterhub\_config.pyに `c.JupyterHub.bind_url = 'http://127.0.0.1:8000'` を設定し、外部からHTTPの8000番ポートへ直接接続できないようにします。

```
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 443 ssl;
    server_name hub.example.com;
    # ssl_certificate と ssl_certificate_key は環境に合わせて指定する

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket（カーネル接続）に必須
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header X-Scheme $scheme;

        proxy_buffering off;
    }
}
```

`map` はhttpブロックに置く指令なので、`/etc/nginx/conf.d/` 配下のファイルに書くか、nginx.confのhttpブロックに入れます。WebSocketとHTTPの接続の違いは[SSEとWebSocketの違いと使い分け｜WebRTC・WebTransportまで性能比較【2026年10月】](/tech/details/4539/)で解説しています。

### systemdで常駐させる：ユニットファイルの例

手動起動のままではSSHを切ると止まり、再起動後も上がりません。ここでは、公式配布のTLJHが同梱する[jupyterhub.service](https://github.com/jupyterhub/the-littlest-jupyterhub/blob/main/tljh/systemd-units/jupyterhub.service)を、前章の `/opt/jupyterhub` の配置に合わせて書き換えました。`systemd-analyze verify` で構文エラーが無いことを確認しています。

```
[Unit]
Description=JupyterHub
After=network-online.target
Wants=network-online.target

[Service]
User=root
WorkingDirectory=/etc/jupyterhub
Environment=PATH=/opt/jupyterhub/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/opt/jupyterhub/bin/jupyterhub -f /etc/jupyterhub/jupyterhub_config.py
Restart=always

[Install]
WantedBy=multi-user.target
```

これを `/etc/systemd/system/jupyterhub.service` に保存し、`systemctl daemon-reload` の後に `systemctl enable --now jupyterhub` で起動と自動起動を有効にします。`Environment=PATH` は、npmで入れたconfigurable-http-proxyの置き場所（多くは `/usr/local/bin` か `/usr/bin`）を含めるためのもので、ここが漏れるとProxyを起動できずにハブが停止します。ユニットファイルの各項目の意味は[systemdとは？読み方・SysVinitとの違いとsystemctl・ユニットファイルの基本【v262】](/tech/details/8160/)を参照してください。

ハブをrootで動かしたくない場合は、公式の[root以外で動かす手順](https://jupyterhub.readthedocs.io/en/stable/howto/configuration/config-sudo.html)に従い、専用ユーザーにSudoSpawner（最新版1.0.0）の起動だけを許すsudo設定を与えます。sudoersの編集とPAMの読み取り権限の調整が要るので、手順が増える分、利用者の少ない検証環境ではroot実行のままとする判断もあります。

## 認証方式の選択：PAM・OAuth・LDAP・共有パスワード

既定のPAMAuthenticatorはサーバーのOSアカウントでログインさせる方式で、利用者を増やすたびに `useradd` が必要になります。既存のアカウント基盤がある場合は、入退職や受講登録に伴う認証管理をそちらへ集約できます。ただし、LocalProcessSpawnerを使う場合は、認証方式を変えても対応するOSアカウントが必要です。

| Authenticator               | 最新版         | 向く場面                          |
| --------------------------- | ----------- | ----------------------------- |
| PAMAuthenticator            | 本体同梱        | OSアカウントがある少人数                 |
| OAuthenticator              | 17.4.0      | GitHub・Google・Entra ID・汎用OIDC |
| LDAPAuthenticator           | 2.0.2       | 社内のActive Directory・LDAP      |
| SharedPasswordAuthenticator | 本体同梱（5.3以降） | 短期のワークショップ                    |

SharedPasswordAuthenticatorは一般利用者間でパスワードを共有する方式です。パスワードを知る人は他の一般利用者としてもログインできるため、利用者間の保護が不要な短期環境に限って使います。利用者用パスワードは8文字以上、別に設定する管理者用パスワードは32文字以上でないと起動時に弾かれます。`allow_all = True` と組み合わせると、パスワードを知る人が任意のユーザー名で無制限に利用者を作れる点に注意が必要です。以前ワークショップで使われていた `DummyAuthenticator.password` は5.3で非推奨になり、6.0.1で使うと移行を促す警告が出ます。

OAuthenticatorはOAuth 2.0／OIDC向けで、SAMLには対応していません。SAMLしか出せないIdPを使っている場合は、OIDCを出せるIDaaSを間に置く判断が必要になります。IdPとの接続方式の整理は[IDaaSとは？SSO・IdPとの違いとSAML・OIDC・SCIM連携を実装視点で解説](/tech/details/16401/)にまとめています。

## リソース制限とGPUの割り当て

設定ファイルには `c.Spawner.mem_limit` と `c.Spawner.cpu_limit` がありますが、設定の説明には「既定のLocalProcessSpawnerはこの制限を実装していない」と明記されています。既定構成のままメモリ上限を書いても効かず、1人の処理が資源を使い切ると、他の利用者の処理やサーバー全体に影響するおそれがあります。上限を効かせるには、DockerSpawner・KubeSpawner・systemdspawnerのいずれかに切り替えます。

GPUを配る場合もSpawner次第です。Z2JHではKubeSpawnerの `extra_resource_limits` にNVIDIAのデバイスプラグインが提供するリソース名を書き、プロファイルで「CPUのみ」と「GPU 1枚」を利用者に選ばせる構成が定番です。

```
singleuser:
  profileList:
    - display_name: "CPUのみ"
      default: true
    - display_name: "GPU 1枚"
      kubespawner_override:
        extra_resource_limits:
          nvidia.com/gpu: "1"
```

GPUは利用者が作業を終えてもサーバーを止めない限り確保されたままになるため、次章のアイドル停止とセットで導入しないと、数人で全GPUが埋まります。誰がGPUメモリを握っているかは、ノード上で[nvidia-smiの使い方｜GPU使用率とメモリの見方・CSV記録・DCGMへの移行判断](/tech/details/17936/)の手順で確かめられます。自前でGPUサーバーを持たずに試すなら、[Runpodとは？料金・使い方・支払い方法とGPUクラウドの選び方【2026年10月】](/tech/details/9628/)のような時間課金のGPUクラウドで検証してから台数を決める方が無駄がありません。

## アイドルサーバーの自動停止：jupyterhub-idle-culler 2.0

放置されたサーバーを止める仕組みはJupyterHub本体には無く、公式の[jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler)（最新版2.0.0・2026年6月16日公開）をサービスとして登録します。2.0で設定の仕組みがtraitletsへ置き換わりましたが、コマンドラインのフラグ名は変わっていません。先に `/opt/jupyterhub/bin/python -m pip install jupyterhub-idle-culler==2.0.0` を実行し、次の設定を既存のjupyterhub\_config.pyに追加します。

```
import sys

c.JupyterHub.load_roles = [
    {
        "name": "jupyterhub-idle-culler-role",
        "scopes": ["list:users", "read:users:activity", "read:servers", "delete:servers"],
        "services": ["jupyterhub-idle-culler-service"],
    }
]
c.JupyterHub.services = [
    {
        "name": "jupyterhub-idle-culler-service",
        "command": [sys.executable, "-m", "jupyterhub_idle_culler", "--timeout=3600"],
    }
]
```

`--timeout` は、Hubが記録する最後の活動時刻（last\_activity）からの経過秒数のしきい値で、2.0.0の既定値は600秒です。last\_activityはキーボード操作そのものではなく、カーネル・端末・通信の活動が定期的にHubへ報告された値で、READMEは報告間隔（既定5分）とWebSocketのping間隔（既定30秒）の合計より長くするよう求めています。READMEの例の3600秒を出発点に、授業中の利用状況に合わせて調整します。なお、Z2JH 4.4.2のハブイメージに入るのは1.4.0で、TLJHも2未満を指定しているため、配布パッケージでは1系が動きます。`load_roles` でサービスに必要な権限だけを与えるのがJupyterHub 2.0以降のRBACの書き方で、以前の `"admin": True` で丸ごと権限を渡す方式は避けます。

## JupyterHub 6.0の変更点とアップグレード前の確認

6.0.0は2026年9月1日、修正版の6.0.1は9月14日に公開されました。公式の[Upgrading to JupyterHub 6](https://jupyterhub.readthedocs.io/en/stable/howto/upgrading-v6.html)は「影響を受ける環境は少ない」としつつ、データベースのスキーマ変更を含みます。

- **Python 3.10以上が必須**：ハブ側だけでなく、利用者のサーバー側の環境も3.10以上にそろえる必要があります。
- **データベースの更新**：利用者サーバーとHubを停止してデータベースをバックアップし、Hubの実行環境・設定ファイル・作業ディレクトリをそろえて移行します。本記事の配置では、rootシェルで `cd /etc/jupyterhub` の後に `/opt/jupyterhub/bin/jupyterhub upgrade-db -f /etc/jupyterhub/jupyterhub_config.py` を実行します。
- **名前付きサーバーの命名規則**：1〜30文字のASCII英小文字・数字・単独のハイフンのみで、先頭は英小文字、末尾は英小文字か数字に制限されました。表示用の `display_name` が別に設けられ、既存の不適合な名前は既定の `allow-start` で起動・停止・削除だけ許されます。
- **起動オプションの渡し方**：GETのクエリで渡すSpawnerオプションには `opt-` の接頭辞が必要になりました。
- **新機能**：内部OAuthでPKCEが有効になり、`start:servers` スコープ、管理画面の「起動時刻」「使用プロファイル」列、起動待ち画面の停止ボタンなどが加わりました。

5.5.2で作ったデータベースのまま6.0.1を起動すると、ハブは終了コード1で止まり、次のように表示されます。

```
Found database schema version 4621fec11365 != f460b0348206. Backup your database and run `jupyterhub upgrade-db` to upgrade to the latest schema.
```

続けて `jupyterhub upgrade-db` を実行すると、PKCE対応、利用者情報の追加、`display_name` 列の追加を含む4段の移行が走り、SQLiteの場合は `jupyterhub.sqlite.2026-10-14-170730` のような日時付きのバックアップが同じディレクトリに残りました。その後は6.0.1が正常に起動します。起動のたびに自動で移行させる `--upgrade-db` オプションもあり、TLJHのユニットファイルはこれを付けています。ただしヘルプには「データベースをバックアップしてある場合だけ安全」とあり、自動でバックアップされるのはSQLiteだけです。PostgreSQLやMySQLを使っている環境では手動で移行する方が安全です。

判断としては、既存の本番環境をすぐ6.0へ上げる必要はありません。6.0.0と同じ2026年9月1日に5.5.2も公開されています。ただし、この公開実績だけで5系の今後の保守継続や期間までは判断できません。Z2JHとTLJHも2026年10月時点では5系を入れるため、配布パッケージを使っている環境は、そちらが6.0へ追随するのを待つのが順当です。pipで手動構築している環境だけが、名前付きサーバーを使っているかを確認したうえで先に上げる対象になります。

## JupyterHubを導入すべきでない場面

JupyterHubは利用者が増えるほど効く仕組みで、少人数では運用の手間の方が大きくなります。次の条件に当てはまるなら、別の選択肢を先に検討すべきです。

- **利用者が1〜2人で、各自のPCに必要な計算資源とデータを置ける**：各自のPCでJupyterLabを動かせば足ります。共有が目的ならGitでノートブックを受け渡す方が簡単です。
- **サーバーを保守する担当者がいない**：OSとJupyterHubの更新、証明書の更新、バックアップを誰も担えないなら、Google ColabやSageMakerのようなマネージド環境の方が安全です。
- **ノートブックの実行順序による不具合に悩んでいる**：これはJupyterHubでは解決しません。セルの依存関係を自動で追う[Marimoとは？使い方とUI要素・SQLセル・Jupyter移行を実測で解説](/tech/details/9756/)のような別方式のノートブックが候補になります。

逆に、分析チームや研究室の共通基盤として認証・計算資源・データの置き場所まで含めて設計したい場合は、JupyterHub単体ではなくデータ基盤側の設計が先になります。弊社の[データ分析基盤構築・MLOps構築支援](/service/ai/data-platform/)では、こうした分析環境の構成から相談を受けています。

## よくある質問

### JupyterHubの読み方は？

「ジュピターハブ」と読みます。Jupyterは、プロジェクトが当初対象にした3言語のJulia・Python・Rに由来する名前です。

### JupyterHubは無料で商用利用できますか？

できます。ライセンスはBSD-3-Clauseで、社内や有償の講座で使っても利用料はかかりません。費用が発生するのはサーバーやGPU、クラウドの利用料です。

### JupyterHubはWindowsで動きますか？

公式にはサポートされていません。READMEは対象をLinux/Unix系と明記しています。Windows PCで試す場合はWSL2上のUbuntuで動かし、本番はLinuxサーバーに置くのが確実です。

### Google Colabとの違いは何ですか？

Colabのホスト型ランタイムはGoogle側が管理しますが、自組織のマシンで動くローカルランタイムにも接続できます。ただし、ローカルランタイムへの接続だけでは、JupyterHubのような利用者別サーバーの起動・管理機能は提供されません。JupyterHubは自前のサーバーに置くため、社外に出せないデータを扱う場合や、授業の受講者をまとめて管理したい場合に向きます。

### ログイン後に「Spawn failed」と出るときは何を確認しますか？

利用者側のサーバーが起動できていません。原因はハブのログに出る利用者サーバーの出力で確認します。多いのは、利用者の環境に `jupyterhub` パッケージやJupyterLabが入っていない場合と、起動が遅くタイムアウトする場合です。後者は `c.Spawner.start_timeout`（既定60秒）と `c.Spawner.http_timeout`（既定30秒）を延ばすと解消します。Dockerコンテナ内でSimpleLocalProcessSpawnerなどを使い、利用者サーバー自体をrootとして起動すると、利用者サーバーが「Running as root is not recommended」で停止し、ハブ側には「never showed up … after 30 seconds」としか出ないこともあります。タイムアウトを延ばしても直らないときは、この行がログに無いか探してください。

## 関連記事

- [Jupyter Notebookのインストール手順｜7.6系をpip・uv・condaで入れる方法](/tech/details/17961/)
- [Marimoとは？使い方とUI要素・SQLセル・Jupyter移行を実測で解説](/tech/details/9756/)
- [pipとcondaの違いと使い分け｜Anaconda・Miniconda・商用ライセンスまで解説](/tech/details/7775/)
- [k8sをローカルで動かす手順｜kindでクラスタ構築からDeployment公開・撤収まで](/tech/details/17438/)
- [IDaaSとは？SSO・IdPとの違いとSAML・OIDC・SCIM連携を実装視点で解説](/tech/details/16401/)

---

出典: [JupyterHubとは？JupyterLabとの違い・構築手順と6.0の変更点](<https://www.issoh.co.jp/tech/details/3517/>)（株式会社一創）
