Remote login using SSH
It is possible to remotely log in to the NASA-Openscapes and NMFS-Openscapes JupyterHubs using SSH (Secure Shell). This allows you to access the JupyterHub server from your local machine, either in the terminal or from your Interactive Development Environment (IDE). This page is written primarily for workshop leads and researchers experimenting with cloud-based workflows who want to access the cloud environment and work using familiar tools. This can include your local terminal, VSCode, Positron, or other IDE’s that support remote development via SSH. It is also useful for hub administrators doing maintenance tasks.
This functionality is enabled on our 2i2c-managed JupyterHubs thanks to 2i2c’s amazing infrastructure and support, with the use of jupyter-sshd-proxy. Much of this documentation is adapted from the jupyter-sshd-proxy documentation. jupyter-sshd-proxy is pre-installed in the NASA-Openscapes default environment (source). If you want to SSH into a hub using a different image, see the server pre-requisites for instructions for installing on your image.
There are several steps that you need to do once only to set this up. Once you have completed the setup, you can connect whenever your JupyterHub server is running.
Setup
If you are using Windows, it is recommended to use Git for Windows to get a bash terminal with ssh capabilities. If you use Git, you probably have this installed already. We recommend using Git Bash for the terminal-based setup steps below, as well as for connecting via SSH in the terminal later.
1: Install websocat on your computer
websocat is a a tool that enables secure communication between your computer and the JupyterHub server. Install websocat on your local machine.
For macOS, you can use Homebrew:
brew install websocatFor Windows and most Linux distributions, you can download the latest precompiled binary from the releases page.
1. Download websocat
- Go to the websocat releases page: https://github.com/vi/websocat/releases
- Download the latest Windows binary - look for a file named something like
websocat_win64.exeorwebsocat.x86_64-pc-windows-gnu.exe - Create a directory for the executable (e.g.,
C:/Program Files/websocat/orC:/Users/YourUsername/AppData/Roaming/websocat/) - Move the downloaded
.exefile to this directory - Rename the file to
websocat.exe
2. Add to PATH (optional but recommended)
To make websocat accessible from any command prompt or PowerShell window:
Option A: Using Windows Settings (Windows 10/11) This is different depending on your version of Windows, but generally: 1. Open the Start Menu and search for “Environment Variables” 2. Select “Edit the system environment variables” 3. In the System Properties window, click on the “Environment Variables…” button 4. In the “System variables” or “User variables” section (depending on your permissions), find and select the Path variable, 5. Click “Edit…” 6. Click “New” and add the path to the directory where you placed websocat.exe (e.g., C:\Path\To\Websocat\) 7. Click “OK” to close all dialog boxes
Option B: Using CMD prompt
- Open a Command Prompt
- Run the following command, replacing
C:\Path\To\Websocat\with the actual path where you placedwebsocat.exe:
setx PATH "%PATH%;C:\Path\To\Websocat\"
- Verify Installation
Open a new command prompt or PowerShell window and run:
websocat --version
If you weren’t able to add websocat to your PATH, you can still use it by providing the full path to the websocat.exe. For example:
C:/Users/YourUsername/AppData/Roaming/websocat/websocat --version
If installed correctly, you should see the version information.
Note: You must open a new terminal window after modifying the PATH for the changes to take effect.
2. Set up SSH keys on your local machine
SSH is a secure protocol that allows you to connect to a remote server and run commands as if you were logged in directly. It uses a “key pair”, with a private key stored on your local machine and a public key stored on the remote server, to authenticate the connection.
To securely connect to the JupyterHub server, you need to generate an SSH key pair (if you don’t already have one) on your local computer.
First, read about SSH keys here, then follow these steps:
Check if you already have an SSH key pair: Follow the operating system-specific instructions on GitHub.
If you don’t already have an SSH key, follow the operating system-specific instructions on GitHub to generate a new SSH key pair. If you already have an SSH key pair, you can skip this step.
The instructions to use a Powershell command to start the ssh agent didn’t work for me. I ran eval $(ssh-agent -s) in git bash instead and that worked.
- (Optional but recommended) Add your public SSH key to your GitHub account by following the instructions on GitHub. When prompted while adding your key to GitHub, set it as an authentication key (not “commit signing”).
3. Set up your local SSH config file
Create a JupyterHub Token
We will need to create a JupyterHub token for authentication. We will add this token to our SSH configuration, and it will be sent to the JupyterHub server to authenticate when we connect via SSH.
Go to the JupyterHub control panel: NASA or NOAA, or if you are in the JupyterHub already, click File -> Hub Control Panel.
In the top bar, select Token.
Create a new Token, and keep it safe. Treat this like you would treat a password to your JupyterHub instance! It is recommended you set an expiry date for this.
Setup your local ~/.ssh/config file
~
~ is a shortcut that refers to your user home directory. On Mac this will usually be /Users/your-username/, and on Linux it will usually be /home/your-username/. On Windows, this will usually be C:/Users/your-username/. The ~ as a shortcut works in most terminal applications, including Git Bash, WSL, and PowerShell on Windows. If you are using the Windows Command Prompt, you will need to use the full path or the environment variable %USERPROFILE% to refer to your home directory instead of ~.
We will set up our ssh config file to tell ssh how to connect to our JupyterHub. Add an entry that looks like this to the end of your ~/.ssh/config file. If the file does not exist, create it, then open it in a text editor.
Host <YOUR-JUPYTERHUB-DOMAIN>
User jovyan
ProxyCommand websocat --binary -H="Authorization: token <YOUR-JUPYTERHUB-TOKEN>" asyncstdio: wss://%h/user/<YOUR-JUPYTERHUB-USERNAME>/sshd/
On Windows, the asyncstdio: argument will not work. You can simply omit it and use:
Host <YOUR-JUPYTERHUB-DOMAIN> User jovyan ProxyCommand websocat --binary -H="Authorization: token <YOUR-JUPYTERHUB-TOKEN>" wss://%h/user/<YOUR-JUPYTERHUB-USERNAME>/sshd/
replace:
<YOUR-JUPYTERHUB-DOMAIN>with your hub domain (NASA:openscapes.2i2c.cloud, NMFS:nmfs-openscapes.2i2c.cloud))<YOUR-JUPYTERHUB-TOKEN>with the token you generated earlier<YOUR-JUPYTERHUB-USERNAME>with your jupyterhub username that you log in to the hub with (usually your github username)
Here’s an example:
Host openscapes.2i2c.cloud
User jovyan
ProxyCommand websocat --binary -H="Authorization: token ajklhdkfs989dfsbuw89983bf89se" asyncstdio: wss://%h/user/ateucher/sshd/
On Windows, it would look like this:
Host openscapes.2i2c.cloud
User jovyan
ProxyCommand websocat --binary -H="Authorization: token ajklhdkfs989dfsbuw89983bf89se" wss://%h/user/ateucher/sshd/
Note that if you are connecting to your JupyterHub in a VSCode fork such as VSCodium, Cursor, or Positron, or any other IDE that uses the open-remote-ssh extension, you need to make sure the value of the -H argument ("Authorization: token xxxx") is enclosed in double quotes and not single quotes, or the connection will fail.
websocat to your PATH…
You will need to provide the full path to the websocat executable in the ProxyCommand line above (e.g., C:/path/to/websocat instead of just websocat).
For example, if you placed websocat.exe in C:/Users/andy/AppData/Roaming/websocat/, your ~/.ssh/config entry would look like this:
Host openscapes.2i2c.cloud
User jovyan
ProxyCommand C:/Users/andy/AppData/Roaming/websocat/websocat --binary -H="Authorization: token ajklhdkfs989dfsbuw89983bf89se" wss://%h/user/ateucher/sshd/
4. Add public ssh key to your JupyterHub server
Now that you have have private SSH keys available in your local machine, and your configuration set up, you need to put SSH public keys in ~/.ssh/authorized_keys on your JupyterHub server.
The simplest way to do this is to rely on your GitHub public keys:
After you start your JupyterHub server, open a terminal in JupyterLab
Run the following commands in the JupyterLab terminal:
mkdir -p ~/.ssh wget https://github.com/<YOUR-GITHUB-USERNAME>.keys -O ~/.ssh/authorized_keys chmod 0600 ~/.ssh/authorized_keysreplacing
<YOUR-GITHUB-USERNAME>with your github username.
If you didn’t add your public ssh key to your GitHub account, you can manually add it to the authorized_keys file instead: 1. After you start your JupyterHub server, open a terminal in JupyterLab 2. Run the following commands in the JupyterLab terminal:
mkdir -p ~/.ssh
echo "<YOUR-PUBLIC-SSH-KEY>" >> ~/.ssh/authorized_keys
chmod 0600 ~/.ssh/authorized_keysreplacing <YOUR-PUBLIC-SSH-KEY> with the contents of your public ssh key (usually found in ~/.ssh/id_rsa.pub or ~/.ssh/id_ed25519.pub on your local machine).
Connect to JupyterHub via SSH
Having completed the above setup steps once, you should be able to connect to your JupyterHub server via SSH from your local machine.
Connecting in the terminal
The simplest way is to make sure your JupyterHub server is running, open a terminal and then run:
ssh openscapes.2i2c.cloudfor NASA-Openscapes, or:
ssh nmfs-openscapes.2i2c.cloudfor NMFS-Openscapes.
If everything is set up correctly, you should be logged into your JupyterHub server via SSH, and you will have a new prompt in your terminal that looks something like this:
(notebook) $
If you type whoami, you should see jovyan printed to the terminal.
In that terminal, you can now run commands as if you were in a terminal inside JupyterLab.
To exit the SSH session, simply type exit and press Enter.
Connecting from VSCode, Positron, etc.
You can also connect to your JupyterHub server via SSH from an IDE such as VSCode or Positron.
- Make sure your JupyterHub server is running.
- Open your IDE.
- Open the command palette (e.g.,
Ctrl+Shift+Pin VSCode). - Search for and select
Remote-SSH: Connect to Host... - Type or select the name of the host you set up in your
~/.ssh/configfile (e.g.,openscapes.2i2c.cloudornmfs-openscapes.2i2c.cloud) and press Enter.

- A new IDE window will open, and you can open a folder or workspace on your JupyterHub server, and work there as if you were working locally. In the explorer pane, you should see buttons giving you the option to “Open Folder” or “Clone Repository”. You can use “Open Folder” to open an existing folder on the JupyterHub server, or “Clone Repository” to clone a git repository directly into your JupyterHub server.
To close the remote connection, click on the box in the bottom-left corner of the IDE window and select “Close Remote Connection”.