TechEarl

Use Multiple SSH Keys with ~/.ssh/config

Run separate SSH keys for work, personal, and GitHub by binding each to its host in ~/.ssh/config with IdentityFile and IdentitiesOnly, so the right key is always offered.

Ishan Karunaratne⏱️ 4 min readUpdated
Share thisCopied
Bind separate SSH keys to separate hosts in ~/.ssh/config with IdentityFile and IdentitiesOnly so the correct key is offered every time.

To use multiple SSH keys, bind each key to its host in ~/.ssh/config with an IdentityFile line plus IdentitiesOnly yes, so SSH offers only the right key per host. If you keep separate SSH keys (work versus personal, prod versus staging, one GitHub account versus another), the problem is making SSH pick the right one automatically. The answer is ~/.ssh/config: bind each key to the host that should use it.

Why you get "too many authentication failures"

By default SSH offers every key it can find, in order, until one works or the server cuts you off (MaxAuthTries, usually 6). With several keys loaded you can exhaust that limit before the correct key is tried, and the server returns Too many authentication failures. The fix is to tell SSH exactly which key goes with which host, and to offer only that one.

A config that maps keys to hosts

code
# ~/.ssh/config

Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_personal
    IdentitiesOnly yes

Host work-git
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work
    IdentitiesOnly yes

Host prod
    HostName prod.example.com
    User deploy
    IdentityFile ~/.ssh/id_ed25519_prod
    IdentitiesOnly yes

IdentitiesOnly yes is the important line: it stops SSH from offering any key except the listed IdentityFile, which is what prevents the "too many failures" cutoff.

Two GitHub accounts on one machine

This is the classic case. GitHub identifies you by the key, not the URL, so you cannot use git@github.com for both. Use a host alias for the second account (the work-git block above), then point the repo at the alias:

bash
git clone git@work-git:company/repo.git
# or change an existing repo's remote:
git remote set-url origin git@work-git:company/repo.git

Personal repos keep using git@github.com:...; work repos use git@work-git:.... Each resolves to github.com but offers a different key.

Test which key a host will use

bash
ssh -T git@github.com      # personal account
ssh -T git@work-git        # work account

GitHub answers Hi USERNAME! with the account the offered key belongs to, so you can confirm each alias maps to the right identity.

FAQ

Without configuration, SSH offers all available keys in a fixed order and the server accepts the first valid one, which may not be the account you intended. Pin the key per host with IdentityFile and add IdentitiesOnly yes so only that key is offered.

Create a second key, add it to the second account, and define a Host alias in ~/.ssh/config (for example work-git) with its own IdentityFile. Clone work repos with git@work-git:owner/repo.git and personal repos with git@github.com:owner/repo.git.

It tells SSH to offer only the keys named by IdentityFile for that host, ignoring keys loaded in the agent. This avoids the Too many authentication failures error that happens when SSH tries several wrong keys first.

See also

Sources

Authoritative references this article was fact-checked against.

TagsSSHssh-configIdentityFileGitHubLinuxDevOps

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Software Systems Architect · Senior Software Engineer · Engineering Leadership

Software systems architect and senior software engineer with more than two decades designing, building, and running production software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Now a CTO, though what I write here is drawn from the full arc of that work, across architecture, engineering, and operations, not any single job.

Keep reading

Related posts

Search multiple patterns with grep: grep -e 'A' -e 'B', grep -E 'A|B' alternation, and grep -f patterns.txt. Covers -F fixed strings, AND logic with chained greps and PCRE lookahead, and BSD vs GNU differences on macOS.

How to Search Multiple Patterns with grep

grep can OR several patterns three ways: -e per pattern, -E with alternation, or -f reading the list from a file. The one-liner is grep -E 'ERROR|WARN|FATAL' file. Here is when to pick each, how -F speeds up literal multi-pattern search, why grep has no single-pass AND, and the BSD vs GNU differences that bite on macOS.

How to set up push-to-deploy with GitHub Actions: a CI/CD workflow that builds and deploys on every push to main.

Push-to-Deploy with GitHub Actions

A beginner-friendly intro to CI/CD with GitHub Actions: a real workflow YAML that builds and deploys on every push to main, plus how to handle secrets safely.

Push one change to a fleet of WordPress installs from one Google Sheet: group rows by a website column, fan each batch out to its site, with partial-failure handling.

Manage Multiple WordPress Sites From One Google Sheet

Run a fleet of WordPress installs from a single Google Sheet: a website column per row, a small controller that groups the rows by site and pushes each batch to that site's endpoint, and partial-failure handling so one dead site never blocks the rest.