fxpppr – Setting up ssh

Author

flip phillips (fxpppr)

Modified

September 17, 2025

Why

ssh aka “secure shell”1 allows you to securely connect from machine to machine. It allows you to go beyond just a prompt — You can copy files between machines, electronically sign and verify documents, and set up secure remote sessions with Visual Studio Code (VS Code) — just for a few examples.

VS Code has integrated features that make remote editing very direct and easy. Once we set up ssh we’ll talk about how to integrate it into your development practices.

How - ssh

But - to get started you need a few things.

ssh and friends rely on Public Key Cryptography. As the name suggests, public key cryptography relies on “keys” or, more specifically, a “key pair”. A key pair is two chunks of information — One that you can share freely / publically (the public key), and another that you keep secret (the private key). It is computationally difficult2 to determine one from the other, but, given the public key, it is easy to match it to the private key. It is this magic that allows your key to unlock passwordless communication between machines.

The Tools

All macOS, most Linux, and some Windows distributions have OpenSSH3 built in, otherwise you can easily install it.

The ssh family of commands mostly start with ssh.4 On my machine —

λ ssh ⟨tab⟩
Completing external command
ssh          ssh-add      ssh-agent    ssh-copy-id  ssh-keygen   ssh-keyscan  sshd

We mainly care about —

  • ssh - the main application (client) you use to connect to other machines.
  • ssh-keygen - generates a key.
  • ssh-copy-id - moves the keypair around to different machines.

The remaining commands are the sshd host5 and commands for dealing with the authentication agent.6

We also care about a special hidden directory and the files inside it —

λ ls ~/.ssh
config  id_ed25519  id_ed25519_github  id_ed25519_github.pub
id_ed25519_picam  id_ed25519_picam.pub  id_ed25519.pub
id_rsa  id_rsa.pub  known_hosts
  • ~/.ssh/ - the hidden directory “dot-ssh” in your home directory (~).
  • config - configuration for ssh.
  • known_hosts - a list of approved connections.
  • id_*** - private keys.
  • id_***.pub - public keys - one to match each private key.

Getting started

The very first thing you need to do is generate a keypair. You only need to do this once per machine, or, if you’re clever about moving things around, you can manage a single key, especially for some tasks (like GitHub access for example). To do this, we use ssh-keygen

λ ssh-keygen -t ed25519 -C 'flip@flipphillips.com'

Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/fxpppr/.ssh/id_ed25519): ⟨return⟩
Created directory '/Users/fxpppr/.ssh'.
Enter passphrase for "/Users/fxpppr/.ssh/id_ed25519" (empty for no passphrase): ⟨return⟩
Enter same passphrase again: ⟨return⟩
Your identification has been saved in /Users/fxpppr/.ssh/id_ed25519
Your public key has been saved in /Users/fxpppr/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:EFLBHwy5pPzYiCd96hN5HqQBRTfrImfNd4gYmk8rYqU flip@flipphillips.com
The key's randomart image is:
+--[ED25519 256]--+
|   o+oB=         |
|  .  o++o        |
|   o.ooo .       |
|   o+*oo..       |
|  ++*X= S .      |
|  =*Oo*. .       |
|.E.oo* .         |
|.. .o .          |
|   ...           |
+----[SHA256]-----+

For insane security, you can specify a password for your keys, and it can be anything; But, to make your life easier, and as long as these keys aren’t guarding a nuclear arsenal, you can just ⟨return⟩ through them for an empty prompt. Believe it or not this is usual practice (you do keep your keys secure with proper access permissions, right?)

If you look in your ~/.ssh you’ll see that they were created for you —

λ ls ~/.ssh

id_ed25519  id_ed25519.pub

and if you look closely at their permissions you’ll see —

...
-rw------- 1 fxpppr staff 411 Sep 17 14:04 id_ed25519
-rw-r--r-- 1 fxpppr staff 103 Sep 17 14:04 id_ed25519.pub
...

