October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
VGSources
Blog

How to Set Up a Secure JupyterLab Environment on an Ubuntu VPS

A practical guide to installing JupyterLab on an Ubuntu VPS, keeping it isolated and authenticated, connecting privately over SSH, and publishing it safely behind HTTPS when needed.
Length10 min Posted Quest giverVGSources Team
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install JupyterLab in a dedicated Python virtual environment, run it as a non-root user, and keep its default listener on 127.0.0.1:8888. For private administration, connect through an SSH tunnel. If other people must reach it over the internet, put Jupyter Server behind an HTTPS reverse proxy, keep authentication enabled, and restrict the firewall. The procedure below covers installation, first login, persistent service management, public exposure, upgrades, and the failures most often encountered on an Ubuntu VPS.

What you are building

This guide creates a single-user JupyterLab server on an Ubuntu virtual private server. The notebook service runs under a normal account, inside an isolated Python environment, and stores notebooks in that account’s home directory or another directory you explicitly choose. JupyterLab is free software; your VPS provider, storage, bandwidth, and any attached services are separate costs.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

There are two access designs:

  • Private administration: Jupyter listens only on loopback and your laptop reaches it through an SSH tunnel. This is the safest and simplest arrangement for one operator.
  • Public web access: Jupyter remains on loopback while an HTTPS reverse proxy accepts connections on the public web port. This requires a domain or reachable address, a TLS certificate, authentication, proxy WebSocket support, and carefully scoped firewall rules.

Jupyter Server’s default behavior is local binding at 127.0.0.1:8888. A browser on your laptop cannot connect to that address on the VPS directly; the tunnel or proxy is the component that carries the connection.

Prepare the Ubuntu VPS

Create a dedicated, non-root account

Log in over SSH with an administrative account, then create a normal user for notebooks and services. Replace jupyter with the account name you want to use.

sudo adduser jupyter
sudo usermod -aG sudo jupyter

Using a separate account limits the damage a notebook can do compared with running kernels as root. If the account does not need administrative privileges after setup, remove it from the sudo group and perform maintenance through a separate administrator account.

Apply updates and verify SSH first

sudo apt update
sudo apt upgrade

Open a second terminal and confirm that you can sign in as the new account before changing any firewall or SSH settings. Keep an existing administrative session open while testing so a mistake does not lock you out.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose a data directory

The account’s home directory is adequate for a small installation. For larger notebooks or datasets, create a dedicated mount point and grant ownership to the service account:

sudo mkdir -p /srv/jupyter
sudo chown -R jupyter:jupyter /srv/jupyter

Plan backups for this directory. A virtual machine snapshot is not a substitute for an independent backup, and notebooks may contain credentials, personal data, or proprietary code.

Install JupyterLab in an isolated Python environment

Use Ubuntu’s packaged Python, virtual-environment support, and pip. Do not install the application into the system interpreter, where OS packages and your project dependencies can conflict.

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

Switch to the notebook account and create a virtual environment:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo -iu jupyter
python3 -m venv ~/venvs/jupyterlab
source ~/venvs/jupyterlab/bin/activate
python -m pip install --upgrade pip
python -m pip install jupyterlab

The source command affects only the current shell. Every manual start and every service definition must use the environment’s executable, or explicitly activate it first. Using an absolute path such as /home/jupyter/venvs/jupyterlab/bin/jupyter is more reliable for automation.

Alternative installation methods

Option Best fit Trade-offs to evaluate
venv plus pip Small, single-user VPS Lightweight and familiar; you are responsible for dependency upgrades and resolving conflicts.
conda or mamba Data-science stacks with compiled dependencies Convenient environment management, but a larger disk footprint and another package ecosystem.
uv Teams adopting modern Python tooling Fast environment and package operations; confirm that your team and operational policies support it.
Docker Reproducible, image-based deployments Adds container operations, image updates, and persistent-volume planning. When using Jupyter’s Docker image, set JUPYTER_ENABLE_LAB=yes.
JupyterHub Several users needing separate accounts More components and administration, but it is the official multi-user architecture rather than a shared single-user server.

Compare an option’s dependency isolation, reproducibility, upgrade path, memory and disk requirements, backup design, and number of users—not just the initial install command.

Start JupyterLab and verify it locally

From the activated environment, start the server without trying to open a browser on the VPS:

jupyter lab --no-browser

The terminal prints a URL containing an authentication token, usually on the local endpoint. Leave this process running while you test it. In another shell, you can list running servers and their URLs:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
jupyter server list

