---
title: JupyterLab
description: Run token-authenticated notebooks in an isolated Python environment
icon: "flask"
---

<Tooltip tip="This example publishes JupyterLab to a port on the computer running the CLI, which is not available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

This example installs JupyterLab into a Python microVM, stores notebooks on a sized root disk, and exposes the server only on host loopback.

## Run JupyterLab

<Steps>
<Step title="Start JupyterLab">

Set a temporary token in the host shell:

<CodeGroup>
```sh macOS & Linux
export JUPYTER_TOKEN="$(openssl rand -hex 24)"
```

```powershell Windows
$bytes = New-Object byte[] 24
$rng = [Security.Cryptography.RandomNumberGenerator]::Create()
$rng.GetBytes($bytes)
$rng.Dispose()
$env:JUPYTER_TOKEN = -join ($bytes | ForEach-Object { $_.ToString('x2') })
```
</CodeGroup>

Create a startup script for the guest:

```sh start-jupyter.sh
#!/bin/sh
set -eu

pip install --no-cache-dir jupyterlab==4.6.2
exec jupyter lab \
  --ip=0.0.0.0 \
  --port=8888 \
  --no-browser \
  --allow-root \
  --IdentityProvider.token="$JUPYTER_TOKEN"
```

Start the server:

<CodeGroup>
```sh macOS & Linux
msb run -d --name jupyter-demo --replace \
  --cpus 2 --memory 2G --root-disk 6G \
  -p 127.0.0.1:8888:8888 \
  -e JUPYTER_TOKEN="$JUPYTER_TOKEN" \
  --mkdir /workspace \
  --workdir /workspace \
  --script-path start-jupyter:./start-jupyter.sh \
  --entrypoint start-jupyter \
  python:3.13-slim
```

```powershell Windows
msb run -d --name jupyter-demo --replace `
  --cpus 2 --memory 2G --root-disk 6G `
  -p 127.0.0.1:8888:8888 `
  -e "JUPYTER_TOKEN=$env:JUPYTER_TOKEN" `
  --mkdir /workspace `
  --workdir /workspace `
  --script-path start-jupyter:./start-jupyter.sh `
  --entrypoint start-jupyter `
  python:3.13-slim
```
</CodeGroup>

Open `http://127.0.0.1:8888/lab?token=<token>` in your browser and replace `<token>` with the value generated above.

</Step>

<Step title="Verify the service">

Check the authenticated API from the host:

<CodeGroup>
```sh macOS & Linux
curl -sS "http://127.0.0.1:8888/api?token=$JUPYTER_TOKEN" | head
```

```powershell Windows
curl.exe -sS "http://127.0.0.1:8888/api?token=$env:JUPYTER_TOKEN" | Select-Object -First 10
```
</CodeGroup>

Then inspect the recent server output:

```sh
msb logs --tail 20 jupyter-demo
```

The logs show Jupyter Server listening on guest port 8888. Notebooks saved under `/workspace` remain on the root disk when the sandbox stops and starts.

<Warning>
  The token is visible to the guest and to processes that can inspect the host command environment. Use the [secrets workflow](/sandboxes/secrets) for production credentials, retain the loopback bind, and place a TLS-terminating authenticated proxy in front of any remote deployment.
</Warning>

</Step>

<Step title="Clean up">

Remove the sandbox:

```sh
msb rm -f jupyter-demo
```

Clear the token from the host shell:

<CodeGroup>
```sh macOS & Linux
rm -f start-jupyter.sh
unset JUPYTER_TOKEN
```

```powershell Windows
Remove-Item start-jupyter.sh
Remove-Item Env:JUPYTER_TOKEN
```
</CodeGroup>

Copy any notebooks you want to keep to the host before removing the sandbox.

</Step>
</Steps>