The public key, id_ed25519.pub, has user+read, user+write, group+read, and world+read, pretty much everyone can see it but not change it. Only you can do that. The private key only has user+read and write permissions. No one else can see it.7 You want to protect the private key since it is the way you identify yourself. Anyone who has your private key can ‘be’ you. Anyone with your public key can challenge you to see if they match.

The option -t ed25519 tell ssh-keygen to create an ed25519 key, which is current ‘best practice’ for key security. The -C 'flip@flipphillips.com' option gives the contact information for the key. Neither of these are necessary. If you don’t specify a key type, it defaults to an rsa key which is still pretty secure, but not currently the ‘best’. If you omit the -C it creates an anonymous email, so simply running ssh-keygen will get you all you need, just different types of keys and anonymous.

There are other useful things like the fingerprint of your key8 and a randomart image that I still don’t know the purpose of, other than being fun to look at. I presume that it, like the fingerprint are ways to verify / validate your key, but I’ve never had to use either in a normal setting.

Logging In

What do we do with these? Let’s start with the simplest, easiest use of the ssh key — Logging in to a remote machine.

Usually, logging in requires you to enter your username and password. When you ssh to another machine, the same typically applies. Let’s see what happens when we try to ssh into a machine in the lab —

λ ssh mystery.magic.rit.edu

The authenticity of host 'mystery.magic.rit.edu (129.121.222.123)' can't be established.
ED25519 key fingerprint is SHA256:6LsvBhYxtw27j7BHotO8nSIdjGHWIAt7Yr4He6Eo.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes ⟨return⟩

The first time you log in, you are asked if you want to continue connecting. This is because ssh doesn’t recognize the host in its database of “places we’ve been before”. If you’re pretty sure you’re actually connecting to the machine, you can just answer yes to the promt and move on. This puts a copy of the machine’s public key in the ~/.ssh/known_hosts file and, therefore, won’t ask you in the future.9

After you answer yes you see —

Warning: Permanently added 'mystery.magic.rit.edu' (ED25519) to the list of known hosts.
(fxpppr@mystery.magic.rit.edu) Password:

Notice that it is asking about fxpppr@mystery.magic.rit.edu. It is using my username on the machine I’m logged into (fxpppr because it’s an RIT managed machine.). Hopefully my account on that machine is also fxpppr, because that’s what it is asking for. If it is not (I use flip for machines I control because I’ve used flip as a login for decades.) you have to specify it in the command —

λ ssh flip@mystery.magic.rit.edu

Either way, if you respond to the password correctly10 you’re logged in and good to go.

λ ssh mystery.magic.rit.edu
(fxpppr@mystery.magic.rit.edu) Password: type_password⟨return⟩

Last login: Wed Sep 17 15:06:56 2025 from 50.108.178.99

fxpppr in 🌐 mystery in ~
λ

The first lines are typed on the host you want to access from. Then, from Last login: forward, it is the remote machine responding. Note that my prompt is set up to tell me the name of the remote machine and which directory I am in, when I’m logged in remotely fxpppr in 🌐 mystery in ~. This says user fxpppr logged into (world = my icon for remote machines) named mystery and I’m in the ~ or my home directory.

I can now go about acting like I am logged directly into that remote machine —

fxpppr in 🌐 mystery in ~
λ hostname

mystery

fxpppr in 🌐 mystery in ~
λ ls Music

'Audio Music Apps'/   GarageBand/   Music/

To logout, I can just logout or ^D

But Let’s Make It Easier

One of the most useful things to use your ssh keys for is logging in without having to type a password. To do that, the remote machine needs to ‘know’ about you, and how does it know? By you copying your public key to it so you can compare keys next time you log in!

The easy way to do that is to use ssh-copy-id from your local machine to the host11

λ ssh-copy-id mystery.magic.rit.edu

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ssh-add -L
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 3 key(s) remain to be installed -- if you are prompted now it is to install the new keys
(fxpppr@mystery.magic.rit.edu) Password:

