How To Run Remote Jupyter Notebooks with SSH on Windows 10


Being able to run Jupyter Notebooks on remote systems adds tremendously to the versatility of your workflow. In this post I will show a simple way to do this by taking advantage of some nifty features of secure shell (ssh). What I'll do is mostly OS independent but I am putting an emphasis on Windows 10 since many people are not familiar with tools like ssh on that OS.

One of the most useful tools for data-science and ML/AI work is the Jupyter notebook. I am assuming you are familiar with this great interactive browser interface. If not, then you owe it to yourself to check it out. It's extremely popular for Python development and experimentation but also supports many other languages.

It is possible to set up Jupyter notebook "servers" for multi-user access. However, that requires system administration skills beyond what a "normal" user would be expected to know. What we will cover is simple. It will give you the ability to launch a Jupyter notebook browser interface connected to any machine that you have an account on that has Jupyter installed and that has an ssh setup.

We'll go over the general details of using an ssh "local port forward tunnel" to access a Jupyter notebook on a remote machine. For an example I'll connect from a Windows 10 machine to another Windows 10 system. My gaming rig!

If you can connect to a system with ssh then you have potential to do this regardless of what operating systems are involved.

Step 1) SSH setup

I recently wrote a post titled "How To Use SSH Client and Server on Windows 10". In that post I teased that I would be writing other posts that would refer back to that — this is one of them.

Windows 10 now comes with a full OpenSSH client and server. The ssh client seems to be enabled by default and that would be all you need if you are only using Windows 10 as a "client". If you want to connect to a Windows 10 machine (like your gaming rig) that has Jupyter notebook installed then you will need to enable the ssh server on that machine. The post above should be an easy guide for doing that.

Step 2) Jupyter notebook setup

For a guide that includes a simple Jupyter notebook setup using Anaconda Python see, "How to Install TensorFlow with GPU Support on Windows 10 (Without Installing CUDA) UPDATED!)" or for Linux see, "Install TensorFlow with GPU Support the Easy Way on Ubuntu 18.04 (without installing CUDA)".

Step 3) SSH to the remote system and start Jupyter notebook

The general syntax is,

ssh user-name-on-remote-sys@ip-address-of-remote-sys

For example; A terminal session using Powershell connecting from a Windows 10 machine to another Windows 10 machine would look like,

PS C:Usersdon> ssh [email protected]
[email protected]'s password:

Microsoft Windows [Version 10.0.18362.113]
(c) 2019 Microsoft Corporation. All rights reserved.

don@I7W C:Usersdon>

By default when you ssh to a Windows 10 machine you get a CMD prompt. You can change to Powershell by typing "powershell" or just use CMD to start your Jupyter notebook.

Step 4) Start Jupyter notebook with –no-browser and –port

Now I will "cd" to my projects directory on that system and start a Jupyter notebook.

don@I7W C:Usersdon>cd projects

don@I7W C:Usersdonprojects>jupyter notebook --no-browser --port 8889

The two things that are different from how you would normally start up a notebook are,

  • "–no-browser" without that flag the notebook would try to open in a browser on the remote machine which is not what you want.
  • "–port" You will want to specify the port number to start the notebook on. The default is 8888. It's good to use a different port so you don't interfere with any instances you may have recently opened. It's conventional to use a port starting with 80 or 88. I used 8889. [When you start a Jupyter notebook you are starting a small web server that your browser will connects to.

You will get output that looks something like,

don@I7W C:Usersdonprojects>jupyter notebook --no-browser --port 8889
[I 17:02:05.627 NotebookApp] JupyterLab extension loaded from C:UsersdonAnaconda3libsite-packagesjupyterlab
[I 17:02:05.627 NotebookApp] JupyterLab application directory is C:UsersdonAnaconda3sharejupyterlab
[I 17:02:05.627 NotebookApp] Serving notebooks from local directory: C:Usersdonprojects
[I 17:02:05.627 NotebookApp] The Jupyter Notebook is running at:
[I 17:02:05.627 NotebookApp] http://localhost:8889/?token=11c3159a7187ce15093143109aafe824c8efa757a59d2d2b
[I 17:02:05.627 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 17:02:05.642 NotebookApp]

    To access the notebook, open this file in a browser:
    Or copy and paste one of these URLs:

That last line is what you will use after the next step. You will need to copy that to your local browser after we create the ssh port tunnel. [You can copy from the shell by selecting and right-click.]

Note: you can close that notebook session (kernel) by doing CTRL-C

Leave that shell running. You will need to open a new shell for the next step.

Step 5) Create an SSH “local port forward”

SSH Local port forward explained!

The general syntax for an ssh local port forward looks like,

ssh -N -L local-address:local-port:remote-address:remote-port remote-user@remote-host

ssh port forwarding can be very confusing! Here's what the command above would do,

  • "-N" is saying don't execute any commands after the "tunnel" is established. That's a little extra security.
  • "-L" is indicating that we want a Local port forward to the remote machine (-R goes the other way).
  • "local-address" is optional, but good to use, since it restricts what system can access the port.
  • "local-port" is the forwarded port
  • "remote-address:remote-port" is the address and port that the local-port will be forwarded to on the remote host.
  • "remote-user@remote-host" is the user login and address for the remote connection. Note: remote-host does not have to be the same as "remote-address" i.e. "remote-host" is the machine you connect to, remote-address is the address to use "from" there, for example, it could be "localhost" on the remote machine.

Example Local port forward with SSH tunnel

The example below will show a local port forward from localhost:8889 on the machine I am sitting in front of, to the localhost address on the machine I am connecting to, using the same port number i.e. localhost:8889. The remote machine is one of my Windows 10 machines with user "don" at address "".

In short, I am connecting localhost:8889 to the localhost:8889 on (remember that port 8889 is what was used to start Jupyter notebook in the last step).

ssh -N -L localhost:8889:localhost:8889 [email protected]

In a new Powershell window running that command will do nothing other than open the ssh tunnel and do the port forward. It just waits until you close it. You close the tunnel by doing CTRL-C

Step 6) Open Jupyter notebook with your “Local” browser

In Step 4) we logged into with ssh and started a Jupyter notebook with –no-browser and used port 8889. In Step 5) we created an ssh tunnel to and forwarded connections from our localhost:8889 to localhost:8889 on that machine.

So, now if we copy the line we got from starting the notebook (http://localhost:8889/?token=11c3159a7187ce15093143109aafe824c8efa757a59d2d2b) into a browser it will start that notebook running on the remote machine.

Here's a screen shot showing the 2 Powershell sessions and a browser running the remote notebook. I (sloppily) circled the relevant points,

ssh local port forward on Windows 10


I hope you find this ssh local port forward useful! I use this a lot myself. It's nice to be able sit somewhere comfortable with a laptop and easily do some Python work in a Jupyter notebook that's running on another machine. I use this with my systems at home and to connect to machines at work. It's one of those nifty ssh "tricks" that can make life easier.

Happy computing! –dbk @dbkinghorn

Looking for a
Scientific Compute System?

Do you have a project that needs serious compute power, and you don’t know where to turn? Puget Systems offers a range of HPC workstations and servers tailored for both CPU and GPU workloads.

Configure a Scientific Compute System

Why Choose Puget Systems?

gears icon

Built Specifically for You

Rather than getting a generic workstation, our systems are designed around your unique workflow and are optimized for the work you do every day.

people icon

We’re Here, Give Us a Call!

We make sure our representatives are as accessible as possible, by phone and email. At Puget Systems, you can actually talk to a real person!

delivery icon

Fast Build Times

By keeping inventory of our most popular parts, and maintaining a short supply line to parts we need, we are able to offer an industry-leading ship time.

repair icon

Lifetime Labor & Tech Support

Even when your parts warranty expires, we continue to answer your questions and even fix your computer with no labor costs.
Click here for even more reasons!