This is how I work on projects involving jupyter notebooks running on a remote computer (ie, how I type away on my laptop while a beefy computer sits in the corner doing all the real work)

The general idea

Jupyter notebooks (both the older Jupyter Notebook IDE, and the current Jupyter lab IDE - click here for an explanation of the differences, but I’ll assume you’re using JupyterLab) work by running a server (= hosting a website) on your computer, which you access by opening your browser (firefox, chrome, etc) and navigating to eg. localhost:8888. localhost is an alias for the computer you’re currently using. 8888 refers to the port being accessed. Similarly, HTTP and HTTPS (which the internet runs on) use ports 80 and 443 by default. So, it really is just hosting a website on your computer which isn’t visible to people outside your wifi network. When you launch a jupyter notebook server, you see a printout like the following:

# a few lines of logging, then:

To access the notebook, open this file in a browser:
    file:///home/alex/.local/share/jupyter/runtime/nbserver-2088-open.html
Or copy and paste one of these URLs:
    http://localhost:8888/?token=6ee1ddcbb5aa79ce64086a12d5a032dbbc309afb94aa6b0b
    or http://127.0.0.1:8888/?token=6ee1ddcbb5aa79ce64086a12d5a032dbbc309afb94aa6b0b

The idea behind remotely using jupyter notebooks, is that you run the notebook server on your powerful computer (let’s call it remote), establish a connection to it from the computer you want to type from/look at (let’s call it laptop), forward the port that the remote is hosting the website at (8888 by default for notebooks, but you can change it) and then access the user interface on your laptop.

I’ll use alex@laptop $ <command> to indicate when I’m running commands on my laptop, and alex@remote $ <command> when running commands on the remote computer, connected via ssh (ie, without connecting a keyboard directly to the remote computer)

Remote access

Assuming you already know how to access a linux computer via ssh, you likely use a command like:

alex@laptop $ ssh alex@192.168.1.101

If you’re running windows on your laptop, you’ll likely have a different way of using ssh, like eg PuTTy. Unfortunately, all the following commands that execute on your laptop will likely be different, so you’ll have to figure out equivalents for your setup

Now, if you were to run a notebook on the remote machine and open the corresponding URL on your laptop (by clicking the link in the printout above) you’d find that it doesn’t work. That’s because the connections at remote port 8888 aren’t automatically forwarded to your laptop’s port 8888. So, we pass ssh the -L A:localhost:B command to tell it to forward port A on the remote pc’s localhost to port B on our laptop. (PuTTy instructions). For me, that’s just:

alex@laptop $ ssh alex@192.168.1.101 -L 8888:localhost:8888

Next, launch jupyter lab as you normally would, but let’s be explicit about which port it should run on, since it must correspond to the port forwarded previously:

alex@remote $ jupyter lab --port 8888

Wait for the printout, click the link when it gets printed (something like http://localhost:8888/?token=6ee1d...) and you should find it opens on your laptop. Great!

Make jupyter keep running after you finish your ssh session

Unfortunately, if your ssh connection closes for any reason, any programs you were running on the remote computer get closed too. There are a few ways of dealing with this - I use nohup, which comes pre-installed on linux distros. Nohup “executes another command, and instructs the system to continue running it even if the session is disconnected.” - just what we need! Any output from running that command will be written to a file called nohup.out. Putting an & at the end of a command will cause it to run in the background, so that you can keep doing other things with your ssh session

So, you’ll need to use a command like:

alex@remote $ nohup jupyter lab --port 8888 &

Now, disconnect from the remote computer, reconnect, type less nohup.out in the directory where you launched the notebooks, click the notebook link and you should find that the jupyter server is still running. If your previous jupyter session was stopped and you want to start another one, you should probably first remove the old nohup.out file (rm nohup.out) since nohup will just keep appending to the same file otherwise

If you don’t want to open the nohup file and manually click it, the following magical one-liner should print out the link (fifth line of the printout):

alex@remote $ sed '5q;d' ./nohup.out | cut -d " " -f 4

Setting up aliases

I highly recommend setting up an alias instead of trying to remember these commands or searching through your terminal history. This depends on which shell you use - I use fish shell, so I have a command set up on my laptop to establish the ssh connection as follows:

# ~/.config/fish/functions/summon-minibeast-portforwarding.fish
function summon-minibeast-portforwarding
    ssh alex@192.168.1.101 -L 8889:localhost:8889
end

Now typing summon-minibeast-portforwarding in a terminal on my laptop logs me in with portforwarding on port 8889

Aside: I actually use ssh alex@192.168.1.101 -L 8889:localhost:8889 -t 'fish', where the -t flag causes the command that follows to run in the shell once you’ve logged in. Running eg. ssh alex@192.168.1.101 -t 'echo 123' would log you in, run the echo 123 command, then log out. -t ‘fish’ just launches the fish shell. It’s not important though, so you can leave that out. Also, I use port 8889 as others might use the same remote computer, and they’d default to port 8888

I start the notebook server and get the link using the following commands, saved on the remote computer:

function start-nb-server
    cd ~/alknemeyer/; rm -f nohup.out; conda activate my-env; and nohup jupyter lab --port 8889 &
end

function show-nb-link
    sed '5q;d' ~/alknemeyer/nohup.out | cut -d " " -f 4
end

which I run using $ start-nb-server; and sleep 15; and show-nb-link. It prints out something like http://localhost:8889/?token=6ee1ddc.... The conda part is specific to my work flow - change it as needed

If there is already a server running, I just log in and use show-nb-link

So the whole workflow is:

alex@laptop $ summon-minibeast-portforwarding
alex@remote $ show-nb-link

Easy! Tab completion/command history means I don’t actually have to write those whole commands out

Setting up a keypair

Typing your password each time is a bit annoying, so you can set up a secure key-pair which makes logging in a bit quicker. Do the following:

  1. create a key in ~/.ssh/id_rsa on your laptop (using your email) using ssh-keygen:

    alex@laptop $ ssh-keygen -t rsa -b 4096 -C "your-email@example.com"
    
  2. copy it to the remote server (using the remote computer’s ip address):

    alex@laptop $ ssh-copy-id -i ~/.ssh/id_rsa alex@192.168.1.112
    

Now, try logging in again and you’ll find you don’t need a password

VS code remote

Another (super easy!) way to remotely program computers is via VS code. Remote code editing arguably one of the its best features. Their documentation on this is quite good, so you should just follow the instructions in their overview and in particular, their ssh tutorial

Auto code reloading, typing, making a library, and more

The next post in this series discusses how you’d combine the jupyter notebook setup above with development in a more traditional IDE (like VS code, which also works remotely). It works regardless of whether or not you’re running code remotely. Check it out!