Number of key(s) added:        3

Now try logging into the machine, with: "ssh 'mystery.magic.rit.edu'"
and check to make sure that only the key(s) you wanted were added.

You are presented with some information about the number and type of keys to be copied and then asked for your password on the remote machine. If everything comes up Millhouse, you will receive the bottom message tellying you to test your copy. And if we do that now —

λ ssh mystery.magic.rit.edu

Last login: Wed Sep 17 15:30:00 2025 from 50.108.178.88

fxpppr in 🌐 mystery in ~
λ

Notice that it logged us right in — no password! It compared the keys and said you were OK, so we’ll let you in.12 This part of the process is important for doing things like remote editing, because you don’t want to have to constantly type your password.

Let’s look at that now.

What Happens Under The Hood

Here’s a sequence diagram that illustrates the SSH key-based authentication process. You read it left-to-right, top-to-bottom —

sequenceDiagram
    autonumber
    participant Client
    participant Config as "~/.ssh/config"
    participant PrivateKey as "id_ed25519 (private)"
    participant KnownHosts as "~/.ssh/known_hosts"
    participant Server

    Client->>Client: ssh-keygen creates id_ed25519 + id_ed25519.pub
    Client->>Server: ssh-copy-id adds id_ed25519.pub to server's authorized_keys
    note over Client,Server: Setup completes before the first key-based login

    Client->>Config: Read host alias, user, IdentityFile
    Client->>PrivateKey: Load private key from ~/.ssh/

    Client->>Server: Open TCP connection on port 22
    Server-->>Client: Send host key + algorithms
    Client->>KnownHosts: Compare host key with stored entry
    KnownHosts-->>Client: Match? (warn if new/changed)
    Client->>Server: Negotiate crypto, derive session key
    Server->>Client: Request proof of identity
    Client->>PrivateKey: Sign challenge with id_ed25519
    Client->>Server: Return signature for verification
    Server-->>Client: Validate signature, open session

How — Remote Editing in VS Code

This is the fun part. Let’s say I want to edit a file on a machine in the lab that isn’t my primary workstation. How do I do it?

There are a few prerequsites —

  1. You need a ssh key on your local machine.
  2. You need to copy that key to the remote machine.

We’ve just been through that above, so if you can ssh into a remote machine without a password like we did up there, you’re good to go.

On your local machine you need the Microsoft Remote SSH plugin installed —

The Plugin

and when you click on the lower-left corner of VS Code, the remote-access panel —

the main menu offers you a selection of ways to remotely connect —

The Connect to Host... shows that it is via the Remote-SSH plugin, and when you click on it you are presented to select or create a new host —

Now. You can dive right in and enter, say, heybuddy@mystery.magic.rit.edu into the box, good enough for a one-off edit session. To make it better we can Add or Configure a new ssh host. Let’s try Add —

You can see I put the command for logging in to the remote machine (don’t forget the ssh at the beginning) followed by -A but you only need this if you’re doing agent forwarding, and I mentioned before this is an advanced topic, so you can usually just leave it out for now.

It will ask you which ssh configuration file to put it in. Unless you have specific reasons, you can just put it in your default ~/.ssh/config file13

Now, on my local machine, I have an entry in the config file that looks like —

λ cat ~/.ssh/config

Host mystery.magic.rit.edu
  HostName mystery.magic.rit.edu
  User fxpppr
  ForwardAgent yes

If you’re clever, you can edit this file to make it easier to specify hosts in the future by giving them a nickname, and there are countless other options that you might want to set. Regardless, once you’re here, you’re 99% done. The next time you come back, VS Code will read your config file for hosts and populate the connect menu so you don’t need to enter it again!

Once it starts connecting you’ll notice that the lower-blue bar will give you a status update, and a dialog box on the lower right will let you know about the status of loading the Visual Studio Code Server on the remote machine.

and when you’re finally connected, you’ll see the lower right status change —

Clicking on the Open Folder button gives you a slightly different GUI for picking, based more on the filesystem than the OS —

You can select a folder and edit it just like on your local host but the file has to be there in the first place! How do we do that?

Remote files

There are two easy ways to get files onto the remote host, the most practical is via GitHub. You can Clone Repository rather than opening a file, and it will put a copy right there for you.14

You can also drag & drop from (and to) your local machine into the sidebar on the left! That will copy files from/to the remote host. Useful if you have a bunch of non-repo files like training data, etc.

Here’s a video example —

If you prefer to stay in a terminal, there are other SSH-savvy tools that make copying and syncing straightforward —

  • scp — quick, secure copy; think cp but between hosts, e.g. scp notebook.ipynb remote:/tmp/.15
  • sftp — an FTP-like interactive shell for uploading/downloading over SSH.16
  • rsync — keeps directories in sync efficiently and can resume partial transfers, rsync -avz data/ remote:projects/data/.17
  • sshfs — mounts a remote directory locally so regular tools can read/write through SSH transparently.18

How — GitHub

NoteWork in Progress

This section is still being written. Check back soon for complete instructions on setting up SSH keys with GitHub.

GitHub uses SSH keys for authentication when you push and pull from repositories. This allows you to work with GitHub repositories without having to enter your username and password each time.

To add your SSH key to GitHub:

  1. Copy your public key to your clipboard:
λ cat ~/.ssh/id_ed25519.pub
  1. Go to GitHub → Settings → SSH and GPG keys
  2. Click “New SSH key”
  3. Paste your public key and give it a descriptive title
  4. Test your connection:
λ ssh -T git@github.com

For a detailed walkthrough, see Setting up SSH keys for GitHub.

Once set up, you can clone repositories using SSH URLs:

λ git clone git@github.com:username/repository.git

Notes

Footnotes

  1. The OpenSSH project provides the widely used SSH implementation and documentation — https://www.openssh.com/.↩︎

  2. But not impossible. Of course, an entire ‘industry’ of study concerns itself with this, as you can easily imagine there being a good market for determining faults with such systems.↩︎

  3. The OpenSSH project provides the widely used SSH implementation and documentation — https://www.openssh.com/.↩︎

  4. My prompt on most machines is a lambda, λ. Yours is probably different.↩︎

  5. e.g., The symmetric thing that ssh connects to.↩︎

  6. Advanced lore for another time.↩︎

  7. In numerical permissions, these are 622 and 600 respectively.↩︎

  8. A way you can make sure someone has your key without revealing your key.↩︎

  9. Unless weird things happen like keys change, machines get reformatted, etc. Also, if you’re super paranoid, you can obtain that fingerprint from the owner of the machine and compare it. This is useful if you have to log in to a machine under someone else’s control and want to make sure you’re actually logging into the ‘right’ machine.↩︎

  10. And the remote host is set to accept passwords — It is possible to disable this requiring you to use your ssh key instead.↩︎

  11. You can specify the username too if you need to, just like in ssh.↩︎

  12. When we talked about giving the key its own password, this is what we were talking about. If someone can log into your host machine, they can log into a remote machine easily. Again, because you don’t leave yourself logged in, this isn’t a problem, right? But, if you’re worried or guarding the keys to Fort Knox, you can give the keys a password too. Hopefully something different than the password you usually use and probably repeate on too many machines tsk tsk.↩︎

  13. One of those important files I mentioned above.↩︎

  14. Note you need to be logged in to GitHub to push modifications back to the repository. That is yet another use of ssh keys.↩︎

  15. scp(1) manual — https://man.openbsd.org/scp.↩︎

  16. sftp(1) manual — https://man.openbsd.org/sftp.↩︎

  17. rsync(1) manual — https://manpages.ubuntu.com/manpages/latest/man1/rsync.1.html.↩︎

  18. sshfs(1) manual — https://man.archlinux.org/man/sshfs.1.en.↩︎