Using SSH keys to streamline access to frequently-accessed servers

Even though Apple has effectively killed off macOS Server (or at least gutted it and left it a smoking ruin of its former glory) there are still a lot of uses for a big box full of drives stuck in a closet for people to keep all their files on. While the assorted macOS Server services have largely gone away there are lots of good third-party services that have taken their place, and they are still things that need remote access, control, troubleshooting and tweaking. Which means you still need to be able to get to them quickly, fully, and securely.

Now, there’s a phrase that I trot out whenever I’m asked to stand up in front of a crowd in a hotel ballroom and talk about security. Helen Keller nailed when she said that “Security is mostly a superstition. It does not exist in nature, nor do the children of men as a whole experience it.” It’s a quote that I think should be seared onto the back of the eyelids of anyone who works in IT; there’s no such thing as “security,” and when you’re talking about that as a concept what you’re really talking about it the Mitigation of Risk.

There are no absolutes; every security procedure is effectively just a barricade, and you have to assume that time and ingenuity by bad actors are going to bring it down. The best thing you can do is stay vigilant and use common sense and good tools. In this case, that means using encrypted keys to authenticate access to servers.

So, here’s the scoop:

I have a 2009 Mac Pro sitting under my desk that I’ve hotrodded within an inch of its life with NVMe storage, a beefy graphics card, USB-C 3.1 and an astonishing twelve (twelve!) core 3.47Ghz Xeon. It’s full of big, fast storage and it’s a beast for Xcode builds, and the best thing about it is that I cobbled the thing together out of a lot of boxes of scrap. It’s running Catalina 10.15.1 with the dosdude1 hack, and I’ve ported my old .profile file into the new, shiny, zsh-compliant .zprofile file. I like to throw a lot of aliases in there, and what I really wanted to do was have aliases I could bang into the keyboard that’d log me into one remote server in my basement and another that sits across town in my office. Additionally, there are a couple of client servers that we have maintenance contracts on that I like to keep an eye on a couple of times a day on the grounds that this is an excellent way to catch little things before they turn into big things.

So, in total there are four servers, each in a separate geographic location and each with their own frighteningly complex password structure. I don’t keep passwords and credentials on a sticky note on my desk because that’s breathtakingly irresponsible, and Terminal doesn’t want to play nice with stashing credentials in Keychain, so I needed a better way of quickly getting remote access from the Terminal, and this is where SSH came in.

Step 1: Make some SSH keys using ssh-keygen.

It’s worth looking through the man page for ssh-keygen, as there’s a lot of good stuff there. What we need to do is pretty straightforward, though; make a private/public key pair and specify the type of key you want to make with the -t flag. There are a few options, but I used rsa:

ssh-keygen -t rsa

Step 2: Answer some questions.

Hit return to save the key to the default location in your home folder. Enter a passphrase, because not password-protecting your keys is A Bad Idea. There are many reasons to password-protect this key but the biggest, scariest one is that in the very unlikely event that anyone got hold of your ~/.ssh/id_rsa file then they’d be able to use it to log in as root on any server set up to take use that for authentication. Password protecting it with a strong password is essential.

Step 3: Push the public key to the remote machine.

You’ll need to have SSH enabled for this on the remote machine, but chances are that if you’re doing this then you already enabled SSH several months ago. The following command goes and reads the public key you created in ~/.ssh, then pipes that to an ssh session that logs into the remote machine, creates the user-level .ssh directory and writes that key into the authorized_keys file:

cat ~/.ssh/ | ssh user@remotelocation.server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Step 4: Tell your client machine to cache the keys.

The key pair you generated way back in step 1 essentially works on a session basis. If you restart your Mac then you’ll have to enter the password to get this all working again. Fortunately, you can pre-cache the keys by using the ssh-add command

Step 5: Embrace the laziness.

Fire up your command-line text editor of choice (I like pico/nano) and edit your .zprofile with something like the following:

alias server1="ssh"

alias server2="ssh"

alias server3="ssh"

…you get the idea. Save the file, open a new shell, and all things being equal you’ll be able to use those new aliases to securely log in to the appropriate remote server without fat-fingering a lot of fiddly passwords.