At this stage, Jupyter should listen on 127.0.0.1:8888, not on every network interface. That loopback binding is intentional: it prevents an internet client from reaching the notebook service before you have selected and secured an access method.

Access it privately through an SSH tunnel

For one administrator, an SSH tunnel avoids opening a Jupyter port in the VPS firewall. Keep Jupyter bound to loopback, then run this command on your laptop:

ssh -N -L 8888:127.0.0.1:8888 jupyter@VPS_IP

The first 8888 is the laptop’s local port. The address and second port identify the service as seen from the VPS. If local port 8888 is already occupied, use another local port:

ssh -N -L 8899:127.0.0.1:8888 jupyter@VPS_IP

Now open http://127.0.0.1:8888 (or port 8899 in the second example) on the laptop and paste the token printed by Jupyter. Keep the SSH process running; closing it closes the forwarding path. You can add SSH keepalive settings in your client configuration if an idle connection is routinely dropped.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep authentication enabled

The launch token is an effective first login method. Do not disable both token and password unless another, fully managed authentication layer replaces them. Anyone who obtains an unauthenticated notebook endpoint can execute code as the service account.

Set a password

With the virtual environment active, run:

jupyter server password

Jupyter prompts for the password and stores a hash in jupyter_server_config.json; it does not need to keep the clear-text password in that file. Use a long, unique password and protect the configuration and home directory with normal Unix permissions.

After setting a password, a login page can accept it instead of the one-time URL token. Keep the token mechanism available during initial setup and recovery unless you have deliberately configured another authentication provider.

Make public access safe enough for production

Public access is a different deployment from an SSH tunnel. Do not simply bind Jupyter to 0.0.0.0 and rely on obscurity. Use a fixed internal port, authentication, TLS, and a reverse proxy that forwards WebSocket traffic.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configure Jupyter for a proxy

Set the server to avoid launching a local browser and to use a known port. A configuration file lets you keep these choices consistent across restarts. Generate one if needed:

jupyter server --generate-config

Edit the resulting Jupyter Server configuration and set the equivalent of:

c.ServerApp.ip = '127.0.0.1'
c.ServerApp.port = 8888
c.ServerApp.open_browser = False

Keep the loopback address when the reverse proxy runs on the same VPS. If you intentionally expose Jupyter directly, use a narrowly scoped firewall rule and still require authentication and HTTPS; a proxy is generally easier to harden and to renew certificates for.

Terminate TLS at the reverse proxy

Point your DNS name at the VPS, obtain a certificate from a trusted certificate authority, and configure an HTTPS reverse proxy such as Nginx or Caddy. The proxy should:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Listen publicly on TCP 443 and redirect plain HTTP to HTTPS.
  • Forward normal HTTP requests to 127.0.0.1:8888.
  • Forward the Upgrade and Connection headers required for WebSockets.
  • Preserve the Jupyter authentication layer rather than replacing it with an accidental unauthenticated route.
  • Apply sensible request-size, timeout, and access-log policies for your workload.

Jupyter kernels use WebSockets for interactive communication. A page may load while terminals and notebooks fail if the proxy omits WebSocket forwarding or applies an overly restrictive content-security policy.

Use HTTPS with password authentication

When a password is accepted on a public endpoint, TLS is mandatory so the credential is encrypted in transit. Jupyter’s public-server guidance also supports supplying certificate and key files directly, but a reverse proxy commonly centralizes certificate renewal and public firewall policy. Never send a password over an unencrypted public HTTP connection.

Run JupyterLab reliably with systemd

A shell process ends when its SSH session ends and will not automatically recover from a crash. A systemd unit runs the virtual-environment executable as the dedicated account, sets the notebook directory, disables browser launching, and restarts after failure.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Create /etc/systemd/system/jupyter.service as an administrator:

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

[Service]
Type=simple
User=jupyter
Group=jupyter
WorkingDirectory=/srv/jupyter
ExecStart=/home/jupyter/venvs/jupyterlab/bin/jupyter lab --no-browser --ip=127.0.0.1 --port=8888
Restart=on-failure
RestartSec=5
# Add environment-specific limits deliberately; do not copy arbitrary values.

[Install]
WantedBy=multi-user.target

Adapt the paths, account, port, and working directory. The Jupyter documentation does not prescribe a canonical systemd unit, so treat this as deployment glue and review it against your VPS’s resource limits and security policy.

Enable and start it:

sudo systemctl daemon-reload
sudo systemctl enable --now jupyter.service
sudo systemctl status jupyter.service
sudo journalctl -u jupyter.service -f

