Namespacing SSH Credentials with Git
Why Namespace SSH Credentials with Git?
Why would you ever want to namespace your SSH credentials with Git? If you have multiple accounts on the same Git hosting service, you might want to use different SSH keys for each account. This is a common scenario for developers who have both personal and work accounts on GitHub, GitLab, or Bitbucket. This post will show you how to set up SSH namespaces with Git, so you can use different SSH keys for different accounts on various hosting services.
Overview
To successfully namespace SSH credentials with Git required several steps. Before we detail these steps, let’s first
look at the high-level overview of the process. We begin by explaining the meaning of a ssh namespace, then outline
the general flow of the process, including the call stack layers of both git
and ssh
. If you want to skip this
overview and begin setting up your namespaces, you can jump to the next section.
SSH Namespaces
An SSH namespace is essentially a description of which SSH keys to use for which repositories. Specifically, it is a combination of:
- A git host (e.g.
github.com
,gitlab.com
,bitbucket.org
) - A namespace within that host (e.g. a username or organization name)
- An SSH key to use for that namespace
- One or more repositories within that namespace
- A local directory containing all the relevant repositories
General Flow of Git and SSH
The general flow of the process is outlined in the diagram below. It begins with a call to git
, which then uses
configuration files to determine a namespace. This namespace is then used to determine how to modify the url for the
subsequent call to ssh
. The ssh
call then uses the url to determine which key to use.
Where the numbered steps correspond to the steps in the following section.
Setting Up Namespaces: 4 Steps
For this walkthrough, we will implement 3 namespaces, two for GitHub and one for GitLab. All source code will be stored
locally under the ~/code
directory, under which we will create subdirectories for each namespace.
Step 0: Prerequisites
Before we begin, we need to establish the context for the 3 namespaces. We will use the following as examples of the Host/Account/Email/Repo combinations that might motivate the use of namespaces:
- Name:
personal
- Host: GitHub
- Account:
personal
- Email:
personal@email.com
- Repos:
repo1
andrepo2
- Name:
work
- Host: GitHub
- Account:
organization
- Email:
work@email.com
- Repos:
repo3
andrepo4
- Name:
collab
- Host: GitLab
- Account:
collab
- Email:
collab@email.com
- Repos:
repo5
andrepo6
Step 1: Create SSH Keys and Add to Hosts
First, we need to create SSH keys for each namespace. We will create 3 keys, one for each namespace. We will use the
default names for the keys, id_ed25519_{name}
and id_ed25519_{name}.pub
, and store them in the default
location, ~/.ssh
. For creating the keys, we can use the following commands:
|
|
Where {email}
is the email associated with the namespace. For example, for the personal
namespace, we would use:
|
|
Make sure that these keys are added to the appropriate host. The GitHub and GitLab documentation provide instructions for adding SSH keys to your account 1 2.
Step 2: SSH Key Routing
Next, we need to create an SSH config file to route the namespaces to the appropriate keys. We will create a file at
~/.ssh/config
with the following contents:
|
|
This file tells SSH to use the appropriate key for each namespace. The Host
lines define the namespace, and the
IdentityFile
lines define the key to use for that namespace. The IdentitiesOnly
line tells SSH to only use the
specified key for that namespace. We will use git url modification to route the namespaces to the appropriate host.
Step 3: Git Namespace Configs
Next, we need to tell git
how to configure each namespace. This is achieved by creating a .gitconfig
file in the
root directory of each namespace. Specific examples are provided below for the three namespaces in this walkthrough.
The file ~/code/personal/.gitconfig
should contain the following:
|
|
The file ~/code/work/.gitconfig
should contain the following:
|
|
The file ~/code/collab/.gitconfig
should contain the following:
|
|
These files tell git
to modify the host name for each namespace. The user
section specifies the email to use for
each namespace, and the url
section specifies the namespace and the host to use for that namespace. We need one more
step, though, to make this work.
Step 4: Git Namespace Routing
The final step is to tell git
to use the ~/code/{name}/.gitconfig
files for each namespace. This is achieved by
modifying the overall ~/.gitconfig
file to include the following:
|
|
This tells git
to use the appropriate .gitconfig
file for each namespace. The includeif
lines specify the
directory to use for each namespace, and the path
lines specify the .gitconfig
file to use for that namespace.
gitdir
path should include a trailing forward slash. This is because git
uses the gitdir
path to match the
directory of the repository, and the trailing forward slash behaves like a recursive glob pattern, e.g. ~code/personal/**
.Using Namespaces
Once the namespaces are set up, you can use them as you would use any other git repository. For example, to clone a
repository in the personal
namespace, you would use the following command:
|
|
git
routing works based on the working directory when the command is run. This means that you need to be in the
appropriate directory for the namespace you want to use. For example, to use the personal
namespace, you would need to
be in the ~/code/personal
directory.Thats it! You should now be able to use different SSH keys for different accounts on the same Git hosting service.
References
This post was adapted from and inspired by several sources, with a few key changes and summary 3 4 5.