SSH passwords are a pain. So are usernames.
So, for that matter, are hostnames, ports, and IP addresses.
If you're regularly doing maintenance on websites or web apps, chances are you're logging into remote servers using SSH. But even if you use a password manager—and if you don't you should—SSH passwords are a pain. Usually it's necessary to switch away from the terminal, retrieve the password, switch back to the terminal, and then proceed with the login. You probably also need to retrieve the hostname or IP address, ssh port, and username. Not convenient.
This workflow can be gotten around using tools like Coda, and Lastpass's new command-line tools, but if you don't use Coda, and if you don't use Lastpass, then you can be stuck using passwords (in fact, the solution I explain below can also be used with Coda).
So what's the alternative?
The alternative is public key authentication. Essentially, you achieve this by generating public and private cryptographic keys and copying the public key to each remote server. On ssh login, if these keys correspond, no password will be required.
Setting this up is not difficult, but it does require that you be comfortable in the terminal (but so does SSH after all…) The directions that follow assume you're running some reasonably recent version of OSX, but the basic steps would be the same on Linux systems.
Set it up
1. Generate a public-private key pair
The first thing you need is to create the actual public-private key pair using
ssh-keygen. It's important to remember that your keys are
1a. Passphrase-protect your key
ssh-keygen command will prompt (but not require)
you to use a passphrase. I strongly encourage the use of passphrases with SSH
keys. It means you'll have to re-enter the passphrase the first time you make
an SSH connection using that key when you restart or re-login to your computer,
but since the key can be used to connect to multiple systems, the extra
security is essential.
1b. Give your key a custom name
I create different keys with their own names for different purposes. For example, I might create one named after my employer for use at work and a different one for use on side projects. This means that if ever I need to retire a given key pair, I won't have to reconfigure my authentication for every server I need to connect with.
The following command will create a custom-named public-private key pair in the conventional directory (change the 'demo_key' text to change the name of your key):
ssh-keygen -b 4096 -t rsa -f ~/.ssh/demo_key
There are three flags used in the command:
-b: number of bits in the created key; very generally, more is better and 4096 should be ok
-t: type of key; use 'rsa'
-f: file name; use this to name your key; unless you have some good reason not to, put it in the
.sshdirectory with your other key(s)
The whole creation process should go something like this (again, I encourage you to use a passphrase when creating your key):
1 Username$ ssh-keygen -b 4096 -t rsa -f ~/.ssh/demo_key 2 Generating public/private rsa key pair. 3 Enter passphrase (empty for no passphrase): 4 Enter same passphrase again: 5 Your identification has been saved in /Users/Username/.ssh/demo_key. 6 Your public key has been saved in /Users/Username/.ssh/demo_key.pub. 7 The key fingerprint is: 8 dd:6b:c9:de:d0:df:3c:74:92:97:1c:97:7b:7d:9b:fb Username@Username.local 9 The key's randomart image is: 10 +--[ RSA 4096]----+ 11 | | 12 | | 13 | .| 14 | . . o.| 15 | S . . ..*| 16 | . +o=*| 17 | * oo*| 18 | o o *.| 19 | . ..E| 20 +-----------------+
2. Copy your public key to your server(s)
In principle, it's quite possible to get your public key to the remote server in a variety of ways. However, since the public key must be copied into a specific file with specific permissions in a specific directory, I prefer to use a purpose-built tool,
ssh-copy-id (and I prefer to install it using Homebrew).
ssh-copy-id, transferring your public key to the server is a cinch:
ssh-copy-id -i ~/.ssh/demo_key.pub -p 1234 email@example.com
The parts of this command are:
-i: the location of the public key file
-p: the SSH port (leave this out if you connect to SSH on port 22)
firstname.lastname@example.org: this is the username/hostname combination you generally use to connect to your server
You'll be prompted to enter your password, but this should be the last timer. The tool will also suggest you check to see that the right key was added. This means you need to:
- SSH to the server (you should already be able to do this passwordless:
- inspect the contents of
~/.ssh/authorized_keysto make sure your new key is present
3. Create an alias to the server
This is the part I really enjoy about passwordless SSH. Typing
ssh email@example.com without needing to enter a password is good, but it turns out that we can shorten or simplify the command itself.
We've already elminiated the password, but we can also create a file containing the remainder of the information we need to login, the username, hostname (or IP), and the port (if not '22').
Create a new file in your
.ssh directory called simply
config. This file will contain all the information you use to connect to your various SSH host machines.
3b. Add the alias to the file
The file is a simple text file, and the entries look like this:
1 Host example 2 Hostname example.com 3 Port 1234 4 User user
Here, we record the username (
user), the hostname (
example.com), and the
1234). We also have a line beginning with
Host. This is the shortcut
we'll use for SSH connections for now on. So our command which used to be
firstname.lastname@example.org -p 1234 (plus password) will now be
ssh example (without a
When I first set this up, I was ecstatic just at the prospect of being able to have instant SSH access to servers I needed to work on directly from the terminal (I do almost all of my coding in Vim, so I'm usually working in a terminal in the first place). But besides that, there are a couple of things to know when passwordless SSH is part of your regular workflow.
It works with SCP
This is a teriffic side benefit. As development has moved away from the use of FTP, we really don't do as many manual file transfers as we used to. However it's still sometimes necessary to transfer a tarball, database dump, or other file from a development machine to some remote server.
The safe way to do this is to use SCP. Happily, our passwordless SSH setup works directly with SCP. Using our above example we can transfer a file up or down using the alias from the config file:
scp ./local-file.txt example:~/local-file.txt
scp example:~/remote-file.txt ./remote-file.txt
Enabling passphrase-protected keys
If you passphrase-protect your keys (as suggested above), you'll need to
authenticate before you can use them. This is done with the
This produces a dialogue like this:
1 Username$ ssh-add ~/.ssh/demo_key 2 Enter passphrase for /Users/Username/.ssh/demo_key: 3 Identity added: /Users/Username/.ssh/demo_key (/Users/Username/.ssh/demo_key)
Removing access to a remote server
When using passwordless SSH logins, the private key is stored on the local machine, but the public key resides on as many servers as the local machine has access to. These keys must sometimes be removed if an employee moves, a temporary job finishes, or a client moves on.
To do this, all that's necessary is to log into the server (passwordless!) open
the file at
~/.ssh/authorized_keys, and delete the line containing the