Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
FREEDOM251

Freedom251 › Blog › Jupyter

How to Run Jupyter Notebook on a VPS and Connect via an SSH Tunnel

By Freedom251 Team · · 10 min read

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

Run JupyterLab on the VPS loopback address, then forward that private port to your computer with OpenSSH. The complete pattern is:

jupyter lab --no-browser --ip=127.0.0.1 --port=8888
ssh -N -L 8888:127.0.0.1:8888 USER@VPS_HOST

Keep the Jupyter process and the SSH tunnel running, open the forwarded address in your local browser, and enter the token printed by Jupyter. Nothing requires port 8888 to be exposed to the public internet.

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.

What this setup does

A VPS gives you a remote Linux machine with its own CPU, memory, storage and network connection. Jupyter runs there, so notebooks use the VPS environment and continue to access files and data stored on that machine. Your browser remains on your laptop or desktop.

The secure arrangement has two separate connections:

  • Jupyter listens on 127.0.0.1 on the VPS. That loopback address is reachable from the VPS itself, not directly from the internet.
  • SSH creates a local listening port on your computer and carries its traffic through the encrypted SSH connection to the VPS loopback port.

This is an SSH-only, single-user pattern. It avoids a public firewall rule for the notebook port, but it does not replace Jupyter authentication. The token or password still protects the web application after the tunnel is established.

Requirements and decisions before you begin

VPS and account

Use a Linux VPS that you can reach with SSH. Record its public hostname or IP address, the SSH username, and the SSH key or other credential required by your provider. Work as a normal, dedicated user with only the permissions needed for the project. Avoid running Jupyter as root unless a deployment specifically requires it.

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

Local computer

Your local computer needs an SSH client and a web browser. OpenSSH is available by default on most Linux and macOS systems and can be installed or enabled on current Windows systems. The local computer does not need Python or Jupyter for this tunnel method.

Port choices

Port 8888 is a common example and Jupyter’s usual default, not a requirement. You need one free port on the VPS and one free port on your computer. They may be different: the first number in the SSH -L expression is local, while the last number is the remote Jupyter port.

Choose the operating model

Decide whether this is an interactive session that you start and stop manually or a longer-lived service. Manual operation is easiest for one person and occasional work. A persistent service needs a service manager, restart policy, logging and a plan for updates; those are operational choices beyond the basic tunnel.

Log in and prepare the VPS

  1. From your local terminal, connect with the credentials supplied for the VPS:
    ssh USER@VPS_HOST

    Replace USER and VPS_HOST with your actual account and hostname or address. If your SSH key uses a non-default filename, add the appropriate identity option.

  2. Confirm that you are using the intended non-root account. Keep project files and the Python environment owned by that account.
  3. Update the project directory and select the Python environment you intend to use. A separate environment prevents notebook packages from changing the operating system’s Python installation.

If you already have a project environment, activate it before installing JupyterLab. If not, create one using the environment manager your project supports. The important requirement is that the environment containing JupyterLab is active when you launch the server.

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.

Install JupyterLab in the project environment

Project Jupyter documents three common installation routes: conda, mamba and pip. Pick one; do not install the same application into several environments unless you have a specific reason.

Route Typical command When it fits
conda
conda install -c conda-forge jupyterlab
Projects already managed with conda environments and packages.
mamba
mamba install -c conda-forge jupyterlab
Conda-compatible environments where you prefer mamba’s package solver.
pip
python -m pip install jupyterlab
A standard Python virtual environment or a project that uses pip requirements.

After installation, verify that the command resolves inside the active environment:

which jupyter
jupyter lab --version

The first command should point to the environment you selected. If it points to a system location, activate the environment again or invoke Jupyter through that environment’s Python installation.

Start Jupyter privately on the VPS

Launch Jupyter without attempting to open a browser on the headless VPS:

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.
jupyter lab --no-browser --ip=127.0.0.1 --port=8888

--no-browser prevents a graphical browser launch. --ip=127.0.0.1 binds the server to the VPS loopback interface. --port=8888 selects the remote listening port; replace it if another process already uses 8888.

Jupyter prints a URL containing an authentication token in the VPS terminal. Leave this terminal session running. Copy the complete URL somewhere private, or copy only the token and use the local URL after creating the tunnel.

If port 8888 is occupied

The startup output will identify the port Jupyter actually uses or report that the requested port is unavailable. You can stop the conflicting process and restart on 8888, or choose another explicit remote port:

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

Whatever remote port you choose must be the final number in the SSH forwarding command. Do not assume that changing the local browser port changes the port on the VPS.

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

