Skip to content

Instantly share code, notes, and snippets.

@Skenvy
Last active May 11, 2022 12:39
Show Gist options
  • Save Skenvy/8e16d4f044707e63c670f5b487da02c0 to your computer and use it in GitHub Desktop.
Save Skenvy/8e16d4f044707e63c670f5b487da02c0 to your computer and use it in GitHub Desktop.
SSH for multiple GH accounts

SSH for multiple GH accounts

While a proper ~/.ssh/config can be great, this should be a minimal way to set up new keys for using multiple accounts on Mac, Windows, and WSL, and covers some of the traps in simultaneous use of Windows AND WSL.

Creating a new key

To connect from "this machine" to a new GH account. While ~ will be different from your windows and WSL's perspective, WSL's ~/.ssh should be a soft link to your window's ~/.ssh, so it's ok to use either

# Make the soft link, if it doesn't yet exist.
# Might need to mkdir if this is your first key.
YOUR_WINDOWS_USERNAME=example
mkdir -p /mnt/c/Users/$YOUR_WINDOWS_USERNAME/.ssh
ln -s /mnt/c/Users/$YOUR_WINDOWS_USERNAME/.ssh ~/.ssh
# Make the key
EMAIL=your_email@example.com
KEYNAME=GH_Username
ssh-keygen -t ed25519 -C "$EMAIL" -f ~/.ssh/$KEYNAME

Upload the public key

Upload the public key ~/.ssh/$KEYNAME.pub to https://github.com/settings/ssh/new

Add the new key to the ssh-agent

If you're going to chmod you might need ..

.. to add the following to /etc/wsl.conf from WSL

[automount]
options = "metadata"

and then close all sessions and wsl --shutdown from cmd/pwsh, and apply the user read only permissions to the key, which is required by *nix's openssh but appears to have no affect on windows' ssh-agent.

chmod 400 ~/.ssh/$KEYNAME

Now you can start the ssh-agent

On Windows

Get-Service -Name ssh-agent | Start-Service
# Or to make it automatic, from an admin pwsh
Get-Service -Name ssh-agent | Set-Service -StartupType Automatic

On WSL

Add the following to ~/.bashrc to allow ssh-agent to start automatically.

if [ -z "$SSH_AUTH_SOCK" ] ; then
    eval `ssh-agent -s` > /dev/null
    # ssh-add
fi

Without this, it can be started manually each time with eval "$(ssh-agent -s)"

And add the key to the agent

ssh-add ~/.ssh/$KEYNAME

but you need to do this for BOTH windows AND wsl, they use distinct agents.

Test

This should show you which keys the agent is aware of, and which one is being used by ssh.

ssh-add -l
ssh -vT git@github.com

But then things get dicey...

By using the ssh -v setting in the environment variable GIT_SSH_COMMAND (which supersedes GIT_SSH), and trying to git pull / clone for an account that has its key in the agent, we can see an issue. It appears git uses the ssh-agent on *nix by default but not on windows? To add ssh-agent to the keys tried by git on windows, open powershell and;

[Environment]::SetEnvironmentVariable("GIT_SSH", "$((Get-Command ssh).Source)", [System.EnvironmentVariableTarget]::User)

Which should be a persistent fix!

Set the GIT_SSH_COMMAND to verbose

Shell Command
sh export GIT_SSH_COMMAND="ssh -v"
cmd set GIT_SSH_COMMAND=ssh -v
pwsh $env:GIT_SSH_COMMAND='ssh -v'

However, the ssh reference in pwsh is slightly more cumbersome. For some reason, although backslashes cause no issue in GIT_SSH, as set by the above, Write-Host $env:GIT_SSH_COMMAND yielding the same output as Write-Host $env:GIT_SSH results in git trying to use the path for Get-Command ssh without backslashes. So to add verbose temporarily to GIT_SSH_COMMAND in pwsh, we need the following.

[Environment]::SetEnvironmentVariable("GIT_SSH_COMMAND", "$(((Get-Command ssh).Source).replace('\','/')) -v", [System.EnvironmentVariableTarget]::Process)

Then things get even more dicey.

Git ssh doesn't retry when a key is accepted but not valid. That is to say, when multiple keys are added to the agent, it appears the first key that could be accepted by the site, will be. In other words, if multiple keys will be accepted by a server, because they are all valid for something, the first key to be accepted, might not be valid for the account you're trying to access!! For example, ssh-add A followed by ssh-add B will make git attempt to use key B first. If the account for the repo you're working with has key A attached to it, and B is attached to some other account, then key B will be "accepted", and then subsequently denied as not being for that account.

These are all besides, as the the ssh-agent is ephemeral.

The agent, besides however it interacts with keychain on mac, is totally ephemeral on wsl. So it would not be unreasonable to assume if you want to work with the ssh-agent to handle keys, that you'd be familiar with ssh-add -l to list the keys in the agent, and ssh-add -D to remove all active one. While The agent is ephemeral on WSL, and will need specific keys added on each start up, without a default one being loaded in an rc, Windows appears to store the keys in the agent permanently, so would need to have the previous entry deleted before adding another (it will use whatever the most recent unique addition was that was not already present).

Set your URL from HTTPS to SSH

If you've been using some https method, you'll need to update, or add a remote that uses ssh instead.

# HTTPS format is https://github.com/USERNAME/REPOSITORY.git
git remote get-url --all origin
git remote set-url origin git@github.com:USERNAME/REPOSITORY.git
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment