# Auto-switching SSH keys for work repos

https://blog.cynexia.com/auto-switching-ssh-keys-for-work-repos

Author: [Rob Aleck](https://blog.cynexia.com/pages/about) · https://github.com/mnbf9rca · https://www.linkedin.com/in/robertaleck/ · https://family-foqos.app/

Published: 2026-03-04
Categories: How-to


I have a personal GitHub account and a corporate one, and I found it annoying to have to select the correct SSH key for work repos, so I configured git and SSH to pick the correct key for me. After initial setup, there are three config files to modify:

After the initial setup, there are three config files involved:

1. **Git URL rewrite** (`~/.gitconfig`) — rewrites work org URLs to an SSH host alias
2. **SSH host alias** (`~/.ssh/config`) — maps that alias to the right key (and port `443` if needed)
3. **Work-only Git identity** (`~/.gitconfig.work`) — sets work email/name/signing key, loaded automatically for work repos

How does it work? well

- Whenever it sees a matching string, **Git** rewrites `git@github.com:my-org/...` → `git@github.com-work:my-org/...`
- **SSH** sees `github.com-work` and uses the work SSH key (and optional port `443`)
- **Git config** loads the work identity/signing settings only when the repo is a work repo

I clone a work repo now and everything is already correct.

## Generating the keys

### SSH key first:

```
ssh-keygen -t ed25519 -C "you@work.com" -f ~/.ssh/work_id_ed25519
```

Give it a passphrase, then add the **public** key (`~/.ssh/work_id_ed25519.pub`) to your work GitHub account under Settings > SSH and GPG keys.

### (Optional if you want commit signing) GPG key:

```
brew install gnupg # if not installed
gpg --full-generate-key
```

Pick RSA 4096 or ed25519, enter work email. Then grab the key ID:

```
gpg --list-secret-keys --keyid-format long
```

The hex string after the algorithm (e.g.`ed25519/94DC844444530B75`) is your signing key ID. Add the public key to GitHub too:

```
gpg --armor --export 94DC844444530B75
```

Paste that into Settings > SSH and GPG keys > New GPG key.

## Git URL rewrite (`~/.gitconfig`)

Configure Git to map the work github host to a pseudo-hostname (a "hook" that SSH can match on):

```
[url "git@github.com-work:my-org/"]
    insteadOf = git@github.com:my-org/
```

Now whenever I clone, push etc. to a repo under my work org, git transparently rewrites the host to the pseudo-hostname.

## SSH host alias (`~/.ssh/config`)

SSH resolves `github.com-work` here and connects to GitHub's SSH-over-HTTPS endpoint with my work key.

```
Host github.com-work
    HostName ssh.github.com
    Port 443
    IdentityFile ~/.ssh/work_id_ed25519
    IdentitiesOnly yes
```

- `IdentitiesOnly` yes stops the agent from trying my personal key.
- It uses port `443` because corporate the firewall blocks `22`.

Quickly check SSH config works:

```
❯ ssh -T git@github.com-work
Hi your-work-github-username! You've successfully authenticated, but GitHub does not provide shell access.
```

## Configure work-specific git config

Create `~/.gitconfig.work` with work identity:

```
[user]
    email = you@work.com
    name = Your Name
    signingkey = YOUR_GPG_KEY_ID
[github]
    user = your-work-github-username
[commit]
    # if you want signed commits
    gpgsign = true
```

### Hook it up with `includeIf` so it auto-loads

This tells Git *when* to include the work config. Because the URL rewrite above changes work remotes to `git@github.com-work:my-org/...`, you can include your work identity only when a repo has a remote URL matching that pattern:

```
# ~/.gitconfig
[includeIf "hasconfig:remote.*.url:git@github.com-work:my-org/"]
    path = ~/.gitconfig.work
```

That tells Git: if any remote URL in this repo matches `git@github.com-work:my-org/...`, load `~/.gitconfig.work` to set my work email/name/signing key.

All three files are templates gated on a `machineRole` variable in Chezmoi, which gets set during `chezmoi init`. On a personal machine, none of this renders.

I clone a work repo now and everything is already correct and i haven't thought about it since setting it up.

