Last updated: 28 April 2021

In our article about SSH basics we connected to a remote server by entering our user password. You can instead set up key-based, or passwordless, authentication.

There are a number of reasons why you might want to set up key-based authentication:

  • It is convenient, as you don’t have to enter the user password every time you use SSH.
  • On a VPS or dedicated server it can add an extra layer of security. After you have set up key-based authentication you can disable password authentication. That makes it more difficult for attackers to brute-force their way in to your server.

How does key-based authentication work?

To set up key-based authentication you need a private and public key (also called a “key pair”). As the name suggests, the private key should never be shared.

Ideally, the private key is also password-protected. It is worth noting that giving your private key a password takes away the convenience argument. The remote server won’t prompt you for the user password, but instead your operating system prompts you for the key’s password.

As a compromise you can tell your operating system to remember the password. Whether or not that is a good solution depends on how much you value security vs convenience. There are various considerations here. For instance, having an unprotected private key on an unencrypted laptop that travels a lot is not a good idea. If your laptop gets stolen the thief can SSH to your server without needing a password.

Generate a key pair

If you don’t have a key pair yet you need to first create one. On macOS and Linux you can simply run the command ssh-keygen in a terminal window. If you are on Windows you need to do some extra work. First, you first need to make sure that the OpenSSH module is installed by running the following command in PowerShell:

Install-Module -Force OpenSSHUtils

Next, you need to start the service:

Start-Service ssh-agent
Start-Service sshd

And finally, before you run the ssh-keygen command you need to change to the %HOMEDRIVE%\ProgramData\ssh folder.

Generating a key pair

You get quite a bit of ouput when you run the ssh-keygen command, including some ASCII art. The main thing to note is that you have the option to protect your private key with a password:

[localhost ~]$ ssh-keygen
Generating public/private rsa key pair.

Enter file in which to save the key (/home/c2/.ssh/id_rsa): 
Created directory '/home/c2/.ssh'.

Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 

Your identification has been saved in /home/c2/.ssh/id_rsa.
Your public key has been saved in /home/c2/.ssh/id_rsa.pub.

The key fingerprint is:
SHA256:u/ivj2YiC4dkTwroJWYmvxhmRb+tPKTEpYMwAMkrXAA c2@localhost

The key's randomart image is:
+---[RSA 3072]----+
|Eo.              |
|o. .             |
|o o.             |
|=o. ..           |
|**=o+.  S        |
|**+X .o  .       |
|.+* *. ..        |
|oo =o.o.oo       |
|. . .=o==+o      |
+----[SHA256]-----+

In the above example we generated a key paid on a Linux machine. On Unix-like operating systems the private and public key are stored in the ~/.ssh directory:

[localhost ~]$ ls -lA .ssh/
-rw-------. 1 c2 c2 2602 Feb 17 22:57 id_rsa
-rw-r--r--. 1 c2 c2  570 Feb 17 22:57 id_rsa.pub

Copy the public key to the remote server

Next, we need to copy the public key to the remote server. You can do that manually, but it is much easier to use the ssh-copy-id command instead:

[localhost ~]$ ssh-copy-id -p 2222 example@cpweb6-premium.active-ns.com
The authenticity of host '[cpweb6-premium.active-ns.com]:2222 ([84.18.203.45]:2222)' can't be established.
ECDSA key fingerprint is SHA256:JEDa817fgEReGADSzmipl9FgnIKXR2.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

example@cpweb6-premium.active-ns.com's password: 

Number of key(s) added: 1

Now try logging into the machine, with: "ssh -p '2222' 'example@cpweb6-premium.active-ns.com'"
and check to make sure that only the key(s) you wanted were added.

[localhost ~]$ ssh -p 2222 example@cpweb6-premium.active-ns.com
[example@cpweb6-premium ~]$ 

The ssh-copy-id command uses the same syntax as the ssh utility. We specified the port we wanted to connect to followed by our username and the server’s hostname. As we had not connected from this machine before we had to accept the authenticity of the remote host.

After that the local public key was copied to the remote server, and ssh-copy-id invited us to check if we can now connect to the server. When we connected via SSH we got a command prompt on the remote host straight away.

Adding more security

If you are using a VPS or dedicated server then there are various ways to increase the level of security. Please contact us if you would like to discuss the pros and cons of various options.