Set up SSH for your GitHub accounts

Categories: Git Shell Tutorial

November 17, 2021

Introduction

Few weeks ago when I needed to work on something that I stored in another github account, I came across the issue of managing multiple github accounts. After some digging I notice that many articles are only giving instructions, but hardly any explanations. So here I intend to provide the most up-to-date information, and explain “why” so you understand the purpose of each step. This series will answer the following questions:

  • How to set up multiple github accounts in one computer?
  • Some terms mentioned in this series of articles: SSH, SSH-agent, SSH-Identiy, … What are these and why do we need to use them?
  • How to generate SSH keys?
  • How to set up global account? How to switch when you want to use another one?
  • I want to set a default account for one path that applies to all sub-directories. How do I do that?
  • I want to set up account individually for each project/directory. How do I do that?
  • My github repo is private. How to make sure I can interact with that repo?

Let’s jump right in. As the first article of this series, I’ll explain the steps to set up SSH with different github accounts first, and explain what SSH is. I’ll put the nuances associated with these setups in the later posts.

In the following examples, I’ll assume we work with the following two accounts:

  • personal github: gh-personal; personal@abc.com –> let’s assume you want your personal account to be the global setting, and only use office account for certain directories.
  • office github: gh-office; office@abc.com

Note that git account and github account are two different things. You can link them with email address, but not the user name.

Step 1: Generate new SSH keys

There are different encryption algorithms you can use to generate SSH keys. GitHub Docs recommend using ed25519 for highest security, although a lot of the articles on this topic still use rsa 4096. At the moment Github still supports RSA keys that used SHA-2 signature algorithm, but DSA key will not be supported after March 2022.

SSH keys are usually stored in home directory, under .ssh/. In mac, go to terminal, then type the following to go to .ssh/ folder:

cd ~/.ssh 

Once you are in /.ssh folder, you can type in ls to view all the files in that folder. If you don’t see a file called ssh.config, you probably haven’t configured any SSH keys yet. So let’s create it by typing in the following command, and associated it with your personal email:

ssh-keygen -t ed25519 -C "personal@abc.com" -f "github-personal-key"  

Note here the -f ... part is to name the key, which is optional, but recommended if you have more than one account. Now, system will prompt you to type in a password. This password is not your github account password, it is a password to protect the key.

Now let’s do the same for your office account:

ssh-keygen -t ed25519 -C "office@abc.com" -f "github-office-key" 

To check if you now have two sets of keys, us the “list all” command ls -al to show all files in that folder. Note that SSH-keys are generated in pairs. So you should see the keys with the names that you gave, as well as the suffix indicating whether it is a public key (with .pub as suffix) or private key (no suffix) returned in terminal like this:

github keys

Figure 1: github keys

Step 2: Add key to SSH-agent

This step is optional. SSH-agent manages your passphrases, so adding SSH keys (private key) to SSH-agent saves you the hussle of having to re-enter passphrase every time you use SSH key.

Still in the ~/.ssh directory, let’s start SSH-agent:

eval "$(ssh-agent -s)"  

First, check if your SSH-agent already have any private key added:

ssh-add -L

If it says “The agent has no identities”, that means no private key is added to ssh agent yet. If there’s something prompt, meaning there are existing identities. We can remove them:

ssh-add -D

Then add your newly generated private keys to SSH-agent. Note that here the “-K” is to add passphrase to Keychain (for Mac users). If you do not wish to add it to Keychain, just skip the “-K” part.

ssh-add -K github-personal-key

When you add key to SSH-agent, you will be prompted to enter passphrase. Do the same thing for another account. If successful, terminal will return “Identity added: github-public-key ( personal@abc.com)”.

If you have multiple github accounts, and want to add all the keys to SSH-agent in one go, use ssh-add. For demonstration purpose, let’s only add the personal account key for now.

Now if we call ssh-add -L again, we should see both keys, with the coresponding email in the end. That means the keys are now added to SSH Agent.

Step 3: Modify SSH config

In this step, we will finally add the keys to config file to specify what keys to look for when using different hosts. If there’s no config file in your ~/.ssh folder, we can create one by typing in command touch config. If you want to create a config file and enter the edit mode at the same time, use nano config.

Then, put the following in your config file:

