== What SSH keys in your .ssh/config will be offered to servers Recently I've become aware that some things about specifying keys in _.ssh/config_ don't work quite the way I absently thought they did. Let's start with a simple situation: .pn prewrap on > Host * > # encrypted & usually loaded into > # ssh-agent > IdentityFile /u/cks/.ssh/ids/key-ed2 > > Host github.com > IdentitiesOnly > IdentityFile /u/cks/.ssh/ids/github When I set up my _.ssh/config_, this configuration looked like it would offer Github only my Github specific key. It doesn't; it offers _key-ed2_ as well (in fact it offers _key-ed2_ first). What's happening is that _IdentityFile_ is *cumulative*, and so every _IdentityFile_ in every matching _Host_ stanza is another key that will be offered. When you connect to _github.com_, both the '_Host *_' and the '_Host github.com_' stanzas match, so the _IdentityFile_ directives from both are used. (Where this matters is that servers have a limit on how many keys you can offer them before they drop your connection. This can make it important to send them the right key first or at least very early.) This can make _IdentitiesOnly_ into an essentially meaningless directive. If the only key we ever load into our _ssh-agent_ is the _key-ed2_ generic key, that's what happens here; it's always a candidate _IdentityFile_ key so it will never be excluded. _IdentitiesOnly_ only matters if you load extra keys from outside your _.ssh/config_ (or at least from outside a '_Host *_'). If _ssh-agent_ is not running or does not have keys loaded, you can get around this by reordering your _.ssh/config_. ~~Without _ssh-agent_, keys are offered to servers in the order of _IdentityFile_ directives~~. If the '_Host github.com_' stanza is before '_Host *_', the Github specific key will be offered first (and then accepted). Unfortunately this doesn't work if you have keys loaded into _ssh-agent_, as ~~keys from _ssh-agent_ are always tried first before keys from _.ssh/config_~~ ([[in the order they were loaded into _ssh-agent_ SshAgentAndMultipleKeys]], not the order in _.ssh/config_). This is the case even with _IdentitiesOnly_ specified. The rather awkward and not very scalable hack fix for this is to specifically exclude some destinations from the generic '_Host *_' stanza: > Host * !github.com !elsewhere.com ... > ... As long as you specify _IdentitiesOnly_ in the host-specific _Host_ stanza, things work right (and the order in _.ssh/config_ doesn't matter). This is clearly not scalable if you have very many of these hosts; every time you add a new one, you need to remember to add it to the '_Host * ..._' exclusion as well or things will go subtly wrong. And if you have truly generic parameters other than _IdentityFile_, you'll need a separate '_Host *_' stanza for them. The other workaround is to only use your general keys through _ssh-agent_ and strip them out of _.ssh/config_ (here we'd delete the _IdentityFile_ line for _key-ed2_). This costs you the ability to use them with _ssh_ when _ssh-agent_ is not running (or doesn't have them loaded), but it makes _IdentitiesOnly_ do what we want it to. As far as I know there's no other way around this, although I'd love to be wrong. The whole situation is kind of irritating and I wish there was a version of _IdentitiesOnly_ that meant 'only identities from this specific Host/Match stanza'. It's also irritating that such an important issue as key choice and key ordering is not discussed explicitly in the OpenSSH client documentation. (Of course this also means that OpenSSH is free to change any or all of this on you in future versions, because they never made any official promises about how it worked. It's almost all 'undocumented behavior' and we're on our own.)