Deploy a production-ready Jupyter notebook server with JupyterLab on Ubuntu 22.04. Complete with systemd service management, secure token authentication, and browser access over the public network.
This guide exists as a tested, machine-readable recipe in the Massed Compute MCP. Connect the agent, say “Deploy a Jupyter server on Ubuntu”, and it will provision the right VM, run these exact steps, and report back with your server URL and token.
Jupyter notebooks are essential for data science, research, and interactive Python development. This guide shows you how to deploy a secure, production-ready JupyterLab server on Ubuntu 22.04 with systemd service management and token-based authentication accessible from any browser.
| Component | Version | Purpose |
|---|---|---|
| Ubuntu | 22.04 LTS | Base operating system |
| Python | 3.10+ | Runtime for Jupyter |
| pipx | Latest | Isolated Python package installation |
| JupyterLab | Latest | Web-based notebook interface |
| systemd | Built-in | Service management and auto-restart |
| Resource | Minimum | Recommended |
|---|---|---|
| vCPUs | 2 | 4+ |
| RAM | 4 GB | 8 GB+ |
| Storage | 10 GB | 50 GB+ |
| OS | Ubuntu 22.04 | Ubuntu 22.04 |
Massed Compute VM Pricing
Step-by-Step Deployment
Launch Your VM
Create a new instance with at least 2 vCPUs and 4GB RAM. Attach your SSH key during launch to ensure secure access.
Connect to Your VM
SSH into your instance using the IP address from your dashboard:
ssh username@YOUR_VM_IP
Wait for the VM status to show “Running” before attempting to connect. This typically takes 1-3 minutes for CPU instances.
Install pipx and JupyterLab
Update the system and install pipx for isolated Python package management:
sudo apt-get update
sudo apt-get install -y pipx
pipx ensurepath
Install JupyterLab with dependencies:
# --include-deps exposes the jupyter wrapper script
pipx install jupyterlab --include-deps
Configure Jupyter Path
Open a fresh shell or source your bashrc to make jupyter available:
source ~/.bashrc
Generate Config and Token
Create the Jupyter configuration and generate a secure access token:
jupyter lab --generate-config
TOKEN=$(openssl rand -hex 24)
echo "Your Jupyter token: $TOKEN"
Save this token – you’ll need it to access your Jupyter server from the browser.
Configure Server Settings
Add server configuration to allow external access. Replace YOUR_TOKEN with the token from step 5:
cat <<EOF >> ~/.jupyter/jupyter_lab_config.py
c.ServerApp.ip = "0.0.0.0"
c.ServerApp.port = 8888
c.ServerApp.open_browser = False
c.ServerApp.token = "YOUR_TOKEN"
c.ServerApp.allow_root = False
EOF
Create systemd Service
Set up Jupyter as a system service for automatic startup and management. Replace USERNAME with your actual username:
sudo tee /etc/systemd/system/jupyter.service > /dev/null <<EOF
[Unit]
Description=JupyterLab
After=network.target
[Service]
Type=simple
User=USERNAME
ExecStart=/home/USERNAME/.local/bin/jupyter lab --config /home/USERNAME/.jupyter/jupyter_lab_config.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
Start Jupyter Service
Enable and start the Jupyter service:
sudo systemctl daemon-reload
sudo systemctl enable --now jupyter
Check the service status:
sudo systemctl status jupyter
Verify Installation
Confirm Jupyter is running and accessible:
# Check service is active
sudo systemctl is-active jupyter
# Verify port 8888 is listening
sudo ss -ltnp | grep 8888
Test external access from your local machine:
curl -sS -o /dev/null -w "%{http_code}\n" http://YOUR_VM_IP:8888/lab
You should see a 200 or 302 response code.
Access Your Jupyter Server
Open your browser and navigate to:
http://YOUR_VM_IP:8888/?token=YOUR_TOKEN
Or visit http://YOUR_VM_IP:8888/ and enter your token at the password prompt.
Troubleshooting
pipx Not Found
If pipx isn’t available in the apt repository, fall back to pip:
pip install --user jupyterlab
Update the systemd ExecStart path to use ~/.local/bin/jupyter instead.
Service Fails to Start
Check the service logs for detailed error information:
sudo journalctl -u jupyter -n 50
Common issues include wrong config file paths or incorrect user settings in the service file.
Token Authentication Issues
If the browser rejects your token, regenerate both the config and token together:
TOKEN=$(openssl rand -hex 24)
echo "c.ServerApp.token = \"$TOKEN\"" >> ~/.jupyter/jupyter_lab_config.py
sudo systemctl restart jupyter
Port 8888 Blocked
Massed Compute instances may filter inbound ports by default. Check your instance settings to open port 8888 for external access.
Skip All of This: Deploy with an AI Agent
This entire guide exists as a tested, machine-readable recipe in the Massed Compute MCP (tested June 2, 2026). Connect an MCP-compatible AI agent with this config:
{
"mcpServers": {
"massed-compute": {
"type": "http",
"url": "https://vm.massedcompute.com/api/mcp",
"headers": { "Authorization": "Bearer MC_TOKEN" }
}
}
}
Then say:
The agent will match your request against the recipe catalog, provision a VM with the right specs, run the setup and verification steps above, and report back with your server URL and access token. If any step fails, it stops immediately and shows you the exact error.
Quick Setup Reference
For experienced users, here’s the condensed command sequence:
# Install and configure
sudo apt-get update && sudo apt-get install -y pipx
pipx ensurepath && source ~/.bashrc
pipx install jupyterlab --include-deps
jupyter lab --generate-config
TOKEN=$(openssl rand -hex 24)
# Configure server
cat <<EOF >> ~/.jupyter/jupyter_lab_config.py
c.ServerApp.ip = "0.0.0.0"
c.ServerApp.port = 8888
c.ServerApp.open_browser = False
c.ServerApp.token = "$TOKEN"
c.ServerApp.allow_root = False
EOF
# Create and start service
sudo tee /etc/systemd/system/jupyter.service > /dev/null <<EOF
[Unit]
Description=JupyterLab
After=network.target
[Service]
Type=simple
User=$USER
ExecStart=$HOME/.local/bin/jupyter lab --config $HOME/.jupyter/jupyter_lab_config.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now jupyter
echo "Access: http://$(curl -s ifconfig.me):8888/?token=$TOKEN"
Frequently Asked Questions
01Can I use a custom domain instead of IP:8888?
Yes, set up a reverse proxy with nginx or Apache to serve Jupyter through a custom domain. Configure SSL termination and update the Jupyter config to trust the proxy headers.
02How do I install additional Python packages?
Since Jupyter runs in a pipx environment, use pipx inject jupyterlab package-name to add packages to the same isolated environment, or install them from within a notebook using !pip install package-name.
03What if I need GPU acceleration for machine learning?
Launch your VM with a GPU SKU and install CUDA drivers, then add GPU-enabled packages like tensorflow-gpu or torch to your Jupyter environment. The notebook interface will automatically detect available GPUs.
04How do I backup my notebooks and data?
Jupyter stores notebooks in the user’s home directory. Set up automated backups to object storage or use git integration to version control your notebook files. Consider mounting external storage for large datasets.
05Can multiple users share the same Jupyter server?
This setup creates a single-user server. For multi-user environments, consider JupyterHub which provides user authentication and isolated notebook environments. You can deploy JupyterHub using a similar systemd approach.