# This first part is for git to authenticate yor personal github account
Host github-personal        # or whatever name you want to use to call your personal github account. It does NOT need to be the same as your github handle. Although some articles recommend the "github.com-{user-handle}" format
    HostName github.com     # this is the address of the host that you want to connect. in this case, it's github.com
    UseKeychain yes     #  only for macOS users. If you want to keep the passphrase in Keychain, add this line. Otherwise don't include this line
	User git        # because you are allowing git to authenticate github 
	IdentityFile ~/.ssh/github-personal-key     # this tells SSH-agent which key it should use to authenticate the specified host, so it NEEDS to be the same key you created for your personal github account
	IdentitiesOnly yes      # this is optional. It is recommended when you have many different accounts and keys, as SSH-agent iterates over all the keys and try with each one. Specifying identity saves the searching process

# leave a blank line so SSH-agent knows the following section is for a different account, and add your 2nd account here:
Host github-office
    UseKeychain yes
    HostName github.com
    User git
    IdentityFile ~/.ssh/github-office-key
    IdentitiesOnly yes

Step 4: Add public key to GitHub

To build a connection between your local git accounts and remote GitHub accounts via SSH, you will need to give the public key to GitHub. GitHub Docs explained this step very clearly, so just follow that along. After adding your public key to your GitHub account, you want to test the connection. But first, authenticate this action. Note that in GitHub Docs, only the git@github.com is authenticated, which will be only for your global account. Because we are dealing with multiple accounts, we need to authenticate each account separately.

Still in ~/.ssh folder, use the following command:

ssh -T github-account-personal # this should be the same as the Host alias that you just put in ssh config file

If the connection is succesfully authenticated, terminal will tell you (rather excited): “Hi gh-personal (your personal github handle)! You’ve succesfully authenticated, but GitHub does not provide shell access.”. Do the same for your office account.

Step 5: Test connection

Clone from a public repo

Here we can explore a few scenarios The first scenario is probably the most common one, clone from a public repo. When a repo is public, everyone can clone it. First, create a directory where you want to store the cloned repo. Assume it’s under ~/test. Navigate to that directory, and let’s clone a GitHub’s public repo Spoon-Knife. On the repo page, you’ll see the green “Code” button on the upper right. Under “SSH”, copy the address.

Spoon-Knife Repo

Figure 2: Spoon-Knife Repo

In the ~/test directory, type in the following command:

git clone git@github.com:octocat/Spoon-Knife.git

Notice here the actual command is only git clone, and the address following would be the url you just copied. You should have no problem cloning the repo, and you’ll see a new folder called “Spoon-Knife” under your ~/test directory.

We can do a bit of digging. Navigate to the Spoon-Knife folder, in terminal, type in the following command:

nano .git/config

This is to go to the folder .git and open the file config. .git is a system file so usually it is hidden. You will see something like this:

octocat git config

Figure 3: octocat git config

Look! The same address you just used to clone the repo is under [remote "origin"]. Make a note of that as we’ll see something different next. Let’s return to ~/test directory, and delete this “Spoon-Knife” folder:

rm -r Spoon-Knife

Now let’s clone this repo again. Only this time, we’ll specify which key we want to use to connect with the host. We can try the personal key. Remember in Step 4 we specified configuration for each github account, and the host alias for personal github account is github-personal, which is associated with the key github-personal-key, which is then associated with personal email address “ personal@abc.com”. To use this account to clone, type the following in terminal:

git clone git@github-personal:octocat/Spoon-Knife.git

note that the only difference from last attempt is what’s in between the at sign “@” and semicolon “:”. This part is the Host alias, and now we replaced it with our personal host. The repo is successfully cloned, but with a minor difference. Just like what we did in last attempt, let’s open up the config file and take a look again nano Spoon-Knife/.git/config. You’ll notice that under section [remote "origin"], the url is different.

octocat git config with personal account

Figure 4: octocat git config with personal account

If you just want to clone a repo to local and play with it, which account you use does not really make much of a difference. However, if you want to push to that repo, without the right connection, you won't be able to.

Clone from a private repo

When clone from a private repo, you need to make sure to use the right host alias, which will use the correct private key to authenticate the connection. For instance, you created a private repo called “privateRepo-personal” in your personal github account, when clone, the url will look like this:

git clone git@github-personal:gh-personal/privateRepo-personal

Note here the naming for the url follows:

git@<your-host-alias-for-github-account>:<your-github-username>/<your-repo-name>

If you put “github-office” as the host alias, you won’t be able to clone, as it is not the right connection (the private key the host uses does not match the public key you give to your personal github account).

Having the right host alias is important, because when you need to push, make sure the host alias is authenticated and has the right to write (the host alias will refer to the private key to build the connection, and if the corresponding public key is given to the repo’s GitHub account, the connection can be successfully authenticated, meaning you will be able to make commits to that repo.

In the next post, I’ll explain how to set up git account, specify default git account for a specific directory, and what can you change in git config file.