Keep passwords and other secrets in protected Jupyter configuration or an approved secret-management method. Do not put credentials directly in a world-readable unit file or shell history. If you change the environment or configuration, restart the service and inspect the journal for the actual executable path and bind address.

Configure the VPS firewall

At minimum, allow SSH from the addresses and ports you actually use. For a reverse-proxy deployment, allow HTTPS on TCP 443 and normally leave Jupyter’s 8888 port closed to the internet. If you expose Jupyter directly, allow its configured port only from trusted source addresses—not from the entire internet.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Jupyter’s local kernel communication may use randomly selected ports in the range 49152–65535. Do not broadly open that range. Keeping the server and kernels on loopback behind the proxy avoids exposing those internal channels. Verify both the VPS firewall and any provider-level security group; either layer can block a correctly configured service.

When to choose JupyterHub instead

A single-user remote server is appropriate when one operator owns the notebooks and the VPS. It is not the multi-user solution. Choose JupyterHub when several people need independent authenticated sessions, separate home directories, per-user permissions, or centrally managed spawning and resource limits. JupyterHub adds administration and components, so do not introduce it merely to serve one account.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Upgrade and backup routine

Upgrade the isolated environment

Schedule maintenance rather than upgrading a running production kernel unexpectedly:

sudo -iu jupyter
source ~/venvs/jupyterlab/bin/activate
python -m pip install --upgrade jupyterlab jupyter-server
python -m pip check
exit
sudo systemctl restart jupyter.service

Test a representative notebook after upgrades. For reproducibility, record the environment after a known-good change:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo -iu jupyter
source ~/venvs/jupyterlab/bin/activate
python -m pip freeze > ~/requirements-lock.txt

Review that file before restoring it on another machine; a freeze captures versions, but it does not replace a tested backup and does not include external services or system packages.

Back up notebooks and configuration

Back up the notebook directory, Jupyter configuration, environment requirements, and any reverse-proxy configuration. Encrypt backups when notebooks contain secrets or personal data. Test restoration on a separate directory or VPS; a backup that has never been restored is only an assumption.

Troubleshooting checklist

jupyter: command not found

Activate the virtual environment, or call its executable with the full path. If you used a user-level pip install instead, the executable may be under $HOME/.local/bin; add that directory to the account’s PATH or use the environment-based installation described above.

The browser cannot connect remotely

Check the service log and confirm whether it is intentionally listening on 127.0.0.1. That address is local to the VPS, not your laptop. Use the SSH tunnel for private access or verify that the reverse proxy forwards to the correct loopback port. Do not “fix” the symptom by exposing every interface before securing authentication and TLS.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The login page loops or rejects a known password

Obtain the current URL and token with jupyter server list. If the password is the problem, run jupyter server password again as the same account that owns the service, then restart it. Confirm that the systemd unit is using the same home directory and configuration location as your manual shell.

HTTPS loads, but terminals or kernels do not work

Inspect the reverse-proxy error log and verify WebSocket upgrade forwarding. Check for a restrictive content-security policy or a proxy timeout that closes idle kernel connections. The browser may render the initial HTML even when the WebSocket channel is broken.

A kernel starts and then dies

Read journalctl -u jupyter.service and the Jupyter log. Confirm that the selected kernel has the packages your notebook imports and that the kernel points to the intended virtual environment. Check available RAM, swap, disk space, and any provider or systemd resource limits; a notebook can be killed even when the Jupyter web process remains healthy.

The service works manually but not under systemd

Compare the manual command with ExecStart, including the executable path, user, working directory, port, and configuration search path. Systemd does not load your interactive shell profile, so aliases, activated environments, and user-level PATH changes are not automatically present.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Security checks before you share the URL

  • Jupyter runs as a non-root account.
  • The service uses the intended virtual environment and notebook directory.
  • Authentication remains enabled; neither token nor password was disabled accidentally.
  • Public credentials are protected by HTTPS.
  • The firewall exposes only SSH and the required HTTPS port, or restricts a direct Jupyter port to trusted addresses.
  • Reverse-proxy WebSockets work in a real terminal and notebook session.
  • Notebook and configuration backups are encrypted where appropriate and have been tested.
  • Logs, disk usage, memory, and certificate expiry are monitored.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More quests from Patch Notes

  1. How to Set Up a RedM (RDR2) Server in 2026: License Key, txAdmin and server.cfg, Step by StepBlog11min
  2. Best RedM (RDR2) Server Hosting in 2026: Comparing Four Hosts on Slots, Memory and PriceBlog10min
  3. How to Host a Mindustry Server in 2026: server-release.jar, Port 6567 and the Commands That MatterBlog7min
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.