1

I'm trying to define a compact SSH config that matches 3 host naming schemes but also matching many wildcard possibilities, all with a single Host definition like so:

Host xyz-*.domain.com xyz-* xyz*
  HostName xyz-%h.domain.com
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  ProxyCommand nc -x proxy.company.com %h %p

The idea is to match all these hosts, but connect only to the fully qualified version (to reduce the # of entries in the "known_hosts" file):

  • xyz-dev.domain.com = xyz-dev = xyzdev
  • xyz-test.domain.com = xyz-test = xyztest
  • xyz-prod.domain.com = xyz-prod = xyzprod
  • etc.

I know the the above HostName value won't work, as I'm trying to find a way to perform a "regex capture" of sorts in the Host and use it in the HostName expansion.

By using some more advanced config syntax, I managed to come up with a much less readable form that mostly works except the need to still manually accept host keys or having them ignored altogether (not ideal), which still automatically adds them into the "known_hosts" file.

Match exec "echo %h | grep -Eq '^xyz-?[^.]+(\.domain\.com|)$'"
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  ProxyCommand nc -x proxy.company.com $(echo "%h" | sed -rn 's/^xyz-?([^.]+).*/xyz-\1/p').domain.com %p
  # StrictHostKeyChecking no

Is there a better way? It would be great if HostName itself allowed the same kind of shell manipulation that I'm using the ProxyCommand for, but I haven't seen any evidence for that.

1 Answer 1

2

Your easiest option is to write a wrapper script, I'd say.

If you could drop xyzfoo and only keep xyz-foo, then it would be much simpler – just use two config blocks, one with %h and the other without:

Host xyz-*.domain.com
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  ProxyCommand nc -x proxy.company.com %h %p

Host xyz-*
  Hostname %h.domain.com
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  ProxyCommand nc -x proxy.company.com %h %p

In recent OpenSSH versions, you can also make use of two-pass processing:

Host xyz-*.domain.com
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  ProxyCommand nc -x proxy.company.com %h %p

Host xyz-*
  CanonicalizeHostname yes
  CanonicalDomains domain.com
  # (nothing else)

or:

Match final xyz-*.domain.com
  User ubuntu
  IdentityFile ~/.ssh/id_rsa
  ProxyCommand nc -x proxy.company.com %h %p

Host xyz-*
  Hostname %h.domain.com
  # (nothing else)

(The practical difference between these two is that 'CanonicalizeHostname' performs a live DNS check against a list of domains until it finds a match, making it suitable for Host *; meanwhile the '%h' approach is completely static – faster but limits you to exactly one domain per pattern.)

As for known_hosts entries, if you are managing the file manually (or generating it from a script), you could add all the aliases to the same entry:

xyz-foo.domain.com,xyz-foo,xyzfoo ssh-ed25519 AAAAC3NzaC1lZ...
xyz-bar.domain.com,xyz-bar,xyzbar ssh-ed25519 AAAAC3NzaC1lZ...
2
  • Since there's tab-completion on Host block aliases, it shouldn't make any difference on the CLI to drop the no-- aliases. If you drop them, ssh xy{TAB} becomes ssh xyz-, ready for you to type prod and go. Commented Oct 30, 2023 at 19:09
  • Haha, nice edit. I was just about to comment again, suggesting CanonicalizeHostname. Commented Oct 30, 2023 at 19:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .