1 16/10/2026 10 min

Su Ubuntu 22.04 la strada più pulita per JupyterLab è evitare l’installazione globale via pip e usare un ambiente virtuale dedicato. Così separi dipendenze, riduci il rischio di rompere pacchetti di sistema e tieni il runtime sotto controllo. In pratica: installi i prerequisiti, crei un venv, aggiorni pip, installi JupyterLab, verifichi l’avvio e, se serve, lo esponi in modo controllato con systemd e un reverse proxy.

Perché non installarlo “a sistema”

Ubuntu 22.04 usa Python 3.10 e integra diversi pacchetti che dipendono dal gestore di sistema. Installare JupyterLab globalmente con pip può creare conflitti con librerie già presenti o con aggiornamenti futuri. Un virtual environment isola tutto in una directory dedicata, ad esempio /opt/jupyterlab o nella home dell’utente che lo usa.

Se il nodo è personale o di laboratorio, puoi fermarti al venv e lanciare JupyterLab manualmente. Se invece deve restare acceso, il passo successivo è un servizio systemd con binding su localhost e accesso tramite SSH tunnel o reverse proxy. Evita di esporre direttamente la porta 8888 su Internet senza autenticazione e senza TLS.

Prerequisiti su Ubuntu 22.04

Prima di tutto aggiorna l’indice dei pacchetti e installa Python, pip e il modulo per i virtual environment. Se lavori su una macchina minimale, può mancare anche python3-venv, che è il punto più comune di errore durante la creazione del venv.

Comandi base:

sudo apt update
sudo apt install -y python3 python3-venv python3-pip

Verifica rapida delle versioni:

python3 --version
pip3 --version

Atteso: Python 3.10.x e pip disponibile. Se python3-venv manca, il comando python3 -m venv fallisce con un errore esplicito sul modulo assente.

Creazione dell’ambiente virtuale

Qui conviene scegliere una directory stabile. Due opzioni sensate: una home utente, oppure una path dedicata sotto /opt con permessi ben definiti. Per uso personale, la home è più semplice. Per un servizio condiviso o amministrato, /opt/jupyterlab è più ordinato.

Esempio nella home dell’utente:

mkdir -p ~/apps/jupyterlab
cd ~/apps/jupyterlab
python3 -m venv .venv

Attiva il venv e aggiorna gli strumenti di packaging prima di installare JupyterLab:

source .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel

Il dettaglio pratico è semplice: senza l’attivazione del venv, installi nel Python sbagliato. Se lavori spesso su più ambienti, controlla sempre il prompt o usa which python e which pip.

Installazione di JupyterLab

Con il venv attivo, installa JupyterLab direttamente dal repository Python. La versione corrente può cambiare nel tempo, quindi non fissare un numero a meno che tu non abbia bisogno di riproducibilità stretta. Se invece il progetto richiede stabilità, blocca una versione in un file di requisiti.

python -m pip install jupyterlab

Verifica che il binario sia presente nel venv:

which jupyter-lab
jupyter-lab --version

Se il comando non viene trovato, quasi sempre significa che il venv non è attivo oppure l’installazione è fallita per problemi di rete, proxy aziendale o certificati CA mancanti. In quel caso guarda l’output completo di pip, non solo l’ultima riga.

Avvio manuale e primo test

Per il primo test non serve complicarsi la vita. Avvia JupyterLab in ascolto solo su localhost e con porta esplicita. È la scelta più sicura per capire se il software parte e se il token viene generato correttamente.

jupyter lab --ip=127.0.0.1 --port=8888 --no-browser

Nel terminale dovresti vedere un URL con token, qualcosa del tipo http://127.0.0.1:8888/lab?token=.... Aprilo localmente o fai tunnel SSH da una postazione remota:

ssh -L 8888:127.0.0.1:8888 utente@server

Questo approccio evita di aprire la porta al mondo intero. Se il server sta dietro firewall, il binding su localhost è anche più facile da gestire perché non richiede regole aggiuntive per il test iniziale.

Installazione con file requisiti per ambienti ripetibili

Se vuoi replicare l’ambiente su più macchine, conviene introdurre un file requirements.txt o, meglio ancora, un lock controllato dal tuo flusso di lavoro. Per molti casi basta un requisito esplicito con la versione di JupyterLab e delle estensioni principali.

