Search code examples
gitssh

SSH config using wrong key?


I started in a new job today, where they use bitbucket, and they have created me an account using my new work email address.

However, when I pasted my SSH key in, Bitbucket complained that the key was already in use (my personal account), so I had to set up another key.

My SSH config looked like this, but it didn't work and seemed to pick up the wrong key:

Host work
  HostName bitbucket.org
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_work
  IdentitiesOnly yes

Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_rsa

then I tried git clone work:path/to/some.git but got "could not read from repo."

I had to edit away my normal id_rsa before it would work, so now it looks like this:

Host *
  HostName bitbucket.org
  User git
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_work
  IdentitiesOnly yes

What did I do wrong?


Solution

  • Using your initial config file (the one with Host work and Host *), you can do a

    ssh -Tv work
    

    You will see what key is actually used. If it is id_rsa, that means what is specified in Host * takes precedence over Host work.

    If you want to use your personal key for everything except work, you would need to use a pattern:

    Host * !work
      AddKeysToAgent yes
      UseKeychain yes
      IdentityFile ~/.ssh/id_rsa
    

    I assumed the wildcard host was a "fallback" option with the lowest precedence. I guess that's not true?

    In an SSH configuration files (~/.ssh/config), the options are applied based on the order they appear in the file, not just based on the specificity of the Host patterns:

    • SSH reads the configuration file from top to bottom.
    • For each Host block, SSH checks if the target host matches the pattern specified. Multiple Host blocks can match the same target host.
    • If a Host block matches, SSH applies the options within that block. Options are cumulative, meaning they can add up, and later options can override earlier ones if they are for the same parameter.

    Since SSH applies configurations in the order they appear, a general Host * block that appears after a specific Host work block can override settings specified earlier for work. The last matching option for a given parameter is what takes effect.

    That is why I excluded work from the Host * pattern (Host * !work)

    Alternatively, you could place the Host * block before the Host work block, but it is not reliable for IdentityFile: SSH can still accumulate multiple identity files from matching blocks unless you use IdentitiesOnly yes.

    For more information, see "What SSH identities will be offered to a remote server and when" from Chris Siebenmann.