Authentication is still required

Jupyter Server generates a token by default. Keep token or password authentication enabled. Configuring an empty token disables authentication altogether and is explicitly not recommended. A private SSH tunnel limits network exposure, but anyone who gains access to your local browser session or the forwarded port could still reach the web application, so retain Jupyter’s own authentication.

Create the SSH tunnel from your computer

Open a second local terminal; do not run this command in the VPS terminal where Jupyter is running. For a VPS Jupyter process on port 8888, use:

ssh -N -L 8888:127.0.0.1:8888 USER@VPS_HOST

OpenSSH’s -L option creates local forwarding. In local_port:destination_host:remote_port, the first port is opened on your computer, the destination host is evaluated from the VPS side of the connection, and the final port is the Jupyter listener on the VPS. 127.0.0.1 as the destination deliberately targets the VPS loopback interface. -N tells SSH not to start a remote shell; this terminal is used only to carry the tunnel.

Use a different local port

If another local application already listens on 8888, keep Jupyter on the VPS at 8888 and select a free local port, such as 8890:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
ssh -N -L 8890:127.0.0.1:8888 USER@VPS_HOST

In that case, browse to http://127.0.0.1:8890. The local and remote numbers do not need to match.

Use a different remote port

If Jupyter is listening on 8899 on the VPS and local 8888 is free, forward it with:

ssh -N -L 8888:127.0.0.1:8899 USER@VPS_HOST

Use the local address http://127.0.0.1:8888 in your browser. If both sides differ, make both changes explicit so that you can diagnose each end independently.

Keep the listener local

Use an explicit localhost address in the forwarding expression. Binding the local listener to localhost keeps the forwarded port for local use only instead of advertising it on other network interfaces. The browser address should likewise remain 127.0.0.1, not the VPS’s public hostname.

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

Open Jupyter and work normally

  1. Leave the tunnel terminal running. Closing it closes the forwarding connection.
  2. Open the matching local URL in your browser: http://127.0.0.1:8888 for the first command, or the alternate local port you selected.
  3. Paste the token from the VPS Jupyter output when prompted. If you copied the full token-bearing URL, you can open that URL through the local forwarded address after checking that its port matches your local listener.
  4. Use JupyterLab as usual. Kernels, files and installed libraries are on the VPS, not on the local computer.

The browser-to-localhost leg and the SSH connection must both remain available. A browser refresh cannot repair a stopped Jupyter process or a closed SSH tunnel.

Stop the session cleanly

  1. Save notebooks and stop active kernels from JupyterLab.
  2. In the local tunnel terminal, press Ctrl-C. This closes the SSH forwarding process.
  3. In the VPS terminal running Jupyter, press Ctrl-C and confirm the shutdown if Jupyter asks. This stops the server process.

If you need the server to survive a disconnected shell, configure an intentional service-manager or session-management solution and document its restart, logging and authentication settings. A manually launched process should not be assumed to persist after its controlling session ends.

Security controls that matter

Keep Jupyter on loopback for SSH-only access

Binding to 127.0.0.1 means the notebook port is not directly reachable through the VPS’s public interfaces. Binding to 0.0.0.0 or a public address changes the exposure model: the port may become reachable from networks allowed by routing and firewall rules. Use that only when you deliberately configure firewall policy, authentication and encrypted web access.

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

Protect the token and any password

Do not paste a live token into a public issue tracker, shell transcript, screenshot or shared chat. Treat it like a credential. If you believe it has leaked, stop the server and restart it so a new token is generated, or set a deliberate password-based configuration according to Jupyter’s documentation.

Use least privilege

Run the server as the dedicated project user, keep file permissions appropriate to that user, and avoid granting notebook code unnecessary operating-system privileges. A notebook can execute arbitrary Python and shell commands available to its account, so the account boundary is meaningful.

If you publish Jupyter directly

A public deployment is a different architecture, not a minor variation of this tunnel. Use HTTPS and authentication when publishing a notebook server. Official guidance for public servers states that an SSL deployment should always be accessed with an https:// URL. You also need deliberate firewall rules, certificate management, hostname handling and an access-control plan.

Troubleshoot by separating the three endpoints

There are three points to check: the browser’s local port, the SSH listener and the VPS Jupyter process. Test them in that order.

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

Browser refuses the connection

  • Confirm that the Jupyter terminal is still running and has not exited.
  • Check that the browser port is the first number in -L. For -L 8890:127.0.0.1:8888, the browser address is http://127.0.0.1:8890.
  • Make sure the tunnel terminal is still connected and has not been interrupted.