Esempio minimo:

cat > requirements.txt <<'EOF'
jupyterlab==4.*
EOF python -m pip install -r requirements.txt

Se il tuo caso d’uso richiede notebook classici, kernel aggiuntivi o plugin, aggiungili in modo esplicito. Non dare per scontato che un ambiente nuovo abbia già tutto ciò che serve per eseguire notebook vecchi o kernel non Python.

Servizio systemd per esecuzione automatica

Quando JupyterLab deve restare attivo dopo il logout o il reboot, systemd è la soluzione più lineare. L’idea è semplice: utente dedicato, venv fisso, binding su localhost, log nel journal. In questo modo il servizio è osservabile e più facile da riavviare senza passare per sessioni interattive.

Supponiamo di usare l’utente jupyter e la directory /opt/jupyterlab:

sudo useradd -r -m -d /opt/jupyterlab -s /usr/sbin/nologin jupyter
sudo mkdir -p /opt/jupyterlab/app
sudo chown -R jupyter:jupyter /opt/jupyterlab

Prepara il venv come utente jupyter o correggi i permessi in modo coerente. Poi crea un file di unità, ad esempio /etc/systemd/system/jupyterlab.service:

[Unit]
Description=JupyterLab
After=network.target [Service]
Type=simple
User=jupyter
Group=jupyter
WorkingDirectory=/opt/jupyterlab/app
Environment="PATH=/opt/jupyterlab/app/.venv/bin"
ExecStart=/opt/jupyterlab/app/.venv/bin/jupyter lab --ip=127.0.0.1 --port=8888 --no-browser
Restart=on-failure
RestartSec=5 [Install]
WantedBy=multi-user.target

Ricarica systemd e avvia il servizio:

sudo systemctl daemon-reload
sudo systemctl enable --now jupyterlab
sudo systemctl status jupyterlab --no-pager

Per l’osservabilità, il comando più utile è il journal:

journalctl -u jupyterlab -f

Se il servizio fallisce subito, controlla prima permessi, path del venv e porta occupata. Un errore classico è avere ExecStart puntato a un interprete che non esiste più dopo uno spostamento della directory.

Accesso remoto: tunnel SSH o reverse proxy

Hai due strade sane. La prima è il tunnel SSH, ideale per accesso personale e rapido. La seconda è un reverse proxy con TLS, utile se vuoi pubblicare JupyterLab dietro Nginx o Apache e gestire certificati, hostname e autenticazione di rete in modo più ordinato.

Con tunnel SSH non devi toccare la configurazione di JupyterLab: lasci il servizio in ascolto su 127.0.0.1 e porti la porta in locale sul client. Con reverse proxy, invece, puoi esporre /lab o un sottodominio dedicato, ma devi curare WebSocket, header corretti e timeout più lunghi del normale.

Esempio minimale con Nginx

Se usi Nginx, la configurazione deve passare i WebSocket e preservare gli header. Questo è un punto in cui molte installazioni “sembrano” funzionare ma poi rompono terminali, kernel o riconnessioni lente.

