Skip to main content
  1. Posts/

Stop Making Shell Aliases for SSH!

Stop me if you’ve had this problem before. You need to ssh into a server, but it has some horribly complicated rules, so your SSH command looks something like

ssh -p 9999 myuser@complicated.hostname.com

Then you add public key authentication (you are using pubkey authentication right?), only to discover that because you used a nonstandard key name, you have to pass the keyfile to SSH. So now your SSH command looks like

ssh -i ~/.ssh/myspecialkey -p 9999 myuser@complicated.hostname.com

and typing it out is really starting to get painful.

So you try for a while, but eventually you get tired of all this typing, and add the following line to your ~/.bashrc:

alias sshcomplicated="ssh -i ~/.ssh/myspecialkey -p 9999 myuser@complicated.hostname.com"

and all is well and good.

Right?

All is not well and good
#

First off, I’d like to applaud you for reaching this solution: given the choice, it is almost always better to use an automated solution to avoid lots of repetitive typing. Unfortunately, in this case, a shell alias is the lowest level of automation, and it suffers from quite a few nasty issues:

  1. You have to make an alias for each host you want to visit. If you only have one host, this is fine. If you have 5 hosts, maybe fine. If you have 20 or 30 hosts you want to SSH into, this becomes a mess to keep track of.
  2. What about other remote access services? What if you want to use rsync, scp, sftp, or even mosh or the VSCode Remote Plugins? Do you need to now make aliases for each of these programs? What if you combine this with the previous problem? If you assume a modest 10 machines and 5 services, you now have 50 aliases you have to write.
  3. What if your weird SSH port changes for one set of your SSH machines, but not another? (For example, one organization changed the SSH port but the rest are keeping the default). Do you have to manually pick your way through your 50 aliases to find the ones you need to change?

It seems like what we need is some sort of way of storing our SSH information that:

  • Can easily store lots of different host info without being too complex (solves problem 1)
  • Can be read + understood by many different programs (solves problem 2)
  • Can store information hierarchically, that is, some information is automatically applied to multiple entries at once (solves problem 3)

Fortunately, it turns out there’s already a file that does this for us: the SSH Config

The SSH Config File: Overview
#

Let’s take a look at a basic SSH config entry in ~/.ssh/config:

Host unicorns
    Hostname prettyhorses.company.org
    User myuser
    Port 3355
    IdentityFile ~/.ssh/myspecialkey

This sets the Hostname, User, Port, and IdentityFile entries for the host unicorns. Now, if I go to the command line and type ssh unicorns, SSH will know to apply certain options: it’s functionally equivalent to if I typed

ssh -i ~/.ssh/myspecialkey -p 3355 myuser@prettyhorses.company.org

Now, on it’s own, this may not seem like much savings over a simple shell alias. What gets really good is that scp knows how to interpret this file as well. So if I type

scp ~/myfile unicorns:myfile

scp will know to apply the options it finds for Host unicorns in the SSH config file, and it’s the same as if I typed

scp -i ~/.ssh/myspecialkey -P 3355 ~/myfile myuser@prettyhorses.company.org:myfile

In fact, many (I might go as far as to say most) Unix programs that access remote computers can understand the SSH Config file format. This makes it easy to write your config exactly once, then forget about it.

Advanced Config: Match Clauses
#

So now you’re setting up your SSH config, but you have a lot of computers from this one organization that all have the same settings. For example, let’s say you’re part of the Institute for Silliness (IS) and you always use the same settings there: the username is sillyuser, the keyfile is your sillykey, and all the systems have SSH on port 3000 as a matter of protocol.

You can set up a match clause in your SSH file that will apply settings to all hosts that meet a certain criteria. It might look something like this:

Host clowns
    Hostname clowns.silly.institute.edu

Host balloon
    Hostname balloon-animals.silly.institute.edu

Host strings
    Hostname silly-string.silly.institute.edu

# etc. etc.

Match host *.silly.institute.edu
    User sillyuser
    Identityfile ~/.ssh/sillykey
    Port 3000

Now all your hosts that have silly.institute.edu will have the special settings applied at once. Even better: if the Institute for Silliness ever changes its settings, you only have to edit a few lines to change everything over!

Conclusion
#

This is far from the total power of SSH Config files: you can go nuts with options like proxy hosts, allowing/disallowing certain ciphers on some hosts, automatially running commands once you log in to a certain host–in general, if you can run an SSH command to do something, you can usually encode it into the SSH config so that it does that every time.

Hopefully I’ve convinced you that setting up an SSH config is definitely worth your time. If you want to just what these things can do, there are some great tutorials out there on the internet!