This was started as a ~/.ssh
cleanup. Single config file for every host:
# another globals omited
IdentitiesOnly yes
IdentityFile id_%r
IdentityFile ~/.ssh/%h/id_%r
# basically bare minimum
Host github.com
User git
# just add another entry and that's it
Host peptide
HostName 192.168.0.201
Port 1234
User remote
And separate directory per host for identities:
$ tree ~/.ssh
config
github.com
id_git
id_git.pub
peptide
id_remote
id_remote.pub
After inventing such a great scheme that structure well enought SSH keys directory, it was a bit disappointing to find out there is no way to use Host
as a name for directory with identities. man ssh_config
says:
TOKENS
Arguments to some keywords can make use of tokens, which are expanded at runtime:
%% A literal `%'.
%C Shorthand for %l%h%p%r.
%d Local user's home directory.
%h The remote hostname.
%i The local user ID.
%L The local hostname.
%l The local hostname, including the domain name.
%n The original remote hostname, as given on the command line.
%p The remote port.
%r The remote username.
%u The local username.
Match exec accepts the tokens %%, %h, %L, %l, %n, %p, %r, and %u.
CertificateFile accepts the tokens %%, %d, %h, %l, %r, and %u.
ControlPath accepts the tokens %%, %C, %h, %i, %L, %l, %n, %p, %r, and %u.
HostName accepts the tokens %% and %h.
IdentityAgent and IdentityFile accept the tokens %%, %d, %h, %l, %r, and %u.
LocalCommand accepts the tokens %%, %C, %d, %h, %l, %n, %p, %r, and %u.
ProxyCommand accepts the tokens %%, %h, %p, and %r.
RemoteCommand accepts the tokens %%, %C, %d, %h, %l, %n, %p, %r, and %u.
It means, this works well as intended but not as expected by the scheme:
$ ssh remote@peptide date
no such identity: id_remote: No such file or directory
no such identity: /home/paul/.ssh/192.168.0.201/id_remote: No such file or directory
Not good at all. Even so, workaround exists. Placing this line at the end of ~/.ssh/config
does a dirty fix.
Match exec "[ %n != %h ] && [ -d %n ] && ln -fs ~/.ssh/%n ~/.ssh/%h"
Usually, Match
narrows ongoing Host
declarations, e.g pointing to another location of a id_rsa
file when user@
came from command line. This time it works as a sort of autorun command. It compares "original" remote (nice mnemonic name for the host) with HostName
from config file and force creation of a symlink to the directory with keys. Even though it look like misuse, it works nice in another context too. Match
may help in transparent port knocking:
Host alp
HostName 127.0.0.1
Match exec "for port in 3000 4000 5000; do nc -zw3 %h $port; sleep 1; done"
Hacky, right?