JupyterLab es el entorno web de Jupyter para trabajar con notebooks, terminales y archivos desde el navegador, muy usado en ciencia de datos y machine learning. Ejecutarlo en un servidor remoto te permite aprovechar su CPU, su memoria o su GPU desde cualquier equipo. En este tutorial instalarás JupyterLab en Ubuntu 24.04 dentro de un entorno virtual, lo protegerás con contraseña, lo ejecutarás como servicio de systemd y lo publicarás con Nginx y un certificado de Let's Encrypt.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con un usuario no root con privilegios
sudo. En esta guía el usuario se llamayour_user. - Un dominio o subdominio con un registro DNS A apuntando a la IP del servidor. Los ejemplos usan
jupyter.your_domain. - UFW activo con el acceso SSH permitido.
AdvertenciaJupyterLab permite ejecutar código y abrir una terminal con los permisos del usuario que lo ejecuta. Quien obtenga acceso a la interfaz tiene, en la práctica, una shell en tu servidor. Usa una contraseña robusta y no lo ejecutes nunca como root.
Paso 1: Instalar JupyterLab en un entorno virtual
Ubuntu 24.04 no permite instalar paquetes con pip en el Python del sistema (PEP 668), y además es buena práctica aislar Jupyter en su propio entorno. Instala las herramientas para crear entornos virtuales:
sudo apt update
sudo apt install python3-venv python3-pip
Crea el entorno en tu directorio personal e instala JupyterLab:
python3 -m venv ~/jupyter/venv
~/jupyter/venv/bin/pip install --upgrade pip
~/jupyter/venv/bin/pip install jupyterlab
Comprueba la versión instalada:
~/jupyter/venv/bin/jupyter lab --version
4.4.9
Crea también el directorio donde guardarás los notebooks:
mkdir -p ~/notebooks
Paso 2: Configurar la contraseña y el servidor
Por defecto Jupyter genera un token aleatorio en cada arranque. Para un servidor permanente es más práctico usar una contraseña. El siguiente comando la pide dos veces y guarda su hash en ~/.jupyter/jupyter_server_config.json:
~/jupyter/venv/bin/jupyter server password
Enter password:
Verify password:
[JupyterPasswordApp] Wrote hashed password to /home/your_user/.jupyter/jupyter_server_config.json
Genera el archivo de configuración del servidor:
~/jupyter/venv/bin/jupyter server --generate-config
El comando crea ~/.jupyter/jupyter_server_config.py con todas las opciones comentadas. Ábrelo:
nano ~/.jupyter/jupyter_server_config.py
Añade al final estas líneas, sustituyendo your_user:
c.ServerApp.ip = "127.0.0.1"
c.ServerApp.port = 8888
c.ServerApp.open_browser = False
c.ServerApp.root_dir = "/home/your_user/notebooks"
c.ServerApp.trust_xheaders = True
Qué hace cada opción:
ip = "127.0.0.1": Jupyter solo escucha en local. El acceso desde fuera llegará siempre a través de Nginx, con HTTPS.root_dir: el directorio que se muestra en el explorador de archivos de JupyterLab.trust_xheaders: hace que Jupyter use las cabecerasX-Forwarded-*de Nginx para conocer la IP real del cliente y el esquemahttps.
Prueba el servidor en primer plano:
~/jupyter/venv/bin/jupyter lab
[I 2026-09-25 11:20:04.311 ServerApp] Jupyter Server 2.17.0 is running at:
[I 2026-09-25 11:20:04.311 ServerApp] http://127.0.0.1:8888/lab
Si ves esas líneas, detén el servidor con Ctrl+C y confirma con y.
Paso 3: Ejecutar JupyterLab como servicio de systemd
Un servicio de systemd arranca Jupyter con el sistema, lo reinicia si falla y centraliza sus logs en el journal. Crea la unidad:
sudo nano /etc/systemd/system/jupyter.service
[Unit]
Description=JupyterLab
After=network.target
[Service]
Type=simple
User=your_user
Group=your_user
WorkingDirectory=/home/your_user/notebooks
ExecStart=/home/your_user/jupyter/venv/bin/jupyter lab
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Al definir User=, systemd establece HOME=/home/your_user, así que Jupyter lee la configuración de ~/.jupyter sin más ajustes. Activa e inicia el servicio:
sudo systemctl daemon-reload
sudo systemctl enable --now jupyter
systemctl status jupyter --no-pager
● jupyter.service - JupyterLab
Loaded: loaded (/etc/systemd/system/jupyter.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-09-25 11:23:40 UTC; 4s ago
Comprueba que responde en local:
curl -sI http://127.0.0.1:8888/lab | head -n 1
HTTP/1.1 302 Found
La redirección 302 hacia la página de login es la respuesta esperada. Para ver los logs, usa sudo journalctl -u jupyter -f.
Paso 4: Configurar Nginx como proxy inverso
Nginx recibirá las conexiones HTTPS y las reenviará a Jupyter. JupyterLab usa WebSockets para comunicarse con los kernels, así que el proxy debe reenviar las cabeceras Upgrade y Connection.
Instala Nginx y abre los puertos HTTP y HTTPS en el firewall:
sudo apt install nginx
sudo ufw allow 'Nginx Full'
Crea el archivo del sitio:
sudo nano /etc/nginx/sites-available/jupyter
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name jupyter.your_domain;
client_max_body_size 100M;
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 $connection_upgrade;
proxy_read_timeout 1d;
}
}
El bloque map envía Connection: upgrade solo cuando el cliente pide un WebSocket. proxy_read_timeout 1d evita que Nginx corte las conexiones de kernels que están un rato sin tráfico, y client_max_body_size permite subir archivos de hasta 100 MB desde el navegador.
Activa el sitio, comprueba la sintaxis y recarga Nginx:
sudo ln -s /etc/nginx/sites-available/jupyter /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Paso 5: Activar HTTPS con Let's Encrypt
Instala Certbot con su plugin de Nginx y solicita el certificado. Certbot añade la configuración TLS al bloque server y una redirección de HTTP a HTTPS:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d jupyter.your_domain --redirect
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/jupyter.your_domain/fullchain.pem
...
Successfully deployed certificate for jupyter.your_domain to /etc/nginx/sites-enabled/jupyter
Congratulations! You have successfully enabled HTTPS on https://jupyter.your_domain
El paquete de Ubuntu instala un timer de systemd que renueva el certificado automáticamente. Comprueba que la renovación funcionará:
sudo certbot renew --dry-run
Abre https://jupyter.your_domain en el navegador. Verás la pantalla de login de Jupyter; introduce la contraseña del paso 2. Crea un notebook con el kernel Python 3 y ejecuta una celda como import sys; sys.version para comprobar que el kernel responde a través del proxy.
Paso 6: Añadir kernels de otros entornos virtuales
El kernel por defecto usa el entorno virtual de Jupyter. Para trabajar con proyectos que tienen sus propias dependencias, crea un entorno por proyecto y regístralo como kernel, sin instalar Jupyter en él. Solo necesita ipykernel:
python3 -m venv ~/venvs/analisis
~/venvs/analisis/bin/pip install ipykernel pandas matplotlib
~/venvs/analisis/bin/python -m ipykernel install --user --name analisis --display-name "Python (analisis)"
Lista los kernels disponibles:
~/jupyter/venv/bin/jupyter kernelspec list
Available kernels:
analisis /home/your_user/.local/share/jupyter/kernels/analisis
python3 /home/your_user/jupyter/venv/share/jupyter/kernels/python3
Recarga JupyterLab en el navegador y el nuevo kernel aparecerá en el lanzador. Para eliminar un kernel que ya no usas, ejecuta ~/jupyter/venv/bin/jupyter kernelspec remove analisis.
Para instalar paquetes desde un notebook, usa %pip install nombre_paquete en una celda: instala en el entorno del kernel activo, no en el de Jupyter.
Alternativa: acceso solo por túnel SSH
Si eres el único usuario y no quieres exponer Jupyter en internet, puedes saltarte los pasos 4 y 5. Como Jupyter escucha en 127.0.0.1, crea un túnel SSH desde tu equipo local:
ssh -N -L 8888:127.0.0.1:8888 your_user@your_server_ip
Mientras el comando esté en ejecución, abre http://localhost:8888 en tu navegador local. El tráfico viaja cifrado dentro de la conexión SSH.
Solución de problemas
El servicio no arranca. Revisa sudo journalctl -u jupyter -n 50 --no-pager. Los errores habituales son una ruta incorrecta en ExecStart, un User= que no coincide con el propietario de ~/jupyter, o que root_dir apunta a un directorio que no existe.
502 Bad Gateway en el navegador. Nginx no puede conectar con Jupyter. Comprueba que el servicio está activo y que curl -I http://127.0.0.1:8888/lab responde en el servidor.
La página carga pero el kernel se queda en "Connecting" o "Disconnected". Los WebSockets no pasan por el proxy. Verifica que la configuración de Nginx incluye proxy_http_version 1.1 y las cabeceras Upgrade y Connection, y revisa /var/log/nginx/error.log.
Blocking Cross Origin API request o errores 403 al abrir notebooks. La cabecera Host no llega a Jupyter. Asegúrate de que el bloque location contiene proxy_set_header Host $host;.
Olvidaste la contraseña. Ejecuta de nuevo ~/jupyter/venv/bin/jupyter server password y reinicia el servicio con sudo systemctl restart jupyter.
Conclusión
JupyterLab está funcionando como servicio en tu servidor Ubuntu 24.04, protegido con contraseña, accesible por HTTPS a través de Nginx y con kernels separados por proyecto. Como siguientes pasos, puedes instalar los drivers de NVIDIA y PyTorch en un kernel dedicado para usar la GPU desde los notebooks, añadir la extensión jupyterlab-git para versionar tu trabajo, o pasar a JupyterHub si varias personas necesitan su propio entorno en el mismo servidor.