server { listen 443 ssl; server_name jupyter.example.com; location / { proxy_pass http://127.0.0.1:8888; proxy_http_version 1.1; 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_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400; }
}

Con Apache il principio è lo stesso, ma la sintassi cambia. Se non hai già un proxy standardizzato, Nginx tende a essere meno verboso per questo caso. In ogni caso, il backend resta su localhost: non esporre JupyterLab direttamente se puoi evitarlo.

Autenticazione e sicurezza minima

JupyterLab usa token per impostazione predefinita, e questo è il minimo sindacale. Non disabilitare l’autenticazione se il servizio è raggiungibile da altri host. Se devi semplificare l’accesso, fallo attraverso un reverse proxy con autenticazione esterna, VPN o accesso SSH, non con porte aperte e token statici condivisi.

Per un uso più serio, limita i privilegi dell’utente del servizio, tieni separati dati e runtime, e controlla che la directory di lavoro non sia scrivibile da utenti non autorizzati. Se il server è multiutente, valuta anche quote, backup e una policy chiara sui notebook che possono eseguire codice arbitrario.

Se configuri un token o una password via file di configurazione, non scrivere segreti in chiaro in documentazione condivisa. In ambiente operativo, conserva il valore in un vault o ruotalo se è già stato esposto. Il file di configurazione deve rimanere leggibile solo dall’utente del servizio o da root.

Configurazione persistente di JupyterLab

Per fare ordine puoi generare la configurazione utente e poi modificarla. Questo è utile quando vuoi fissare porta, IP, browser e directory di lavoro. Il comando classico è:

jupyter lab --generate-config

Il file risultante si trova tipicamente in ~/.jupyter/jupyter_lab_config.py. Lì puoi impostare parametri come:

c.ServerApp.ip = '127.0.0.1'
c.ServerApp.port = 8888
c.ServerApp.open_browser = False
c.ServerApp.root_dir = '/opt/jupyterlab/data'

In molte installazioni basta passare gli argomenti a riga di comando o nel service file. La configurazione persistente è comoda quando vuoi evitare che un riavvio del servizio cambi comportamento in modo implicito.

Notebook, kernel e dipendenze aggiuntive

JupyterLab è il front-end; i kernel sono un discorso a parte. Se ti servono ambienti Python separati, puoi creare più venv e registrarli come kernel. In questo modo un utente può scegliere interpreti diversi senza mischiare librerie incompatibili nello stesso runtime.

Esempio con ipykernel:

source /opt/jupyterlab/app/.venv/bin/activate
python -m pip install ipykernel
python -m ipykernel install --user --name jupyterlab-main --display-name "Python 3 (JupyterLab)"

Se lavori con dati, librerie scientifiche o notebook legacy, pianifica subito le dipendenze. Il problema più frequente non è l’installazione di JupyterLab, ma il primo notebook che importa moduli mancanti o versioni non compatibili di numpy, pandas o matplotlib.

Verifiche finali che vale la pena fare

Dopo l’installazione, controlla tre cose: che il servizio sia attivo, che ascolti solo sull’indirizzo previsto e che il browser raggiunga l’interfaccia senza errori di WebSocket o di autenticazione. Un controllo rapido lato host è questo:

ss -ltnp | grep 8888
curl -I http://127.0.0.1:8888

Atteso: una socket in ascolto su 127.0.0.1:8888 e una risposta HTTP coerente, spesso 302 o 200 a seconda dello stato della sessione. Se usi un proxy, controlla anche i log del web server e il comportamento dei terminali interni a JupyterLab, perché sono il punto in cui emergono quasi sempre gli errori di upgrade.

Problemi tipici e lettura rapida dei sintomi

Se il comando jupyter lab non esiste, il venv non è attivo o l’installazione non è andata a buon fine. Se il servizio systemd parte e poi muore, il problema di solito è nel path dell’eseguibile, nei permessi della directory o in una porta già occupata. Se il browser mostra una pagina bianca o i terminali non si aprono, il sospetto cade quasi sempre sul reverse proxy e sul supporto WebSocket.

Un controllo utile è il journal del servizio e, se c’è un proxy, il relativo access log ed error log. In assenza di questi due livelli di osservabilità stai andando a tentativi. Meglio leggere il messaggio preciso che cambiare tre variabili insieme.

Una procedura compatta da riusare

Se vuoi una sequenza breve ma affidabile, questa è quella che uso più spesso: aggiorna pacchetti, crea il venv, installa JupyterLab, avvia in localhost, verifica con curl, poi decidi se aggiungere systemd o un proxy. Così separi il problema di installazione dal problema di esposizione rete.

sudo apt update
sudo apt install -y python3 python3-venv python3-pip
mkdir -p ~/apps/jupyterlab
cd ~/apps/jupyterlab
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel
python -m pip install jupyterlab
jupyter lab --ip=127.0.0.1 --port=8888 --no-browser

Se questa sequenza funziona in locale, hai già validato la parte software. Tutto il resto — servizio, proxy, TLS, accesso remoto — è solo strato di esposizione e va aggiunto dopo, con modifiche reversibili e testate una alla volta.

In sintesi operativa: su Ubuntu 22.04 JupyterLab si installa bene, ma il punto non è “farlo partire”; il punto è farlo partire nel posto giusto, con dipendenze isolate, con un binding sicuro e con un percorso di accesso che non trasformi una macchina di lavoro in un servizio esposto senza controllo.