9th Inning Thoughts
When the bases are full a single bunt will suffice



Switching SSH Private Key based on Folder Paths

2026-02-08T00:00:00-03:00


Intro

Anyone working on multiple repositories from multiple clients developer will adopt the pattern of using a single Private Key shared between project to facilitate the workflow.

The problem with that approach is: Once your private key gets leaked every single repository you had associed with is now compromised.

To avoid that I prefer to use different keys to different groups of repositories.

The First Step

The easiest way to start working with multiple keys is make use of .ssh/config file.

This file let us create a set of configurations based on domain used by git.

Let's assume you have two repos:

To avoid any chances of editing the wrong "repo-X" We will organize them in sub-folders:

/home/johndoe
    ├── Projects
    │   ├── acme
    │   └── personal

and here's our .ssh/ folder:

/home/johndoe/.ssh
  id_ed25519
  id_ed25519.pub
  id_ed25519_acme
  id_ed25519_acme.pub

Where id_ed25519 is our Secret Key for personal projects.

Now we will clone our private repo on the personal folder:

cd ~/Projects/personal
git clone git@github.com:johndoe/repo-2.git

That will work just fine, resulting in:

/home/johndoe
    ├── Projects
    │   ├── acme
    │   └── personal
    │       └── repo-2

but if you try the same for the repo-1 it will not work.

cd ~/Projects/acme;
git clone git@github.com:acmegroup/repo-1.git

It will fail because git will try to use the same key for the personal repos.

We can represent the git clone as:

FROM git@github.com CLONE acmegroup/repo-1 WITH ~/.ssh/id_ed25519

So how can we tell git (ssh) to use a different key?

We edit the .ssh/config file and tell ssh to use a certain key when trying to reach certain host domain:

# ~/.ssh/config
Host github.com
    IdentityFile ~/.ssh/id_ed25519_acme

then we re-execute:

cd ~/Projects/acme;
git clone git@github.com:acmegroup/repo-1.git

resulting in:

/home/johndoe
    ├── Projects
    │   ├── acme
    │       └── repo-1
    │   └── personal
    │       └── repo-2

All done! Right? Not quite, but we are halfway there.

Even though our previous git clone for ACME's repo-1 will worked now any other operations (push, fetch, etc) for our personal's repo-2 will fail.

How do we fix the personal repository operation?

Simple. Instead of using github.com we will use a custom (alias) domain when cloning our non-personal repositories. For example: We will use github_acme.com (alias) domain when cloning our ACME's repo-1.

cd ~/Projects/acme;
git clone git@github_acme.com:acmegroup/repo-1.git

Of course the new (alias) domain does not exist in the real WWW and cloning will fail. That is because we need one last step: Update the .ssh/config file to handle the "alias" domain.

Host github_acme.com
	IdentityFile ~/.ssh/id_ed25519_acme
	HostName github.com

This will tell ssh to do two things before when we try to clone from the custom github_acme.com:

We can represent that as something like:

IF host == github_acme.com THEN
    FROM git@github.com CLONE <some-repo> WITH ~/.ssh/id_ed25519_acme
ELSE
    FROM git@github.com CLONE <some-repo> WITH ~/.ssh/id_ed25519
END

At this point you're all set to start working with even more Secrets Keys per repository.

As long as you remember to always adjust your git repo's domain to match the configuration from .ssh/config

Over-engineering to reduce cognitive load

At some point the motions required to adjust your git repo's domain will get old. Believe me.

The endgame here is to:

To do so we will create a .gitconfig_acme to change the git domain (github.com) to the "alias" domain we use on .ssh/config: github_acme.com

# ~/.gitconfig_acme
[url "git@github_acme.com"]
  insteadOf = git@github.com

And we want to do that only for git operations from our ~/Projects/acme folder. That is achieved by editting the ~/.gitconfig (no suffix)

# ~/.gitconfig
[includeIf "gitdir:~/Projects/acme/"]
    path = .gitconfig_acme

So now everytime we do:

cd ~/Projects/acme;
git clone git@github.com:acmegroup/repo-1.git

The following logic will be executed:

GIT {
  IF current_path == ~/Projects/acme THEN
    host = github_acme.com
  END
}

SSH {
  IF host == github_acme.com THEN
    FROM git@github.com CLONE <some-repo> WITH ~/.ssh/id_ed25519_acme
  ELSE
    FROM git@github.com CLONE <some-repo> WITH ~/.ssh/id_ed25519
  END
}

Conclusion

We added two extra steps of rewriting our initial request but in exchange we finally achieve and smooth git workflow working with multiple secret keys.