SSH Basics

SSH is a protocol that allows you to connect to a remote computer. It is widely used in remote computing, such as connecting to a remote server or running Jupyter Lab in a remote host.

The following steps are adapted from the Generating a new SSH key and adding it to the ssh-agent. The procedure has been tested on macOS Sequoia.

First check for existing SSH keys on your computer by running:

1
2
ls -al ~/.ssh
# Lists the files in your .ssh directory, if they exist

Check the directory listing to see if you have files named either id_ed25519.pub or id_ed25519.pub. If you don’t have either of those files then read on, otherwise skip the next section.

Open Terminal. Paste the text below, substituting in your GitHub email address. This creates a new ssh key, using the provided email as a label.

1
ssh-keygen -t ed25519 -C "your_email@example.com"

Start the ssh-agent in the background.

1
eval "$(ssh-agent -s)"

If you’re using macOS Sierra 10.12.2 or later, you will need to modify your ~/.ssh/config file to automatically load keys into the ssh-agent and store passphrases in your keychain.

First, check to see if your ~/.ssh/config file exists in the default location.

1
open ~/.ssh/config

If the file doesn’t exist, create the file.

1
touch ~/.ssh/config

Next, open your ~/.ssh/config file, then modify the file to contain the following lines. If your SSH key file has a different name or path than the example code, modify the filename or path to match your current setup.

1
2
3
4
Host github.com
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519

Add your SSH private key to the ssh-agent. If you created your key with a different name, or if you are adding an existing key that has a different name, replace id_ed25519 in the command with the name of your private key file.

1
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

For a detailed explanation, refer to my previous post.

In summary:

  1. Generate a key pair in the local SSH client.
  2. Activate the ssh-agent and link the private key to it.

In Windows, this process can be executed in PowerShell:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Generate a key pair
ssh-keygen -t ed25519

# By default, the ssh-agent service is disabled. Configure it to start automatically. Ensure you're running as an Administrator.
Get-Service ssh-agent | Set-Service -StartupType Automatic

# Activate the service
Start-Service ssh-agent

# This should return a status of Running
Get-Service ssh-agent

# Load your key files into ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519
1
2
3
4
5
# Set the sshd service to start automatically
Get-Service -Name sshd | Set-Service -StartupType Automatic

# Activate the sshd service
Start-Service sshd

Your public key, \.ssh\id_ed25519.pub, should be placed on the server in a text file named administrators_authorized_keys located in C:\ProgramData\ssh\.

For example, to use PowerShell as the default shell:

1
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force

In Windows, sshd reads configuration data from `%programdata%\ssh\sshd_config`` by default.

You can modify the configuration file to change the default port, for example:

1
2
# Port 22 is the default port for SSH
Port 22

You can also disable password authentication to prevent brute-force attacks:

1
2
# Disable password authentication
PasswordAuthentication no

You can enable public key authentication:

1
2
# Enable public key authentication
PubkeyAuthentication yes
1
ssh <username>@<hostname>

To connect, you need to know the username and hostname of the remote host.

The username typically matches the account name of the remote host, retrievable by:

1
echo $env:USERNAME

However, if you’re using a Microsoft account to log in, the username might be the associated email address.

The hostname, which is the IP address of the remote host, can be retrieved with:

1
ipconfig

Try enable Port 22

1
netsh advfirewall firewall add rule name="Open SSH Port 22" dir=in action=allow protocol=TCP localport=22 remoteip=any

Try enabling Remote server listen on socket in VS Code.

For a comprehensive guide, refer here.

Since Windows uses port 22 by default for SSH, consider changing the SSH port in WSL2 to 2222 to prevent conflicts.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Install openssh-server
sudo apt install openssh-server

# Modify the SSH configuration to use port 2222
sudo sed -i -E 's,^#?Port.*$,Port 2222,' /etc/ssh/sshd_config
sudo service ssh restart

# Allow passwordless sudo for the current user to start the SSH service
sudo sh -c "echo '${USER} ALL=(root) NOPASSWD: /usr/sbin/service ssh start' >/etc/sudoers.d/service-ssh-start"

# Start the SSH service without requiring a password
sudo /usr/sbin/service ssh start
1
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd) for WSL' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 2222

Create a CMD script to initiate the SSHD service in WSL2.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@echo off
setlocal

C:\Windows\System32\bash.exe -c "sudo /usr/sbin/service ssh start"

C:\Windows\System32\netsh.exe interface portproxy delete v4tov4 listenport=2022 listenaddress=0.0.0.0 protocol=tcp

for /f %%i in ('wsl hostname -I') do set IP=%%i
C:\Windows\System32\netsh.exe interface portproxy add v4tov4 listenport=2022 listenaddress=0.0.0.0 connectport=2022 connectaddress=%IP%

endlocal
1
ssh -p 2222 <username>@<hostname>

Note that the username here is distinct from the Windows host username; it pertains to the Linux system. Determine it using:

1
whoami

The hostname, however, remains consistent with the Windows host.

Edit the ~/.ssh/config on the local client:

1
2
3
4
5
6
7
8
9
Host <hostname>
    HostName <nickname_windows>
    User <username_windows>
    Port 22

Host <hostname>
    HostName <nickname_wsl>
    User <username_wsl>
    Port 2222

Use ssh to run jupyter lab on a remote host and access it from a local browser.

If you designate <remote_port> for the remote and <local_port> for the local, redirect the traffic as:

1
ssh -L <local_port>:localhost:<remote_port> <username>@<hostname>
1
jupyter lab --no-browser --port=<remote_port>

For more details, consult this link.

Navigate to the directory you wish to sync:

1
croc send --code <code> .

To receive the files:

1
croc --yes --overwrite <code>