SSH reports that the local port is busy

Choose another unused local port, such as 8890, and browse to that port:

ssh -N -L 8890:127.0.0.1:8888 USER@VPS_HOST

Do not change the final number unless the VPS Jupyter process also moved.

Jupyter prints a different port

Either stop the conflicting process and restart Jupyter on your planned remote port, or forward the port Jupyter actually selected. The final number in -L must equal the VPS listening port.

HTTP 403 or a host-header error

Keep the browser URL on 127.0.0.1. Review Jupyter’s allow_remote_access setting only when you intentionally use a reverse proxy or a non-local hostname. Changing that setting is not a substitute for correcting a tunnel that points to the wrong address.

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

The tunnel connects but the page hangs

  • Verify that Jupyter is listening on the VPS loopback address and the expected remote port.
  • Check that the SSH account can reach that loopback address and port.
  • Confirm that the tunnel’s destination address is 127.0.0.1 on the VPS side, not an address that exists only on your local computer.

The connection drops

Run the tunnel with verbose SSH logging to observe negotiation and forwarding errors:

ssh -v -N -L 8888:127.0.0.1:8888 USER@VPS_HOST

Inspect the actual log and the VPS’s resource limits before changing settings. A dropped tunnel can result from network interruption, an SSH timeout, a stopped Jupyter process or resource exhaustion; the verbose output distinguishes these cases better than guessing.

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

Compare deployment choices before exposing anything

The SSH tunnel is usually the smallest security and operations footprint for one person. A direct public deployment can be convenient for a team or an automated service, but it adds responsibilities that the tunnel avoids.

Deployment Exposure Authentication Persistence Audience Operational burden
Localhost plus SSH tunnel Jupyter port stays on VPS loopback; SSH is the entry point. SSH access plus Jupyter token or password. Usually a manually started process unless you add a service manager. Single user or one controlled operator. Low; maintain the VPS, Python environment and SSH access.
Public Jupyter behind HTTPS Web service is reachable through a public hostname and firewall path. Jupyter authentication plus the access controls you configure; SSO may be appropriate for an organization. Normally managed as a service with restart and logging policies. Selected external or organizational users. Higher; firewall, TLS certificates, proxy headers, updates and account management are your responsibility.
Multi-user platform Designed around an application gateway rather than one personal listener. Centralized user authentication and per-user sessions. Managed centrally with lifecycle and resource policies. Teams and classes. Highest initial setup, but clearer separation than sharing one personal server.

Jupyter’s documentation distinguishes a personal notebook server from a multi-user server. If several people need accounts, isolated kernels or shared administration, evaluate JupyterHub or another managed architecture instead of handing one user’s token to a group.

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

Choose a VPS with the right practical characteristics

No single VPS size or provider is required by this workflow. Select based on the notebooks you will run and where your users are located. Compare:

  • CPU and RAM for the kernels and data-processing jobs you expect to execute.
  • Storage type and capacity for environments, datasets, checkpoints and notebook outputs.
  • Region and network latency between the VPS and your normal working location.
  • Bandwidth limits and transfer pricing if notebooks move large datasets.
  • Snapshot and backup facilities so you can recover the environment and project files.
  • IPv4 and IPv6 availability, SSH key support and the provider’s recovery console.
  • Support and maintenance expectations, especially if the server will run continuously.

These are infrastructure decisions, not reasons to expose port 8888. The tunnel works over the SSH access you already secure, regardless of which VPS host supplies the machine.

End-to-end checklist

  • Linux VPS provisioned and reachable by SSH.
  • Dedicated non-root user selected.
  • Project Python environment created or activated.
  • JupyterLab installed with conda, mamba or pip.
  • Jupyter started with --no-browser --ip=127.0.0.1 and a known remote port.
  • Token copied privately from the VPS terminal.
  • Local SSH forwarding command uses a free local port and the actual remote port.
  • Browser opened at the local 127.0.0.1 address.
  • SSH tunnel kept open while working.
  • Jupyter and the tunnel stopped deliberately when finished.

Bottom line

For a personal Jupyter workload on a VPS, bind Jupyter to the VPS loopback address and reach it through an SSH local-forward tunnel. This keeps the notebook port off the public internet while preserving Jupyter’s token or password protection. Change only the local forwarding port when your computer has a conflict; change the remote forwarding port only when Jupyter is listening elsewhere. If your audience grows beyond one controlled user, move to an HTTPS-protected, managed multi-user design rather than sharing a personal notebook server.

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.

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

JupyterJupyterLabLinuxremote developmentSSH tunnelVPS

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.

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

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.