For some of us developers, our personal laptop is also our work device (BOYD.) Some organizations might also allow us to use our personal Github account for the work. However, if the later is not the case, it is often inconvenient to switch between two different SSH profiles.
Switchable SSH Profiles for Git and Github + Signing Commits with Appropriate Keys (Bonus Content)
The main idea is to have two SSH profiles switchable with corresponding shell
commands, one for the work and another for the personal projects. A different
way would have been to just use HTTPS in Github instead of SSH, but that comes
with it’s own set of annoyances, which this article will not be diving into
today. Instead, the goal here will be to have two custom aliases, gitp
for
personal, and gitw
for work, which do the required switching.
Background
When fetching from a private Github repository via SSH connection, the public keys are exchanged between your machine and the Git server. This is when Git verifies the machine’s SSH key from the list of the SSH keys Github present in the Github account. This is a very simplified explanation, but it works for our purpose.
The above flow is fine, until we need to work on our personal project that we have set as private. We simply get permission error when trying to fetch or push to that personal repository. The reason is that we don’t have the work related SSH key added to our personal Github. Let’s say that we don’t want to do that, as we want to keep things (like email and SSH keys) separated.
So, how can we solve that? One easy way could be to set repo level Github
configs. For example, running
git config user.email personal_email@example.com
, and other similar commands
in the shell while being inside the project directory should do the job. This is
very flexible, however, I like having a way to just set these values as globals
and get on with the project. I see it like this: if it’s time to work on my
employer’s / client’s stuff, switch to the work mode, and when the work hours
are over, switch to the personal mode. I hope the idea is clearer.
Don’t worry if you got lost somewhere though, as we will go through all the steps, from generating keys and adding them to our Github accounts, to (as bonus content) even using them to sign every commit we make, so that it shows as a verified commit in the Github.
Now let’s start with the setup!
Generating SSH keys
I have taken the reference from the Github docs regarding generating the SSH keys. The steps here should work for any UNIX (-like) shell (Linux, Mac OS, Git Bash for Windows, etc.) If you encounter an error, try following the above reference.
-
Open the terminal and then type the following in the shell, with your correct personal email, of course.
ssh-keygen -t ed25519 -C "personal_email@example.com"
Immediately after running the above, you should get a prompt to enter the location where the generate file is to be saved. If you don’t enter anything, it will be saved in the default path, for example,
/home/[user]/.ssh/id_ed25519
, where[user]
is whatever the actual username in your machine is. However, since we want to have multiple profiles, let’s make the file name a little bit more meaningful by adding-personal
as the suffix. Hence, let’s copy the default path from the prompt itself, and replace the filename fromid_ed25519
toid_ed25519-personal
. The response to the prompt should look something like/home/[user]/.ssh/id_ed25519-personal
. Again, let’s not forget to replace[user]
with the actual username. Now finally, hitEnter ⏎
. -
Immediately, a new prompt asks for the passphrase. You can choose to not have a passphrase. Details on that is beyond the scope of this guide. So just hit
Enter ⏎
a couple more times to get the SSH key generated. To confirm if the files have been generated at the correct location, runls -l ~/.ssh
. The output should look something like this:-rw------- 1 [user] [user] 419 Dec 29 16:50 id_ed25519-personal -rw-r--r-- 1 [user] [user] 106 Dec 29 16:50 id_ed25519-personal.pub
-
Now repeat the above steps 1 and 2, but for work profile. This means you want to run the commands again, but with the work email and
-work
prefix, as shown below:ssh-keygen -t ed25519 -C "work_email@example.com"
In the prompt, enter
/home/[user]/.ssh/id_ed25519-work
, and hitEnter ⏎
. When asked about the passphrase, simply ignore it and hitEnter ⏎
a couple more times. After that running commandls -l ~/.ssh
should give an output like the following:-rw------- 1 [user] [user] 419 Dec 29 16:50 id_ed25519-personal -rw-r--r-- 1 [user] [user] 106 Dec 29 16:50 id_ed25519-personal.pub -rw------- 1 [user] [user] 411 Dec 29 16:49 id_ed25519-work -rw-r--r-- 1 [user] [user] 101 Dec 29 16:49 id_ed25519-work.pub
Notice the two new work related keys.
-
Now time to create the SSH configs. Run the following in the command prompt.
touch ~/.ssh/config-personal touch ~/.ssh/config-work
Open the
~/.ssh/config-personal
file and edit it to have the content as follows.Host * IgnoreUnknown UseKeychain UseKeychain yes AddKeysToAgent yes IdentityFile ~/.ssh/id_ed25519-personal IdentitiesOnly yes
Similarly, edit
~/.ssh/config-work
to have the following content.Host * IgnoreUnknown UseKeychain UseKeychain yes AddKeysToAgent yes IdentityFile ~/.ssh/id_ed25519-work IdentitiesOnly yes
-
Let’s add the keys to the ssh-agent next. But first, the ssh-agent needs to be started, like so:
eval "$(ssh-agent -s)"
Expected output:
Agent pid 59566
Note that pid might be a different number.
Note from the Github docs: Depending on your environment, you may need to use a different command. For example, you may need to use root access by running
sudo -s -H
before starting the ssh-agent, or you may need to useexec ssh-agent bash
orexec ssh-agent zsh
to run the ssh-agent.Next, run one of the following commands depending upon your machine.
For Mac OS
ssh-add -K ~/.ssh/id_ed25519-personal ssh-add -K ~/.ssh/id_ed25519-work
For Linux
ssh-add ~/.ssh/id_ed25519-personal ssh-add ~/.ssh/id_ed25519-work
Adding aliases to switch between the profiles
Now, the SSH keys are ready to be added to the respective Github accounts. However, there is not a way to activate the specific config, yet. Let’s fix that first, and then move to adding the SSH keys to the Github account.
Open your shell’s corresponding rc file, for example .bashrc
for Bash or
.zshrc
for Zsh, and append the following lines at the end.
alias gitp="git config --global core.sshCommand \"ssh -F ~/.ssh/config-personal\" && \
git config --global user.email personal_email@example.com && \
git config --global user.name \"My Name\" && \
echo \"Switched git to personal profile\""
alias gitw="git config --global core.sshCommand \"ssh -F ~/.ssh/config-work\" && \
git config --global user.email work_email@example.com && \
git config --global user.name \"My Name\" && \
echo \"Switched git to work profile\""
We are basically creating a couple of aliases which are going to work as our
commands for switching to the personal and work profiles easily just by running
the gitp
and gitw
commands.
Adding SSH keys to Github
To add the SSH keys that we generated earlier, just follow the Github documentation. We can find all sorts of screenshots to help us out.
Remember to follow the steps two times: first, add the personal SSH public key
~/.ssh/id_ed25519-personal.pub
to your personal Github, and then again the
work SSH public key ~/.ssh/id_ed25519-work.pub
to your work Github account.
Party Time
Let’s try out to see if our hard-work pays off!
Personal Github
In the web browser, from the personal Github open any of the private repositories, and copy the SSH URL for the repo. It looks something like this:
In the terminal, run the following commands.
gitp # Expected output> "Switched git to personal profile"
git clone git@github.com:exanup/anupdhakal.com.git
If everything goes as expected, you should be able to successfully pull the private repositories from our personal Github.
Work Github
Now, let’s repeat the above steps for any of the private repository from our work Github.
gitw # Expected output> "Switched git to work profile"
git clone git@github.com:[organization]/[repository].git # Make sure to use proper repo URL here
Bonus: Signing the Git commits
To sign Git commits, we first need to generate GPG keys and add them to our Github accounts.
The Github documentation has the best illustration for generating the GPG key, and uploading the key to the Github account.
Just like the previous steps, remember to enter the correct personal email address while generating for the personal Github account, and upload it there. Then, repeat that for the work profile, double checking the work email address and the work Github account.
The fun part is now it’s time to update the aliases gitp
and gitw
to allow
the Git commit signature with the correct key.
Again, open the shell’s corresponding rc file, for example .bashrc
for Bash or
.zshrc
for Zsh, and update the following lines like so:
alias gitp="git config --global core.sshCommand \"ssh -F ~/.ssh/config-personal\" && \
git config --global user.email personal_email@example.com && \
git config --global user.name \"My Name\" && \
+ git config --global commit.gpgsign true && \
+ git config --global user.signingkey XXXXXXXXXXXXXXXX && \
echo \"Switched git to personal profile\""
alias gitw="git config --global core.sshCommand \"ssh -F ~/.ssh/config-work\" && \
git config --global user.email work_email@example.com && \
git config --global user.name \"My Name\" && \
+ git config --global commit.gpgsign true && \
+ git config --global user.signingkey YYYYYYYYYYYYYYYY && \
echo \"Switched git to work profile\""
Replace XXXXXXXXXXXXXXXX
with the GPG key ID of your personal GPG key, and
YYYYYYYYYYYYYYYY
with the GPG key ID of your work GPG key.
Now let’s try to create the commits in the personal repo using gitp
first and
pushing the commit. Also, try the same thing, but with the work profile; start
with gitw
and then create and push a new commit.
Go to the Github and check the commits page. Hopefully, you should see the “Verified” label in your latest commit.
Conclusion
That’s it! We should by now have working aliases gitp
and gitw
, which we can
use to easily switch between corresponding SSH profiles for Git.
There are a lot more stuff that we didn’t go into the details, but those are out of the scope for this post. Maybe in another post sometime in the future, we will revisit those in more depth.
Also, this might have opened your mind to multiple possibilities, like creating a dedicated command, instead of the two aliases, to achieve not just two, but multiple SSH profiles. Happy tinkering!
What do you think about the above guide? Did it come in handy for your use case? Feel free to DM me any suggestions or your issues in my Twitter, or just send me a message through the contact portal.