Puget Systems print logo
Read this article at https://www.pugetsystems.com/guides/1477
Dr Donald Kinghorn (Scientific Computing Advisor )

How To Run Remote Jupyter Notebooks with SSH on Windows 10

Written on June 11, 2019 by Dr Donald Kinghorn


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 don@
don@'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 don@

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.

Why Choose Puget Systems?

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.

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.

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!

Lifetime Support/Labor Warranty

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!

Puget Systems Hardware Partners

Tags: Jupyter notebook, Windows 10, ssh
Prachi Sharma

Hi! This is a nice piece of information. I followed but still have some problem. I am using Putty for windows to access remote Ubuntu PC. I am able to open jupyter notebook in the browser as given in this post. When I did all this, a code was already running on my remote PC's notebook but it was not showing like that on windows notebook. I had to refresh it every time to check the status of my results. This is one problem that it is not showing the training process simultaneously on my windows PC's notebook.
Another problem: Now, the code on remote PC's notebook has completed. When I tried to ran that code again on windows PC's notebook, I got resource exhaustion error (basically running InceptionV3) even when the kernel is the same as in remote PC's notebook and in the cuda available devices, the windows PC's notebook is showing the remote PC's GPU. Can't understand why all this is happening. Any help will be appreciated.

Posted on 2020-04-12 07:14:11
Prachi Sharma

I basically used putty for the same.

Posted on 2020-04-12 07:33:47
Donald Kinghorn

PuTTY has been a great resource for Windows over the years, but I'm really happy that Microsoft has finally added a full native ssh server and client to Windows.

I'm not sure why those changes in the notebook are are not refreshing??? Also, the resource exhausted error is concerning! Again I'm not completely sure what is happening there ... It may be that the training job didn't disconnect from the notebook process(?) so the memory is still in use by the GPU. I've had problems like this in the past where I had to kill notebook kernels manually and restart the jupyter notebook-server to get process memory to release from GPU. That was when I was running notebooks from Docker images and I just considered it related to that setup ... I think it is the same kind of trouble you are seeing.

Thank you for posting your observations! I will definitely look into this! It could impact another project I'm working on for remote system usage --Don

Posted on 2020-04-13 16:37:24
Prachi Sharma

Hey Thanks for the reply Donald! I appreciate your suggetions and applied them by killing all kernels and then restarting the notebook. But the problme is still there. In the mean time, I have shifted to Google chrome remote desktop which is really good. But nowadays, there is much problem of session dropping. So keeping my fingers crossed.

Posted on 2020-04-14 01:58:44